| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562 |
- /*
- ** Command & Conquer Renegade(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/>.
- */
- /***********************************************************************************************
- *** Confidential - Westwood Studios ***
- ***********************************************************************************************
- * *
- * Project Name : Commando *
- * *
- * $Archive:: /Commando/Code/Combat/scriptzone.cpp $*
- * *
- * $Author:: Byon_g $*
- * *
- * $Modtime:: 1/18/02 10:44a $*
- * *
- * $Revision:: 18 $*
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "scriptzone.h"
- #include "gameobjmanager.h"
- #include "scripts.h"
- #include "colmath.h"
- #include "colmathinlines.h"
- #include "debug.h"
- #include "persistfactory.h"
- #include "combatchunkid.h"
- #include "wwhack.h"
- #include "simpledefinitionfactory.h"
- #include "combat.h"
- #include "smartgameobj.h"
- #include "playertype.h"
- #include "wwprofile.h"
- #include "pscene.h"
- #include "phys.h"
- #include "soldier.h"
- /*
- ** ScriptZoneGameObjDef
- */
- DECLARE_FORCE_LINK( Zone )
- /*
- ** Namespaces
- */
- using namespace ZoneConstants;
- /*
- ** Constants
- */
- static const char * ZONE_TYPE_NAMES[TYPE_COUNT] =
- {
- "Default",
- "Capture The Flag",
- "Vehicle Construction",
- "Vehicle Repair",
- "Tiberium Field",
- "Beacon",
- "GDI Tiberium Field",
- "NOD Tiberium Field",
- };
- /*
- ** Editable and Save/Load system stuff
- */
- SimplePersistFactoryClass<ScriptZoneGameObjDef, CHUNKID_GAME_OBJECT_DEF_SCRIPT_ZONE> _ScriptZoneGameObjDefPersistFactory;
- DECLARE_DEFINITION_FACTORY(ScriptZoneGameObjDef, CLASSID_GAME_OBJECT_DEF_SCRIPT_ZONE, "Script Zone") _ScriptZoneGameObjDefDefFactory;
- ScriptZoneGameObjDef::ScriptZoneGameObjDef( void ) :
- Color( 0, 0.7F, 0 ),
- CheckStarsOnly( true ),
- ZoneType( TYPE_DEFAULT ),
- IsEnvironmentZone( false )
- {
- EDITABLE_PARAM( ScriptZoneGameObjDef, ParameterClass::TYPE_COLOR, Color );
- EDITABLE_PARAM( ScriptZoneGameObjDef, ParameterClass::TYPE_BOOL, CheckStarsOnly );
- EDITABLE_PARAM( ScriptZoneGameObjDef, ParameterClass::TYPE_BOOL, IsEnvironmentZone );
- //
- // Configure the zone type parameter
- //
- #ifdef PARAM_EDITING_ON
- EnumParameterClass *zone_type_param = new EnumParameterClass( (int*)&ZoneType );
- zone_type_param->Set_Name( "Zone Type" );
- for ( int index = 0; index < TYPE_COUNT; index++ ) {
- zone_type_param->Add_Value( ZONE_TYPE_NAMES[index], index );
- }
- GENERIC_EDITABLE_PARAM(ScriptZoneGameObjDef,zone_type_param);
- #endif
- }
- uint32 ScriptZoneGameObjDef::Get_Class_ID (void) const
- {
- return CLASSID_GAME_OBJECT_DEF_SCRIPT_ZONE;
- }
- PersistClass * ScriptZoneGameObjDef::Create( void ) const
- {
- ScriptZoneGameObj * obj = new ScriptZoneGameObj;
- obj->Init( *this );
- return obj;
- }
- enum {
- XXXCHUNKID_DEF_PARENT_OLD = 1111991132,
- CHUNKID_DEF_VARIABLES,
- CHUNKID_DEF_PARENT,
- MICROCHUNKID_DEF_IS_CTF_ZONE = 1,
- MICROCHUNKID_DEF_ZONE_COLOR,
- MICROCHUNKID_DEF_CHECK_STARS_ONLY,
- MICROCHUNKID_DEF_ZONE_TYPE,
- MICROCHUNKID_DEF_IS_ENVIRONMENT_ZONE,
- };
- bool ScriptZoneGameObjDef::Save( ChunkSaveClass & csave )
- {
- csave.Begin_Chunk( CHUNKID_DEF_PARENT );
- ScriptableGameObjDef::Save( csave );
- csave.End_Chunk();
- csave.Begin_Chunk( CHUNKID_DEF_VARIABLES );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_ZONE_COLOR, Color );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_CHECK_STARS_ONLY, CheckStarsOnly );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_ZONE_TYPE, ZoneType );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_IS_ENVIRONMENT_ZONE, IsEnvironmentZone );
- csave.End_Chunk();
- return true;
- }
- bool ScriptZoneGameObjDef::Load( ChunkLoadClass &cload )
- {
- while (cload.Open_Chunk()) {
- switch(cload.Cur_Chunk_ID()) {
- case CHUNKID_DEF_PARENT:
- ScriptableGameObjDef::Load( cload );
- break;
-
- case CHUNKID_DEF_VARIABLES:
- while (cload.Open_Micro_Chunk()) {
- switch(cload.Cur_Micro_Chunk_ID()) {
- READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_ZONE_COLOR, Color );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_CHECK_STARS_ONLY, CheckStarsOnly );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_ZONE_TYPE, ZoneType );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_IS_ENVIRONMENT_ZONE, IsEnvironmentZone );
- default:
- Debug_Say(( "Unrecognized ZoneDef Variable chunkID\n" ));
- break;
- }
- cload.Close_Micro_Chunk();
- }
- break;
- default:
- Debug_Say(( "Unrecognized ZoneDef chunkID\n" ));
- break;
- }
- cload.Close_Chunk();
- }
- return true;
- }
- const PersistFactoryClass & ScriptZoneGameObjDef::Get_Factory (void) const
- {
- return _ScriptZoneGameObjDefPersistFactory;
- }
- /*
- ** ScriptZoneGameObj
- */
- SimplePersistFactoryClass<ScriptZoneGameObj, CHUNKID_GAME_OBJECT_SCRIPT_ZONE> _ScriptZoneGameObjPersistFactory;
- ScriptZoneGameObj::ScriptZoneGameObj( void ) :
- PlayerType( PLAYERTYPE_NEUTRAL )
- {
- }
- ScriptZoneGameObj::~ScriptZoneGameObj( void )
- {
- GameObjReference * ref;
- while ( (ref = InsideList.Remove_Head() ) != NULL ) {
- *ref = NULL;
- delete ref;
- }
- }
- const PersistFactoryClass & ScriptZoneGameObj::Get_Factory (void) const
- {
- return _ScriptZoneGameObjPersistFactory;
- }
- /*
- **
- */
- void ScriptZoneGameObj::Init( void )
- {
- Init( Get_Definition() );
- }
- void ScriptZoneGameObj::Init( const ScriptZoneGameObjDef & definition )
- {
- ScriptableGameObj::Init( definition );
- }
- const ScriptZoneGameObjDef & ScriptZoneGameObj::Get_Definition( void ) const
- {
- return (const ScriptZoneGameObjDef &)BaseGameObj::Get_Definition();
- }
- /*
- ** ScriptZoneGameObj Save and Load
- */
- enum {
- CHUNKID_PARENT_OLD = 922991806,
- CHUNKID_VARIABLES,
- CHUNKID_INSIDE_LIST,
- CHUNKID_INSIDE_LIST_ENTRY,
- CHUNKID_PARENT,
- MICROCHUNKID_BOUNDING_BOX = 1,
- MICROCHUNKID_PLAYER_TYPE,
- };
- bool ScriptZoneGameObj::Save( ChunkSaveClass & csave )
- {
- csave.Begin_Chunk( CHUNKID_PARENT );
- ScriptableGameObj::Save( csave );
- csave.End_Chunk();
- csave.Begin_Chunk( CHUNKID_VARIABLES );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_BOUNDING_BOX, BoundingBox );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_PLAYER_TYPE, PlayerType );
- csave.End_Chunk();
- csave.Begin_Chunk( CHUNKID_INSIDE_LIST );
- SLNode<GameObjReference> *pobjrefnode;
- for ( pobjrefnode = InsideList.Head(); pobjrefnode; pobjrefnode = pobjrefnode->Next() ) {
- GameObjReference *ref = pobjrefnode->Data();
- if ( *ref != NULL ) {
- csave.Begin_Chunk( CHUNKID_INSIDE_LIST_ENTRY );
- ref->Save( csave );
- csave.End_Chunk();
- }
- }
- csave.End_Chunk();
- return true;
- }
- bool ScriptZoneGameObj::Load( ChunkLoadClass &cload )
- {
- while (cload.Open_Chunk()) {
- switch(cload.Cur_Chunk_ID()) {
- case CHUNKID_PARENT:
- ScriptableGameObj::Load( cload );
- break;
-
- case CHUNKID_VARIABLES:
- while (cload.Open_Micro_Chunk()) {
- switch(cload.Cur_Micro_Chunk_ID()) {
- READ_MICRO_CHUNK( cload, MICROCHUNKID_BOUNDING_BOX, BoundingBox );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_PLAYER_TYPE, PlayerType );
- default:
- Debug_Say(( "Unrecognized ScriptZoneGameObj Variable chunkID\n" ));
- break;
- }
- cload.Close_Micro_Chunk();
- }
- break;
-
- case CHUNKID_INSIDE_LIST:
- WWASSERT( InsideList.Get_Count()== 0 );
- while (cload.Open_Chunk()) {
- WWASSERT( cload.Cur_Chunk_ID() == CHUNKID_INSIDE_LIST_ENTRY );
- GameObjReference * ref = new GameObjReference;
- ref->Load( cload );
- InsideList.Add_Head( ref );
- cload.Close_Chunk();
- }
- break;
- default:
- Debug_Say(( "Unrecognized ScriptZoneGameObj chunkID\n" ));
- break;
- }
- cload.Close_Chunk();
- }
- // Legacy Fix
- switch( PlayerType ) {
- case 2: PlayerType = PLAYERTYPE_NEUTRAL; break; // Remap TEAM2
- case 3: PlayerType = PLAYERTYPE_NEUTRAL; break; // Remap TEAM3
- case 4: PlayerType = PLAYERTYPE_NOD; break; // Remap NOD
- case 5: PlayerType = PLAYERTYPE_GDI; break; // Remap GDI
- }
- return true;
- }
- /*
- **
- */
- void ScriptZoneGameObj::Think()
- {
- ScriptableGameObj::Think();
- if ( Get_Observers().Count == 0 && Get_Definition().ZoneType != TYPE_CTF ) {
- return;
- }
- WWPROFILE( "ScriptZone Think" );
- // check current objects for exiting
- SLNode<GameObjReference> *pobjrefnode;
- for ( pobjrefnode = InsideList.Head(); pobjrefnode; ) {
- SmartGameObj * obj = (SmartGameObj*)pobjrefnode->Data()->Get_Ptr();
-
- SLNode<GameObjReference> * next = pobjrefnode->Next();
- if ( obj == NULL ) {
- Debug_Say(( "Object died inside me\n" ));
- GameObjReference * ref = pobjrefnode->Data();
- InsideList.Remove( ref );
- *ref = NULL;
- delete ref;
- } else if ( !Inside_Me( obj ) ) {
- const GameObjObserverList & observer_list = Get_Observers();
- for( int index = 0; index < observer_list.Count(); index++ ) {
- observer_list[ index ]->Exited( this, (PhysicalGameObj*)obj );
- }
- GameObjReference * ref = pobjrefnode->Data();
- InsideList.Remove( ref );
- *ref = NULL;
- delete ref;
- }
- pobjrefnode = next;
- }
- // If only gathering stars...
- if (Get_Definition().CheckStarsOnly ) {
- WWPROFILE( "Star Enter" );
- // check all stars for entering
- SLNode<SoldierGameObj> *objnode;
- for ( objnode = GameObjManager::Get_Star_Game_Obj_List()->Head(); objnode; objnode = objnode->Next()) {
- SoldierGameObj * obj = objnode->Data();
- if ( obj && Inside_Me( obj ) && !In_List( obj ) ) {
- Entered( obj );
- }
- }
- } else {
- WWPROFILE( "All Enter" );
- // Collect the dynamic physics objects overlapping this zone
- NonRefPhysListClass objs_in_zone;
- PhysicsSceneClass::Get_Instance()->Collect_Objects( BoundingBox, false, true, &objs_in_zone );
- NonRefPhysListIterator it(&objs_in_zone);
- for (it.First(); !it.Is_Done(); it.Next()) {
- if ( it.Peek_Obj()->Get_Observer() != NULL ) {
- PhysicalGameObj * gameobj = ((CombatPhysObserverClass *)it.Peek_Obj()->Get_Observer())->As_PhysicalGameObj();
- if (gameobj != NULL) {
- SmartGameObj *obj = gameobj->As_SmartGameObj();
- if ( obj && Inside_Me( obj ) && !In_List( obj ) ) {
- Entered( obj );
- }
- }
- }
- }
- }
- }
- /*
- **
- */
- void ScriptZoneGameObj::Entered( SmartGameObj * obj )
- {
- const GameObjObserverList & observer_list = Get_Observers();
- for( int index = 0; index < observer_list.Count(); index++ ) {
- observer_list[ index ]->Entered( this, obj );
- }
- // Create a new reference and add it to our list
- GameObjReference * ref = new GameObjReference;
- *ref = obj;
- InsideList.Add_Head( ref );
- }
- /*
- **
- */
- bool ScriptZoneGameObj::In_List( SmartGameObj * obj )
- {
- WWASSERT( obj != NULL );
- SLNode<GameObjReference> *pobjrefnode;
- for ( pobjrefnode = InsideList.Head(); pobjrefnode; pobjrefnode = pobjrefnode->Next() ) {
- if ( obj == *pobjrefnode->Data() ) {
- return true;
- }
- }
- return false;
- }
- /*
- **
- */
- bool ScriptZoneGameObj::Inside_Me( const SmartGameObj * obj )
- {
- if ( obj && obj->Peek_Physical_Object() ) { // hack to hide zones
- Vector3 pos;
- obj->Get_Position(&pos);
- return (CollisionMath::Overlap_Test(BoundingBox,pos) == CollisionMath::INSIDE);
- }
- return false;
- }
- /*
- **
- */
- ScriptZoneGameObj *ScriptZoneGameObj::Find_Closest_Zone (const Vector3 &pos, ZoneConstants::ZoneType type)
- {
- SList<BaseGameObj> *list = GameObjManager::Get_Game_Obj_List ();
- float closest_dist2 = 999999.0F;
- ScriptZoneGameObj *closest_zone = NULL;
- //
- // Loop over all the objects looking for zones
- //
- SLNode<BaseGameObj> *node = NULL;
- for (node = list->Head (); node != NULL; node = node->Next ()) {
- BaseGameObj *game_obj = node->Data ();
-
- //
- // Is this a building on our team?
- //
- if (game_obj != NULL && game_obj->As_ScriptableGameObj () != NULL) {
- ScriptZoneGameObj *zone = game_obj->As_ScriptableGameObj ()->As_ScriptZoneGameObj ();
- if (zone != NULL) {
-
- //
- // Is the type of zone we are looking for?
- //
- if (zone->Get_Definition ().Get_Type () == type) {
- float dist2 = (pos - zone->Get_Bounding_Box ().Center).Length2 ();
-
- //
- // Is this the closest zone we've found yet?
- //
- if (dist2 < closest_dist2) {
- closest_dist2 = dist2;
- closest_zone = zone;
- }
- }
- }
- }
- }
-
- return closest_zone;
- }
- /*
- **
- */
- int ScriptZoneGameObj::Count_Team_Members_Inside( int player_type )
- {
- SLNode<GameObjReference> *pobjrefnode;
- int count = 0;
- for ( pobjrefnode = InsideList.Head(); pobjrefnode; pobjrefnode = pobjrefnode->Next() ) {
- SmartGameObj * obj = (SmartGameObj*)pobjrefnode->Data()->Get_Ptr();
- if ( obj->Get_Player_Type() == player_type ) {
- count++;
- }
- }
- return count;
- }
- /*
- **
- */
- /*
- bool ScriptZoneGameObj::Exists_On_Client( void ) const
- {
- bool retval = false;
-
- //
- // Allow the C&C mode zone's to exist on the client
- //
- switch (Get_Definition ().Get_Type ())
- {
- case TYPE_VEHICLE_CONSTRUCTION:
- case TYPE_VEHICLE_REPAIR:
- case TYPE_TIBERIUM_FIELD:
- case TYPE_BEACON:
- retval = false;
- break;
- }
- return retval;
- }
- */
- /*
- if (Get_Definition().ZoneType == TYPE_CTF && obj->As_SoldierGameObj() != NULL) {
- CombatManager::Soldier_Enters_Pedestal(obj->As_SoldierGameObj(), Get_Player_Type());
- }
- */
|