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