00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "spawnobject.h"
00022 #include "action-registry.h"
00023
00024 #include "removeobject.h"
00025 #include "../vehicle.h"
00026 #include "../gamemap.h"
00027
00028 SpawnObject::SpawnObject( GameMap* gamemap, const MapCoordinate& position, int objectID, int direction )
00029 : GameAction( gamemap ), pos(position)
00030 {
00031 this->objectID = objectID;
00032 this->direction = direction;
00033 objectLaid = false;
00034
00035 objectAvailableBeforehand = false;
00036 oldObjectDirection = 0;
00037 objectImmediatelyDisappearsAgain = false;
00038 }
00039
00040
00041 ASCString SpawnObject::getDescription() const
00042 {
00043 const ObjectType* object = getMap()->getobjecttype_byid( objectID );
00044 ASCString res ;
00045 if ( object )
00046 res = "Spawn Object of type " + object->getName();
00047 else
00048 res = "Spawn Object " ;
00049 res += " at " + pos.toString();
00050 return res;
00051 }
00052
00053 static const int spawnObjectStreamVersion = 3;
00054
00055 void SpawnObject::readData ( tnstream& stream )
00056 {
00057 int version = stream.readInt();
00058 if ( version < 1 || version > spawnObjectStreamVersion )
00059 throw tinvalidversion ( "SpawnObject", spawnObjectStreamVersion, version );
00060
00061 objectID = stream.readInt();
00062 pos.read( stream );
00063 direction = stream.readInt();
00064 objectLaid = stream.readInt();
00065 if ( version >= 2 ) {
00066 objectAvailableBeforehand = stream.readInt();
00067 oldObjectDirection = stream.readInt();
00068 } else {
00069 objectAvailableBeforehand = false;
00070 oldObjectDirection = 0;
00071 }
00072
00073 if ( version >= 3 )
00074 objectImmediatelyDisappearsAgain = stream.readInt();
00075 else
00076 objectImmediatelyDisappearsAgain = false;
00077 };
00078
00079
00080 void SpawnObject::writeData ( tnstream& stream ) const
00081 {
00082 stream.writeInt( spawnObjectStreamVersion );
00083 stream.writeInt( objectID );
00084 pos.write( stream );
00085 stream.writeInt( direction );
00086 stream.writeInt( objectLaid );
00087 stream.writeInt( objectAvailableBeforehand );
00088 stream.writeInt( oldObjectDirection );
00089 stream.writeInt( objectImmediatelyDisappearsAgain );
00090 };
00091
00092
00093 GameActionID SpawnObject::getID() const
00094 {
00095 return ActionRegistry::SpawnObject;
00096 }
00097
00098 class ActionObjectRemovalStrategy : public MapField::ObjectRemovalStrategy {
00099 const Context& context;
00100 const ObjectType* originalObject;
00101 bool immediateRemoval;
00102 public:
00103 ActionObjectRemovalStrategy( const Context& actionContext, const ObjectType* object )
00104 : context( actionContext ), originalObject( object ), immediateRemoval(false)
00105 {}
00106
00107 virtual void removeObject( MapField* fld, const ObjectType* objectType ) {
00108 if ( objectType != originalObject )
00109 (new RemoveObject( fld->getMap(), fld->getPosition(), objectType->id ))->execute( context );
00110 else {
00111 for ( MapField::ObjectContainer::iterator o = fld->objects.begin(); o != fld->objects.end(); ) {
00112 if ( o->typ == objectType ) {
00113 o = fld->objects.erase( o );
00114 } else
00115 ++o ;
00116 }
00117
00118 immediateRemoval = true;
00119 }
00120 };
00121
00122 bool getImmediateRemoval()
00123 {
00124 return immediateRemoval;
00125 }
00126 };
00127
00128 ActionResult SpawnObject::runAction( const Context& context )
00129 {
00130 MapField* fld = getMap()->getField(pos);
00131 if ( !fld )
00132 return ActionResult( 21002, pos );
00133
00134 const ObjectType* object = getMap()->getobjecttype_byid( objectID );
00135 if ( !object )
00136 return ActionResult( 21201, "Object id is " + ASCString::toString(objectID));
00137
00138 Object* old = fld->checkForObject( object );
00139 if ( old ) {
00140 objectAvailableBeforehand = true;
00141 oldObjectDirection = old->dir;
00142 } else {
00143 objectAvailableBeforehand = false;
00144 oldObjectDirection = 0;
00145 }
00146
00147 ActionObjectRemovalStrategy aors( context, object );
00148 objectLaid = fld->addobject( object, direction, false, &aors );
00149
00150 objectImmediatelyDisappearsAgain = aors.getImmediateRemoval();
00151 return ActionResult(0);
00152 }
00153
00154
00155 ActionResult SpawnObject::undoAction( const Context& context )
00156 {
00157 MapField* fld = getMap()->getField(pos);
00158 if ( !fld )
00159 return ActionResult( 21002, pos );
00160
00161 const ObjectType* object = getMap()->getobjecttype_byid( objectID );
00162 if ( !object )
00163 return ActionResult( 21201, "Object id is " + ASCString::toString(objectID));
00164
00165 if ( objectAvailableBeforehand ) {
00166 Object* o = fld->checkForObject( object );
00167 if ( !o )
00168 return ActionResult( 21505 );
00169 o->dir = oldObjectDirection;
00170 } else
00171 if ( !objectImmediatelyDisappearsAgain )
00172 fld->removeObject( object, true );
00173
00174 return ActionResult(0);
00175 }
00176
00177 ActionResult SpawnObject::verify()
00178 {
00179 return ActionResult(0);
00180 }
00181
00182
00183 namespace {
00184 const bool r1 = registerAction<SpawnObject> ( ActionRegistry::SpawnObject );
00185 }
00186