FIFE  be64c707dea6b3250bd4355bf5c825d25920087d
trigger.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 #include <vector>
24 
25 // 3rd party library includes
26 
27 // FIFE includes
28 // These includes are split up in two parts, separated by one empty line
29 // First block: files included from the FIFE root src directory
30 // Second block: files included from the same folder
31 
32 #include "cell.h"
33 #include "cellcache.h"
34 #include "instance.h"
35 #include "layer.h"
36 #include "location.h"
37 #include "trigger.h"
38 
39 namespace FIFE {
40 
42  public:
44  m_trigger = trigger;
45  }
47 
48  // InstanceDeleteListener callback
49  virtual void onInstanceDeleted(Instance* instance) {
50  const std::vector<TriggerCondition>& types = m_trigger->getTriggerConditions();
51  if (std::find(types.begin(), types.end(), INSTANCE_TRIGGER_DELETE) != types.end()) {
53  }
54  m_trigger->detach();
55  }
56 
57  // CellChangeListener callback
58  virtual void onInstanceEnteredCell(Cell* cell, Instance* instance) {
59  const std::vector<TriggerCondition>& types = m_trigger->getTriggerConditions();
60  if (std::find(types.begin(), types.end(), CELL_TRIGGER_ENTER) != types.end()) {
61  const std::vector<Instance*>& restrict = m_trigger->getEnabledInstances();
63  std::find(restrict.begin(), restrict.end(), instance) != restrict.end()) {
65  }
66  }
67  }
68 
69  // CellChangeListener callback
70  virtual void onInstanceExitedCell(Cell* cell, Instance* instance) {
71  const std::vector<TriggerCondition>& types = m_trigger->getTriggerConditions();
72  if (std::find(types.begin(), types.end(), CELL_TRIGGER_EXIT) != types.end()) {
73  const std::vector<Instance*>& restrict = m_trigger->getEnabledInstances();
75  std::find(restrict.begin(), restrict.end(), instance) != restrict.end()) {
77  }
78  }
79  }
80 
81  // CellChangeListener callback
82  virtual void onBlockingChangedCell(Cell* cell, CellTypeInfo type, bool blocks) {
83  const std::vector<TriggerCondition>& types = m_trigger->getTriggerConditions();
84  if (std::find(types.begin(), types.end(), CELL_TRIGGER_BLOCKING_CHANGE) != types.end()) {
86  }
87  }
88 
89  // InstanceChangeListener callback
90  virtual void onInstanceChanged(Instance* instance, InstanceChangeInfo info) {
91  const std::vector<TriggerCondition>& types = m_trigger->getTriggerConditions();
92  if (m_trigger->getAttached() == instance && (info & ICHANGE_CELL) == ICHANGE_CELL) {
93  m_trigger->move();
94  }
95 
96  if (types.empty()) {
97  return;
98  }
99 
100  if ((info & ICHANGE_LOC) == ICHANGE_LOC && std::find(types.begin(), types.end(), INSTANCE_TRIGGER_LOCATION) != types.end()) {
102  } else if ((info & ICHANGE_ROTATION) == ICHANGE_ROTATION && std::find(types.begin(), types.end(), INSTANCE_TRIGGER_ROTATION) != types.end()) {
104  } else if ((info & ICHANGE_SPEED) == ICHANGE_SPEED && std::find(types.begin(), types.end(), INSTANCE_TRIGGER_SPEED) != types.end()) {
106  } else if ((info & ICHANGE_ACTION) == ICHANGE_ACTION && std::find(types.begin(), types.end(), INSTANCE_TRIGGER_ACTION) != types.end()) {
108  } else if ((info & ICHANGE_TIME_MULTIPLIER) == ICHANGE_TIME_MULTIPLIER && std::find(types.begin(), types.end(), INSTANCE_TRIGGER_TIME_MULTIPLIER) != types.end()) {
110  } else if ((info & ICHANGE_SAYTEXT) == ICHANGE_SAYTEXT && std::find(types.begin(), types.end(), INSTANCE_TRIGGER_SAYTEXT) != types.end()) {
112  } else if ((info & ICHANGE_BLOCK) == ICHANGE_BLOCK && std::find(types.begin(), types.end(), INSTANCE_TRIGGER_BLOCK) != types.end()) {
114  } else if ((info & ICHANGE_CELL) == ICHANGE_CELL && std::find(types.begin(), types.end(), INSTANCE_TRIGGER_CELL) != types.end()) {
116  } else if ((info & ICHANGE_TRANSPARENCY) == ICHANGE_TRANSPARENCY && std::find(types.begin(), types.end(), INSTANCE_TRIGGER_TRANSPARENCY) != types.end()) {
118  } else if ((info & ICHANGE_VISIBLE) == ICHANGE_VISIBLE && std::find(types.begin(), types.end(), INSTANCE_TRIGGER_VISIBLE) != types.end()) {
120  } else if ((info & ICHANGE_STACKPOS) == ICHANGE_STACKPOS && std::find(types.begin(), types.end(), INSTANCE_TRIGGER_STACKPOS) != types.end()) {
122  } else if ((info & ICHANGE_VISUAL) == ICHANGE_VISUAL && std::find(types.begin(), types.end(), INSTANCE_TRIGGER_VISUAL) != types.end()) {
124  }
125  }
126 
127  private:
129  };
130 
132  m_name(""),
133  m_triggered(false),
134  m_enabledAll(false),
135  m_attached(NULL) {
137  }
138 
139  Trigger::Trigger(const std::string& name):
140  m_name(name),
141  m_triggered(false),
142  m_enabledAll(false),
143  m_attached(NULL) {
145  }
146 
148  detach();
149  std::vector<Cell*>::iterator it = m_assigned.begin();
150  for (; it != m_assigned.end(); ++it) {
151  (*it)->removeChangeListener(m_changeListener);
152  }
153  delete m_changeListener;
154  }
155 
157  std::vector<ITriggerListener*>::iterator it = std::find(m_triggerListeners.begin(), m_triggerListeners.end(), listener);
158  if (it == m_triggerListeners.end()) {
159  m_triggerListeners.push_back(listener);
160  }
161  }
162 
164  std::vector<ITriggerListener*>::iterator i = m_triggerListeners.begin();
165  while (i != m_triggerListeners.end()) {
166  if ((*i) == listener) {
167  // set the pointer to null, so it can be removed later
168  *i = NULL;
169  return;
170  }
171  ++i;
172  }
173  }
174 
175  void Trigger::reset() {
176  m_triggered = false;
177  }
178 
180  if (!m_triggered) {
181  m_triggered = true;
182  std::vector<ITriggerListener*>::iterator i = m_triggerListeners.begin();
183  while (i != m_triggerListeners.end()) {
184  if (*i) {
185  (*i)->onTriggered();
186  }
187  ++i;
188  }
189  }
190  // remove null pointer
191  m_triggerListeners.erase(std::remove(m_triggerListeners.begin(), m_triggerListeners.end(), (ITriggerListener*)NULL), m_triggerListeners.end());
192  }
193 
195  std::vector<TriggerCondition>::iterator it = std::find(m_triggerConditions.begin(), m_triggerConditions.end(), type);
196  if (it == m_triggerConditions.end()) {
197  m_triggerConditions.push_back(type);
198  }
199  }
200 
201  const std::vector<TriggerCondition>& Trigger::getTriggerConditions() {
202  return m_triggerConditions;
203  }
204 
206  std::vector<TriggerCondition>::iterator it = std::find(m_triggerConditions.begin(), m_triggerConditions.end(), type);
207  if (it != m_triggerConditions.end()) {
208  m_triggerConditions.erase(it);
209  }
210  }
211 
213  std::vector<Instance*>::iterator it = std::find(m_enabledInstances.begin(), m_enabledInstances.end(), instance);
214  if (it == m_enabledInstances.end()) {
215  m_enabledInstances.push_back(instance);
216  }
217  }
218 
219  const std::vector<Instance*>& Trigger::getEnabledInstances() {
220  return m_enabledInstances;
221  }
222 
224  std::vector<Instance*>::iterator it = std::find(m_enabledInstances.begin(), m_enabledInstances.end(), instance);
225  if (it != m_enabledInstances.end()) {
226  m_enabledInstances.erase(it);
227  }
228  }
229 
231  m_enabledAll = true;
232  }
233 
235  return m_enabledAll;
236  }
237 
239  m_enabledAll = false;
240  }
241 
242  void Trigger::assign(Layer* layer, const ModelCoordinate& pt) {
243  Cell* cell = layer->getCellCache()->getCell(pt);
244  if (!cell) {
245  return;
246  }
247  std::vector<Cell*>::iterator it = std::find(m_assigned.begin(), m_assigned.end(), cell);
248  if (it == m_assigned.end()) {
249  m_assigned.push_back(cell);
251  }
252  }
253 
254  void Trigger::remove(Layer* layer, const ModelCoordinate& pt) {
255  Cell* cell = layer->getCellCache()->getCell(pt);
256  if (!cell) {
257  return;
258  }
259  std::vector<Cell*>::iterator it = std::find(m_assigned.begin(), m_assigned.end(), cell);
260  if (it != m_assigned.end()) {
261  m_assigned.erase(it);
263  }
264  }
265 
266  void Trigger::assign(Cell* cell) {
267  std::vector<Cell*>::iterator it = std::find(m_assigned.begin(), m_assigned.end(), cell);
268  if (it == m_assigned.end()) {
269  m_assigned.push_back(cell);
271  }
272  }
273 
274  void Trigger::remove(Cell* cell) {
275  std::vector<Cell*>::iterator it = std::find(m_assigned.begin(), m_assigned.end(), cell);
276  if (it != m_assigned.end()) {
277  m_assigned.erase(it);
279  }
280  }
281 
282  const std::vector<Cell*>& Trigger::getAssignedCells() {
283  return m_assigned;
284  }
285 
286  void Trigger::attach(Instance* instance) {
287  if (instance == m_attached) {
288  return;
289  }
290 
291  if (m_attached) {
292  detach();
293  }
294  m_attached = instance;
297  }
298 
300  if (m_attached) {
303  m_attached = 0;
304  }
305  }
306 
307  void Trigger::move() {
308  if (m_assigned.empty()) {
309  return;
310  }
313  moveTo(newPos, oldPos);
314  }
315 
316  void Trigger::moveTo(const ModelCoordinate& newPos, const ModelCoordinate& oldPos) {
317  ModelCoordinate mc(newPos.x-oldPos.x, newPos.y-oldPos.y);
318 
320  std::vector<Cell*> newCells;
321  std::vector<Cell*>::iterator it = m_assigned.begin();
322  for (; it != m_assigned.end(); ++it) {
323  ModelCoordinate coord = (*it)->getLayerCoordinates();
324  coord.x += mc.x;
325  coord.y += mc.y;
326  Cell* c = cache->getCell(coord);
327  if (c) {
328  newCells.push_back(c);
329  }
330  }
331  for (it = newCells.begin(); it != newCells.end(); ++it) {
332  std::vector<Cell*>::iterator found = std::find(m_assigned.begin(), m_assigned.end(), *it);
333  if (found != m_assigned.end()) {
334  m_assigned.erase(found);
335  } else {
336  // add new
337  (*it)->addChangeListener(m_changeListener);
338  }
339  }
340  // remove old
341  for (it = m_assigned.begin(); it != m_assigned.end(); ++it) {
342  (*it)->removeChangeListener(m_changeListener);
343  }
344  m_assigned = newCells;
345  }
346 }
TriggerChangeListener(Trigger *trigger)
Definition: trigger.cpp:43
void detach()
Detaches trigger from instance.
Definition: trigger.cpp:299
TriggerChangeListener * m_changeListener
main change listener (cell and instance listener)
Definition: trigger.h:268
void move()
Callback for TriggerChangeListener.
Definition: trigger.cpp:307
Layer * getLayer() const
Gets the layer where this location is pointing to.
Definition: location.cpp:83
void attach(Instance *instance)
Attaches the trigger to the given instance.
Definition: trigger.cpp:286
void addDeleteListener(InstanceDeleteListener *listener)
Adds new instance delete listener.
Definition: instance.cpp:1256
std::string m_name
name of the trigger. This should be unique per Map.
Definition: trigger.h:256
Listener interface for changes happening on a cell.
Definition: cell.h:97
A CellCache is an abstract depiction of one or a few layers and contains additional information...
Definition: cellcache.h:111
virtual ~Trigger()
Destructor.
Definition: trigger.cpp:147
void enableForInstance(Instance *instance)
Enables trigger for given instance.
Definition: trigger.cpp:212
CellCache * getCellCache()
Returns the CellCache of this layer.
Definition: layer.cpp:573
void addTriggerCondition(TriggerCondition type)
Adds trigger condition.
Definition: trigger.cpp:194
void removeTriggerCondition(TriggerCondition type)
Removes trigger condition.
Definition: trigger.cpp:205
TriggerCondition
Definition: trigger.h:50
void addChangeListener(CellChangeListener *listener)
Adds new cell change listener.
Definition: cell.cpp:408
void remove(Layer *layer, const ModelCoordinate &pt)
Removes trigger from given layer and position.
Definition: trigger.cpp:254
virtual ~TriggerChangeListener()
Definition: trigger.cpp:46
Location & getLocationRef()
Gets reference of current location of instance.
Definition: instance.cpp:315
virtual void onInstanceDeleted(Instance *instance)
Definition: trigger.cpp:49
void removeDeleteListener(InstanceDeleteListener *listener)
Removes associated instance delete listener.
Definition: instance.cpp:1260
const std::vector< Cell * > & getAssignedCells()
Returns vector with the cells where the trigger is assigned to.
Definition: trigger.cpp:282
void addChangeListener(InstanceChangeListener *listener)
Adds new instance change listener.
Definition: instance.cpp:381
std::vector< ITriggerListener * > m_triggerListeners
Vector of the listeners that get called.
Definition: trigger.h:265
virtual void onInstanceChanged(Instance *instance, InstanceChangeInfo info)
Definition: trigger.cpp:90
uint32_t InstanceChangeInfo
Definition: instance.h:77
Cell * getCell(const ModelCoordinate &mc)
Returns cell on this coordinate.
Definition: cellcache.cpp:704
uint8_t CellTypeInfo
Definition: cell.h:65
Location & getOldLocationRef()
Gets reference of old location of instance.
Definition: instance.cpp:890
A basic layer on a map.
Definition: layer.h:99
bool m_enabledAll
true if the trigger is enabled for all instances
Definition: trigger.h:262
void removeChangeListener(InstanceChangeListener *listener)
Removes associated instance change listener.
Definition: instance.cpp:400
void assign(Layer *layer, const ModelCoordinate &pt)
Assigns trigger on given layer and position.
Definition: trigger.cpp:242
const std::vector< TriggerCondition > & getTriggerConditions()
Returns trigger conditions in an vector.
Definition: trigger.cpp:201
A basic cell on a CellCache.
Definition: cell.h:123
std::vector< Instance * > m_enabledInstances
all enabled instances
Definition: trigger.h:277
Instance * m_attached
instance where the trigger is attached to
Definition: trigger.h:280
Instance * getAttached()
Returns pointer to instance where the trigger is attached to.
Definition: trigger.h:241
void moveTo(const ModelCoordinate &newPos, const ModelCoordinate &oldPos)
Moves the trigger from the old position to the new position.
Definition: trigger.cpp:316
const std::vector< Instance * > & getEnabledInstances()
Returns instance which the trigger is enabled for.
Definition: trigger.cpp:219
void disableForAllInstances()
Disables trigger for all instances.
Definition: trigger.cpp:238
void reset()
Reset trigger.
Definition: trigger.cpp:175
A 3D Point.
Definition: point.h:205
virtual void onBlockingChangedCell(Cell *cell, CellTypeInfo type, bool blocks)
Called when some instance changed its blocking property.
Definition: trigger.cpp:82
std::vector< TriggerCondition > m_triggerConditions
all trigger conditions
Definition: trigger.h:274
Trigger()
Default constructor.
Definition: trigger.cpp:131
void removeTriggerListener(ITriggerListener *listener)
Removes a listener from the trigger.
Definition: trigger.cpp:163
Trigger get triggered when a specific set of criteria are met.
Definition: trigger.h:83
void disableForInstance(Instance *instance)
Disables trigger for given instance.
Definition: trigger.cpp:223
ModelCoordinate getLayerCoordinates() const
Gets cell precision layer coordinates set to this location.
Definition: location.cpp:113
void enableForAllInstances()
Enables trigger for all instances.
Definition: trigger.cpp:230
bool m_triggered
true if this trigger has been triggered
Definition: trigger.h:259
virtual void onInstanceExitedCell(Cell *cell, Instance *instance)
Called when some instance exited the cell.
Definition: trigger.cpp:70
void addTriggerListener(ITriggerListener *listener)
Add a listener to the trigger.
Definition: trigger.cpp:156
An Instance is an "instantiation" of an Object at a Location.
Definition: instance.h:94
bool isEnabledForAllInstances()
Returns if trigger is enabled for all instances.
Definition: trigger.cpp:234
void removeChangeListener(CellChangeListener *listener)
Removes cell change listener.
Definition: cell.cpp:412
void setTriggered()
Sets the trigger to triggered and calls ITriggerListener->onTriggered()
Definition: trigger.cpp:179
virtual void onInstanceEnteredCell(Cell *cell, Instance *instance)
Called when some instance entered the cell.
Definition: trigger.cpp:58
std::vector< Cell * > m_assigned
cells in which the trigger is assigned
Definition: trigger.h:271