00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <engine/ActionController.h>
00022 #include <engine/ScorchedContext.h>
00023 #include <movement/TargetMovement.h>
00024 #include <common/Logger.h>
00025 #include <common/OptionsScorched.h>
00026 #include <list>
00027
00028 ActionController::ActionController() :
00029 GameStateI("ActionController"),
00030 speed_(1), referenceCount_(0), time_(0),
00031 context_(0), lastTraceTime_(0),
00032 actionTracing_(false), stepTime_(0),
00033 actionEvents_(false), actionProfiling_(false),
00034 stopImmediately_(false),
00035 actionNumber_(0)
00036 {
00037
00038 }
00039
00040 ActionController::~ActionController()
00041 {
00042
00043 }
00044
00045 void ActionController::clear(bool warn)
00046 {
00047
00048 std::list<Action *>::iterator newItor;
00049 for (newItor = newActions_.begin();
00050 newItor != newActions_.end();
00051 newItor++)
00052 {
00053 Action *act = *newItor;
00054 if (warn)
00055 {
00056 Logger::log(S3D::formatStringBuffer("Warning: removing added timed out action %s, %s",
00057 act->getActionType().c_str(), (act->getReferenced()?"Ref":"UnRef")));
00058 }
00059 delete act;
00060 }
00061 newActions_.clear();
00062
00063
00064 for (newItor = newLastActions_.begin();
00065 newItor != newLastActions_.end();
00066 newItor++)
00067 {
00068 Action *act = *newItor;
00069 if (warn)
00070 {
00071 Logger::log(S3D::formatStringBuffer("Warning: removing added timed out action %s, %s",
00072 act->getActionType().c_str(), (act->getReferenced()?"Ref":"UnRef")));
00073 }
00074 delete act;
00075 }
00076 newLastActions_.clear();
00077
00078
00079 for (int a=0; a<actions_.actionCount; a++)
00080 {
00081 Action *act = actions_.actions[a];
00082 if (warn)
00083 {
00084 Logger::log(S3D::formatStringBuffer("Warning: removing added timed out action %s, %s",
00085 act->getActionType().c_str(), (act->getReferenced()?"Ref":"UnRef")));
00086 }
00087 delete act;
00088 }
00089 actions_.clear();
00090
00091
00092 referenceCount_ = 0;
00093 }
00094
00095 bool ActionController::allEvents()
00096 {
00097
00098
00099
00100 std::list<Action *>::iterator newItor;
00101 for (newItor = newActions_.begin();
00102 newItor != newActions_.end();
00103 newItor++)
00104 {
00105 Action *act = *newItor;
00106 if (!act->getActionEvent() &&
00107 act->getReferenced()) return false;
00108 }
00109 for (int a=0; a<actions_.actionCount; a++)
00110 {
00111 Action *act = actions_.actions[a];
00112 if (!act->getActionEvent() &&
00113 act->getReferenced()) return false;
00114 }
00115 return true;
00116 }
00117
00118 void ActionController::logActions()
00119 {
00120 Logger::log(S3D::formatStringBuffer("ActionLog : Time %.2f, New %i, New Last %i, Ref %i",
00121 time_.asFloat(),
00122 (int) newActions_.size(),
00123 (int) newLastActions_.size(),
00124 referenceCount_));
00125 for (int a=0; a<actions_.actionCount; a++)
00126 {
00127 Action *act = actions_.actions[a];
00128 Logger::log(S3D::formatStringBuffer("Action : %s", act->getActionType().c_str()));
00129 }
00130 }
00131
00132 void ActionController::logProfiledActions()
00133 {
00134 if (!actionProfiling_) return;
00135
00136 Logger::log("Logging Profiled Actions --------------------");
00137 int totalCount = 0;
00138 std::map<std::string, int>::iterator itor;
00139 for (itor = actionProfile_.begin();
00140 itor != actionProfile_.end();
00141 itor++)
00142 {
00143 const std::string &name = (*itor).first;
00144 int count = (*itor).second;
00145 totalCount += count;
00146 Logger::log(S3D::formatStringBuffer("%s - %i", name.c_str(), count));
00147 }
00148 Logger::log(S3D::formatStringBuffer("Total - %i", totalCount));
00149 Logger::log("---------------------------------------------");
00150
00151 actionProfile_.clear();
00152 }
00153
00154 bool ActionController::noReferencedActions()
00155 {
00156 bool finished =
00157 newActions_.empty() &&
00158 newLastActions_.empty() &&
00159 (referenceCount_ == 0);
00160
00161 if (actionTracing_)
00162 {
00163 if (time_ - lastTraceTime_ > 5)
00164 {
00165 lastTraceTime_ = time_;
00166 logActions();
00167 }
00168 }
00169
00170 return finished;
00171 }
00172
00173 void ActionController::resetTime()
00174 {
00175 time_ = 0;
00176 lastTraceTime_ = 0;
00177 stepTime_ = 0;
00178
00179 syncCheck_.clear();
00180 }
00181
00182 void ActionController::setScorchedContext(ScorchedContext *context)
00183 {
00184 context_ = context;
00185 }
00186
00187 void ActionController::setFast(fixed speedMult)
00188 {
00189 speed_ = speedMult;
00190 }
00191
00192 void ActionController::addSyncCheck(const std::string &msg)
00193 {
00194 if (!stopImmediately_) return;
00195
00196 DIALOG_ASSERT(context_->getOptionsGame().getActionSyncCheck());
00197 syncCheck_.push_back(msg);
00198 }
00199
00200 void ActionController::addAction(Action *action)
00201 {
00202 action->setScorchedContext(context_);
00203 action->setActionStartTime(time_);
00204 action->setActionEvent(actionEvents_);
00205
00206 if (action->getReferenced())
00207 {
00208 action->setActionNumber(++actionNumber_);
00209 if (context_->getOptionsGame().getActionSyncCheck())
00210 {
00211 std::string actionType = action->getActionType();
00212 std::string actionDetails = action->getActionDetails();
00213 addSyncCheck(
00214 S3D::formatStringBuffer("Add Action : %i %s:%s",
00215 time_.getInternal(),
00216 actionType.c_str(),
00217 actionDetails.c_str()));
00218 }
00219 }
00220
00221 newActions_.push_back(action);
00222
00223 if (actionProfiling_)
00224 {
00225 std::map<std::string, int>::iterator findItor =
00226 actionProfile_.find(action->getActionType());
00227 if (findItor == actionProfile_.end())
00228 {
00229 actionProfile_[action->getActionType()] = 1;
00230 }
00231 else
00232 {
00233 (*findItor).second++;
00234 }
00235 }
00236 }
00237
00238 void ActionController::addLastAction(Action *action)
00239 {
00240 newLastActions_.push_back(action);
00241 }
00242
00243 void ActionController::addNewLastActions()
00244 {
00245 if (newActions_.empty() &&
00246 referenceCount_ == 0)
00247 {
00248 while (!newLastActions_.empty())
00249 {
00250 Action *action = newLastActions_.front();
00251 addAction(action);
00252 newLastActions_.pop_front();
00253 }
00254 }
00255 }
00256
00257 void ActionController::addNewActions()
00258 {
00259 while (!newActions_.empty())
00260 {
00261 Action *action = newActions_.front();
00262
00263 action->setScorchedContext(context_);
00264 action->setActionStartTime(time_);
00265 if (action->getReferenced()) referenceCount_ ++;
00266
00267 action->init();
00268 actions_.push_back(action);
00269
00270 newActions_.pop_front();
00271 }
00272 }
00273
00274 void ActionController::draw(const unsigned state)
00275 {
00276
00277 for (int a=0; a<actions_.actionCount; a++)
00278 {
00279 Action *act = actions_.actions[a];
00280 act->draw();
00281 }
00282 }
00283
00284 void ActionController::simulate(const unsigned state, float ft)
00285 {
00286 fixed frameTime = fixed::fromFloat(ft);
00287
00288 frameTime *= speed_;
00289
00290
00291
00292 stepTime_ += frameTime;
00293
00294
00295 const fixed stepSize = fixed(1) / fixed(context_->getOptionsGame().getPhysicsFPS());
00296 while (stepTime_ >= stepSize && !(stopImmediately_ && noReferencedActions()))
00297 {
00298 time_ += stepSize;
00299 stepActions(stepSize);
00300
00301
00302 stepTime_ -= stepSize;
00303 }
00304 }
00305
00306 void ActionController::stepActions(fixed frameTime)
00307 {
00308
00309 addNewLastActions();
00310
00311
00312 addNewActions();
00313
00314
00315 if (time_ < 10 && !allEvents())
00316 {
00317 actionEvents_ = true;
00318 events_.simulate(frameTime, *context_);
00319 actionEvents_ = false;
00320 }
00321
00322
00323 context_->getTargetMovement().simulate(*context_, frameTime);
00324
00325
00326 int keepcount=0;
00327 for (int a=0; a<actions_.actionCount; a++)
00328 {
00329 Action *act = actions_.actions[a];
00330 bool remove = false;
00331 act->simulate(frameTime, remove);
00332
00333
00334 if (act->getReferenced())
00335 {
00336 if ((time_ - act->getActionStartTime() > 30))
00337 {
00338 Logger::log(S3D::formatStringBuffer("Warning: removing timed out action %s",
00339 act->getActionType().c_str()));
00340 remove = true;
00341 }
00342 }
00343
00344
00345 if (remove)
00346 {
00347 if (act->getReferenced())
00348 {
00349 referenceCount_--;
00350 if (referenceCount_<0) referenceCount_ = 0;
00351
00352 if (context_->getOptionsGame().getActionSyncCheck())
00353 {
00354 std::string actionType = act->getActionType();
00355 std::string actionDetails = act->getActionDetails();
00356 addSyncCheck(
00357 S3D::formatStringBuffer("Rm Action : %i %s:%s",
00358 time_.getInternal(),
00359 actionType.c_str(),
00360 actionDetails.c_str()));
00361 }
00362 }
00363
00364 delete act;
00365 }
00366 else
00367 {
00368 actions_.actions[keepcount] = act;
00369 keepcount++;
00370 }
00371 }
00372 actions_.actionCount = keepcount;
00373 }
00374