Advanced Strategic Command
gameeventsystem.cpp
Go to the documentation of this file.
1 
5 /*
6  This file is part of Advanced Strategic Command; http://www.asc-hq.de
7  Copyright (C) 1994-2010 Martin Bickel and Marc Schellenberger
8 
9  This program is free software; you can redistribute it and/or modify
10  it under the terms of the GNU General Public License as published by
11  the Free Software Foundation; either version 2 of the License, or
12  (at your option) any later version.
13 
14  This program is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  GNU General Public License for more details.
18 
19  You should have received a copy of the GNU General Public License
20  along with this program; see the file COPYING. If not, write to the
21  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
22  Boston, MA 02111-1307 USA
23 */
24 
25 #include <stdio.h>
26 
27 #include <cstring>
28 
29 #include "global.h"
30 #include "buildingtype.h"
31 #include "vehicletype.h"
32 #include "gameeventsystem.h"
33 #include "typen.h"
34 #include "gamemap.h"
35 #include "spfst.h"
36 
37 
38 
39 
40 
42 {
43  if ( gamemap->eventTimes.empty() )
44  return;
45 
46  GameTime t = gamemap->eventTimes.back();
47  if ( gamemap->time.abstime >= t.abstime ) {
48  checkevents( gamemap, md );
49  gamemap->eventTimes.pop_back();
50  }
51 
52 }
53 
54 
55 
56 void eventReady( GameMap* gamemap )
57 {
58  for ( int i = 0; i < 8; i++ )
59  gamemap->player[i].queuedEvents++;
60 }
61 
62 
63 
65 {
66  // this is not for synchronizing between threads, but in the same threat inside the call stack
67  static bool isRunning = false;
68  if ( isRunning )
69  return false;
70 
71  VariableLocker l( isRunning );
72 
73  gamemap->player[gamemap->actplayer].queuedEvents++;
74  while ( gamemap->player[gamemap->actplayer].queuedEvents ) {
75 
76  gamemap->player[gamemap->actplayer].queuedEvents = 0;
77 
78  for ( GameMap::Events::iterator ev = gamemap->events.begin(); ev != gamemap->events.end(); ++ev )
79  (*ev)->check( md );
80 
81  }
82  return true;
83 }
84 
85 
86 
87 
88 
89 Event::Event ( GameMap& map_ ) : gamemap ( map_ ), playerBitmap(0xff), reArmNum(0), action(NULL)
90 {
91  id = ++gamemap.eventID;
92  triggerTime.abstime = -1;
95 }
96 
97 
99 {
100  if ( triggerFinal ) {
101  return stateCache;
102  } else {
103  State s = getState( player );
104  if ( invert ) {
105  switch ( s ) {
106  case unfulfilled: return fulfilled;
107  case fulfilled: return unfulfilled;
108  case finally_failed: triggerFinal = true;
109  stateCache = finally_fulfilled;
110  return finally_fulfilled;
111  case finally_fulfilled: triggerFinal = true;
112  stateCache = finally_failed;
113  return finally_failed;
114  }
115  return unfulfilled;
116  } else {
117  if ( s == finally_fulfilled || s == finally_failed ) {
118  stateCache = s;
119  triggerFinal = true;
120  }
121  return s;
122  }
123  }
124 }
125 
127 {
128  if ( event ) {
129  for ( int i = 0; i < 8; ++i )
130  if ( event->playerBitmap & (1<<i)) {
131  State s = state( i );
132  if ( s == fulfilled || s == finally_fulfilled)
133  return true;
134  }
135  }
136  return false;
137 }
138 
139 
140 const int currentEventVersion = 4;
141 
142 void Event::write ( tnstream& stream )
143 {
144  stream.writeInt( currentEventVersion );
145  stream.writeInt( trigger.size() );
146  for ( int i = 0; i < trigger.size(); i++ ) {
147  stream.writeInt( trigger[i]->getTriggerID() );
148  stream.writeInt( trigger[i]->invert );
149  trigger[i]->writeData( stream );
150  }
151  stream.writeInt ( id );
152  stream.writeInt( playerBitmap );
153  stream.writeString ( description );
154  stream.writeInt( triggerTime.abstime );
155  stream.writeInt( delayedexecution.turn );
156  stream.writeInt( delayedexecution.move );
157  stream.writeInt( reArmNum );
158  stream.writeInt ( triggerConnection );
159  stream.writeInt ( status );
160  if ( action ) {
161  stream.writeInt( 1 );
162  stream.writeInt ( action->getActionID() );
163  action->writeData( stream );
164  } else
165  stream.writeInt( 0 );
166 }
167 
168 void Event::clear()
169 {
170  if ( action ) {
171  delete action;
172  action = NULL;
173  }
174  for ( Trigger::iterator i = trigger.begin(); i != trigger.end(); ++i )
175  delete *i;
176  trigger.clear();
177 }
178 
179 void Event::read ( tnstream& stream )
180 {
181  clear();
182 
183  int version = stream.readInt();
184  if ( version > currentEventVersion )
185  throw tinvalidversion ( "Event", currentEventVersion, version );
186 
187  int triggerNum = stream.readInt();
188  for ( int i = 0; i < triggerNum; i++ ) {
189  EventTrigger* et = spawnTrigger( EventTriggerID( stream.readInt()) );
190  if ( version > 2 )
191  et->invert = stream.readInt();
192  et->readData ( stream );
193  trigger.push_back ( et );
194  }
195 
196  id = stream.readInt();
197  playerBitmap = stream.readInt();
198  description = stream.readString();
199  triggerTime.abstime = stream.readInt();
200  delayedexecution.turn = stream.readInt();
201  delayedexecution.move = stream.readInt();
202 
203  if ( version >= 2 )
204  reArmNum = stream.readInt();
205  else
206  reArmNum = 0;
207 
208  if ( version >= 4 ) {
209  int tc = stream.readInt();
210  if ( tc == 0 )
212  else
214 
215  status = Status ( stream.readInt() );
216  } else {
219  }
220 
221  if( stream.readInt() ) {
222  spawnAction ( stream.readInt( ));
223  action->readData( stream );
224  } else
225  stream.writeInt( 0 );
226 }
227 
228 
229 
231 {
232  if ( playerBitmap & (1 << gamemap.actplayer )) {
233  if ( status == Triggered ) {
234 
236 
237  if ( gamemap.getgameparameter(cgp_debugEvents) )
238  infoMessage( "Event " + description + " timer started");
239 
240  triggerTime.set ( gamemap.time.turn() + delayedexecution.turn, gamemap.time.move() + delayedexecution.move - 1 );
241  if ( triggerTime.move() < 0 )
242  triggerTime.set ( triggerTime.turn(), 0 );
243 
244  if ( gamemap.time.abstime < triggerTime.abstime ) {
245  gamemap.eventTimes.push_back ( triggerTime );
246  sort ( gamemap.eventTimes.begin(), gamemap.eventTimes.end(), GameTime::comp );
247  }
248 
249  } else
250  triggerTime = gamemap.time;
251 
252  status = Timed;
253  }
254  if ( status == Timed && gamemap.time.abstime >= triggerTime.abstime ) {
255 
256  gamemap.actions.breakUndo();
257 
258  if ( action )
259  action->execute( md );
260 
261  if ( reArmNum > 0 )
263  else
264  status = Executed;
265 
266  if ( gamemap.getgameparameter(cgp_debugEvents) )
267  infoMessage( "Event " + description + " executed");
268 
269  executed();
270 
271  if ( reArmNum > 0 ) {
272  arm();
273  --reArmNum;
274  check(md);
275  }
276  }
277  }
278 }
279 
281 {
282  if ( playerBitmap & (1 << gamemap.actplayer ))
283  if ( status == Untriggered ) {
284  if ( triggerConnection == AND ) {
285  status = Triggered;
286  for ( Trigger::iterator i = trigger.begin(); i != trigger.end(); i++ ) {
287  EventTrigger::State s = (*i)->state( gamemap.actplayer );
290 
291  if ( gamemap.getgameparameter(cgp_debugEvents) == 2 )
292  infoMessage( "Event " + description + " / Trigger " + (*i)->getDetailledName() + ": false" );
293  } else
294  if ( gamemap.getgameparameter(cgp_debugEvents) == 2 )
295  infoMessage( "Event " + description + " / Trigger " + (*i)->getDetailledName() + ": true" );
296  }
297  } else {
298  for ( Trigger::iterator i = trigger.begin(); i != trigger.end(); i++ ) {
299  EventTrigger::State s = (*i)->state( gamemap.actplayer );
301  status = Triggered;
302 
303  if ( gamemap.getgameparameter(cgp_debugEvents) == 2 )
304  infoMessage( "Event " + description + " / Trigger " + (*i)->getDetailledName() + ": true" );
305  } else
306  if ( gamemap.getgameparameter(cgp_debugEvents) == 2 )
307  infoMessage( "Event " + description + " / Trigger " + (*i)->getDetailledName() + ": false" );
308 
309  }
310  }
311 
312  if ( status == Triggered )
313  if ( gamemap.getgameparameter(cgp_debugEvents) )
314  infoMessage( "Event " + description + " triggered");
315 
316  }
317 
318 
319 
320  if ( status == Triggered || status == Timed )
321  execute( md );
322 }
323 
324 
326 {
327  action = eventActionFactory::Instance().createObject( eai );
328  action->setMap ( &gamemap );
329 }
330 
332 {
333  EventTrigger* et = eventTriggerFactory::Instance().createObject( eti );
334  et->setMap ( &gamemap );
335  et->setEvent ( this );
336  return et;
337 }
338 
339 
341 {
342  for ( Trigger::iterator i = trigger.begin(); i != trigger.end(); ++i )
343  (*i)->arm();
344 
345  if ( status == Timed ) {
346  gamemap.eventTimes.push_back ( triggerTime );
347  sort( gamemap.eventTimes.begin(), gamemap.eventTimes.end(), GameTime::comp );
348  }
349 }
350 
351 
353 {
354  clear();
355 }
the time in ASC, measured in turns and moves
Definition: typen.h:178
int queuedEvents
if ASC should check all events for fullfilled triggers, this variable will be set to true...
Definition: player.h:193
void arm()
virtual void writeInt(int i)
Writes a 32 bit signed Integer. In the stream little-endian byte order is used and a translation is p...
Definition: basestrm.cpp:363
map accessing and usage routines used by ASC and the mapeditor
void eventReady(GameMap *gamemap)
void setMap(GameMap *gamemap_)
int abstime
Definition: typen.h:183
virtual int readInt(void)
Reads a 32 bit signed Integer. In the stream little-endian byte order is used and a translation is pe...
Definition: basestrm.cpp:284
void spawnAction(EventActionID eai)
int turn() const
Definition: typen.h:181
virtual void writeData(tnstream &stream)=0
void setMap(GameMap *gamemap_)
ASCString description
int reArmNum
the number of times this event can be executed; makes only sense in cunjunction with delayedexecution...
Events events
Definition: gamemap.h:291
EventAction * action
Global platform dependant definitions. This file just branches to the platform specific files in thei...
The interface for all kinds of IO stream.
void write(tnstream &stream)
void checktimedevents(GameMap *gamemap, MapDisplayInterface *md)
bool checkevents(GameMap *gamemap, MapDisplayInterface *md)
void setEvent(Event *ev)
void read(tnstream &stream)
virtual void writeString(const string &pc, bool binary=true)
writes the C++ String pc to the stream.
Definition: basestrm.cpp:545
int move() const
Definition: typen.h:180
virtual State getState(int player)=0
int playerBitmap
vector< GameTime > eventTimes
Definition: gamemap.h:293
Definition of THE central asc class: GameMap.
EventTrigger * spawnTrigger(EventTriggerID eti)
The interface for the buildingtype class.
struct Event::Delayedexecution delayedexecution
void breakUndo()
to be called when some modification to the map is taking place that is not recorded by undo ...
signed char actplayer
the player who is currently making his moves (may be human or AI)
Definition: gamemap.h:232
const int currentEventVersion
GameTime triggerTime
Player player[9]
Definition: gamemap.h:253
virtual void readData(tnstream &stream)=0
virtual ASCString readString(bool includeCR=false)
Reads and returns a string.
Definition: basestrm.cpp:535
int getgameparameter(GameParameter num) const
Definition: gamemap.cpp:1047
virtual void readData(tnstream &stream)=0
Event(GameMap &map_)
virtual void execute(MapDisplayInterface *md)=0
int eventID
Definition: gamemap.h:288
enum Event::Status status
int EventActionID
ActionContainer actions
Records all action that have been done for undo/redo purposes.
Definition: gamemap.h:390
EventActionID getActionID()
Interface to the event handling of ASC.
void check(MapDisplayInterface *md)
virtual ~Event()
static bool comp(const GameTime &a, const GameTime &b)
Definition: typen.h:182
Trigger trigger
enum Event::TriggerConnection triggerConnection
sigc::signal< void > executed
State state(int player)
takes the inversion into account, which getState(int) does not
void execute(MapDisplayInterface *md)
GameTime time
the time in the game, mesured in a turns and moves
Definition: gamemap.h:235
void infoMessage(const ASCString &string)
The map. THE central structure of ASC, which holds everything not globally available together...
Definition: gamemap.h:182
int EventTriggerID
void set(int turn, int move)
Definition: typen.h:183