00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <iostream>
00024
00025
00026 #include <SDL.h>
00027
00028
00029
00030
00031
00032 #include "util/log/logger.h"
00033 #include "util/base/exception.h"
00034 #include "util/math/fife_math.h"
00035 #include "util/time/timemanager.h"
00036 #include "model/metamodel/grids/cellgrid.h"
00037 #include "model/metamodel/abstractpather.h"
00038 #include "model/metamodel/action.h"
00039 #include "model/metamodel/timeprovider.h"
00040 #include "model/structures/layer.h"
00041 #include "model/structures/map.h"
00042 #include "model/structures/instancetree.h"
00043
00044 #include "instance.h"
00045
00046 namespace FIFE {
00047 static Logger _log(LM_INSTANCE);
00048
00049 class ActionInfo {
00050 public:
00051 ActionInfo(AbstractPather* pather, const Location& curloc):
00052 m_action(NULL),
00053 m_target(NULL),
00054 m_speed(0),
00055 m_repeating(false),
00056 m_action_start_time(0),
00057 m_action_offset_time(0),
00058 m_prev_call_time(0),
00059 m_pather_session_id(-1),
00060 m_pather(pather),
00061 m_leader(NULL) {}
00062
00063 ~ActionInfo() {
00064 if (m_pather_session_id != -1) {
00065 m_pather->cancelSession(m_pather_session_id);
00066 }
00067 delete m_target;
00068 m_target = NULL;
00069 }
00070
00071
00072 Action* m_action;
00073
00074 Location* m_target;
00075
00076 double m_speed;
00077
00078 bool m_repeating;
00079
00080 unsigned int m_action_start_time;
00081
00082 unsigned int m_action_offset_time;
00083
00084 unsigned int m_prev_call_time;
00085
00086 int m_pather_session_id;
00087
00088 AbstractPather* m_pather;
00089
00090 Instance* m_leader;
00091 };
00092
00093 class SayInfo {
00094 public:
00095 SayInfo(const std::string& txt, unsigned int duration):
00096 m_txt(txt),
00097 m_duration(duration),
00098 m_start_time(0) {}
00099
00100 std::string m_txt;
00101 unsigned int m_duration;
00102 unsigned int m_start_time;
00103 };
00104
00105 Instance::InstanceActivity::InstanceActivity(Instance& source):
00106 m_location(source.m_location),
00107 m_facinglocation(),
00108 m_action(),
00109 m_speed(0),
00110 m_timemultiplier(1.0),
00111 m_saytxt(""),
00112 m_changelisteners(),
00113 m_actionlisteners(),
00114 m_actioninfo(NULL),
00115 m_sayinfo(NULL),
00116 m_timeprovider(NULL) {
00117 if (source.m_facinglocation) {
00118 m_facinglocation = *source.m_facinglocation;
00119 }
00120 }
00121
00122 Instance::InstanceActivity::~InstanceActivity() {
00123 delete m_actioninfo;
00124 delete m_sayinfo;
00125 delete m_timeprovider;
00126 }
00127
00128 void Instance::InstanceActivity::update(Instance& source) {
00129 source.m_changeinfo = ICHANGE_NO_CHANGES;
00130 if (m_location != source.m_location) {
00131 source.m_changeinfo |= ICHANGE_LOC;
00132 m_location = source.m_location;
00133 }
00134 if (source.m_facinglocation && (m_facinglocation != *source.m_facinglocation)) {
00135 source.m_changeinfo |= ICHANGE_FACING_LOC;
00136 m_facinglocation = *source.m_facinglocation;
00137 }
00138 if (m_actioninfo && (m_speed != m_actioninfo->m_speed)) {
00139 source.m_changeinfo |= ICHANGE_SPEED;
00140 m_speed = m_actioninfo->m_speed;
00141 }
00142 if (m_actioninfo && (m_action != m_actioninfo->m_action)) {
00143 source.m_changeinfo |= ICHANGE_ACTION;
00144 m_action = m_actioninfo->m_action;
00145 }
00146 if (m_timeprovider && (m_timemultiplier != m_timeprovider->getMultiplier())) {
00147 source.m_changeinfo |= ICHANGE_TIME_MULTIPLIER;
00148 m_timemultiplier = m_timeprovider->getMultiplier();
00149 }
00150 if (m_sayinfo && (m_saytxt != m_sayinfo->m_txt)) {
00151 source.m_changeinfo |= ICHANGE_SAYTEXT;
00152 m_saytxt = m_sayinfo->m_txt;
00153 }
00154
00155 if (source.m_changeinfo != ICHANGE_NO_CHANGES) {
00156 std::vector<InstanceChangeListener*>::iterator i = m_changelisteners.begin();
00157 while (i != m_changelisteners.end()) {
00158 if (NULL != *i)
00159 {
00160 (*i)->onInstanceChanged(&source, source.m_changeinfo);
00161 }
00162 ++i;
00163 }
00164
00165 m_changelisteners.erase(
00166 std::remove(m_changelisteners.begin(),m_changelisteners.end(),
00167 (InstanceChangeListener*)NULL),
00168 m_changelisteners.end());
00169 }
00170 }
00171
00172 Instance::Instance(Object* object, const Location& location, const std::string& identifier):
00173 m_id(identifier),
00174 m_rotation(0),
00175 m_activity(NULL),
00176 m_changeinfo(ICHANGE_NO_CHANGES),
00177 m_object(object),
00178 m_location(location),
00179 m_facinglocation(NULL),
00180 m_visual(NULL) {
00181 }
00182
00183 Instance::~Instance() {
00184 std::vector<InstanceDeleteListener *>::iterator itor;
00185 for(itor = m_deletelisteners.begin();
00186 itor != m_deletelisteners.end();
00187 ++itor) {
00188 (*itor)->onInstanceDeleted(this);
00189 }
00190
00191 if(m_activity && m_activity->m_actioninfo) {
00192
00193
00194 m_activity->m_actionlisteners.clear();
00195 finalizeAction();
00196 }
00197
00198 delete m_activity;
00199 delete m_facinglocation;
00200 delete m_visual;
00201 }
00202
00203 void Instance::initializeChanges() {
00204 if (!m_activity) {
00205 m_activity = new InstanceActivity(*this);
00206 }
00207 }
00208
00209 void Instance::setLocation(const Location& loc) {
00210 initializeChanges();
00211 m_location = loc;
00212 bindTimeProvider();
00213 }
00214
00215 void Instance::setRotation(int rotation) {
00216 m_rotation = rotation;
00217 m_changeinfo |= ICHANGE_ROTATION;
00218 }
00219
00220 void Instance::setId(const std::string& identifier) {
00221 m_id = identifier;
00222 }
00223
00224 void Instance::addActionListener(InstanceActionListener* listener) {
00225 initializeChanges();
00226 m_activity->m_actionlisteners.push_back(listener);
00227 }
00228
00229 void Instance::removeActionListener(InstanceActionListener* listener) {
00230 if (!m_activity) {
00231 return;
00232 }
00233 std::vector<InstanceActionListener*>::iterator i = m_activity->m_actionlisteners.begin();
00234 while (i != m_activity->m_actionlisteners.end()) {
00235 if ((*i) == listener) {
00236 *i = NULL;
00237 return;
00238 }
00239 ++i;
00240 }
00241 FL_WARN(_log, "Cannot remove unknown listener");
00242 }
00243
00244 void Instance::addChangeListener(InstanceChangeListener* listener) {
00245 initializeChanges();
00246 m_activity->m_changelisteners.push_back(listener);
00247 }
00248
00249 void Instance::removeChangeListener(InstanceChangeListener* listener) {
00250 if (!m_activity) {
00251 return;
00252 }
00253 std::vector<InstanceChangeListener*>::iterator i = m_activity->m_changelisteners.begin();
00254 while (i != m_activity->m_changelisteners.end()) {
00255 if ((*i) == listener) {
00256 *i = NULL;
00257 return;
00258 }
00259 ++i;
00260 }
00261 FL_WARN(_log, "Cannot remove unknown listener");
00262 }
00263 void Instance::initializeAction(const std::string& action_name) {
00264 assert(m_object);
00265 assert(m_activity);
00266 const Action *old_action = m_activity->m_actioninfo ? m_activity->m_actioninfo->m_action : NULL;
00267 if (m_activity->m_actioninfo) {
00268 delete m_activity->m_actioninfo;
00269 m_activity->m_actioninfo = NULL;
00270 }
00271 m_activity->m_actioninfo = new ActionInfo(m_object->getPather(), m_location);
00272 m_activity->m_actioninfo->m_action = m_object->getAction(action_name);
00273 if (!m_activity->m_actioninfo->m_action) {
00274 delete m_activity->m_actioninfo;
00275 m_activity->m_actioninfo = NULL;
00276 throw NotFound(std::string("action ") + action_name + " not found");
00277 }
00278 m_activity->m_actioninfo->m_prev_call_time = getRuntime();
00279 if (m_activity->m_actioninfo->m_action != old_action) {
00280 m_activity->m_actioninfo->m_action_start_time = m_activity->m_actioninfo->m_prev_call_time;
00281 }
00282 }
00283
00284 void Instance::move(const std::string& action_name, const Location& target, const double speed) {
00285 initializeChanges();
00286 initializeAction(action_name);
00287 m_activity->m_actioninfo->m_target = new Location(target);
00288 m_activity->m_actioninfo->m_speed = speed;
00289 setFacingLocation(target);
00290 FL_DBG(_log, LMsg("starting action ") << action_name << " from" << m_location << " to " << target << " with speed " << speed);
00291 }
00292
00293 void Instance::follow(const std::string& action_name, Instance* leader, const double speed) {
00294 initializeChanges();
00295 initializeAction(action_name);
00296 m_activity->m_actioninfo->m_target = new Location(leader->getLocationRef());
00297 m_activity->m_actioninfo->m_speed = speed;
00298 m_activity->m_actioninfo->m_leader = leader;
00299 leader->addDeleteListener(this);
00300 setFacingLocation(*m_activity->m_actioninfo->m_target);
00301 FL_DBG(_log, LMsg("starting action ") << action_name << " from" << m_location << " to " << *m_activity->m_actioninfo->m_target << " with speed " << speed);
00302 }
00303
00304 void Instance::act(const std::string& action_name, const Location& direction, bool repeating) {
00305 initializeChanges();
00306 initializeAction(action_name);
00307 m_activity->m_actioninfo->m_repeating = repeating;
00308 setFacingLocation(direction);
00309 }
00310
00311 void Instance::say(const std::string& text, unsigned int duration) {
00312 initializeChanges();
00313 delete m_activity->m_sayinfo;
00314 m_activity->m_sayinfo = NULL;
00315
00316 if (text != "") {
00317 m_activity->m_sayinfo = new SayInfo(text, duration);
00318 m_activity->m_sayinfo->m_start_time = getRuntime();
00319 }
00320 }
00321
00322 const std::string* Instance::getSayText() const {
00323 if (m_activity && m_activity->m_sayinfo) {
00324 return &m_activity->m_sayinfo->m_txt;
00325 }
00326 return NULL;
00327 }
00328
00329 void Instance::setFacingLocation(const Location& loc) {
00330 if (!m_facinglocation) {
00331 m_facinglocation = new Location(loc);
00332 } else {
00333 *m_facinglocation = loc;
00334 }
00335 }
00336
00337 bool Instance::process_movement() {
00338 FL_DBG(_log, "Moving...");
00339 ActionInfo* info = m_activity->m_actioninfo;
00340
00341 unsigned int timedelta = m_activity->m_timeprovider->getGameTime() - info->m_prev_call_time;
00342 FL_DBG(_log, LMsg("timedelta ") << timedelta << " prevcalltime " << info->m_prev_call_time);
00343
00344 double distance_to_travel = (static_cast<double>(timedelta) / 1000.0) * info->m_speed;
00345 FL_DBG(_log, LMsg("dist ") << distance_to_travel);
00346
00347 Location nextLocation = m_location;
00348 info->m_pather_session_id = info->m_pather->getNextLocation(
00349 this, *info->m_target,
00350 distance_to_travel, nextLocation, *m_facinglocation,
00351 info->m_pather_session_id);
00352 m_location.getLayer()->getInstanceTree()->removeInstance(this);
00353 m_location = nextLocation;
00354
00355
00356 m_location.getLayer()->getInstanceTree()->addInstance(this);
00357
00358 if (info->m_pather_session_id == -1) {
00359 return true;
00360 }
00361 return false;
00362 }
00363
00364 InstanceChangeInfo Instance::update() {
00365 if (!m_activity) {
00366 return ICHANGE_NO_CHANGES;
00367 }
00368 m_activity->update(*this);
00369 if (!m_activity->m_timeprovider) {
00370 bindTimeProvider();
00371 }
00372 ActionInfo* info = m_activity->m_actioninfo;
00373 if (info) {
00374 FL_DBG(_log, "updating instance");
00375
00376 if (info->m_target) {
00377 FL_DBG(_log, "action contains target for movement");
00378
00379 if (info->m_leader && (info->m_leader->getLocationRef() != *info->m_target)) {
00380 *info->m_target = info->m_leader->getLocation();
00381 }
00382 bool movement_finished = process_movement();
00383 if (movement_finished) {
00384 FL_DBG(_log, "movement finished");
00385 finalizeAction();
00386 }
00387 } else {
00388 FL_DBG(_log, "action does not contain target for movement");
00389 if (m_activity->m_timeprovider->getGameTime() - info->m_action_start_time + info->m_action_offset_time >= info->m_action->getDuration()) {
00390 if (info->m_repeating) {
00391 info->m_action_start_time = m_activity->m_timeprovider->getGameTime();
00392
00393 info->m_action_offset_time = 0;
00394 } else {
00395 finalizeAction();
00396 }
00397 }
00398 }
00399
00400
00401 if( m_activity->m_actioninfo ) {
00402 m_activity->m_actioninfo->m_prev_call_time = m_activity->m_timeprovider->getGameTime();
00403 }
00404 }
00405 if (m_activity->m_sayinfo) {
00406 if (m_activity->m_sayinfo->m_duration > 0) {
00407 if (m_activity->m_timeprovider->getGameTime() >= m_activity->m_sayinfo->m_start_time + m_activity->m_sayinfo->m_duration) {
00408 say("");
00409 }
00410 }
00411 }
00412 return m_changeinfo;
00413 }
00414
00415 void Instance::finalizeAction() {
00416 FL_DBG(_log, "finalizing action");
00417 assert(m_activity);
00418 assert(m_activity->m_actioninfo);
00419
00420 if( m_activity->m_actioninfo->m_leader ) {
00421 m_activity->m_actioninfo->m_leader->removeDeleteListener(this);
00422 }
00423
00424 Action* action = m_activity->m_actioninfo->m_action;
00425 delete m_activity->m_actioninfo;
00426 m_activity->m_actioninfo = NULL;
00427
00428 std::vector<InstanceActionListener*>::iterator i = m_activity->m_actionlisteners.begin();
00429 while (i != m_activity->m_actionlisteners.end()) {
00430 if(*i)
00431 (*i)->onInstanceActionFinished(this, action);
00432 ++i;
00433 }
00434 m_activity->m_actionlisteners.erase(
00435 std::remove(m_activity->m_actionlisteners.begin(),
00436 m_activity->m_actionlisteners.end(),
00437 (InstanceActionListener*)NULL),
00438 m_activity->m_actionlisteners.end());
00439 }
00440
00441 Action* Instance::getCurrentAction() const {
00442 if (m_activity && m_activity->m_actioninfo) {
00443 return m_activity->m_actioninfo->m_action;
00444 }
00445 return NULL;
00446 }
00447
00448 Location Instance::getTargetLocation() const {
00449 if (m_activity && m_activity->m_actioninfo && m_activity->m_actioninfo->m_target) {
00450 return *m_activity->m_actioninfo->m_target;
00451 }
00452 return m_location;
00453 }
00454
00455 double Instance::getMovementSpeed() const {
00456 if (m_activity && m_activity->m_actioninfo) {
00457 return m_activity->m_actioninfo->m_speed;
00458 }
00459 return 0;
00460 }
00461
00462 Location Instance::getFacingLocation() {
00463 return this->getFacingLocationRef();
00464 }
00465
00466 Location& Instance::getFacingLocationRef() {
00467 if (!m_facinglocation) {
00468 m_facinglocation = new Location(m_location);
00469 m_facinglocation->setExactLayerCoordinates(m_facinglocation->getExactLayerCoordinates() + ExactModelCoordinate(1.0, 0.0));
00470
00471 }
00472 return *m_facinglocation;
00473 }
00474
00475 unsigned int Instance::getActionRuntime() {
00476 if (m_activity && m_activity->m_actioninfo) {
00477 if(!m_activity->m_timeprovider)
00478 bindTimeProvider();
00479 return m_activity->m_timeprovider->getGameTime() - m_activity->m_actioninfo->m_action_start_time + m_activity->m_actioninfo->m_action_offset_time;
00480 }
00481 return getRuntime();
00482 }
00483
00484 void Instance::setActionRuntime(unsigned int time_offset) {
00485 m_activity->m_actioninfo->m_action_offset_time = time_offset;
00486 }
00487
00488 void Instance::bindTimeProvider() {
00489 float multiplier = 1.0;
00490 if (m_activity->m_timeprovider) {
00491 multiplier = m_activity->m_timeprovider->getMultiplier();
00492 }
00493 delete m_activity->m_timeprovider;
00494 m_activity->m_timeprovider = NULL;
00495
00496 if (m_location.getLayer()) {
00497 Map* map = m_location.getLayer()->getMap();
00498 if (map) {
00499 m_activity->m_timeprovider = new TimeProvider(map->getTimeProvider());
00500 }
00501 }
00502 if (!m_activity->m_timeprovider) {
00503 m_activity->m_timeprovider = new TimeProvider(NULL);
00504 }
00505 m_activity->m_timeprovider->setMultiplier(multiplier);
00506 }
00507
00508 void Instance::refresh() {
00509 initializeChanges();
00510 bindTimeProvider();
00511 }
00512
00513 void Instance::setTimeMultiplier(float multip) {
00514 initializeChanges();
00515 if (!m_activity->m_timeprovider) {
00516 bindTimeProvider();
00517 }
00518 m_activity->m_timeprovider->setMultiplier(multip);
00519 }
00520
00521 float Instance::getTimeMultiplier() {
00522 if (m_activity && m_activity->m_timeprovider) {
00523 return m_activity->m_timeprovider->getMultiplier();
00524 }
00525 return 1.0;
00526 }
00527
00528 float Instance::getTotalTimeMultiplier() {
00529 if (m_activity && m_activity->m_timeprovider) {
00530 return m_activity->m_timeprovider->getTotalMultiplier();
00531 }
00532 if (m_location.getLayer()) {
00533 Map* map = m_location.getLayer()->getMap();
00534 if (map && map->getTimeProvider()) {
00535 return map->getTimeProvider()->getTotalMultiplier();
00536 }
00537 }
00538 return 1.0;
00539 }
00540
00541 unsigned int Instance::getRuntime() {
00542 if (m_activity) {
00543 if(!m_activity->m_timeprovider)
00544 bindTimeProvider();
00545 return m_activity->m_timeprovider->getGameTime();
00546 }
00547 if (m_location.getLayer()) {
00548 Map* map = m_location.getLayer()->getMap();
00549 if (map && map->getTimeProvider()) {
00550 return map->getTimeProvider()->getGameTime();
00551 }
00552 }
00553 return TimeManager::instance()->getTime();
00554 }
00555 void Instance::addDeleteListener(InstanceDeleteListener *listener) {
00556 m_deletelisteners.push_back(listener);
00557 }
00558 void Instance::removeDeleteListener(InstanceDeleteListener *listener) {
00559 std::vector<InstanceDeleteListener*>::iterator itor;
00560 itor = std::find(m_deletelisteners.begin(),
00561 m_deletelisteners.end(),
00562 listener);
00563 if(itor != m_deletelisteners.end()) {
00564 m_deletelisteners.erase(itor);
00565 } else {
00566 FL_WARN(_log, "Cannot remove unknown listener");
00567 }
00568 }
00569 void Instance::onInstanceDeleted(Instance* instance) {
00570 if(m_activity &&
00571 m_activity->m_actioninfo &&
00572 m_activity->m_actioninfo->m_leader == instance) {
00573 m_activity->m_actioninfo->m_leader = NULL;
00574 }
00575 }
00576 }