FIFE
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
instance.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2005-2013 by the FIFE team *
3  * http://www.fifengine.net *
4  * This file is part of FIFE. *
5  * *
6  * FIFE is free software; you can redistribute it and/or *
7  * modify it under the terms of the GNU Lesser General Public *
8  * License as published by the Free Software Foundation; either *
9  * version 2.1 of the License, or (at your option) any later version. *
10  * *
11  * This library is distributed in the hope that it will be useful, *
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
14  * Lesser General Public License for more details. *
15  * *
16  * You should have received a copy of the GNU Lesser General Public *
17  * License along with this library; if not, write to the *
18  * Free Software Foundation, Inc., *
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
20  ***************************************************************************/
21 
22 // Standard C++ library includes
23 #include <iostream>
24 
25 // 3rd party library includes
26 #include <SDL.h>
27 
28 // FIFE includes
29 // These includes are split up in two parts, separated by one empty line
30 // First block: files included from the FIFE root src directory
31 // Second block: files included from the same folder
32 #include "util/log/logger.h"
33 #include "util/base/exception.h"
34 #include "util/math/fife_math.h"
35 #include "util/time/timemanager.h"
38 #include "model/metamodel/action.h"
40 #include "model/structures/layer.h"
41 #include "model/structures/map.h"
43 #include "view/visual.h"
44 #include "pathfinder/route.h"
45 
46 #include "instance.h"
47 
48 namespace FIFE {
49  static Logger _log(LM_INSTANCE);
50 
51  class ActionInfo {
52  public:
53  ActionInfo(IPather* pather, const Location& curloc):
54  m_action(NULL),
55  m_target(NULL),
56  m_speed(0),
57  m_repeating(false),
61  m_pather(pather),
62  m_leader(NULL),
63  m_route(NULL),
64  m_delete_route(true) {}
65 
67  if (m_route) {
68  int32_t sessionId = m_route->getSessionId();
69  if (sessionId != -1) {
70  m_pather->cancelSession(sessionId);
71  }
72  if (m_delete_route) {
73  delete m_route;
74  } else {
75  m_route->setSessionId(-1);
76  }
77  }
78  delete m_target;
79  }
80 
81  // Current action, owned by object
83  // target location for ongoing movement
85  // current movement speed
86  double m_speed;
87  // should action be repeated? used only for non-moving actions, moving ones repeat until movement is finished
89  // action start time (ticks)
91  // action offset time (ticks) for resuming an action
93  // ticks since last call
95  // pather
97  // leader for follow activity
99  // pointer to route that contain path and additional information
102  };
103 
104  class SayInfo {
105  public:
106  SayInfo(const std::string& txt, uint32_t duration):
107  m_txt(txt),
108  m_duration(duration),
109  m_start_time(0) {}
110 
111  std::string m_txt;
114  };
115 
117  m_location(source.m_location),
118  m_oldLocation(source.m_location),
119  m_rotation(source.m_rotation),
120  m_oldRotation(source.m_rotation),
121  m_action(),
122  m_speed(0),
123  m_timeMultiplier(1.0),
124  m_sayText(""),
125  m_changeListeners(),
126  m_actionListeners(),
127  m_actionInfo(NULL),
128  m_sayInfo(NULL),
129  m_timeProvider(NULL),
130  m_blocking(source.m_blocking),
131  m_additional(ICHANGE_NO_CHANGES) {
132  }
133 
135  delete m_actionInfo;
136  delete m_sayInfo;
137  delete m_timeProvider;
138  }
139 
142  if (m_additional != ICHANGE_NO_CHANGES) {
143  source.m_changeInfo = m_additional;
144  m_additional = ICHANGE_NO_CHANGES;
145  }
146  if (m_location != source.m_location) {
147  source.m_changeInfo |= ICHANGE_LOC;
149  m_oldLocation.setLayer(m_location.getLayer());
150  m_oldLocation.setLayerCoordinates(m_location.getLayerCoordinates());
151  source.m_changeInfo |= ICHANGE_CELL;
152  }
153  m_location = source.m_location;
154  }
155  if (m_rotation != source.m_rotation) {
156  m_oldRotation = m_rotation;
157  source.m_changeInfo |= ICHANGE_ROTATION;
158  m_rotation = source.m_rotation;
159  }
160  if (m_actionInfo && (m_speed != m_actionInfo->m_speed)) {
161  source.m_changeInfo |= ICHANGE_SPEED;
162  m_speed = m_actionInfo->m_speed;
163  }
164  if (m_actionInfo && (m_action != m_actionInfo->m_action)) {
165  source.m_changeInfo |= ICHANGE_ACTION;
166  m_action = m_actionInfo->m_action;
167  }
168  if (m_timeProvider && (m_timeMultiplier != m_timeProvider->getMultiplier())) {
170  m_timeMultiplier = m_timeProvider->getMultiplier();
171  }
172  if (m_sayInfo && (m_sayText != m_sayInfo->m_txt)) {
173  source.m_changeInfo |= ICHANGE_SAYTEXT;
174  m_sayText = m_sayInfo->m_txt;
175  }
176  if (m_blocking != source.m_blocking) {
177  source.m_changeInfo |= ICHANGE_BLOCK;
178  m_blocking = source.m_blocking;
179  }
180 
181  if (source.m_changeInfo != ICHANGE_NO_CHANGES) {
182  std::vector<InstanceChangeListener*>::iterator i = m_changeListeners.begin();
183  while (i != m_changeListeners.end()) {
184  if (NULL != *i)
185  {
186  (*i)->onInstanceChanged(&source, source.m_changeInfo);
187  }
188  ++i;
189  }
190  // Really remove "removed" listeners.
191  m_changeListeners.erase(
192  std::remove(m_changeListeners.begin(),m_changeListeners.end(),
193  (InstanceChangeListener*)NULL),
194  m_changeListeners.end());
195  }
196  }
197 
198  Instance::Instance(Object* object, const Location& location, const std::string& identifier):
199  m_id(identifier),
200  m_rotation(0),
201  m_activity(NULL),
203  m_object(object),
204  m_location(location),
205  m_visual(NULL),
206  m_blocking(object->isBlocking()),
207  m_overrideBlocking(false),
208  m_isVisitor(false),
210  m_visitorRadius(0),
212  m_specialCost(object->isSpecialCost()),
213  m_cost(object->getCost()),
214  m_costId(object->getCostId()) {
215  // create multi object instances
216  if (object->isMultiObject()) {
217  uint32_t count = 0;
218  Layer* layer = m_location.getLayer();
220  const std::set<Object*>& multis = object->getMultiParts();
221  std::set<Object*>::const_iterator it = multis.begin();
222  for (; it != multis.end(); ++it, ++count) {
223  if (*it == m_object) {
224  continue;
225  }
226  std::vector<ModelCoordinate> partcoords = (*it)->getMultiPartCoordinates(m_rotation);
227  std::vector<ModelCoordinate>::iterator coordit = partcoords.begin();
228  for (; coordit != partcoords.end(); ++coordit) {
229  ExactModelCoordinate tmp_emc(emc.x+(*coordit).x, emc.y+(*coordit).y, emc.z+(*coordit).z);
230  std::ostringstream counter;
231  counter << count;
232  Instance* instance = layer->createInstance(*it, tmp_emc, identifier+counter.str());
233  InstanceVisual::create(instance);
234  m_multiInstances.push_back(instance);
235  instance->addDeleteListener(this);
236  }
237  }
238  }
239  }
240 
242  std::vector<InstanceDeleteListener *>::iterator itor;
243  for(itor = m_deleteListeners.begin(); itor != m_deleteListeners.end(); ++itor) {
244  if (*itor != NULL) {
245  (*itor)->onInstanceDeleted(this);
246  }
247  }
248 
250  // Don't ditribute onActionFinished in case we're already
251  // deleting.
252  m_activity->m_actionListeners.clear();
253  finalizeAction();
254  }
255 
256  if (!m_multiInstances.empty()) {
257  std::vector<Instance*>::iterator it = m_multiInstances.begin();
258  for (; it != m_multiInstances.end(); ++it) {
259  (*it)->removeDeleteListener(this);
260  }
261  }
262 
263  delete m_activity;
264  delete m_visual;
265  }
266 
268  if (!m_activity) {
269  m_activity = new InstanceActivity(*this);
270  }
271  if (m_location.getLayer()) {
273  }
274  }
275 
276  bool Instance::isActive() const {
277  return (m_activity != 0);
278  }
279 
281  return m_object;
282  }
283 
284  void Instance::setLocation(const Location& loc) {
285  // ToDo: Handle the case when the layers are different
286  if(m_location != loc) {
287  if(isActive()) {
288  refresh();
289  } else {
291  }
292 
295  m_location = loc;
297  } else {
298  m_location = loc;
299  }
300  }
301  }
302 
304  return m_location;
305  }
306 
308  return m_location;
309  }
310 
311  void Instance::setRotation(int32_t rotation) {
312  while (rotation < 0) {
313  rotation += 360;
314  }
315  rotation %= 360;
316  if(m_rotation != rotation) {
317  if(isActive()) {
318  refresh();
319  m_rotation = rotation;
320  } else {
322  m_rotation = rotation;
323  }
324  }
325  }
326 
327  int32_t Instance::getRotation() const {
328  return m_rotation;
329  }
330 
331  void Instance::setId(const std::string& identifier) {
332  m_id = identifier;
333  }
334 
335  const std::string& Instance::getId() {
336  return m_id;
337  }
338 
339  void Instance::setBlocking(bool blocking) {
340  if (m_overrideBlocking) {
341  if(isActive()) {
342  refresh();
343  } else {
345  }
346  m_blocking = blocking;
347  }
348  }
349 
350  bool Instance::isBlocking() const {
351  return m_blocking;
352  }
353 
354  void Instance::setOverrideBlocking(bool overblock) {
355  m_overrideBlocking = overblock;
356  }
357 
359  return m_overrideBlocking;
360  }
361 
364  m_activity->m_actionListeners.push_back(listener);
365  }
366 
368  if (!m_activity) {
369  return;
370  }
371  std::vector<InstanceActionListener*>::iterator i = m_activity->m_actionListeners.begin();
372  while (i != m_activity->m_actionListeners.end()) {
373  if ((*i) == listener) {
374  *i = NULL;
375  return;
376  }
377  ++i;
378  }
379  FL_WARN(_log, "Cannot remove unknown listener");
380  }
381 
384  m_activity->m_changeListeners.push_back(listener);
385  }
386 
387  void Instance::callOnActionFrame(Action* action, int32_t frame) {
388  if (!m_activity) {
389  return;
390  }
391 
392  std::vector<InstanceActionListener*>::iterator i = m_activity->m_actionListeners.begin();
393  while (i != m_activity->m_actionListeners.end()) {
394  if(*i) {
395  (*i)->onInstanceActionFrame(this, action, frame);
396  }
397  ++i;
398  }
399  }
400 
402  if (!m_activity) {
403  return;
404  }
405  std::vector<InstanceChangeListener*>::iterator i = m_activity->m_changeListeners.begin();
406  while (i != m_activity->m_changeListeners.end()) {
407  if ((*i) == listener) {
408  *i = NULL;
409  return;
410  }
411  ++i;
412  }
413  FL_WARN(_log, "Cannot remove unknown listener");
414  }
415 
416  void Instance::initializeAction(const std::string& actionName) {
417  assert(m_object);
418 
420  const Action *old_action = m_activity->m_actionInfo ? m_activity->m_actionInfo->m_action : NULL;
421  if (m_activity->m_actionInfo) {
422  delete m_activity->m_actionInfo;
423  m_activity->m_actionInfo = NULL;
424  }
428  delete m_activity->m_actionInfo;
429  m_activity->m_actionInfo = NULL;
430  throw NotFound(std::string("action ") + actionName + " not found");
431  }
433  if (m_activity->m_actionInfo->m_action != old_action) {
435  }
436  if (isMultiObject()) {
437  std::vector<Instance*>::iterator multi_it = m_multiInstances.begin();
438  for (; multi_it != m_multiInstances.end(); ++multi_it) {
439  (*multi_it)->initializeAction(actionName);
440  }
441  }
442  }
443 
444  void Instance::move(const std::string& actionName, const Location& target, const double speed, const std::string& costId) {
445  // if new move is identical with the old then return
446  if (m_activity) {
447  if (m_activity->m_actionInfo) {
451  m_activity->m_actionInfo->m_action == m_object->getAction(actionName) &&
452  costId == m_activity->m_actionInfo->m_route->getCostId()) {
453 
454  return;
455  }
456  }
457  }
458  }
459  initializeAction(actionName);
460  m_activity->m_actionInfo->m_target = new Location(target);
461  m_activity->m_actionInfo->m_speed = speed;
462  FL_DBG(_log, LMsg("starting action ") << actionName << " from" << m_location << " to " << target << " with speed " << speed);
463 
465  if (!route) {
467  route->setRotation(getRotation());
468  if (costId != "") {
469  route->setCostId(costId);
470  }
471  if (isMultiCell()) {
472  route->setObject(m_object);
475  } else if (m_object->getZStepRange() != -1 || !m_object->getWalkableAreas().empty()) {
476  route->setObject(m_object);
477  }
478  m_activity->m_actionInfo->m_route = route;
479  if (!m_activity->m_actionInfo->m_pather->solveRoute(route)) {
480  setFacingLocation(target);
481  finalizeAction();
482  }
483  }
484  }
485 
486  void Instance::follow(const std::string& actionName, Instance* leader, const double speed) {
487  initializeAction(actionName);
489  m_activity->m_actionInfo->m_speed = speed;
490  m_activity->m_actionInfo->m_leader = leader;
491  leader->addDeleteListener(this);
492  FL_DBG(_log, LMsg("starting action ") << actionName << " from" << m_location << " to " << *m_activity->m_actionInfo->m_target << " with speed " << speed);
493  }
494 
495  void Instance::follow(const std::string& actionName, Route* route, const double speed) {
496  initializeAction(actionName);
498  m_activity->m_actionInfo->m_speed = speed;
499  m_activity->m_actionInfo->m_route = route;
501  if (isMultiCell()) {
502  route->setObject(m_object);
505  } else if (m_object->getZStepRange() != -1 || !m_object->getWalkableAreas().empty()) {
506  route->setObject(m_object);
507  }
508  FL_DBG(_log, LMsg("starting action ") << actionName << " from" << m_location << " to " << *m_activity->m_actionInfo->m_target << " with speed " << speed);
509  }
510 
512  if (m_activity) {
514  if (info) {
515  Route* route = info->m_route;
516  if (route) {
517  route->cutPath(length);
518  }
519  }
520  }
521  }
522 
524  if (m_activity) {
526  if (info) {
527  return info->m_route;
528  }
529  }
530  return NULL;
531  }
532 
533  void Instance::setVisitor(bool visit) {
534  m_isVisitor = visit;
535  }
536 
538  return m_isVisitor;
539  }
540 
542  m_visitorShape = info;
543  }
544 
546  return m_visitorShape;
547  }
548 
550  m_visitorRadius = radius;
551  }
552 
554  return m_visitorRadius;
555  }
556 
558  m_cellStackPos = stack;
559  }
560 
562  return m_cellStackPos;
563  }
564 
566  return m_specialCost;
567  }
568 
569  const std::vector<Instance*>& Instance::getMultiInstances() {
570  return m_multiInstances;
571  }
572 
573  void Instance::act(const std::string& actionName, const Location& direction, bool repeating) {
574  initializeAction(actionName);
575  m_activity->m_actionInfo->m_repeating = repeating;
576  setFacingLocation(direction);
577  }
578 
579  void Instance::act(const std::string& actionName, int32_t rotation, bool repeating) {
580  initializeAction(actionName);
581  m_activity->m_actionInfo->m_repeating = repeating;
582  setRotation(rotation);
583  }
584 
585  void Instance::act(const std::string& actionName, bool repeating) {
586  initializeAction(actionName);
587  m_activity->m_actionInfo->m_repeating = repeating;
588  }
589 
590  void Instance::say(const std::string& text, uint32_t duration) {
592  delete m_activity->m_sayInfo;
593  m_activity->m_sayInfo = NULL;
594 
595  if (text != "") {
596  m_activity->m_sayInfo = new SayInfo(text, duration);
598  }
599  }
600 
601  const std::string* Instance::getSayText() const {
602  if (m_activity && m_activity->m_sayInfo) {
603  return &m_activity->m_sayInfo->m_txt;
604  }
605  return NULL;
606  }
607 
610  Route* route = info->m_route;
611  Location target;
612  if (info->m_leader) {
613  target = info->m_leader->getLocationRef();
614  } else {
615  target = *info->m_target;
616  }
617  if (!route) {
618  route = new Route(m_location, *info->m_target);
619  route->setRotation(getRotation());
620  info->m_route = route;
621  if (isMultiCell()) {
622  route->setObject(m_object);
625  } else if (m_object->getZStepRange() != -1 || !m_object->getWalkableAreas().empty()) {
626  route->setObject(m_object);
627  }
628  if (!info->m_pather->solveRoute(route)) {
629  setFacingLocation(target);
630  return true;
631  }
632  // update target if needed
633  } else if (route->getEndNode().getLayerCoordinates() != target.getLayerCoordinates()) {
634  if (route->isReplanned() || isMultiCell()) {
635  *info->m_target = route->getEndNode();
636  route->setReplanned(false);
637  if (isMultiCell()) {
640  }
641  } else {
642  if (route->getPathLength() == 0) {
643  route->setStartNode(m_location);
644  } else {
645  route->setStartNode(route->getCurrentNode());
646  }
647  route->setEndNode(target);
648  if (!info->m_pather->solveRoute(route)) {
649  setFacingLocation(target);
650  return true;
651  }
652  }
653  }
654 
655  if (route->getRouteStatus() == ROUTE_SOLVED) {
656  // timeslice for this movement
658  // how far we can travel
659  double distance_to_travel = (static_cast<double>(timedelta) / 1000.0) * info->m_speed;
660  // location for this movement
661  Location nextLocation = m_location;
662  bool can_follow = info->m_pather->followRoute(m_location, route, distance_to_travel, nextLocation);
663  if (can_follow) {
664  setRotation(route->getRotation());
665  // move to another layer
666  if (m_location.getLayer() != nextLocation.getLayer()) {
667  m_location.getLayer()->getMap()->addInstanceForTransfer(this, nextLocation);
668  if (!m_multiInstances.empty()) {
669  std::vector<Instance*>::iterator it = m_multiInstances.begin();
670  for (; it != m_multiInstances.end(); ++it) {
671  Location newloc = nextLocation;
672  std::vector<ModelCoordinate> tmpcoords = m_location.getLayer()->getCellGrid()->
673  toMultiCoordinates(nextLocation.getLayerCoordinates(), (*it)->getObject()->getMultiPartCoordinates(m_rotation));
674  newloc.setLayerCoordinates(tmpcoords.front());
676  }
677  }
678  return false;
679  }
680  setLocation(nextLocation);
681  return false;
682  }
683  // move to another layer
684  if (m_location.getLayer() != nextLocation.getLayer()) {
685  m_location.getLayer()->getMap()->addInstanceForTransfer(this, nextLocation);
686  if (!m_multiInstances.empty()) {
687  std::vector<Instance*>::iterator it = m_multiInstances.begin();
688  for (; it != m_multiInstances.end(); ++it) {
689  Location newloc = nextLocation;
690  std::vector<ModelCoordinate> tmpcoords = m_location.getLayer()->getCellGrid()->
691  toMultiCoordinates(nextLocation.getLayerCoordinates(), (*it)->getObject()->getMultiPartCoordinates(m_rotation));
692  newloc.setLayerCoordinates(tmpcoords.front());
694  }
695  }
696  return true;
697  }
698  setLocation(nextLocation);
699  // need new route?
701  if (m_location.getLayerDistanceTo(target) > 1.5) {
702  if (route->getPathLength() == 0) {
703  route->setStartNode(m_location);
704  } else {
705  route->setStartNode(route->getPreviousNode());
706  }
707  route->setEndNode(target);
710  return !info->m_pather->solveRoute(route);
711  }
712  setFacingLocation(target);
713  }
714  return true;
715  } else if (route->getRouteStatus() == ROUTE_FAILED) {
716  return true;
717  }
718  return false;
719  }
720 
722  if (!m_activity) {
723  return ICHANGE_NO_CHANGES;
724  }
725  // remove DeleteListeners
726  m_deleteListeners.erase(std::remove(m_deleteListeners.begin(),m_deleteListeners.end(),
728 
729  if (!m_activity->m_timeProvider) {
731  }
733  if (info) {
734 // FL_DBG(_log, "updating instance");
735 
736  if (info->m_target) {
737 // FL_DBG(_log, "action contains target for movement");
738  bool movement_finished = processMovement();
739  if (movement_finished) {
740 // FL_DBG(_log, "movement finished");
741  finalizeAction();
742  }
743  } else {
744 // FL_DBG(_log, "action does not contain target for movement");
746  if (info->m_repeating) {
748  // prock: offset no longer needed
749  info->m_action_offset_time = 0;
750  } else if (!m_object->isMultiPart()) {
751  finalizeAction();
752  }
753  }
754  }
755 
756  // previous code may invalidate actioninfo.
757  if( m_activity->m_actionInfo ) {
759  }
760  }
761  m_activity->update(*this);
762  if (m_activity->m_sayInfo) {
763  if (m_activity->m_sayInfo->m_duration > 0) {
765  say("");
766  }
767  }
769  // delete superfluous activity
770  delete m_activity;
771  m_activity = 0;
772  return ICHANGE_NO_CHANGES;
773  }
774  return m_changeInfo;
775  }
776 
778  FL_DBG(_log, "finalizing action");
779  assert(m_activity);
780  assert(m_activity->m_actionInfo);
781 
784  }
785 
787  delete m_activity->m_actionInfo;
788  m_activity->m_actionInfo = NULL;
789 
790  std::vector<InstanceActionListener*>::iterator i = m_activity->m_actionListeners.begin();
791  while (i != m_activity->m_actionListeners.end()) {
792  if(*i)
793  (*i)->onInstanceActionFinished(this, action);
794  ++i;
795  }
797  std::remove(m_activity->m_actionListeners.begin(),
799  (InstanceActionListener*)NULL),
801 
802  if (isMultiObject()) {
803  std::vector<Instance*>::iterator multi_it = m_multiInstances.begin();
804  for (; multi_it != m_multiInstances.end(); ++multi_it) {
805  (*multi_it)->finalizeAction();
806  }
807  }
808  }
809 
813  }
814  return NULL;
815  }
816 
819  return *m_activity->m_actionInfo->m_target;
820  }
821  return m_location;
822  }
823 
824  double Instance::getMovementSpeed() const {
827  }
828  return 0;
829  }
830 
833  }
834 
837  }
838 
840  if (m_activity) {
841  return m_activity->m_oldLocation;
842  }
843  return m_location;
844  }
845 
846  int32_t Instance::getOldRotation() const {
847  if (m_activity) {
848  return m_activity->m_oldRotation;
849  }
850  return m_rotation;
851  }
852 
858  }
859  return getRuntime();
860  }
861 
864  }
865 
867  float multiplier = 1.0;
868  if (m_activity->m_timeProvider) {
869  multiplier = m_activity->m_timeProvider->getMultiplier();
870  }
871  delete m_activity->m_timeProvider;
872  m_activity->m_timeProvider = NULL;
873 
874  if (m_location.getLayer()) {
875  Map* map = m_location.getLayer()->getMap();
876  if (map) {
878  }
879  }
880  if (!m_activity->m_timeProvider) {
882  }
884  }
885 
889  }
890 
892  if (m_activity) {
893  return m_changeInfo;
894  }
895  return ICHANGE_NO_CHANGES;
896  }
897 
899  if(isActive()) {
900  refresh();
901  } else {
903  }
905  }
906 
908  if(isActive()) {
909  refresh();
910  } else {
912  }
914  }
915 
917  if(isActive()) {
918  refresh();
919  } else {
921  }
923  }
924 
925  void Instance::setTimeMultiplier(float multip) {
927  if (!m_activity->m_timeProvider) {
929  }
931  }
932 
936  }
937  return 1.0;
938  }
939 
943  }
944  if (m_location.getLayer()) {
945  Map* map = m_location.getLayer()->getMap();
946  if (map && map->getTimeProvider()) {
947  return map->getTimeProvider()->getTotalMultiplier();
948  }
949  }
950  return 1.0;
951  }
952 
954  if (m_activity) {
958  }
959  if (m_location.getLayer()) {
960  Map* map = m_location.getLayer()->getMap();
961  if (map && map->getTimeProvider()) {
962  return map->getTimeProvider()->getGameTime();
963  }
964  }
965  return TimeManager::instance()->getTime();
966  }
967 
968  void Instance::setCost(const std::string& id, double cost) {
969  m_specialCost = true;
970  m_costId = id;
971  m_cost = cost;
972  }
973 
975  m_specialCost = false;
976  }
977 
978  double Instance::getCost() {
979  if (m_specialCost) {
980  return m_cost;
981  }
982  return m_object->getCost();
983  }
984 
985  const std::string& Instance::getCostId() {
986  if (m_specialCost) {
987  return m_costId;
988  }
989  return m_object->getCostId();
990  }
991 
993  return m_object->isMultiObject();
994  }
995 
997  return !m_multiInstances.empty();
998  }
999 
1001  if (!m_multiInstances.empty()) {
1002  // use map coords for rotation and movement
1003  // instances are changed on InstanceTree but not on CellCache
1004  Location loc = m_location;
1006  const ExactModelCoordinate& offset = m_object->getRotationAnchor();
1007  loc.setExactLayerCoordinates(offset);
1008  const ExactModelCoordinate anchor_offset = loc.getMapCoordinates();
1009  int32_t rot = m_rotation;
1010  if (m_object->isRestrictedRotation()) {
1012  }
1013  double mcos = Mathd::Cos(double(rot) * (Mathd::pi()/180.0));
1014  double msin = Mathd::Sin(double(rot) * (Mathd::pi()/180.0));
1015  std::vector<Instance*>::iterator it = m_multiInstances.begin();
1016  for (; it != m_multiInstances.end(); ++it) {
1017  // use rotation 0 to get the "default" coordinate
1018  std::vector<ModelCoordinate> mcv = (*it)->getObject()->getMultiPartCoordinates(0);
1019  loc.setLayerCoordinates(mcv.front());
1021  ExactModelCoordinate nemc(emc.x-anchor_offset.x, emc.y-anchor_offset.y);
1022  emc.x = ((nemc.x * mcos + nemc.y * msin) + anchor_offset.x) + anchor.x;
1023  emc.y = ((-nemc.x * msin + nemc.y * mcos) + anchor_offset.y) + anchor.y;
1024  loc.setMapCoordinates(emc);
1025  (*it)->setLocation(loc);
1026  (*it)->setRotation(rot);
1027  }
1028  }
1029  }
1030 
1032  m_deleteListeners.push_back(listener);
1033  }
1034 
1036  if (!m_deleteListeners.empty()) {
1037  std::vector<InstanceDeleteListener*>::iterator itor;
1038  itor = std::find(m_deleteListeners.begin(), m_deleteListeners.end(), listener);
1039  if(itor != m_deleteListeners.end()) {
1040  if ((*itor) == listener) {
1041  *itor = NULL;
1042  return;
1043  }
1044  } else {
1045  FL_WARN(_log, "Cannot remove unknown listener");
1046  }
1047  }
1048  }
1049 
1052  m_activity->m_actionInfo->m_leader == instance) {
1053  m_activity->m_actionInfo->m_leader = NULL;
1054  }
1055  if (isMultiObject()) {
1056  std::vector<Instance*>::iterator multi_it = m_multiInstances.begin();
1057  for (; multi_it != m_multiInstances.end(); ++multi_it) {
1058  if (*multi_it == instance) {
1059  m_multiInstances.erase(multi_it);
1060  break;
1061  }
1062  }
1063  }
1064  }
1065 }
bool isMultiObject()
Returns true if it is multi object otherwise false.
Definition: instance.cpp:996
static InstanceVisual * create(Instance *instance)
Constructs and assigns it to the passed item.
Definition: visual.cpp:98
#define FL_WARN(logger, msg)
Definition: logger.h:72
void callOnVisibleChange()
Definition: instance.cpp:907
Instance(Object *object, const Location &location, const std::string &identifier="")
Constructor Instances are created by calling addInstance from layer, thus this method should really b...
Definition: instance.cpp:198
void setOccupiedArea(const std::vector< ModelCoordinate > &area)
Sets occupied coordinates for multi cell object.
Definition: route.cpp:252
Timeprovider is an utility providing time management functionality You can have hierarchy of time pro...
Definition: timeprovider.h:42
Map * getMap() const
Get the map this layer is contained in.
Definition: layer.cpp:88
void cutPath(uint32_t length=1)
Cuts path after the given length.
Definition: route.cpp:179
IPather * getPather() const
Gets associated pather.
Definition: object.h:109
void initializeAction(const std::string &actionName)
Initialize action for use.
Definition: instance.cpp:416
double getCost() const
Returns the cost.
Definition: object.cpp:193
InstanceActivity * m_activity
Definition: instance.h:497
void updateMultiInstances()
Updates the visual positions of all instances in case this is a multi object.
Definition: instance.cpp:1000
int32_t getAngleBetween(const Location &loc1, const Location &loc2)
Gets angle of vector defined by given locations.
Definition: angles.cpp:98
void setLayerCoordinates(const ModelCoordinate &coordinates)
Sets &quot;cell precise&quot; layer coordinates to this location.
Definition: location.cpp:94
static T Cos(T _val)
Definition: fife_math.h:216
void setObject(Object *obj)
Sets the object, needed for multi cell and z-step range.
Definition: route.cpp:292
void follow(const std::string &actionName, Instance *leader, const double speed)
Performs given named action to the instance.
Definition: instance.cpp:486
void setMultiplier(float multiplier)
With multiplier, you can adjust the time speed.
IPather * m_pather
Definition: instance.cpp:96
InstanceActivity(Instance &source)
Definition: instance.cpp:116
bool m_isVisitor
is instance a visitor (FoW)
Definition: instance.h:514
VisitorShapeInfo m_visitorShape
visitor shape type
Definition: instance.h:516
void setExactLayerCoordinates(const ExactModelCoordinate &coordinates)
Sets precise layer coordinates to this location.
Definition: location.cpp:87
void addActionListener(InstanceActionListener *listener)
Adds new instance action listener.
Definition: instance.cpp:362
const Location & getPreviousNode()
Returns previous location.
Definition: route.cpp:106
const std::string & getCostId()
Returns cost id.
Definition: instance.cpp:985
virtual bool solveRoute(Route *route, int32_t priority=MEDIUM_PRIORITY, bool immediate=false)=0
Solves the route to create a path.
void initializeChanges()
called when instance has been changed. Causes instance to create InstanceActivity ...
Definition: instance.cpp:267
Helper class to create log strings out from separate parts Usage: LMsg(&quot;some text&quot;) &lt;&lt; variable &lt;&lt; &quot;...
Definition: logger.h:82
void setId(const std::string &identifier="")
Set the identifier for this instance.
Definition: instance.cpp:331
Object class.
Definition: object.h:51
uint32_t m_action_offset_time
Definition: instance.cpp:92
void addDeleteListener(InstanceDeleteListener *listener)
Adds new instance delete listener.
Definition: instance.cpp:1031
void callOnActionFrame(Action *action, int32_t frame)
Auxiliary function to inform ActionListeners about the active ActionFrame.
Definition: instance.cpp:387
bool isActive() const
If this returns true, the instance needs to be updated.
Definition: instance.cpp:276
uint32_t m_action_start_time
Definition: instance.cpp:90
bool isBlocking() const
Gets if instance blocks movement.
Definition: instance.cpp:350
void setFacingLocation(const Location &loc)
Sets the direction where instance is heading.
Definition: instance.cpp:831
void setMapCoordinates(const ExactModelCoordinate &coordinates)
Sets map coordinates to this location.
Definition: location.cpp:98
bool isMultiObject() const
Gets if object uses special cost.
Definition: object.cpp:197
Location getTargetLocation() const
Gets movement target in case instance is moving.
Definition: instance.cpp:817
std::vector< InstanceDeleteListener * > m_deleteListeners
listeners for deletion of the instance
Definition: instance.h:501
InstanceChangeInfo getChangeInfo()
Returns a bitmask of changes of the last update.
Definition: instance.cpp:891
const Location & getEndNode()
Returns the target location.
Definition: route.cpp:92
bool m_blocking
instance blocking info
Definition: instance.h:510
uint32_t m_start_time
Definition: instance.cpp:113
Instance * createInstance(Object *object, const ModelCoordinate &p, const std::string &id="")
Add an instance of an object at a specific position.
Definition: layer.cpp:108
uint32_t getPathLength()
Returns the length of the path.
Definition: route.cpp:213
static Logger _log(LM_AUDIO)
void setVisitorRadius(uint16_t radius)
Sets the range for a visitor.
Definition: instance.cpp:549
void cancelMovement(uint32_t length=1)
Cancel movement after a given length.
Definition: instance.cpp:511
Location m_location
current location
Definition: instance.h:506
uint32_t getActionRuntime()
Gets the time in milliseconds how long action has been active In case there is no current action...
Definition: instance.cpp:853
bool isMultiPart() const
Gets if object is a part of a multi object.
Definition: object.cpp:223
void setActionRuntime(uint32_t time_offset)
Sets the time in milliseconds how long an action has been active This was requested in Ticket #373...
Definition: instance.cpp:862
Action * getCurrentAction() const
Gets the currently active action.
Definition: instance.cpp:810
InstanceTree * getInstanceTree(void) const
Get the instance tree.
Definition: layer.cpp:100
Action * m_action
Definition: instance.cpp:82
Layer * getLayer() const
Gets the layer where this location is pointing to.
Definition: location.cpp:83
bool isSpecialCost()
Returns true if instance or object have special cost otherwise false.
Definition: instance.cpp:565
static TimeManager * instance()
Definition: singleton.h:84
Location & getLocationRef()
Gets reference of current location of instance.
Definition: instance.cpp:307
ModelCoordinate getLayerCoordinates() const
Gets cell precision layer coordinates set to this location.
Definition: location.cpp:113
A basic route.
Definition: route.h:64
void callOnTransparencyChange()
Definition: instance.cpp:898
uint32_t m_prev_call_time
Definition: instance.cpp:94
const std::string * getSayText() const
Returns pointer to currently set saytext.
Definition: instance.cpp:601
void update(Instance &source)
updates cached variables, marks changes
Definition: instance.cpp:140
void removeDeleteListener(InstanceDeleteListener *listener)
Removes associated instance delete listener.
Definition: instance.cpp:1035
ActionInfo(IPather *pather, const Location &curloc)
Definition: instance.cpp:53
uint16_t m_visitorRadius
visitor radius (FoW)
Definition: instance.h:518
void addChangeListener(InstanceChangeListener *listener)
Adds new instance change listener.
Definition: instance.cpp:382
unsigned char uint8_t
Definition: core.h:38
IVisual * m_visual
instance visualization
Definition: instance.h:508
void setRotation(int32_t rotation)
Sets the current rotation.
Definition: route.cpp:229
int32_t m_rotation
The rotation offset of this instance.
Definition: instance.h:446
uint32_t getTime() const
Get the time.
void setStartNode(const Location &node)
Sets the start location.
Definition: route.cpp:65
void setOverrideBlocking(bool overblock)
Sets if instance blocking can overriden.
Definition: instance.cpp:354
const std::string & getCostId() const
Returns the cost id.
Definition: object.cpp:185
const std::vector< Instance * > & getMultiInstances()
Returns a vector that contains all instances of a multi object.
Definition: instance.cpp:569
static bool Equal(T _val1, T _val2)
Definition: fife_math.h:286
std::vector< InstanceActionListener * > m_actionListeners
listeners for action related events
Definition: instance.h:485
Object * getObject()
Gets object where this instance is instantiated from.
Definition: instance.cpp:280
std::vector< InstanceChangeListener * > m_changeListeners
listeners for changes
Definition: instance.h:481
float getMultiplier() const
uint32_t InstanceChangeInfo
Definition: instance.h:73
void callOnStackPositionChange()
Definition: instance.cpp:916
static T Sin(T _val)
Definition: fife_math.h:266
int32_t getRotation() const
Get the rotation offset of this instance Returns direction where instance is heading.
Definition: instance.cpp:327
uint8_t VisitorShapeInfo
Definition: instance.h:92
int32_t getSessionId()
Returns the session identifier.
Definition: route.cpp:225
Location & getOldLocationRef()
Gets reference of old location of instance.
Definition: instance.cpp:839
Location * m_target
Definition: instance.cpp:84
A basic layer on a map.
Definition: layer.h:98
Instance * m_leader
Definition: instance.cpp:98
Location getFacingLocation()
Returns the direction where instance is heading.
Definition: instance.cpp:835
void setCostId(const std::string &cost)
Sets cost identifier which should be used for pathfinding.
Definition: route.cpp:237
uint32_t getGameTime() const
Returns current game ticks, already scaled.
void addInstanceForTransfer(Instance *instance, const Location &target)
Adds instance that is to be transferred to another layer.
Definition: map.cpp:295
void setTimeMultiplier(float multip)
Sets speed for the map.
Definition: instance.cpp:925
uint32_t m_duration
Definition: instance.cpp:112
Location getLocation() const
Gets current location of instance.
Definition: instance.cpp:303
void removeChangeListener(InstanceChangeListener *listener)
Removes associated instance change listener.
Definition: instance.cpp:401
RouteStatusInfo getRouteStatus()
Returns route status.
Definition: route.cpp:61
uint8_t getCellStackPosition()
Gets the cell stack position.
Definition: instance.cpp:561
void onInstanceDeleted(Instance *instance)
callback so other instances we depend on can notify us if they go away
Definition: instance.cpp:1050
void removeInstance(Instance *instance)
Removes an instance from the quad tree.
bool isRestrictedRotation() const
Gets if object uses restricted rotations.
Definition: object.cpp:308
InstanceActivity gets allocated in case there is some runtime activity related to the instance...
Definition: instance.h:456
ExactModelCoordinate & getExactLayerCoordinatesRef()
Gets reference to exact layer coordinates.
Definition: location.cpp:105
unsigned short uint16_t
Definition: core.h:39
CellGrid * getCellGrid() const
Get the Cellgrid.
Definition: layer.cpp:92
void setReplanned(bool replanned)
Sets the route to replanned.
Definition: route.cpp:205
void bindTimeProvider()
rebinds time provider based on new location
Definition: instance.cpp:866
void addInstance(Instance *instance)
Adds an instance to the quad tree.
std::string m_id
Definition: instance.h:442
void act(const std::string &actionName, const Location &direction, bool repeating=false)
Performs given named action to the instance.
Definition: instance.cpp:573
virtual bool cancelSession(const int32_t sessionId)=0
Cancels a given session.
void setBlocking(bool blocking)
Sets if instance blocks movement.
Definition: instance.cpp:339
double getMovementSpeed() const
Gets the speed in case instance is moving otherwise returns 0.
Definition: instance.cpp:824
InstanceChangeInfo m_additional
additional change info, used for visual class (transparency, visible, stackpos)
Definition: instance.h:495
void finalizeAction()
Finalize current action.
Definition: instance.cpp:777
ActionInfo * m_actionInfo
action information, allocated when actions are bind
Definition: instance.h:487
void setCellStackPosition(uint8_t stack)
Sets the cell stack position.
Definition: instance.cpp:557
double m_cost
holds cost value
Definition: instance.h:524
TimeProvider * m_timeProvider
time scaler for this instance
Definition: instance.h:491
SayInfo * m_sayInfo
text to say + duration, allocated when something is said
Definition: instance.h:489
VisitorShapeInfo getVisitorShape()
Gets the shape type for a visitor.
Definition: instance.cpp:545
const std::list< std::string > & getWalkableAreas() const
Returns a list that contains all walkable area ids.
Definition: object.cpp:348
virtual bool followRoute(const Location &current, Route *route, double speed, Location &nextLocation)=0
Follows the path of the route.
InstanceChangeInfo m_changeInfo
bitmask stating current changes
Definition: instance.h:499
SayInfo(const std::string &txt, uint32_t duration)
Definition: instance.cpp:106
bool m_specialCost
indicates special cost
Definition: instance.h:522
std::string m_txt
Definition: instance.cpp:111
std::vector< ModelCoordinate > getMultiObjectCoordinates(int32_t rotation)
Returns all multi object coordinates for the given rotation.
Definition: object.cpp:270
Action * getAction(const std::string &identifier) const
Gets action with given id.
Definition: object.cpp:92
std::string m_costId
holds cost id
Definition: instance.h:526
std::vector< Instance * > m_multiInstances
vector that holds all multi instances
Definition: instance.h:529
double getCost()
Returns cost value.
Definition: instance.cpp:978
float getTotalTimeMultiplier()
Gets instance speed, considering also model and map speeds.
Definition: instance.cpp:940
bool isOverrideBlocking() const
Gets if instance blocking can overriden.
Definition: instance.cpp:358
float getTimeMultiplier()
Gets instance speed.
Definition: instance.cpp:933
void resetCost()
Resets cost.
Definition: instance.cpp:974
const std::string & getCostId()
Returns cost identifier which is used for pathfinding.
Definition: route.cpp:241
static num_type pi()
Definition: fife_math.h:133
InstanceChangeInfo update()
Updates the instance related to the current action.
Definition: instance.cpp:721
int32_t getOldRotation() const
Get the old rotation offset of this instance Returns direction where instance was heading...
Definition: instance.cpp:846
const std::string & getId()
Get the identifier for this instance; possibly null.
Definition: instance.cpp:335
Location m_oldLocation
location on previous cell
Definition: instance.h:467
uint32_t getDuration()
Gets the duration of this action.
Definition: action.h:65
void setRotation(int32_t rotation)
Set the rotation offset of this instance.
Definition: instance.cpp:311
void removeActionListener(InstanceActionListener *listener)
Removes associated instance action listener.
Definition: instance.cpp:367
TimeProvider * getTimeProvider()
Gets timeprovider used in the map.
Definition: map.h:159
const Location & getCurrentNode()
Returns current location.
Definition: route.cpp:96
virtual ~Instance()
Destructor.
Definition: instance.cpp:241
void setEndNode(const Location &node)
Sets the target location.
Definition: route.cpp:80
uint32_t getRuntime()
Gets the scaled runtime in milliseconds.
Definition: instance.cpp:953
Route * getRoute()
Returns a pointer to the route, in case there is no, it returns NULL.
Definition: instance.cpp:523
int32_t getZStepRange() const
Returns z-step range from object.
Definition: object.cpp:326
void refresh()
Refreshes instance e.g.
Definition: instance.cpp:886
int32_t getRotation()
Returns the current rotation.
Definition: route.cpp:233
void setInstanceActivityStatus(Instance *instance, bool active)
Sets the activity status for given instance on this layer.
Definition: layer.cpp:232
const ExactModelCoordinate & getRotationAnchor() const
Returns the rotation anchor for this multi object.
Definition: object.cpp:300
A container of Layer(s).
Definition: map.h:87
void move(const std::string &actionName, const Location &target, const double speed, const std::string &costId="")
Performs given named action to the instance.
Definition: instance.cpp:444
unsigned int uint32_t
Definition: core.h:40
float getTotalMultiplier() const
Object * m_object
object where instantiated from
Definition: instance.h:504
uint16_t getVisitorRadius()
Gets the visitor range.
Definition: instance.cpp:553
bool isVisitor()
If instance is a visitor it returns true otherwise false.
Definition: instance.cpp:537
bool isMultiCell()
Returns true if it is multi cell otherwise false.
Definition: instance.cpp:992
Location getFacing(const Location &loc, const int32_t angle)
Gets facing location defined by given angle and location.
Definition: angles.cpp:113
int32_t getRestrictedRotation(int32_t rotation)
Returns the most obvious rotation, based on multi coordinates.
Definition: object.cpp:312
bool isReplanned()
Gets if the route is replanned.
Definition: route.cpp:209
double getLayerDistanceTo(const Location &location) const
Gets layer distance to another location.
Definition: location.cpp:180
uint8_t m_cellStackPos
position on cell stack
Definition: instance.h:520
void setLocation(const Location &loc)
Sets location of the instance.
Definition: instance.cpp:284
#define FL_DBG(logger, msg)
Definition: logger.h:70
An Instance is an &quot;instantiation&quot; of an Object at a Location.
Definition: instance.h:97
bool processMovement()
Moves instance. Returns true if finished.
Definition: instance.cpp:608
bool m_overrideBlocking
allow to override the blocking property
Definition: instance.h:512
ExactModelCoordinate getMapCoordinates() const
Gets map coordinates set to this location.
Definition: location.cpp:117
void setCost(const std::string &id, double cost)
Sets for the given cost id a cost.
Definition: instance.cpp:968
void setSessionId(int32_t id)
Sets the session identifier.
Definition: route.cpp:221
int32_t m_oldRotation
rotation on previous round
Definition: instance.h:471
void say(const std::string &text, uint32_t duration=0)
Causes instance to &quot;say&quot; given text (shown on screen next to the instance)
Definition: instance.cpp:590
void setVisitor(bool visit)
Marks this instance as a visitor.
Definition: instance.cpp:533
void setVisitorShape(VisitorShapeInfo info)
Sets the shape type for a visitor.
Definition: instance.cpp:541