instance.cpp

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 }
Generated on Wed Nov 23 13:04:43 2011 for FIFE by  doxygen 1.6.3