| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478 |
- /*
- ** Command & Conquer Generals Zero Hour(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- ////////////////////////////////////////////////////////////////////////////////
- // //
- // (c) 2001-2003 Electronic Arts Inc. //
- // //
- ////////////////////////////////////////////////////////////////////////////////
- // FILE: PrisonBehavior.cpp ///////////////////////////////////////////////////////////////////////
- // Author: Colin Day, August 2002
- // Desc: Prison Behavior
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- // INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
- #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
- #include "Common/GameState.h"
- #include "Common/Player.h"
- #include "Common/RandomValue.h"
- #include "Common/ThingFactory.h"
- #include "Common/Xfer.h"
- #include "GameClient/Drawable.h"
- #include "GameClient/InGameUI.h"
- #include "GameClient/GameClient.h"
- #include "GameClient/Line2D.h"
- #include "GameLogic/Object.h"
- #include "GameLogic/Module/PrisonBehavior.h"
- #ifdef ALLOW_SURRENDER
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- class PrisonVisual : public MemoryPoolObject
- {
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( PrisonVisual, "PrisonVisual" )
- public:
- PrisonVisual( void );
- // virtual destructor prototype provied by memory pool object
- ObjectID m_objectID; ///< object that is contained
- DrawableID m_drawableID; ///< associated visual prisoner drawable
- PrisonVisual *m_next; ///< next
- };
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- PrisonVisual::PrisonVisual( void )
- {
- m_objectID = INVALID_ID;
- m_drawableID = INVALID_DRAWABLE_ID;
- m_next = NULL;
- } // end PrisonVisual
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- PrisonVisual::~PrisonVisual( void )
- {
- } // end ~PrisonVisual
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- PrisonBehaviorModuleData::PrisonBehaviorModuleData( void )
- {
- m_showPrisoners = FALSE;
- } // end PrisonBehaviorModuleData
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- /*static*/ void PrisonBehaviorModuleData::buildFieldParse( MultiIniFieldParse &p )
- {
- OpenContainModuleData::buildFieldParse( p );
- static const FieldParse dataFieldParse[] =
- {
- { "ShowPrisoners", INI::parseBool, NULL, offsetof( PrisonBehaviorModuleData, m_showPrisoners ) },
- { "YardBonePrefix", INI::parseAsciiString, NULL, offsetof( PrisonBehaviorModuleData, m_prisonYardBonePrefix ) },
- { 0, 0, 0, 0 }
- };
- p.add( dataFieldParse );
- } // end buildFieldParse
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- PrisonBehavior::PrisonBehavior( Thing *thing, const ModuleData *moduleData )
- : OpenContain( thing, moduleData )
- {
- m_visualList = NULL;
- } // end PrisonBehavior
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- PrisonBehavior::~PrisonBehavior( void )
- {
- } // end ~PrisonBehavior
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- void PrisonBehavior::onDelete( void )
- {
- // extend functionality
- OpenContain::onDelete();
- // delete our list
- Drawable *draw;
- PrisonVisual *visual;
- while( m_visualList )
- {
- // delete drawable if found
- draw = TheGameClient->findDrawableByID( m_visualList->m_drawableID );
- if( draw )
- TheGameClient->destroyDrawable( draw );
- // delete element and set next to head
- visual = m_visualList->m_next;
- m_visualList->deleteInstance();
- m_visualList = visual;
- } // end while
- } // end onDelete
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- void PrisonBehavior::onContaining( Object *obj, Bool wasSelected )
- {
- // extend functionality
- OpenContain::onContaining( obj, wasSelected );
- // objects inside a prison are held
- obj->setDisabled( DISABLED_HELD );
- // if we show visuals, make one
- const PrisonBehaviorModuleData *modData = getPrisonBehaviorModuleData();
- if( modData->m_showPrisoners )
- addVisual( obj );
- } // end onContaining
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- void PrisonBehavior::onRemoving( Object *obj )
- {
- // if we show visuals, remove one
- const PrisonBehaviorModuleData *modData = getPrisonBehaviorModuleData();
- if( modData->m_showPrisoners )
- removeVisual( obj );
- // object is no longer held inside a garrisoned building
- obj->clearDisabled( DISABLED_HELD );
- // extend functionality
- OpenContain::onRemoving( obj );
- } // end onRemoving
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- // PRIVATE ////////////////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- // ------------------------------------------------------------------------------------------------
- /** Pick a random location inside the prison yard */
- // ------------------------------------------------------------------------------------------------
- void PrisonBehavior::pickVisualLocation( Coord3D *pos )
- {
- Object *us = getObject();
- const PrisonBehaviorModuleData *modData = getPrisonBehaviorModuleData();
- Int i;
- // sanity
- if( pos == NULL )
- return;
- // initialize the picked location to that of the prison center
- Coord3D pickedLocation = *us->getPosition();
- // get the positions of the bones that make up the prison yard area
- const Int MAX_YARD_BONES = 16;
- Coord3D yardPositions[ MAX_YARD_BONES ];
- Int yardBones = us->getMultiLogicalBonePosition( modData->m_prisonYardBonePrefix.str(),
- MAX_YARD_BONES,
- yardPositions,
- NULL );
-
- //
- // we must have at least 3 bone locations to make a yard polygon, otherwise we'll
- // default to the object position
- //
- if( yardBones >= 3 )
- {
- // find the bounding region of the yard area
- Region2D yardRegion;
- yardRegion.lo.x = yardPositions[ 0 ].x;
- yardRegion.lo.y = yardPositions[ 0 ].y;
- yardRegion.hi.x = yardPositions[ 0 ].x;
- yardRegion.hi.y = yardPositions[ 0 ].y;
- for( i = 1; i < yardBones; i++ )
- {
- if( yardPositions[ i ].x < yardRegion.lo.x )
- yardRegion.lo.x = yardPositions[ i ].x;
- if( yardPositions[ i ].y < yardRegion.lo.y )
- yardRegion.lo.y = yardPositions[ i ].y;
- if( yardPositions[ i ].x > yardRegion.hi.x )
- yardRegion.hi.x = yardPositions[ i ].x;
- if( yardPositions[ i ].y > yardRegion.hi.y )
- yardRegion.hi.y = yardPositions[ i ].y;
- } // end for i
- //
- // now that we have a yard region, the default visual position will be in the middle
- // of the yard region instead of the position of our object
- //
- pickedLocation.x = yardRegion.lo.x + yardRegion.width() / 2.0f;
- pickedLocation.y = yardRegion.lo.y + yardRegion.height() / 2.0f;
- // NOTE: pickedLocation.z is left alone at the object center Z
- // loop till we find a valid location that is inside the yard area
- Int maxTries = 32;
- Coord3D loc;
- for( i = 0; i < maxTries; ++i )
- {
- // pick a location
- loc.x = GameLogicRandomValueReal( yardRegion.lo.x, yardRegion.hi.x );
- loc.y = GameLogicRandomValueReal( yardRegion.lo.y, yardRegion.hi.y );
- loc.z = pickedLocation.z;
- // must be inside the yard polygon
- if( PointInsideArea2D( &loc, yardPositions, yardBones ) == TRUE )
- {
- // use this location, leave Z alone as the center of the prison
- pickedLocation = loc;
- break; // exit for i
- } // end if
- } // end for i
- } // end if
- // return the location picked
- *pos = pickedLocation;
- } // end pickVisualLocation
- // ------------------------------------------------------------------------------------------------
- /** Add prisoner visual to the prison yard */
- // ------------------------------------------------------------------------------------------------
- void PrisonBehavior::addVisual( Object *obj )
- {
- // sanity
- if( obj == NULL )
- return;
- // create a drawable
- Drawable *draw = TheThingFactory->newDrawable( obj->getTemplate() );
- // set the color of the drawable to that of the object
- if (TheGlobalData->m_timeOfDay == TIME_OF_DAY_NIGHT)
- draw->setIndicatorColor( obj->getNightIndicatorColor() );
- else
- draw->setIndicatorColor( obj->getIndicatorColor() );
- // pick a location insid the prison yard
- Coord3D pos;
- pickVisualLocation( &pos );
- // place drawable withing the prison yard area
- draw->setPosition( &pos );
- draw->setOrientation( GameLogicRandomValueReal( 0, TWO_PI ) );
- DrawableInfo *drawInfo=draw->getDrawableInfo();
- drawInfo->m_shroudStatusObjectID=getObject()->getID();
- // record this object/drawable pair
- PrisonVisual *visual = newInstance(PrisonVisual);
- visual->m_objectID = obj->getID();
- visual->m_drawableID = draw->getID();
- visual->m_next = m_visualList;
- m_visualList = visual;
- } // end addVisual
- // ------------------------------------------------------------------------------------------------
- /** Remove prisoner visual from the prison yard */
- // ------------------------------------------------------------------------------------------------
- void PrisonBehavior::removeVisual( Object *obj )
- {
- // sanity
- if( obj == NULL )
- return;
- // initialize a drawable ID to invalid
- DrawableID drawableID = INVALID_DRAWABLE_ID;
- // find visual info in our list, once found, take this opportunity to remove it from that list
- PrisonVisual *visual, *prevVisual = NULL;
- for( visual = m_visualList; visual; visual = visual->m_next )
- {
- // is this the one we're looking for
- if( visual->m_objectID == obj->getID() )
- {
- // record the information we need here
- drawableID = visual->m_drawableID;
- // remove from list
- if( prevVisual )
- prevVisual->m_next = visual->m_next;
- else
- m_visualList = visual->m_next;
- // delete the element
- visual->deleteInstance();
- break; // exit for
- } // end if
- // keep a pointer to the previous element
- prevVisual = visual;
- } // end for
- // find the drawable visual and destroy it
- Drawable *draw = TheGameClient->findDrawableByID( drawableID );
- if( draw )
- TheGameClient->destroyDrawable( draw );
- } // end removeVisual
- // ------------------------------------------------------------------------------------------------
- /** CRC */
- // ------------------------------------------------------------------------------------------------
- void PrisonBehavior::crc( Xfer *xfer )
- {
- // extend base class
- OpenContain::crc( xfer );
- } // end crc
- // ------------------------------------------------------------------------------------------------
- /** Xfer method
- * Version Info:
- * 1: Initial version */
- // ------------------------------------------------------------------------------------------------
- void PrisonBehavior::xfer( Xfer *xfer )
- {
- // version
- XferVersion currentVersion = 1;
- XferVersion version = currentVersion;
- xfer->xferVersion( &version, currentVersion );
- // extend base class
- OpenContain::xfer( xfer );
- // count and data for the prison visuals
- UnsignedShort visualCount = 0;
- PrisonVisual *visual;
- for( visual = m_visualList; visual; visual = visual->m_next )
- visualCount++;
- xfer->xferUnsignedShort( &visualCount );
- if( xfer->getXferMode() == XFER_SAVE )
- {
- // write all data
- for( visual = m_visualList; visual; visual = visual->m_next )
- {
- // object id
- xfer->xferObjectID( &visual->m_objectID );
- // drawable id
- xfer->xferDrawableID( &visual->m_drawableID );
- } // end for, visual
- } // end if, save
- else
- {
- // the visual list should be empty
- if( m_visualList != NULL )
- {
- DEBUG_CRASH(( "PrisonBehavior::xfer - the visual list should be empty but is not\n" ));
- throw SC_INVALID_DATA;
- } // end if
- // read each item
- for( UnsignedShort i = 0; i < visualCount; ++i )
- {
- // allocate a new visual and tie to list
- visual = newInstance(PrisonVisual);
- visual->m_next = m_visualList;
- m_visualList = visual;
- // read object id
- xfer->xferObjectID( &visual->m_objectID );
- // read drawable id
- xfer->xferDrawableID( &visual->m_drawableID );
- } // end for, i
- } // end else, load
- } // end xfer
- // ------------------------------------------------------------------------------------------------
- /** Load post process */
- // ------------------------------------------------------------------------------------------------
- void PrisonBehavior::loadPostProcess( void )
- {
- // extend base class
- OpenContain::loadPostProcess();
- } // end loadPostProcess
- #endif
|