Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

gameeventsystem.cpp

Go to the documentation of this file.
00001 
00005 /*
00006     This file is part of Advanced Strategic Command; http://www.asc-hq.de
00007     Copyright (C) 1994-2005  Martin Bickel  and  Marc Schellenberger
00008 
00009     This program is free software; you can redistribute it and/or modify
00010     it under the terms of the GNU General Public License as published by
00011     the Free Software Foundation; either version 2 of the License, or
00012     (at your option) any later version.
00013 
00014     This program is distributed in the hope that it will be useful,
00015     but WITHOUT ANY WARRANTY; without even the implied warranty of
00016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017     GNU General Public License for more details.
00018 
00019     You should have received a copy of the GNU General Public License
00020     along with this program; see the file COPYING. If not, write to the 
00021     Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
00022     Boston, MA  02111-1307  USA
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    // this is not for synchronizing between threads, but in the same threat inside the call stack 
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 }

Generated on Tue Jun 24 01:27:42 2008 for Advanced Strategic Command by  doxygen 1.4.2