00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <stdio.h>
00026
00027 #include <cstring>
00028
00029 #include "global.h"
00030 #include "buildingtype.h"
00031 #include "vehicletype.h"
00032 #include "gameeventsystem.h"
00033 #include "typen.h"
00034 #include "gamemap.h"
00035 #include "spfst.h"
00036
00037
00038
00039
00040
00041 void checktimedevents ( MapDisplayInterface* md )
00042 {
00043 if ( actmap->eventTimes.empty() )
00044 return;
00045
00046 GameTime t = actmap->eventTimes.back();
00047 if ( actmap->time.abstime >= t.abstime ) {
00048 checkevents( md );
00049 actmap->eventTimes.pop_back();
00050 }
00051
00052 }
00053
00054
00055
00056 void eventReady()
00057 {
00058 for ( int i = 0; i < 8; i++ )
00059 actmap->player[i].queuedEvents++;
00060 }
00061
00062
00063
00064 bool checkevents( MapDisplayInterface* md )
00065 {
00066
00067 static bool isRunning = false;
00068 if ( isRunning )
00069 return false;
00070
00071 VariableLocker l( isRunning );
00072
00073 actmap->player[actmap->actplayer].queuedEvents++;
00074 while ( actmap->player[actmap->actplayer].queuedEvents ) {
00075
00076 actmap->player[actmap->actplayer].queuedEvents = 0;
00077
00078 for ( GameMap::Events::iterator ev = actmap->events.begin(); ev != actmap->events.end(); ++ev )
00079 (*ev)->check( md );
00080
00081 }
00082 return true;
00083 }
00084
00085
00086
00087
00088
00089 Event::Event ( GameMap& map_ ) : gamemap ( map_ ), playerBitmap(0xff), reArmNum(0), action(NULL)
00090 {
00091 id = ++gamemap.eventID;
00092 triggerTime.abstime = -1;
00093 status = Untriggered;
00094 triggerConnection = AND;
00095 }
00096
00097
00098 EventTrigger::State EventTrigger::state( int player )
00099 {
00100 if ( triggerFinal ) {
00101 return stateCache;
00102 } else {
00103 State s = getState( player );
00104 if ( invert ) {
00105 switch ( s ) {
00106 case unfulfilled: return fulfilled;
00107 case fulfilled: return unfulfilled;
00108 case finally_failed: triggerFinal = true;
00109 stateCache = finally_fulfilled;
00110 return finally_fulfilled;
00111 case finally_fulfilled: triggerFinal = true;
00112 stateCache = finally_failed;
00113 return finally_failed;
00114 }
00115 return unfulfilled;
00116 } else {
00117 if ( s == finally_fulfilled || s == finally_failed ) {
00118 stateCache = s;
00119 triggerFinal = true;
00120 }
00121 return s;
00122 }
00123 }
00124 }
00125
00126 bool EventTrigger::isFulfilled()
00127 {
00128 if ( event ) {
00129 for ( int i = 0; i < 8; ++i )
00130 if ( event->playerBitmap & (1<<i)) {
00131 State s = state( i );
00132 if ( s == fulfilled || s == finally_fulfilled)
00133 return true;
00134 }
00135 }
00136 return false;
00137 }
00138
00139
00140 const int currentEventVersion = 4;
00141
00142 void Event::write ( tnstream& stream )
00143 {
00144 stream.writeInt( currentEventVersion );
00145 stream.writeInt( trigger.size() );
00146 for ( int i = 0; i < trigger.size(); i++ ) {
00147 stream.writeInt( trigger[i]->getTriggerID() );
00148 stream.writeInt( trigger[i]->invert );
00149 trigger[i]->writeData( stream );
00150 }
00151 stream.writeInt ( id );
00152 stream.writeInt( playerBitmap );
00153 stream.writeString ( description );
00154 stream.writeInt( triggerTime.abstime );
00155 stream.writeInt( delayedexecution.turn );
00156 stream.writeInt( delayedexecution.move );
00157 stream.writeInt( reArmNum );
00158 stream.writeInt ( triggerConnection );
00159 stream.writeInt ( status );
00160 if ( action ) {
00161 stream.writeInt( 1 );
00162 stream.writeInt ( action->getActionID() );
00163 action->writeData( stream );
00164 } else
00165 stream.writeInt( 0 );
00166 }
00167
00168 void Event::clear()
00169 {
00170 if ( action ) {
00171 delete action;
00172 action = NULL;
00173 }
00174 for ( Trigger::iterator i = trigger.begin(); i != trigger.end(); ++i )
00175 delete *i;
00176 trigger.clear();
00177 }
00178
00179 void Event::read ( tnstream& stream )
00180 {
00181 clear();
00182
00183 int version = stream.readInt();
00184 if ( version > currentEventVersion )
00185 throw tinvalidversion ( "Event", currentEventVersion, version );
00186
00187 int triggerNum = stream.readInt();
00188 for ( int i = 0; i < triggerNum; i++ ) {
00189 EventTrigger* et = spawnTrigger( EventTriggerID( stream.readInt()) );
00190 if ( version > 2 )
00191 et->invert = stream.readInt();
00192 et->readData ( stream );
00193 trigger.push_back ( et );
00194 }
00195
00196 id = stream.readInt();
00197 playerBitmap = stream.readInt();
00198 description = stream.readString();
00199 triggerTime.abstime = stream.readInt();
00200 delayedexecution.turn = stream.readInt();
00201 delayedexecution.move = stream.readInt();
00202
00203 if ( version >= 2 )
00204 reArmNum = stream.readInt();
00205 else
00206 reArmNum = 0;
00207
00208 if ( version >= 4 ) {
00209 int tc = stream.readInt();
00210 if ( tc == 0 )
00211 triggerConnection = AND;
00212 else
00213 triggerConnection = OR;
00214
00215 status = Status ( stream.readInt() );
00216 } else {
00217 triggerConnection = AND;
00218 status = Untriggered;
00219 }
00220
00221 if( stream.readInt() ) {
00222 spawnAction ( stream.readInt( ));
00223 action->readData( stream );
00224 } else
00225 stream.writeInt( 0 );
00226 }
00227
00228
00229
00230 void Event::execute( MapDisplayInterface* md )
00231 {
00232 if ( playerBitmap & (1 << gamemap.actplayer )) {
00233 if ( status == Triggered ) {
00234
00235 if ( delayedexecution.move || delayedexecution.turn ) {
00236
00237 if ( gamemap.getgameparameter(cgp_debugEvents) )
00238 infoMessage( "Event " + description + " timer started");
00239
00240 triggerTime.set ( gamemap.time.turn() + delayedexecution.turn, gamemap.time.move() + delayedexecution.move - 1 );
00241 if ( triggerTime.move() < 0 )
00242 triggerTime.set ( triggerTime.turn(), 0 );
00243
00244 if ( gamemap.time.abstime < triggerTime.abstime ) {
00245 gamemap.eventTimes.push_back ( triggerTime );
00246 sort ( gamemap.eventTimes.begin(), gamemap.eventTimes.end(), GameTime::comp );
00247 }
00248
00249 } else
00250 triggerTime = gamemap.time;
00251
00252 status = Timed;
00253 }
00254 if ( status == Timed && gamemap.time.abstime >= triggerTime.abstime ) {
00255 if ( action )
00256 action->execute( md );
00257
00258 if ( reArmNum > 0 )
00259 status = Untriggered;
00260 else
00261 status = Executed;
00262
00263 if ( gamemap.getgameparameter(cgp_debugEvents) )
00264 infoMessage( "Event " + description + " executed");
00265
00266 executed();
00267
00268 if ( reArmNum > 0 ) {
00269 arm();
00270 --reArmNum;
00271 check(md);
00272 }
00273 }
00274 }
00275 }
00276
00277 void Event::check( MapDisplayInterface* md )
00278 {
00279 if ( playerBitmap & (1 << gamemap.actplayer ))
00280 if ( status == Untriggered ) {
00281 if ( triggerConnection == AND ) {
00282 status = Triggered;
00283 for ( Trigger::iterator i = trigger.begin(); i != trigger.end(); i++ ) {
00284 EventTrigger::State s = (*i)->state( gamemap.actplayer );
00285 if ( s == EventTrigger::unfulfilled || s == EventTrigger::finally_failed ) {
00286 status = Untriggered;
00287
00288 if ( gamemap.getgameparameter(cgp_debugEvents) == 2 )
00289 infoMessage( "Event " + description + " / Trigger " + (*i)->getDetailledName() + ": false" );
00290 } else
00291 if ( gamemap.getgameparameter(cgp_debugEvents) == 2 )
00292 infoMessage( "Event " + description + " / Trigger " + (*i)->getDetailledName() + ": true" );
00293 }
00294 } else {
00295 for ( Trigger::iterator i = trigger.begin(); i != trigger.end(); i++ ) {
00296 EventTrigger::State s = (*i)->state( gamemap.actplayer );
00297 if ( s == EventTrigger::fulfilled || s == EventTrigger::finally_fulfilled ) {
00298 status = Triggered;
00299
00300 if ( gamemap.getgameparameter(cgp_debugEvents) == 2 )
00301 infoMessage( "Event " + description + " / Trigger " + (*i)->getDetailledName() + ": true" );
00302 } else
00303 if ( gamemap.getgameparameter(cgp_debugEvents) == 2 )
00304 infoMessage( "Event " + description + " / Trigger " + (*i)->getDetailledName() + ": false" );
00305
00306 }
00307 }
00308
00309 if ( status == Triggered )
00310 if ( gamemap.getgameparameter(cgp_debugEvents) )
00311 infoMessage( "Event " + description + " triggered");
00312
00313 }
00314
00315
00316
00317 if ( status == Triggered || status == Timed )
00318 execute( md );
00319 }
00320
00321
00322 void Event::spawnAction( EventActionID eai )
00323 {
00324 action = actionFactory::Instance().createObject( eai );
00325 action->setMap ( &gamemap );
00326 }
00327
00328 EventTrigger* Event::spawnTrigger( EventTriggerID eti )
00329 {
00330 EventTrigger* et = triggerFactory::Instance().createObject( eti );
00331 et->setMap ( &gamemap );
00332 et->setEvent ( this );
00333 return et;
00334 }
00335
00336
00337 void Event::arm()
00338 {
00339 for ( Trigger::iterator i = trigger.begin(); i != trigger.end(); ++i )
00340 (*i)->arm();
00341
00342 if ( status == Timed ) {
00343 gamemap.eventTimes.push_back ( triggerTime );
00344 sort( gamemap.eventTimes.begin(), gamemap.eventTimes.end(), GameTime::comp );
00345 }
00346 }
00347
00348
00349 Event::~Event()
00350 {
00351 clear();
00352 }