00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "diplomacycommand.h"
00023
00024 #include "action-registry.h"
00025 #include "../gamemap.h"
00026 #include "../itemrepository.h"
00027 #include "../cannedmessages.h"
00028 #include "../viewcalculation.h"
00029 #include "../spfst.h"
00030
00031 #include "changediplomaticstate.h"
00032
00033 DiplomacyCommand::DiplomacyCommand( GameMap* map )
00034 : Command( map ), actingPlayer(-1), sneak ( false), newState(WAR), towardsPlayer(-1)
00035 {
00036 }
00037
00038
00039 DiplomacyCommand::DiplomacyCommand( Player& player )
00040 : Command( player.getParentMap() ), actingPlayer( player.getPosition() ), sneak ( false), newState(WAR), towardsPlayer(-1)
00041 {
00042
00043 }
00044
00045
00046
00047
00048 void DiplomacyCommand::readData ( tnstream& stream )
00049 {
00050 Command::readData( stream );
00051 stream.readInt();
00052 actingPlayer = stream.readInt();
00053 readClassContainer( generatedMessages, stream );
00054 sneak = stream.readInt();
00055 newState = (DiplomaticStates) stream.readInt();
00056 towardsPlayer = stream.readInt();
00057 }
00058
00059
00060 void DiplomacyCommand::writeData ( tnstream& stream ) const
00061 {
00062 Command::writeData( stream );
00063 stream.writeInt( 1 );
00064 stream.writeInt( actingPlayer );
00065 writeClassContainer( generatedMessages, stream );
00066 stream.writeInt( sneak );
00067 stream.writeInt( newState );
00068 stream.writeInt( towardsPlayer );
00069 }
00070
00071
00072 void DiplomacyCommand::sneakAttack( Player& enemy )
00073 {
00074 sneak = true;
00075 towardsPlayer = enemy.getPosition();
00076 newState = WAR;
00077 setState( SetUp );
00078 }
00079
00080 void DiplomacyCommand::newstate( DiplomaticStates state, Player& towards )
00081 {
00082 sneak = false;
00083 towardsPlayer = towards.getPosition();
00084 newState = state;
00085 setState( SetUp );
00086 }
00087
00088 void DiplomacyCommand::deleteMessage( int id, MessagePntrContainer& list )
00089 {
00090 for ( MessagePntrContainer::iterator i = list.begin(); i != list.end(); ) {
00091 if ( (*i)->id == id )
00092 i = list.erase( i );
00093 else
00094 ++i;
00095 }
00096 }
00097
00098 void DiplomacyCommand::deleteMessage( int id )
00099 {
00100 for ( int p = 0; p < getMap()->getPlayerCount(); ++p ) {
00101 deleteMessage( id, getMap()->getPlayer(p).unreadmessage );
00102 deleteMessage( id, getMap()->getPlayer(p).oldmessage );
00103 deleteMessage( id, getMap()->getPlayer(p).sentmessage );
00104 }
00105
00106 deleteMessage( id, getMap()->unsentmessage );
00107
00108 for ( MessageContainer::iterator i = getMap()->messages.begin(); i != getMap()->messages.end(); ) {
00109 if ( (*i)->id == id ) {
00110 delete *i;
00111 i = getMap()->messages.erase( i );
00112 } else
00113 ++i;
00114 }
00115 }
00116
00117 void DiplomacyCommand::sendMessage( int to, const ASCString& body )
00118 {
00119 Message* m = new Message ( body, getMap(), to );
00120 generatedMessages.push_back( m->id );
00121 }
00122
00123 void DiplomacyCommand::immediateTwoWayChange( DiplomaticStates newState, const Context& context )
00124 {
00125 Player& acting = getMap()->getPlayer( actingPlayer );
00126 Player& towards = getMap()->getPlayer( towardsPlayer );
00127
00128 ActionResult res = (new ChangeDiplomaticState( acting, towards, 0, newState ))->execute(context);
00129 if ( !res.successful() )
00130 throw res;
00131
00132 res = (new ChangeDiplomaticState( towards, acting, 0, newState ))->execute(context);
00133 if ( !res.successful() )
00134 throw res;
00135 }
00136
00137
00138 ActionResult DiplomacyCommand::go ( const Context& context )
00139 {
00140 if ( getState() != SetUp )
00141 return ActionResult(22000);
00142
00143 if ( actingPlayer < 0 || actingPlayer >= getMap()->getPlayerCount() )
00144 return ActionResult( 23100 );
00145
00146 if ( towardsPlayer < 0 || towardsPlayer >= getMap()->getPlayerCount() )
00147 return ActionResult( 23100 );
00148
00149 Player& acting = getMap()->getPlayer( actingPlayer );
00150 Player& towards = getMap()->getPlayer( towardsPlayer );
00151
00152
00153 bool oldShareView = acting.diplomacy.sharesView( towards );
00154
00155 if ( sneak ) {
00156
00157 immediateTwoWayChange( newState, context );
00158
00159 int to = 0;
00160 for ( int j = 0; j < 8; j++ )
00161 if ( j != actingPlayer )
00162 if ( getMap()->getPlayer(j).exist() )
00163 to |= 1 << j;
00164
00165 ASCString txt;
00166 txt.format ( getmessage( 10001 ), acting.getName().c_str(), getMap()->player[towardsPlayer].getName().c_str() );
00167 sendMessage( to, txt );
00168 } else {
00169
00170
00171 DiplomaticStateVector& targ = towards.diplomacy;
00172
00173 DiplomaticStateVector::QueuedStateChanges::iterator i = targ.queuedStateChanges.find( acting.getPosition() );
00174
00175 DiplomaticStates currentState = acting.diplomacy.getState( towards ) ;
00176
00177 bool initialProposal = i == targ.queuedStateChanges.end();
00178
00179 if ( initialProposal || (newState < currentState && i->second > currentState)) {
00180
00181
00182 ASCString txt;
00183 int msgid;
00184 if ( newState > acting.diplomacy.getState( towardsPlayer ))
00185 msgid = 10003;
00186 else
00187 msgid = 10002;
00188
00189 txt.format( getmessage( msgid ), acting.getName().c_str(), diplomaticStateNames[newState] );
00190
00191 sendMessage(1 << towardsPlayer, txt );
00192
00193 ActionResult res = (new ChangeDiplomaticState( acting, towards, 1, newState ))->execute(context);
00194 if ( !res.successful() )
00195 return res;
00196
00197
00198
00199 } else {
00200
00201
00202 if ( newState > acting.diplomacy.getState( towardsPlayer )) {
00203
00204
00205 if ( newState > i->second ) {
00206
00207
00208 immediateTwoWayChange( i->second, context );
00209
00210 ActionResult res = (new ChangeDiplomaticState( acting, towards, 1, newState ))->execute(context);
00211 if ( !res.successful() )
00212 return res;
00213
00214 } else {
00215
00216
00217 immediateTwoWayChange( newState, context );
00218
00219 }
00220
00221
00222 ActionResult res = (new ChangeDiplomaticState( towards, acting, -1, newState ))->execute(context);
00223 if ( !res.successful() )
00224 return res;
00225
00226 } else {
00227 if ( newState < i->second ) {
00228
00229 immediateTwoWayChange( i->second, context );
00230
00231
00232 ActionResult res = (new ChangeDiplomaticState( towards, acting, -1, newState ))->execute(context);
00233 if ( !res.successful() )
00234 return res;
00235
00236 res = (new ChangeDiplomaticState( acting, towards, 1, newState ))->execute(context);
00237 if ( !res.successful() )
00238 return res;
00239
00240 ASCString txt;
00241
00242 txt.format( getmessage( 10002 ), acting.getName().c_str(), diplomaticStateNames[newState] );
00243 sendMessage(1 << towardsPlayer, txt );
00244
00245 } else {
00246
00247 immediateTwoWayChange( newState, context);
00248 }
00249 }
00250 }
00251 }
00252
00253 if ( acting.diplomacy.sharesView( towards ) != oldShareView ) {
00254 computeview( getMap(), 0, false, &context );
00255 mapChanged( getMap() );
00256 repaintMap();
00257 }
00258
00259 setState( Finished );
00260
00261 return ActionResult(0);
00262 }
00263
00264
00265 ActionResult DiplomacyCommand :: undoAction( const Context& context )
00266 {
00267 for ( vector<int>::iterator i = generatedMessages.begin(); i != generatedMessages.end(); ++i )
00268 deleteMessage( *i );
00269
00270 return Command::undoAction(context );
00271 }
00272
00273
00274 ASCString DiplomacyCommand :: getCommandString() const
00275 {
00276 ASCString c;
00277 c.format("setDiplomacy( map, %d, %d, %s, %d )", actingPlayer, towardsPlayer, sneak?"true":"false", newState );
00278 return c;
00279 }
00280
00281 GameActionID DiplomacyCommand::getID() const
00282 {
00283 return ActionRegistry::DiplomacyCommand;
00284 }
00285
00286 ASCString DiplomacyCommand::getDescription() const
00287 {
00288 ASCString s;
00289 if ( sneak )
00290 s = getMap()->getPlayer( actingPlayer ).getName() + " sneak attacks " + getMap()->getPlayer( towardsPlayer ).getName() ;
00291 else {
00292 s = getMap()->getPlayer( actingPlayer ).getName() + " set diplomatic state towards " + getMap()->getPlayer( towardsPlayer ).getName()
00293 + " to " + diplomaticStateNames[newState];
00294 }
00295 return s;
00296 }
00297
00298
00299 namespace {
00300 const bool r1 = registerAction<DiplomacyCommand> ( ActionRegistry::DiplomacyCommand );
00301 }
00302