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/ipather.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(IPather* 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 uint32_t m_action_start_time;
00081
00082 uint32_t m_action_offset_time;
00083
00084 uint32_t m_prev_call_time;
00085
00086 int32_t m_pather_session_id;
00087
00088 IPather* m_pather;
00089
00090 Instance* m_leader;
00091 };
00092
00093 class SayInfo {
00094 public:
00095 SayInfo(const std::string& txt, uint32_t duration):
00096 m_txt(txt),
00097 m_duration(duration),
00098 m_start_time(0) {}
00099
00100 std::string m_txt;
00101 uint32_t m_duration;
00102 uint32_t m_start_time;
00103 };
00104
00105 Instance::InstanceActivity::InstanceActivity(Instance& source):
00106 m_location(source.m_location),
00107 m_rotation(source.m_rotation),
00108 m_facinglocation(),
00109 m_action(),
00110 m_speed(0),
00111 m_timemultiplier(1.0),
00112 m_saytxt(""),
00113 m_changelisteners(),
00114 m_actionlisteners(),
00115 m_actioninfo(NULL),
00116 m_sayinfo(NULL),
00117 m_timeprovider(NULL),
00118 m_blocking(source.m_blocking) {
00119 if (source.m_facinglocation) {
00120 m_facinglocation = *source.m_facinglocation;
00121 }
00122 }
00123
00124 Instance::InstanceActivity::~InstanceActivity() {
00125 delete m_actioninfo;
00126 delete m_sayinfo;
00127 delete m_timeprovider;
00128 }
00129
00130 void Instance::InstanceActivity::update(Instance& source) {
00131 source.m_changeinfo = ICHANGE_NO_CHANGES;
00132 if (m_location != source.m_location) {
00133 source.m_changeinfo |= ICHANGE_LOC;
00134 if (m_location.getLayerCoordinates() != source.m_location.getLayerCoordinates()) {
00135 source.m_changeinfo |= ICHANGE_CELL;
00136 }
00137 m_location = source.m_location;
00138 }
00139 if (m_rotation != source.m_rotation) {
00140 source.m_changeinfo |= ICHANGE_ROTATION;
00141 m_rotation = source.m_rotation;
00142 }
00143 if (source.m_facinglocation && (m_facinglocation != *source.m_facinglocation)) {
00144 source.m_changeinfo |= ICHANGE_FACING_LOC;
00145 m_facinglocation = *source.m_facinglocation;
00146 }
00147 if (m_actioninfo && (m_speed != m_actioninfo->m_speed)) {
00148 source.m_changeinfo |= ICHANGE_SPEED;
00149 m_speed = m_actioninfo->m_speed;
00150 }
00151 if (m_actioninfo && (m_action != m_actioninfo->m_action)) {
00152 source.m_changeinfo |= ICHANGE_ACTION;
00153 m_action = m_actioninfo->m_action;
00154 }
00155 if (m_timeprovider && (m_timemultiplier != m_timeprovider->getMultiplier())) {
00156 source.m_changeinfo |= ICHANGE_TIME_MULTIPLIER;
00157 m_timemultiplier = m_timeprovider->getMultiplier();
00158 }
00159 if (m_sayinfo && (m_saytxt != m_sayinfo->m_txt)) {
00160 source.m_changeinfo |= ICHANGE_SAYTEXT;
00161 m_saytxt = m_sayinfo->m_txt;
00162 }
00163 if (m_blocking != source.m_blocking) {
00164 source.m_changeinfo |= ICHANGE_BLOCK;
00165 m_blocking = source.m_blocking;
00166 }
00167
00168 if (source.m_changeinfo != ICHANGE_NO_CHANGES) {
00169 std::vector<InstanceChangeListener*>::iterator i = m_changelisteners.begin();
00170 while (i != m_changelisteners.end()) {
00171 if (NULL != *i)
00172 {
00173 (*i)->onInstanceChanged(&source, source.m_changeinfo);
00174 }
00175 ++i;
00176 }
00177
00178 m_changelisteners.erase(
00179 std::remove(m_changelisteners.begin(),m_changelisteners.end(),
00180 (InstanceChangeListener*)NULL),
00181 m_changelisteners.end());
00182 }
00183 }
00184
00185 Instance::Instance(Object* object, const Location& location, const std::string& identifier):
00186 m_id(identifier),
00187 m_rotation(0),
00188 m_activity(NULL),
00189 m_changeinfo(ICHANGE_NO_CHANGES),
00190 m_object(object),
00191 m_location(location),
00192 m_facinglocation(NULL),
00193 m_visual(NULL),
00194 m_blocking(object->isBlocking()),
00195 m_override_blocking(false) {
00196 }
00197
00198 Instance::~Instance() {
00199 std::vector<InstanceDeleteListener *>::iterator itor;
00200 for(itor = m_deletelisteners.begin(); itor != m_deletelisteners.end(); ++itor) {
00201 if (*itor != NULL) {
00202 (*itor)->onInstanceDeleted(this);
00203 }
00204 }
00205
00206 if(m_activity && m_activity->m_actioninfo) {
00207
00208
00209 m_activity->m_actionlisteners.clear();
00210 finalizeAction();
00211 }
00212
00213 delete m_activity;
00214 delete m_facinglocation;
00215 delete m_visual;
00216 }
00217
00218 void Instance::initializeChanges() {
00219 if (!m_activity) {
00220 m_activity = new InstanceActivity(*this);
00221 if(m_location.getLayer()) {
00222 m_location.getLayer()->setInstanceActivityStatus(this, true);
00223 }
00224 }
00225 }
00226
00227 bool Instance::isActive() const {
00228 return (m_activity != 0);
00229 }
00230
00231 void Instance::setLocation(const Location& loc) {
00232
00233 if(m_location != loc) {
00234 if(isActive()) {
00235 if (m_location.getLayerCoordinates() != loc.getLayerCoordinates()) {
00236 m_location.getLayer()->getInstanceTree()->removeInstance(this);
00237 m_location = loc;
00238 m_location.getLayer()->getInstanceTree()->addInstance(this);
00239 } else {
00240 m_location = loc;
00241 }
00242 refresh();
00243 } else {
00244 initializeChanges();
00245 if (m_location.getLayerCoordinates() != loc.getLayerCoordinates()) {
00246 m_location.getLayer()->getInstanceTree()->removeInstance(this);
00247 m_location = loc;
00248 m_location.getLayer()->getInstanceTree()->addInstance(this);
00249 } else {
00250 m_location = loc;
00251 }
00252 }
00253 }
00254 }
00255
00256 void Instance::setRotation(int32_t rotation) {
00257 if(m_rotation != rotation) {
00258 if(isActive()) {
00259 m_rotation = rotation;
00260 refresh();
00261 } else {
00262 initializeChanges();
00263 m_rotation = rotation;
00264 }
00265 }
00266 }
00267
00268 void Instance::setId(const std::string& identifier) {
00269 m_id = identifier;
00270 }
00271
00272 void Instance::setBlocking(bool blocking) {
00273 if (m_override_blocking) {
00274 m_blocking = blocking;
00275 }
00276 }
00277
00278 bool Instance::isBlocking() const {
00279 return m_blocking;
00280 }
00281
00282 void Instance::addActionListener(InstanceActionListener* listener) {
00283 initializeChanges();
00284 m_activity->m_actionlisteners.push_back(listener);
00285 }
00286
00287 void Instance::removeActionListener(InstanceActionListener* listener) {
00288 if (!m_activity) {
00289 return;
00290 }
00291 std::vector<InstanceActionListener*>::iterator i = m_activity->m_actionlisteners.begin();
00292 while (i != m_activity->m_actionlisteners.end()) {
00293 if ((*i) == listener) {
00294 *i = NULL;
00295 return;
00296 }
00297 ++i;
00298 }
00299 FL_WARN(_log, "Cannot remove unknown listener");
00300 }
00301
00302 void Instance::addChangeListener(InstanceChangeListener* listener) {
00303 initializeChanges();
00304 m_activity->m_changelisteners.push_back(listener);
00305 }
00306
00307 void Instance::callOnActionFrame(Action* action, int32_t frame) {
00308 if (!m_activity) {
00309 return;
00310 }
00311
00312 std::vector<InstanceActionListener*>::iterator i = m_activity->m_actionlisteners.begin();
00313 while (i != m_activity->m_actionlisteners.end()) {
00314 if(*i) {
00315 (*i)->onInstanceActionFrame(this, action, frame);
00316 }
00317 ++i;
00318 }
00319 }
00320
00321 void Instance::removeChangeListener(InstanceChangeListener* listener) {
00322 if (!m_activity) {
00323 return;
00324 }
00325 std::vector<InstanceChangeListener*>::iterator i = m_activity->m_changelisteners.begin();
00326 while (i != m_activity->m_changelisteners.end()) {
00327 if ((*i) == listener) {
00328 *i = NULL;
00329 return;
00330 }
00331 ++i;
00332 }
00333 FL_WARN(_log, "Cannot remove unknown listener");
00334 }
00335 void Instance::initializeAction(const std::string& action_name) {
00336 assert(m_object);
00337 assert(m_activity);
00338 const Action *old_action = m_activity->m_actioninfo ? m_activity->m_actioninfo->m_action : NULL;
00339 if (m_activity->m_actioninfo) {
00340 delete m_activity->m_actioninfo;
00341 m_activity->m_actioninfo = NULL;
00342 }
00343 m_activity->m_actioninfo = new ActionInfo(m_object->getPather(), m_location);
00344 m_activity->m_actioninfo->m_action = m_object->getAction(action_name);
00345 if (!m_activity->m_actioninfo->m_action) {
00346 delete m_activity->m_actioninfo;
00347 m_activity->m_actioninfo = NULL;
00348 throw NotFound(std::string("action ") + action_name + " not found");
00349 }
00350 m_activity->m_actioninfo->m_prev_call_time = getRuntime();
00351 if (m_activity->m_actioninfo->m_action != old_action) {
00352 m_activity->m_actioninfo->m_action_start_time = m_activity->m_actioninfo->m_prev_call_time;
00353 }
00354 }
00355
00356 void Instance::move(const std::string& action_name, const Location& target, const double speed) {
00357 initializeChanges();
00358 initializeAction(action_name);
00359 m_activity->m_actioninfo->m_target = new Location(target);
00360 m_activity->m_actioninfo->m_speed = speed;
00361 setFacingLocation(target);
00362 FL_DBG(_log, LMsg("starting action ") << action_name << " from" << m_location << " to " << target << " with speed " << speed);
00363 }
00364
00365 void Instance::follow(const std::string& action_name, Instance* leader, const double speed) {
00366 initializeChanges();
00367 initializeAction(action_name);
00368 m_activity->m_actioninfo->m_target = new Location(leader->getLocationRef());
00369 m_activity->m_actioninfo->m_speed = speed;
00370 m_activity->m_actioninfo->m_leader = leader;
00371 leader->addDeleteListener(this);
00372 setFacingLocation(*m_activity->m_actioninfo->m_target);
00373 FL_DBG(_log, LMsg("starting action ") << action_name << " from" << m_location << " to " << *m_activity->m_actioninfo->m_target << " with speed " << speed);
00374 }
00375
00376 void Instance::act(const std::string& action_name, const Location& direction, bool repeating) {
00377 initializeChanges();
00378 initializeAction(action_name);
00379 m_activity->m_actioninfo->m_repeating = repeating;
00380 setFacingLocation(direction);
00381 }
00382
00383 void Instance::say(const std::string& text, uint32_t duration) {
00384 initializeChanges();
00385 delete m_activity->m_sayinfo;
00386 m_activity->m_sayinfo = NULL;
00387
00388 if (text != "") {
00389 m_activity->m_sayinfo = new SayInfo(text, duration);
00390 m_activity->m_sayinfo->m_start_time = getRuntime();
00391 }
00392 }
00393
00394 const std::string* Instance::getSayText() const {
00395 if (m_activity && m_activity->m_sayinfo) {
00396 return &m_activity->m_sayinfo->m_txt;
00397 }
00398 return NULL;
00399 }
00400
00401 void Instance::setFacingLocation(const Location& loc) {
00402 if (!m_facinglocation) {
00403 m_facinglocation = new Location(loc);
00404 } else {
00405 *m_facinglocation = loc;
00406 }
00407 }
00408
00409 bool Instance::process_movement() {
00410
00411 ActionInfo* info = m_activity->m_actioninfo;
00412
00413 uint32_t timedelta = m_activity->m_timeprovider->getGameTime() - info->m_prev_call_time;
00414
00415
00416 double distance_to_travel = (static_cast<double>(timedelta) / 1000.0) * info->m_speed;
00417
00418
00419 Location nextLocation = m_location;
00420 info->m_pather_session_id = info->m_pather->getNextLocation(
00421 this, *info->m_target,
00422 distance_to_travel, nextLocation, *m_facinglocation,
00423 info->m_pather_session_id);
00424 m_location.getLayer()->getInstanceTree()->removeInstance(this);
00425 m_location = nextLocation;
00426
00427
00428 m_location.getLayer()->getInstanceTree()->addInstance(this);
00429
00430 if (info->m_pather_session_id == -1) {
00431 return true;
00432 }
00433 return false;
00434 }
00435
00436 InstanceChangeInfo Instance::update() {
00437 if (!m_activity) {
00438 return ICHANGE_NO_CHANGES;
00439 }
00440
00441 m_deletelisteners.erase(std::remove(m_deletelisteners.begin(),m_deletelisteners.end(),
00442 (InstanceDeleteListener*)NULL), m_deletelisteners.end());
00443 m_activity->update(*this);
00444 if (!m_activity->m_timeprovider) {
00445 bindTimeProvider();
00446 }
00447 ActionInfo* info = m_activity->m_actioninfo;
00448 if (info) {
00449
00450
00451 if (info->m_target) {
00452
00453
00454 if (info->m_leader && (info->m_leader->getLocationRef() != *info->m_target)) {
00455 *info->m_target = info->m_leader->getLocation();
00456 }
00457 bool movement_finished = process_movement();
00458 if (movement_finished) {
00459
00460 finalizeAction();
00461 }
00462 } else {
00463
00464 if (m_activity->m_timeprovider->getGameTime() - info->m_action_start_time + info->m_action_offset_time >= info->m_action->getDuration()) {
00465 if (info->m_repeating) {
00466 info->m_action_start_time = m_activity->m_timeprovider->getGameTime();
00467
00468 info->m_action_offset_time = 0;
00469 } else {
00470 finalizeAction();
00471 }
00472 }
00473 }
00474
00475
00476 if( m_activity->m_actioninfo ) {
00477 m_activity->m_actioninfo->m_prev_call_time = m_activity->m_timeprovider->getGameTime();
00478 }
00479 }
00480 if (m_activity->m_sayinfo) {
00481 if (m_activity->m_sayinfo->m_duration > 0) {
00482 if (m_activity->m_timeprovider->getGameTime() >= m_activity->m_sayinfo->m_start_time + m_activity->m_sayinfo->m_duration) {
00483 say("");
00484 }
00485 }
00486 } else if (!m_activity->m_actioninfo && m_changeinfo == ICHANGE_NO_CHANGES && m_activity->m_actionlisteners.empty()) {
00487
00488 delete m_activity;
00489 m_activity = 0;
00490 return ICHANGE_NO_CHANGES;
00491 }
00492 return m_changeinfo;
00493 }
00494
00495 void Instance::finalizeAction() {
00496 FL_DBG(_log, "finalizing action");
00497 assert(m_activity);
00498 assert(m_activity->m_actioninfo);
00499
00500 if( m_activity->m_actioninfo->m_leader ) {
00501 m_activity->m_actioninfo->m_leader->removeDeleteListener(this);
00502 }
00503
00504 Action* action = m_activity->m_actioninfo->m_action;
00505 delete m_activity->m_actioninfo;
00506 m_activity->m_actioninfo = NULL;
00507
00508 std::vector<InstanceActionListener*>::iterator i = m_activity->m_actionlisteners.begin();
00509 while (i != m_activity->m_actionlisteners.end()) {
00510 if(*i)
00511 (*i)->onInstanceActionFinished(this, action);
00512 ++i;
00513 }
00514 m_activity->m_actionlisteners.erase(
00515 std::remove(m_activity->m_actionlisteners.begin(),
00516 m_activity->m_actionlisteners.end(),
00517 (InstanceActionListener*)NULL),
00518 m_activity->m_actionlisteners.end());
00519 }
00520
00521 Action* Instance::getCurrentAction() const {
00522 if (m_activity && m_activity->m_actioninfo) {
00523 return m_activity->m_actioninfo->m_action;
00524 }
00525 return NULL;
00526 }
00527
00528 Location Instance::getTargetLocation() const {
00529 if (m_activity && m_activity->m_actioninfo && m_activity->m_actioninfo->m_target) {
00530 return *m_activity->m_actioninfo->m_target;
00531 }
00532 return m_location;
00533 }
00534
00535 double Instance::getMovementSpeed() const {
00536 if (m_activity && m_activity->m_actioninfo) {
00537 return m_activity->m_actioninfo->m_speed;
00538 }
00539 return 0;
00540 }
00541
00542 Location Instance::getFacingLocation() {
00543 return this->getFacingLocationRef();
00544 }
00545
00546 Location& Instance::getFacingLocationRef() {
00547 if (!m_facinglocation) {
00548 m_facinglocation = new Location(m_location);
00549 m_facinglocation->setExactLayerCoordinates(m_facinglocation->getExactLayerCoordinates() + ExactModelCoordinate(1.0, 0.0));
00550
00551 }
00552 return *m_facinglocation;
00553 }
00554
00555 uint32_t Instance::getActionRuntime() {
00556 if (m_activity && m_activity->m_actioninfo) {
00557 if(!m_activity->m_timeprovider)
00558 bindTimeProvider();
00559 return m_activity->m_timeprovider->getGameTime() - m_activity->m_actioninfo->m_action_start_time + m_activity->m_actioninfo->m_action_offset_time;
00560 }
00561 return getRuntime();
00562 }
00563
00564 void Instance::setActionRuntime(uint32_t time_offset) {
00565 m_activity->m_actioninfo->m_action_offset_time = time_offset;
00566 }
00567
00568 void Instance::bindTimeProvider() {
00569 float multiplier = 1.0;
00570 if (m_activity->m_timeprovider) {
00571 multiplier = m_activity->m_timeprovider->getMultiplier();
00572 }
00573 delete m_activity->m_timeprovider;
00574 m_activity->m_timeprovider = NULL;
00575
00576 if (m_location.getLayer()) {
00577 Map* map = m_location.getLayer()->getMap();
00578 if (map) {
00579 m_activity->m_timeprovider = new TimeProvider(map->getTimeProvider());
00580 }
00581 }
00582 if (!m_activity->m_timeprovider) {
00583 m_activity->m_timeprovider = new TimeProvider(NULL);
00584 }
00585 m_activity->m_timeprovider->setMultiplier(multiplier);
00586 }
00587
00588 void Instance::refresh() {
00589 initializeChanges();
00590 bindTimeProvider();
00591 }
00592
00593 void Instance::setTimeMultiplier(float multip) {
00594 initializeChanges();
00595 if (!m_activity->m_timeprovider) {
00596 bindTimeProvider();
00597 }
00598 m_activity->m_timeprovider->setMultiplier(multip);
00599 }
00600
00601 float Instance::getTimeMultiplier() {
00602 if (m_activity && m_activity->m_timeprovider) {
00603 return m_activity->m_timeprovider->getMultiplier();
00604 }
00605 return 1.0;
00606 }
00607
00608 float Instance::getTotalTimeMultiplier() {
00609 if (m_activity && m_activity->m_timeprovider) {
00610 return m_activity->m_timeprovider->getTotalMultiplier();
00611 }
00612 if (m_location.getLayer()) {
00613 Map* map = m_location.getLayer()->getMap();
00614 if (map && map->getTimeProvider()) {
00615 return map->getTimeProvider()->getTotalMultiplier();
00616 }
00617 }
00618 return 1.0;
00619 }
00620
00621 uint32_t Instance::getRuntime() {
00622 if (m_activity) {
00623 if(!m_activity->m_timeprovider)
00624 bindTimeProvider();
00625 return m_activity->m_timeprovider->getGameTime();
00626 }
00627 if (m_location.getLayer()) {
00628 Map* map = m_location.getLayer()->getMap();
00629 if (map && map->getTimeProvider()) {
00630 return map->getTimeProvider()->getGameTime();
00631 }
00632 }
00633 return TimeManager::instance()->getTime();
00634 }
00635
00636 void Instance::addDeleteListener(InstanceDeleteListener *listener) {
00637 m_deletelisteners.push_back(listener);
00638 }
00639
00640 void Instance::removeDeleteListener(InstanceDeleteListener *listener) {
00641 if (!m_deletelisteners.empty()) {
00642 std::vector<InstanceDeleteListener*>::iterator itor;
00643 itor = std::find(m_deletelisteners.begin(), m_deletelisteners.end(), listener);
00644 if(itor != m_deletelisteners.end()) {
00645 if ((*itor) == listener) {
00646 *itor = NULL;
00647 return;
00648 }
00649 } else {
00650 FL_WARN(_log, "Cannot remove unknown listener");
00651 }
00652 }
00653 }
00654
00655 void Instance::onInstanceDeleted(Instance* instance) {
00656 if(m_activity && m_activity->m_actioninfo &&
00657 m_activity->m_actioninfo->m_leader == instance) {
00658 m_activity->m_actioninfo->m_leader = NULL;
00659 }
00660 }
00661 }