FIFE  be64c707dea6b3250bd4355bf5c825d25920087d
cell.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2005-2019 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 
24 // 3rd party library includes
25 
26 // FIFE includes
27 // These includes are split up in two parts, separated by one empty line
28 // First block: files included from the FIFE root src directory
29 // Second block: files included from the same folder
30 #include "util/log/logger.h"
31 #include "view/visual.h"
32 
33 #include "cell.h"
34 #include "cellcache.h"
35 #include "instance.h"
36 #include "layer.h"
37 
38 namespace FIFE {
39 
40  static Logger _log(LM_STRUCTURES);
41 
42  Cell::Cell(int32_t coordint, ModelCoordinate coordinate, Layer* layer):
43  m_coordId(coordint),
44  m_coordinate(coordinate),
45  m_layer(layer),
46  m_zone(NULL),
47  m_transition(NULL),
48  m_inserted(false),
49  m_protect(false) {
50  }
51 
53  // calls CellDeleteListener, e.g. for transition
54  if (!m_deleteListeners.empty()) {
55  std::vector<CellDeleteListener*>::iterator it = m_deleteListeners.begin();
56  for (; it != m_deleteListeners.end(); ++it) {
57  if (*it) {
58  (*it)->onCellDeleted(this);
59  }
60  }
61  }
62  // remove cell from zone
63  if (m_zone) {
64  m_zone->removeCell(this);
65  }
66  // delete m_transition;
67  if (m_transition) {
69  }
70  // remove cell from cache (costs, narrow, area)
72  }
73 
74  void Cell::addInstances(const std::list<Instance*>& instances) {
75  CellCache* cache = m_layer->getCellCache();
76  for (std::list<Instance*>::const_iterator it = instances.begin(); it != instances.end(); ++it) {
77  std::pair<std::set<Instance*>::iterator, bool> ret = m_instances.insert(*it);
78  if (ret.second) {
79  if ((*it)->isSpecialCost()) {
80  cache->registerCost((*it)->getCostId(), (*it)->getCost());
81  cache->addCellToCost((*it)->getCostId(), this);
82  }
83  if ((*it)->isSpecialSpeed()) {
84  cache->setSpeedMultiplier(this, (*it)->getSpeed());
85  }
86  if ((*it)->getObject()->getArea() != "") {
87  cache->addCellToArea((*it)->getObject()->getArea(), this);
88  }
90  }
91  }
93  }
94 
95  void Cell::addInstance(Instance* instance) {
96  std::pair<std::set<Instance*>::iterator, bool> ret = m_instances.insert(instance);
97  if (ret.second) {
98  CellCache* cache = m_layer->getCellCache();
99  if (instance->isSpecialCost()) {
100  cache->registerCost(instance->getCostId(), instance->getCost());
101  cache->addCellToCost(instance->getCostId(), this);
102  }
103  if (instance->isSpecialSpeed()) {
104  cache->setSpeedMultiplier(this, instance->getSpeed());
105  }
106  if (instance->getObject()->getArea() != "") {
107  cache->addCellToArea(instance->getObject()->getArea(), this);
108  }
109  callOnInstanceEntered(instance);
111  }
112  }
113 
114  void Cell::changeInstance(Instance* instance) {
116  }
117 
118  void Cell::removeInstance(Instance* instance) {
119  if (m_instances.erase(instance) == 0) {
120  FL_ERR(_log, "Tried to remove an instance from cell, but given instance could not be found.");
121  return;
122  }
123  CellCache* cache = m_layer->getCellCache();
124  if (instance->isSpecialCost()) {
125  cache->removeCellFromCost(instance->getCostId(), this);
126  }
127  if (instance->isSpecialSpeed()) {
128  cache->resetSpeedMultiplier(this);
129  // try to find other speed value
130  if (!m_instances.empty()) {
131  std::set<Instance*>::iterator it = m_instances.begin();
132  for (; it != m_instances.end(); ++it) {
133  if ((*it)->isSpecialSpeed()) {
134  cache->setSpeedMultiplier(this, (*it)->getSpeed());
135  break;
136  }
137  }
138  }
139  }
140  if (instance->getObject()->getArea() != "") {
141  cache->removeCellFromArea(instance->getObject()->getArea(), this);
142  }
143  callOnInstanceExited(instance);
145  }
146 
147  bool Cell::isNeighbor(Cell* cell) {
148  std::vector<Cell*>::iterator it = m_neighbors.begin();
149  for (; it != m_neighbors.end(); ++it) {
150  if (*it == cell) {
151  return true;
152  }
153  }
154  return false;
155  }
156 
158  CellTypeInfo old_type = m_type;
160  if (!m_instances.empty()) {
161  int32_t pos = -1;
162  bool cellblock = (m_type == CTYPE_CELL_NO_BLOCKER || m_type == CTYPE_CELL_BLOCKER);
163  for (std::set<Instance*>::iterator it = m_instances.begin(); it != m_instances.end(); ++it) {
164  if (cellblock) {
165  continue;
166  }
167  uint8_t stackpos = (*it)->getCellStackPosition();
168  if (stackpos < pos) {
169  continue;
170  }
171  // update cell z
172  if (m_coordinate.z < (*it)->getLocationRef().getLayerCoordinates().z && (*it)->getObject()->isStatic()) {
173  m_coordinate.z = (*it)->getLocationRef().getLayerCoordinates().z;
174  }
175  if ((*it)->getCellStackPosition() > pos) {
176  pos = (*it)->getCellStackPosition();
177  if ((*it)->isBlocking()) {
178  if (!(*it)->getObject()->isStatic()) {
180  } else {
182  }
183  } else {
185  }
186  } else {
187  // if positions are equal then static_blockers win
188  if ((*it)->isBlocking() && m_type != CTYPE_STATIC_BLOCKER) {
189  if (!(*it)->getObject()->isStatic()) {
191  } else {
193  }
194  }
195  }
196  }
197  } else {
200  }
201  }
203  m_coordinate.z = 0;
204  }
205 
206  if (old_type != m_type) {
207  bool block = (m_type == CTYPE_STATIC_BLOCKER ||
210  callOnBlockingChanged(block);
211  }
212  }
213 
216 
217  if (!m_deleteListeners.empty()) {
218  m_deleteListeners.erase(
219  std::remove(m_deleteListeners.begin(), m_deleteListeners.end(),
220  (CellDeleteListener*)NULL), m_deleteListeners.end());
221  }
222  if (!m_changeListeners.empty()) {
223  m_changeListeners.erase(
224  std::remove(m_changeListeners.begin(), m_changeListeners.end(),
225  (CellChangeListener*)NULL), m_changeListeners.end());
226  }
227  }
228 
230  return m_layer->getCellCache()->isDefaultCost(this);
231  }
232 
233  void Cell::setCostMultiplier(double multi) {
234  m_layer->getCellCache()->setCostMultiplier(this, multi);
235  }
236 
238  return m_layer->getCellCache()->getCostMultiplier(this);
239  }
240 
243  }
244 
246  return m_layer->getCellCache()->isDefaultSpeed(this);
247  }
248 
249  void Cell::setSpeedMultiplier(double multi) {
250  m_layer->getCellCache()->setSpeedMultiplier(this, multi);
251  }
252 
254  return m_layer->getCellCache()->getSpeedMultiplier(this);
255  }
256 
259  }
260 
262  return m_zone;
263  }
264 
265  void Cell::setZone(Zone* zone) {
266  m_zone = zone;
267  }
268 
270  m_inserted = false;
271  m_zone = NULL;
272  }
273 
275  return m_inserted;
276  }
277 
278  void Cell::setInserted(bool inserted) {
279  m_inserted = inserted;
280  }
281 
283  return m_protect;
284  }
285 
286  void Cell::setZoneProtected(bool protect) {
287  m_protect = protect;
288  }
289 
291  return m_type;
292  }
293 
295  m_type = type;
296  }
297 
298  const std::set<Instance*>& Cell::getInstances() {
299  return m_instances;
300  }
301 
302  void Cell::setCellId(int32_t id) {
303  m_coordId = id;
304  }
305 
306  int32_t Cell::getCellId() {
307  return m_coordId;
308  }
309 
311  return m_coordinate;
312  }
313 
314  void Cell::addNeighbor(Cell* cell) {
315  m_neighbors.push_back(cell);
316  }
317 
318  const std::vector<Cell*>& Cell::getNeighbors() {
319  return m_neighbors;
320  }
321 
323  m_neighbors.clear();
324  if (m_transition) {
326  if (cache) {
327  Cell* cell = cache->getCell(m_transition->m_mc);
328  if (cell) {
329  m_neighbors.push_back(cell);
330  }
331  }
332  }
333  }
334 
336  return m_layer;
337  }
338 
339  void Cell::createTransition(Layer* layer, const ModelCoordinate& mc, bool immediate) {
340  TransitionInfo* trans = new TransitionInfo(layer);
341  // if layers are the same then it's a portal
342  if (layer != m_layer) {
343  trans->m_difflayer = true;
344  }
345  trans->m_immediate = immediate;
346  trans->m_mc = mc;
347 
349 
350  m_transition = trans;
351 
352  Cell* c = layer->getCellCache()->getCell(mc);
353  if (c) {
354  m_neighbors.push_back(c);
355  c->addDeleteListener(this);
357  } else {
358  delete m_transition;
359  m_transition = NULL;
360  }
361  }
362 
364  if (m_transition) {
366  std::vector<Cell*>::iterator it = m_neighbors.begin();
367  for (; it != m_neighbors.end(); ++it) {
368  if (*it == oldc) {
369  m_neighbors.erase(it);
370  break;
371  }
372  }
373  oldc->removeDeleteListener(this);
375  delete m_transition;
376  m_transition = NULL;
377  }
378  }
379 
381  return m_transition;
382  }
383 
385  m_deleteListeners.push_back(listener);
386  }
387 
389  std::vector<CellDeleteListener*>::iterator it = m_deleteListeners.begin();
390  for (; it != m_deleteListeners.end(); ++it) {
391  if (*it == listener) {
392  *it = NULL;
393  break;
394  }
395  }
396  }
397 
398  void Cell::onCellDeleted(Cell* cell) {
399  std::vector<Cell*>::iterator it = m_neighbors.begin();
400  for (; it != m_neighbors.end(); ++it) {
401  if (*it == cell) {
403  break;
404  }
405  }
406  }
407 
409  m_changeListeners.push_back(listener);
410  }
411 
413  std::vector<CellChangeListener*>::iterator it = m_changeListeners.begin();
414  for (; it != m_changeListeners.end(); ++it) {
415  if (*it == listener) {
416  *it = NULL;
417  break;
418  }
419  }
420  }
421 
423  if (m_changeListeners.empty()) {
424  return;
425  }
426 
427  std::vector<CellChangeListener*>::iterator i = m_changeListeners.begin();
428  while (i != m_changeListeners.end()) {
429  if (*i) {
430  (*i)->onInstanceEnteredCell(this, instance);
431  }
432  ++i;
433  }
434  }
435 
437  if (m_changeListeners.empty()) {
438  return;
439  }
440 
441  std::vector<CellChangeListener*>::iterator i = m_changeListeners.begin();
442  while (i != m_changeListeners.end()) {
443  if (*i) {
444  (*i)->onInstanceExitedCell(this, instance);
445  }
446  ++i;
447  }
448  }
449 
450  void Cell::callOnBlockingChanged(bool blocks) {
451  if (m_changeListeners.empty()) {
452  return;
453  }
454 
455  std::vector<CellChangeListener*>::iterator i = m_changeListeners.begin();
456  while (i != m_changeListeners.end()) {
457  if (*i) {
458  (*i)->onBlockingChangedCell(this, m_type, blocks);
459  }
460  ++i;
461  }
462  }
463 } // FIFE
void setZoneProtected(bool protect)
Mark zone on this cell as protected.
Definition: cell.cpp:286
double getSpeedMultiplier(Cell *cell)
Returns speed multiplier for the cell.
Definition: cellcache.cpp:1216
std::string getCostId()
Returns cost id.
Definition: instance.cpp:1024
double getCostMultiplier()
Returns the current cell cost.
Definition: cell.cpp:237
Layer * m_layer
target layer
Definition: cell.h:72
double getCostMultiplier(Cell *cell)
Returns cost multiplier for the cell.
Definition: cellcache.cpp:1186
bool isNeighbor(Cell *cell)
Called to check if given cell is a neighbor.
Definition: cell.cpp:147
std::vector< CellChangeListener * > m_changeListeners
change listener
Definition: cell.h:390
void setSpeedMultiplier(Cell *cell, double multi)
Sets speed multiplier for the cell.
Definition: cellcache.cpp:1207
bool m_difflayer
is target on another layer
Definition: cell.h:78
void callOnInstanceEntered(Instance *instance)
Called when a instance entered this cell.
Definition: cell.cpp:422
void addInstance(Instance *instance)
Adds a instance to this cell.
Definition: cell.cpp:95
static const double MIN_CELL_Z
Definition: cell.h:48
Layer * getLayer()
Returns the current layer.
Definition: cell.cpp:335
bool isDefaultSpeed(Cell *cell)
Gets if cell uses default speed multiplier.
Definition: cellcache.cpp:1199
void removeTransition(Cell *cell)
Removes a cell as transition.
Definition: cellcache.cpp:1233
double getSpeedMultiplier()
Returns the current cell speed.
Definition: cell.cpp:253
void callOnInstanceExited(Instance *instance)
Called when a instance exited this cell.
Definition: cell.cpp:436
Listener interface for changes happening on a cell.
Definition: cell.h:97
std::set< Instance * > m_instances
Definition: cell.h:381
void removeCellFromCost(Cell *cell)
Removes a cell from costs.
Definition: cellcache.cpp:1050
bool isSpecialSpeed()
Returns true if instance or object have special speed modifier otherwise false.
Definition: instance.cpp:1035
A CellCache is an abstract depiction of one or a few layers and contains additional information...
Definition: cellcache.h:111
void setSpeedMultiplier(double multi)
Changes the cell speed.
Definition: cell.cpp:249
void addCellToCost(const std::string &costId, Cell *cell)
Assigns a cell to a cost identifier.
Definition: cellcache.cpp:1030
bool isDefaultCost(Cell *cell)
Gets if cell uses default cost multiplier.
Definition: cellcache.cpp:1169
CellCache * getCellCache()
Returns the CellCache of this layer.
Definition: layer.cpp:573
void setCellType(CellTypeInfo type)
Sets blocker type.
Definition: cell.cpp:294
void setBlockingUpdate(bool update)
Definition: cellcache.cpp:1531
static Logger _log(LM_AUDIO)
void addInstances(const std::list< Instance *> &instances)
Adds instances to this cell.
Definition: cell.cpp:74
void registerCost(const std::string &costId, double cost)
Adds a cost with the given id and value.
Definition: cellcache.cpp:983
void removeInstance(Instance *instance)
Removes a instance from this cell.
Definition: cell.cpp:118
int32_t getCellId()
Returns the cell identifier.
Definition: cell.cpp:306
void resetSpeedMultiplier(Cell *cell)
Resets the speed multiplier for the cell.
Definition: cellcache.cpp:1225
void addChangeListener(CellChangeListener *listener)
Adds new cell change listener.
Definition: cell.cpp:408
bool defaultCost()
Returns if cell use default cost.
Definition: cell.cpp:229
void resetCostMultiplier()
Resets the cell cost to default, 1.0.
Definition: cell.cpp:241
void removeCell(Cell *cell)
Removes a cell from this zone.
Definition: cellcache.cpp:277
void deleteTransition()
Removes the transistion from Cell and CellCache.
Definition: cell.cpp:363
bool isSpecialCost()
Returns true if instance or object have special cost otherwise false.
Definition: instance.cpp:549
void onCellDeleted(Cell *cell)
Called when a cell gets deleted on this cell.
Definition: cell.cpp:398
void removeCellFromArea(Cell *cell)
Removes the cell from all areas.
Definition: cellcache.cpp:1416
std::string getArea() const
Gets the area id that the instances of this object adds to their cells.
Definition: object.cpp:580
#define FL_ERR(logger, msg)
Definition: logger.h:73
Listener interface for deletions happening on a cell, used for transistions.
Definition: cell.h:85
unsigned char uint8_t
Definition: core.h:38
void setZone(Zone *zone)
Sets zone.
Definition: cell.cpp:265
Simple class to hold the data for transistions.
Definition: cell.h:69
void addNeighbor(Cell *cell)
Adds a neighbor cell to this cell.
Definition: cell.cpp:314
int32_t m_coordId
holds coordinate as a unique integer id
Definition: cell.h:357
static bool Equal(T _val1, T _val2)
Definition: fife_math.h:287
Object * getObject()
Gets object where this instance is instantiated from.
Definition: instance.cpp:292
Cell * getCell(const ModelCoordinate &mc)
Returns cell on this coordinate.
Definition: cellcache.cpp:704
const std::set< Instance * > & getInstances()
Returns all instances on this cell.
Definition: cell.cpp:298
bool isZoneProtected()
Returns whether the zone on this cell is protected.
Definition: cell.cpp:282
uint8_t CellTypeInfo
Definition: cell.h:65
CellTypeInfo getCellType()
Returns blocker type.
Definition: cell.cpp:290
TransitionInfo * m_transition
Pointer to Transistion.
Definition: cell.h:369
A basic layer on a map.
Definition: layer.h:99
Layer * m_layer
parent layer
Definition: cell.h:363
const ModelCoordinate getLayerCoordinates() const
Returns the layer coordinates of this cell.
Definition: cell.cpp:310
const std::vector< Cell * > & getNeighbors()
Returns the layer coordinates of this cell.
Definition: cell.cpp:318
void removeDeleteListener(CellDeleteListener *listener)
Removes cell delete listener.
Definition: cell.cpp:388
A basic cell on a CellCache.
Definition: cell.h:123
bool m_protect
protected
Definition: cell.h:375
void updateCellInfo()
Called to update cell data.
Definition: cell.cpp:214
Cell(int32_t coordint, ModelCoordinate coordinate, Layer *layer)
Constructor.
Definition: cell.cpp:42
void changeInstance(Instance *instance)
Changes a instance on this cell.
Definition: cell.cpp:114
Zone * getZone()
Returns zone.
Definition: cell.cpp:261
void updateCellBlockingInfo()
Definition: cell.cpp:157
void addCellToArea(const std::string &id, Cell *cell)
Adds a cell to a specific area group.
Definition: cellcache.cpp:1405
void setCellId(int32_t id)
Sets the cell identifier.
Definition: cell.cpp:302
void setCostMultiplier(double multi)
Changes the cell cost.
Definition: cell.cpp:233
ModelCoordinate m_coordinate
holds coordinate
Definition: cell.h:360
CellTypeInfo m_type
CellType.
Definition: cell.h:378
A 3D Point.
Definition: point.h:205
double getCost()
Returns cost value.
Definition: instance.cpp:1017
void setInserted(bool inserted)
Mark cell as inserted.
Definition: cell.cpp:278
Zone * m_zone
parent Zone
Definition: cell.h:366
void removeCell(Cell *cell)
Removes cell from CellCache.
Definition: cellcache.cpp:719
std::vector< Cell * > m_neighbors
neighbor cells
Definition: cell.h:384
void createTransition(Layer *layer, const ModelCoordinate &mc, bool immediate=false)
Creates a transistion from this cell to the given layer and coordinates.
Definition: cell.cpp:339
void resetNeighbors()
Removes all neighbors from cell.
Definition: cell.cpp:322
std::vector< CellDeleteListener * > m_deleteListeners
delete listener
Definition: cell.h:387
bool m_inserted
already inserted
Definition: cell.h:372
void addTransition(Cell *cell)
Adds a cell as transition.
Definition: cellcache.cpp:1229
~Cell()
Destructor.
Definition: cell.cpp:52
TransitionInfo * getTransition()
Returns the transition.
Definition: cell.cpp:380
bool isInserted()
Returns whether the cell is part of a zone.
Definition: cell.cpp:274
bool defaultSpeed()
Returns if cell use default speed.
Definition: cell.cpp:245
void addDeleteListener(CellDeleteListener *listener)
Adds new cell delete listener.
Definition: cell.cpp:384
void resetZone()
Resets zone.
Definition: cell.cpp:269
An Instance is an "instantiation" of an Object at a Location.
Definition: instance.h:94
bool m_immediate
use immediate
Definition: cell.h:80
void resetCostMultiplier(Cell *cell)
Resets the cost multiplier for the cell.
Definition: cellcache.cpp:1195
A Zone is an abstract depiction of a CellCache or of a part of it.
Definition: cellcache.h:50
ModelCoordinate m_mc
target coordinates
Definition: cell.h:76
void removeChangeListener(CellChangeListener *listener)
Removes cell change listener.
Definition: cell.cpp:412
void setCostMultiplier(Cell *cell, double multi)
Sets cost multiplier for the cell.
Definition: cellcache.cpp:1177
void callOnBlockingChanged(bool blocks)
Called when the blocking property of this cell changed.
Definition: cell.cpp:450
double getSpeed()
Returns speed modifier.
Definition: instance.cpp:1031
void resetSpeedMultiplier()
Resets the cell speed to default, 1.0.
Definition: cell.cpp:257