FIFE
2008.0
|
00001 /*************************************************************************** 00002 * Copyright (C) 2005-2008 by the FIFE team * 00003 * http://www.fifengine.de * 00004 * This file is part of FIFE. * 00005 * * 00006 * FIFE is free software; you can redistribute it and/or * 00007 * modify it under the terms of the GNU Lesser General Public * 00008 * License as published by the Free Software Foundation; either * 00009 * version 2.1 of the License, or (at your option) any later version. * 00010 * * 00011 * This library is distributed in the hope that it will be useful, * 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 00014 * Lesser General Public License for more details. * 00015 * * 00016 * You should have received a copy of the GNU Lesser General Public * 00017 * License along with this library; if not, write to the * 00018 * Free Software Foundation, Inc., * 00019 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * 00020 ***************************************************************************/ 00021 00022 // Standard C++ library includes 00023 #include <iostream> 00024 00025 // 3rd party library includes 00026 #include <SDL.h> 00027 00028 // FIFE includes 00029 // These includes are split up in two parts, separated by one empty line 00030 // First block: files included from the FIFE root src directory 00031 // Second block: files included from the same folder 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 // Current action, owned by object 00072 Action* m_action; 00073 // target location for ongoing movement 00074 Location* m_target; 00075 // current movement speed 00076 double m_speed; 00077 // should action be repeated? used only for non-moving actions, moving ones repeat until movement is finished 00078 bool m_repeating; 00079 // action start time (ticks) 00080 unsigned int m_action_start_time; 00081 // action offset time (ticks) for resuming an action 00082 unsigned int m_action_offset_time; 00083 // ticks since last call 00084 unsigned int m_prev_call_time; 00085 // session id for pather 00086 int m_pather_session_id; 00087 // pather 00088 AbstractPather* m_pather; 00089 // leader for follow activity 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 // Really remove "removed" listeners. 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 // Don't ditribute onActionFinished in case we're already 00200 // deleting. 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 // timeslice for this movement 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 // how far we can travel 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 //ExactModelCoordinate a = nextLocation.getMapCoordinates(); 00390 //ExactModelCoordinate b = m_actioninfo->m_target->getMapCoordinates(); 00391 m_location.getLayer()->getInstanceTree()->addInstance(this); 00392 // return if we are close enough to target to stop 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 // update target if needed 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 // prock: offset no longer needed 00428 info->m_action_offset_time = 0; 00429 } else { 00430 finalizeAction(); 00431 } 00432 } 00433 } 00434 00435 // previous code may invalidate actioninfo. 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 //m_facinglocation->setLayerCoordinates(ModelCoordinate(1,0)); 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 }