| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635 |
- /*
- ** 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/building.cpp $*
- * *
- * $Author:: Greg_h $*
- * *
- * $Modtime:: 6/20/02 3:09p $*
- * *
- * $Revision:: 68 $*
- * *
- *---------------------------------------------------------------------------------------------*
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "building.h"
- #include "simpledefinitionfactory.h"
- #include "persistfactory.h"
- #include "combatchunkid.h"
- #include "debug.h"
- #include "wwphysids.h"
- #include "meshmdl.h"
- #include "gameobjmanager.h"
- #include "wwaudio.h"
- #include "audiblesound.h"
- #include "sound3d.h"
- #include "translateobj.h"
- #include "translatedb.h"
- #include "combat.h"
- #include "messagewindow.h"
- #include "buildingmonitor.h"
- #include "basecontroller.h"
- #include "bitpackids.h"
- #include "soldier.h"
- #include "playerdata.h"
- #include "encyclopediamgr.h"
- #include "apppackettypes.h"
- #include "wwprofile.h"
- /////////////////////////////////////////////////////////////////////////////
- // Namespaces
- /////////////////////////////////////////////////////////////////////////////
- using namespace BuildingConstants;
- /////////////////////////////////////////////////////////////////////////////
- //
- // Constants
- //
- /////////////////////////////////////////////////////////////////////////////
- static const char * BULDING_TYPE_NAMES[TYPE_COUNT + 1] =
- {
- "<None>",
- "Power Plant",
- "Soldier Factory",
- "Vehicle Factory",
- "Refinery",
- "Com Center",
- "Repair Bay",
- "Shrine",
- "Helipad",
- "Conyard",
- "Base Defense",
- };
- static const char * BULDING_TEAM_NAMES[BASE_COUNT] =
- {
- "GDI",
- "NOD"
- };
- //
- // Class statics
- //
- bool BuildingGameObj::CanRepairBuildings = true;
- /************************************************************************************************
- **
- ** BuildingGameObjDef
- **
- ************************************************************************************************/
- SimplePersistFactoryClass<BuildingGameObjDef, CHUNKID_GAME_OBJECT_DEF_BUILDING> _BuildingGameObjDefPersistFactory;
- DECLARE_DEFINITION_FACTORY(BuildingGameObjDef, CLASSID_GAME_OBJECT_DEF_BUILDING, "<Generic Building>") _BuildingGameObjDefDefFactory;
- /////////////////////////////////////////////////////////////////////////////
- //
- // BuildingGameObjDef
- //
- /////////////////////////////////////////////////////////////////////////////
- BuildingGameObjDef::BuildingGameObjDef (void) :
- MCTSkin(0),
- Type(TYPE_NONE),
- GDIDamageReportID(0),
- NodDamageReportID(0),
- GDIDestroyReportID(0),
- NodDestroyReportID(0)
- {
- EDITABLE_PARAM( BuildingGameObjDef, ParameterClass::TYPE_STRING, MeshPrefix );
- #ifdef PARAM_EDITING_ON
- int skin_type_counter;
- EnumParameterClass * mct_skin_param = new EnumParameterClass( (int*)&MCTSkin );
- mct_skin_param->Set_Name("MCTSkin");
- for ( skin_type_counter = 0; skin_type_counter < ArmorWarheadManager::Get_Num_Armor_Types(); skin_type_counter++ ) {
- mct_skin_param->Add_Value(ArmorWarheadManager::Get_Armor_Name(skin_type_counter), skin_type_counter);
- }
- GENERIC_EDITABLE_PARAM(BuildingGameObjDef,mct_skin_param);
- #endif
- //
- // Configure the building type parameter
- //
- #ifdef PARAM_EDITING_ON
- EnumParameterClass *building_type_param = new EnumParameterClass( (int*)&Type );
- building_type_param->Set_Name("Building Type");
- for ( int index = TYPE_NONE; index < TYPE_COUNT; index++ ) {
- building_type_param->Add_Value(BULDING_TYPE_NAMES[index+1], index);
- }
- GENERIC_EDITABLE_PARAM(BuildingGameObjDef,building_type_param);
- #endif
- EDITABLE_PARAM(BuildingGameObjDef, ParameterClass::TYPE_STRINGSDB_ID, GDIDamageReportID);
- EDITABLE_PARAM(BuildingGameObjDef, ParameterClass::TYPE_STRINGSDB_ID, NodDamageReportID);
- EDITABLE_PARAM(BuildingGameObjDef, ParameterClass::TYPE_STRINGSDB_ID, GDIDestroyReportID);
- EDITABLE_PARAM(BuildingGameObjDef, ParameterClass::TYPE_STRINGSDB_ID, NodDestroyReportID);
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // Get_Class_ID
- //
- /////////////////////////////////////////////////////////////////////////////
- uint32
- BuildingGameObjDef::Get_Class_ID (void) const
- {
- return CLASSID_GAME_OBJECT_DEF_BUILDING;
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // Create
- //
- /////////////////////////////////////////////////////////////////////////////
- PersistClass *
- BuildingGameObjDef::Create (void) const
- {
- BuildingGameObj * obj = new BuildingGameObj;
- obj->Init( *this );
- return obj;
- }
- /////////////////////////////////////////////////////////////////////////////
- // Save/Load constants
- /////////////////////////////////////////////////////////////////////////////
- enum {
- CHUNKID_DEF_PARENT = 207011030,
- CHUNKID_DEF_VARIABLES,
- MICROCHUNKID_DEF_MESHPREFIX = 1,
- MICROCHUNKID_DEF_MCTSKIN,
- MICROCHUNKID_DEF_BUILDING_TYPE,
- LEGACY_MICROCHUNKID_DEF_BUILDING_TEAM,
- MICROCHUNKID_DEF_GDI_DAMAGE_REPORT_ID,
- MICROCHUNKID_DEF_NOD_DAMAGE_REPORT_ID,
- MICROCHUNKID_DEF_GDI_DESTROY_REPORT_ID,
- MICROCHUNKID_DEF_NOD_DESTROY_REPORT_ID,
- };
- /////////////////////////////////////////////////////////////////////////////
- //
- // Save
- //
- /////////////////////////////////////////////////////////////////////////////
- bool
- BuildingGameObjDef::Save (ChunkSaveClass &csave)
- {
- csave.Begin_Chunk( CHUNKID_DEF_PARENT );
- DamageableGameObjDef::Save( csave );
- csave.End_Chunk();
- csave.Begin_Chunk( CHUNKID_DEF_VARIABLES );
- WRITE_MICRO_CHUNK_WWSTRING( csave, MICROCHUNKID_DEF_MESHPREFIX, MeshPrefix );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_MCTSKIN, MCTSkin );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_BUILDING_TYPE, Type );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_GDI_DAMAGE_REPORT_ID, GDIDamageReportID );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_NOD_DAMAGE_REPORT_ID, NodDamageReportID );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_GDI_DESTROY_REPORT_ID, GDIDestroyReportID );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_NOD_DESTROY_REPORT_ID, NodDestroyReportID );
- csave.End_Chunk();
- return true;
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // Load
- //
- /////////////////////////////////////////////////////////////////////////////
- bool
- BuildingGameObjDef::Load (ChunkLoadClass &cload)
- {
- int legacy_team = -1;
- while (cload.Open_Chunk()) {
- switch(cload.Cur_Chunk_ID()) {
- case CHUNKID_DEF_PARENT:
- DamageableGameObjDef::Load( cload );
- break;
-
- case CHUNKID_DEF_VARIABLES:
- while (cload.Open_Micro_Chunk()) {
- switch(cload.Cur_Micro_Chunk_ID()) {
- READ_MICRO_CHUNK_WWSTRING( cload, MICROCHUNKID_DEF_MESHPREFIX, MeshPrefix );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_MCTSKIN, MCTSkin );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_BUILDING_TYPE, Type );
- READ_MICRO_CHUNK( cload, LEGACY_MICROCHUNKID_DEF_BUILDING_TEAM, legacy_team );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_GDI_DAMAGE_REPORT_ID, GDIDamageReportID );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_NOD_DAMAGE_REPORT_ID, NodDamageReportID );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_GDI_DESTROY_REPORT_ID, GDIDestroyReportID );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_NOD_DESTROY_REPORT_ID, NodDestroyReportID );
- default:
- Debug_Say(("Unhandled Micro Chunk:%d File:%s Line:%d\r\n",cload.Cur_Micro_Chunk_ID(),__FILE__,__LINE__));
- break;
- }
- cload.Close_Micro_Chunk();
- }
- break;
- default:
- Debug_Say(("Unhandled Chunk:%d File:%s Line:%d\r\n",cload.Cur_Chunk_ID(),__FILE__,__LINE__));
- break;
- }
- cload.Close_Chunk();
- }
- if ( legacy_team != -1 ) {
- DefaultPlayerType = PLAYERTYPE_GDI;
- if ( legacy_team == BuildingConstants::LEGACY_TEAM_NOD ) {
- DefaultPlayerType = PLAYERTYPE_NOD;
- }
- }
- return true;
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // Get_Factory
- //
- /////////////////////////////////////////////////////////////////////////////
- const PersistFactoryClass &
- BuildingGameObjDef::Get_Factory (void) const
- {
- return _BuildingGameObjDefPersistFactory;
- }
- int BuildingGameObjDef::Get_Damage_Report(int team) const
- {
- if (PLAYERTYPE_GDI == team) {
- return GDIDamageReportID;
- } else if (PLAYERTYPE_NOD == team) {
- return NodDamageReportID;
- }
- return 0;
- }
- int BuildingGameObjDef::Get_Destroy_Report(int team) const
- {
- if (PLAYERTYPE_GDI == team) {
- return GDIDestroyReportID;
- } else if (PLAYERTYPE_NOD == team) {
- return NodDestroyReportID;
- }
- return 0;
- }
- /************************************************************************************************
- **
- ** BuildingGameObj
- **
- ************************************************************************************************/
- SimplePersistFactoryClass<BuildingGameObj, CHUNKID_GAME_OBJECT_BUILDING> _BuildingGameObjPersistFactory;
- /////////////////////////////////////////////////////////////////////////////
- //
- // Get_Factory
- //
- /////////////////////////////////////////////////////////////////////////////
- const PersistFactoryClass &
- BuildingGameObj::Get_Factory (void) const
- {
- return _BuildingGameObjPersistFactory;
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // BuildingGameObj
- //
- /////////////////////////////////////////////////////////////////////////////
- BuildingGameObj::BuildingGameObj (void) :
- Position (0, 0, 0),
- IsPowerOn (true),
- CurrentState (-1),
- AnnouncementSphere (Vector3 (0, 0, 0), 1.0F),
- CollectionSphere (Vector3 (0, 0, 0), 50.0F),
- CurrentAnnouncement (NULL),
- IsDestroyed (false),
- BuildingMonitor (NULL),
- BaseController (NULL)
- {
- GameObjManager::Add_Building (this);
- Update_State ();
- Set_App_Packet_Type(APPPACKETTYPE_BUILDING);
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // ~BuildingGameObj
- //
- /////////////////////////////////////////////////////////////////////////////
- BuildingGameObj::~BuildingGameObj (void)
- {
- Stop_Current_Announcement();
- //
- // Free the building monitor (if we have one)
- //
- if (BuildingMonitor != NULL) {
- Remove_Observer (BuildingMonitor);
- delete BuildingMonitor;
- BuildingMonitor = NULL;
- }
- GameObjManager::Remove_Building( this );
- Reset_Components();
- return ;
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // Init
- //
- /////////////////////////////////////////////////////////////////////////////
- void BuildingGameObj::Init( void )
- {
- Init( Get_Definition() );
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // Init
- //
- /////////////////////////////////////////////////////////////////////////////
- void
- BuildingGameObj::Init (const BuildingGameObjDef &definition)
- {
- DamageableGameObj::Init (definition);
- return ;
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // Get_Definition
- //
- /////////////////////////////////////////////////////////////////////////////
- const BuildingGameObjDef &
- BuildingGameObj::Get_Definition (void) const
- {
- return (const BuildingGameObjDef &)BaseGameObj::Get_Definition();
- }
- /////////////////////////////////////////////////////////////////////////////
- // Save/Load constants
- /////////////////////////////////////////////////////////////////////////////
- enum {
- CHUNKID_PARENT = 207011120,
- CHUNKID_VARIABLES,
- MICROCHUNKID_POSITION = 1,
- MICROCHUNKID_ISPOWERON,
- MICROCHUNKID_COLLECTION_SPHERE
- };
- /////////////////////////////////////////////////////////////////////////////
- //
- // Save
- //
- /////////////////////////////////////////////////////////////////////////////
- bool
- BuildingGameObj::Save (ChunkSaveClass &csave)
- {
- csave.Begin_Chunk (CHUNKID_PARENT);
- DamageableGameObj::Save (csave);
- csave.End_Chunk ();
- csave.Begin_Chunk (CHUNKID_VARIABLES);
- WRITE_MICRO_CHUNK (csave, MICROCHUNKID_POSITION, Position);
- WRITE_MICRO_CHUNK (csave, MICROCHUNKID_ISPOWERON, IsPowerOn);
- WRITE_MICRO_CHUNK (csave, MICROCHUNKID_COLLECTION_SPHERE, CollectionSphere);
- csave.End_Chunk ();
- return true;
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // Load
- //
- /////////////////////////////////////////////////////////////////////////////
- bool
- BuildingGameObj::Load (ChunkLoadClass &cload)
- {
- while (cload.Open_Chunk ()) {
- switch (cload.Cur_Chunk_ID ()) {
- case CHUNKID_PARENT:
- DamageableGameObj::Load (cload);
- break;
-
- case CHUNKID_VARIABLES:
- while (cload.Open_Micro_Chunk ()) {
- switch (cload.Cur_Micro_Chunk_ID ()) {
-
- READ_MICRO_CHUNK (cload, MICROCHUNKID_POSITION, Position);
- READ_MICRO_CHUNK (cload, MICROCHUNKID_ISPOWERON, IsPowerOn);
- READ_MICRO_CHUNK (cload, MICROCHUNKID_COLLECTION_SPHERE, CollectionSphere);
- default:
- Debug_Say(("Unhandled Micro Chunk:%d File:%s Line:%d\r\n",cload.Cur_Micro_Chunk_ID(),__FILE__,__LINE__));
- break;
- }
- cload.Close_Micro_Chunk();
- }
- break;
- default:
- Debug_Say(("Unhandled Chunk:%d File:%s Line:%d\r\n",cload.Cur_Chunk_ID(),__FILE__,__LINE__));
- break;
- }
- cload.Close_Chunk ();
- }
- // Fix player_type (legacy)
- Set_Player_Type( Get_Definition().DefaultPlayerType );
- //
- // Hack to get legacy code to work...
- //
- if (CollectionSphere.Center.X == 0 && CollectionSphere.Center.Y == 0 && CollectionSphere.Center.Z == 0) {
- CollectionSphere.Center = Position;
- }
- return true;
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // Enable_Power
- //
- /////////////////////////////////////////////////////////////////////////////
- void
- BuildingGameObj::Enable_Power (bool onoff)
- {
- if ( IsPowerOn != onoff ) {
- // Notify the observers
- const GameObjObserverList & observer_list = Get_Observers();
- for( int index = 0; index < observer_list.Count(); index++ ) {
- observer_list[ index ]->Custom( this, CUSTOM_EVENT_BUILDING_POWER_CHANGED, onoff, NULL );
- }
- }
- IsPowerOn = onoff;
- Update_State ();
- //
- // Mark the object as dirty so it's state will be mirrored on the client
- //
- if (CombatManager::I_Am_Server ()) {
- Set_Object_Dirty_Bit (NetworkObjectClass::BIT_RARE, true);
- }
- return ;
- }
- void BuildingGameObj::Apply_Damage( const OffenseObjectClass & damager, float scale, int alternate_skin )
- {
- /*
- ** If we're already completely damaged, just return
- */
- if ( DefenseObject.Get_Health() <= 0 ) {
- return;
- }
- // if gameplay not permitted, skip
- if ( !CombatManager::Is_Gameplay_Permitted() ) {
- return;
- }
- //
- // TSS102501
- //
- if ( !CanRepairBuildings && DefenseObject.Is_Repair(damager) ) {
- return;
- }
- float old_health = Get_Defense_Object()->Get_Health();
- DamageableGameObj::Apply_Damage( damager, scale, alternate_skin );
- if ( old_health != Get_Defense_Object()->Get_Health() ) {
- Set_Object_Dirty_Bit( NetworkObjectClass::BIT_OCCASIONAL, true );
- }
- // WWDEBUG_SAY(("Applied damage to a building (prefix=%s) new health = %f\r\n",Get_Definition().MeshPrefix,DefenseObject.Get_Health()));
- // Stats
- if ( DefenseObject.Get_Health() <= 0 ) {
- if ( damager.Get_Owner() != NULL &&
- damager.Get_Owner()->As_SoldierGameObj() != NULL &&
- damager.Get_Owner()->As_SoldierGameObj()->Get_Player_Data() != NULL ) {
- damager.Get_Owner()->As_SoldierGameObj()->Get_Player_Data()->Stats_Add_Building_Destroyed();
- }
- //
- // Reveal this building to the encyclopedia
- //
- EncyclopediaMgrClass::Reveal_Object (this);
- }
- /*
- ** If our health status changed states, switch all of our aggregates
- */
- Update_State();
- }
- void BuildingGameObj::Apply_Damage_Building(const OffenseObjectClass & offense, StaticPhysClass * component )
- {
- /*
- ** If the MCT is being damaged, use an alternate skin type
- */
- ArmorType skin = DefenseObject.Get_Skin();
- if (component->Get_Factory().Chunk_ID() == PHYSICS_CHUNKID_BUILDINGAGGREGATE) {
- if (((BuildingAggregateClass *)component)->Is_MCT()) {
- skin = Get_Definition().MCTSkin;
- }
- }
- /*
- ** Apply the damage
- */
- Apply_Damage( offense, 1.0, skin );
- }
- void BuildingGameObj::Apply_Damage_Building( const OffenseObjectClass & offense, bool mct_damage )
- {
- /*
- ** If the MCT is being damaged, use an alternate skin type
- */
- ArmorType skin = DefenseObject.Get_Skin();
- if ( mct_damage ) {
- skin = Get_Definition().MCTSkin;
- }
- /*
- ** Apply the damage
- */
- Apply_Damage( offense, 1.0, skin );
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // Is_Interior_Mesh_Name
- //
- /////////////////////////////////////////////////////////////////////////////
- bool
- BuildingGameObj::Is_Interior_Mesh_Name (const char * name)
- {
- // (gth) Renegade day 120 patch, accept tiles as building "parts"
- #if 0
- char * meshname = strchr(name,'.');
- if (meshname != NULL) {
- return strchr(meshname,'#') != NULL;
- } else {
- return false;
- }
- #else
- return strchr(name,'#') != NULL;
- #endif
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // Is_Exterior_Mesh_Name
- //
- /////////////////////////////////////////////////////////////////////////////
- bool
- BuildingGameObj::Is_Exterior_Mesh_Name (const char * name)
- {
- // (gth) Renegade day 120 patch, accept tiles as building "parts"
- #if 0
- char * meshname = strchr(name,'.');
- if (meshname != NULL) {
- return strchr(meshname,'^') != NULL;
- } else {
- return false;
- }
- #else
- return strchr(name,'^') != NULL;
- #endif
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // Name_Prefix_Matches_This_Building
- //
- /////////////////////////////////////////////////////////////////////////////
- bool
- BuildingGameObj::Name_Prefix_Matches_This_Building (const char * name)
- {
- bool retval = false;
- if (name != NULL) {
- StringClass prefex(Get_Definition().MeshPrefix,true);
- char * meshname = strchr(name,'.');
- if (meshname != NULL) {
- meshname++;
- retval = (strnicmp(meshname,prefex,strlen(prefex)) == 0);
- } else {
- retval = (strnicmp(name,prefex,strlen(prefex)) == 0);
- }
- }
- return retval;
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // Set_Normalized_Health
- //
- /////////////////////////////////////////////////////////////////////////////
- void
- BuildingGameObj::Set_Normalized_Health (float health)
- {
- //
- // Note: We convert from normalized to absolute values
- //
- DefenseObject.Set_Health (health * DefenseObject.Get_Health_Max ());
- Update_State ();
- WWDEBUG_SAY(("Building State Set:\r\n"));
- WWDEBUG_SAY((" prefix = %s mesh count = %d aggregate count = %d light count = %d\r\n",
- Get_Definition().MeshPrefix,
- InteriorMeshes.Count() + ExteriorMeshes.Count(),
- Aggregates.Count(),
- PowerOnLights.Count() + PowerOffLights.Count()));
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // Update_State
- //
- /////////////////////////////////////////////////////////////////////////////
- void
- BuildingGameObj::Update_State (bool force_update)
- {
- /*
- ** Evaluate our current state
- */
- float health_percentage = 100.0f * DefenseObject.Get_Health()/DefenseObject.Get_Health_Max();
- int health_state = BuildingStateClass::Percentage_To_Health_State(health_percentage);
- int new_state = BuildingStateClass::Compose_State(health_state,IsPowerOn);
-
- /*
- ** If the state has changed, inform all of our components
- */
- if ((new_state != CurrentState) || (force_update == true)) {
- int old_health_state = BuildingStateClass::Get_Health_State( CurrentState );
- if (health_state != old_health_state) {
- int event = CUSTOM_EVENT_BUILDING_DAMAGED;
- if (health_state < old_health_state) {
- event = CUSTOM_EVENT_BUILDING_REPAIRED;
- }
- const GameObjObserverList & observer_list = Get_Observers();
- for( int index = 0; index < observer_list.Count(); index++ ) {
- observer_list[ index ]->Custom( this, event, health_percentage, NULL );
- }
- }
- CurrentState = new_state;
- //
- // Mark the object as dirty so it's state will be mirrored on the client
- //
- if (CombatManager::I_Am_Server ()) {
- Set_Object_Dirty_Bit (NetworkObjectClass::BIT_RARE, true);
- }
- /*
- ** Aggregates: inform all aggregates of the new state
- */
- RefMultiListIterator<BuildingAggregateClass> aggregate_iterator(&Aggregates);
- for (aggregate_iterator.First(); !aggregate_iterator.Is_Done(); aggregate_iterator.Next()) {
- aggregate_iterator.Peek_Obj()->Set_Current_State(CurrentState,force_update);
- }
- /*
- ** Interior meshes: switch to alternate materials if either the power is out or
- ** the building is at zero health
- */
- Enable_Alternate_Materials(InteriorMeshes,((health_state == BuildingStateClass::HEALTH_0) || (!IsPowerOn)));
-
- /*
- ** Exterior meshes: use alternate materials if the building is destroyed
- */
- Enable_Alternate_Materials(ExteriorMeshes,(health_state == BuildingStateClass::HEALTH_0));
- /*
- ** Lights: enable the lights which match the current power status, invalidate all
- ** lighting caches within the bounds of the lights that changed.
- */
- bool disable = ((IsPowerOn == false) || (health_state == BuildingStateClass::HEALTH_0));
- disable &= (!PowerOffLights.Is_Empty()); // for lights, power is not disabled if there are not power-off lights
- AABoxClass light_bounds(Position,Vector3(1,1,1));
-
- RefMultiListIterator<LightPhysClass> light_iterator(&PowerOnLights);
- for (light_iterator.First(); !light_iterator.Is_Done(); light_iterator.Next()) {
- light_iterator.Peek_Obj()->Set_Disabled(disable);
- light_bounds.Add_Box(light_iterator.Peek_Obj()->Peek_Model()->Get_Bounding_Box());
- }
- disable = !disable;
- for (light_iterator.First(&PowerOffLights); !light_iterator.Is_Done(); light_iterator.Next()) {
- light_iterator.Peek_Obj()->Set_Disabled(disable);
- light_bounds.Add_Box(light_iterator.Peek_Obj()->Peek_Model()->Get_Bounding_Box());
- }
- PhysicsSceneClass::Get_Instance()->Invalidate_Lighting_Caches(light_bounds);
- }
- return ;
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // Play_Announcement
- //
- /////////////////////////////////////////////////////////////////////////////
- void
- BuildingGameObj::Play_Announcement(int text_id, bool broadcast)
- {
- Stop_Current_Announcement();
- // Lookup the translation object from the strings database
- TDBObjClass* translate_obj = TranslateDBClass::Find_Object(text_id);
- if (translate_obj) {
- const WCHAR* string = translate_obj->Get_String();
- int sound_def_id = (int)translate_obj->Get_Sound_ID();
- float duration = 2.0F;
- // Play the sound effect
- bool display_text = true;
- if (sound_def_id > 0) {
-
- // Create the sound object
- CurrentAnnouncement = WWAudioClass::Get_Instance()->Create_Sound(sound_def_id);
- if (CurrentAnnouncement) {
- duration = (CurrentAnnouncement->Get_Duration() / 1000.0F);
- if (broadcast == false) {
- // Tweak the radii of the sound so it can be heard throughout the building
- CurrentAnnouncement->Set_DropOff_Radius(AnnouncementSphere.Radius);
- Sound3DClass* sound3D = CurrentAnnouncement->As_Sound3DClass();
- if (sound3D) {
- sound3D->Set_Max_Vol_Radius(AnnouncementSphere.Radius * 0.9F);
- }
- // Play the sound effect at the annoucement position for the building
- CurrentAnnouncement->Set_Transform(Matrix3D(AnnouncementSphere.Center));
- display_text = (CurrentAnnouncement->Is_Sound_Culled() == false);
- }
- CurrentAnnouncement->Add_To_Scene();
- }
- }
- // Display the text on the screen
- if (display_text && string) {
- float message_duration = max(duration, 5.0F);
- CombatManager::Get_Message_Window()->Add_Message(string, Vector3(1, 1, 1), NULL, message_duration);
- }
- }
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // Stop_Current_Announcement
- //
- /////////////////////////////////////////////////////////////////////////////
- void
- BuildingGameObj::Stop_Current_Announcement (void)
- {
- if (CurrentAnnouncement) {
-
- // Stop the sound object and remove it from the world
- CurrentAnnouncement->Stop();
- CurrentAnnouncement->Remove_From_Scene();
- CurrentAnnouncement->Release_Ref();
- CurrentAnnouncement = NULL;
- }
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // Initialize_Building
- //
- /////////////////////////////////////////////////////////////////////////////
- void
- BuildingGameObj::Initialize_Building (void)
- {
- RefMultiListIterator<StaticPhysClass> mesh_iterator (&InteriorMeshes);
- //
- // Generate a bounding box that contains all the building interior meshes
- //
- AABoxClass bounding_box (Position, Vector3 (1, 1, 1));
- for (mesh_iterator.First (); !mesh_iterator.Is_Done (); mesh_iterator.Next ()) {
- bounding_box.Add_Box (mesh_iterator.Peek_Obj ()->Peek_Model ()->Get_Bounding_Box());
- }
- //
- // Turn the bounding box into a sphere that we can use to play building
- // announcement sound effects in
- //
- AnnouncementSphere.Center = bounding_box.Center;
- AnnouncementSphere.Radius = max (bounding_box.Extent.X, bounding_box.Extent.Y);
- AnnouncementSphere.Radius = max (AnnouncementSphere.Radius, bounding_box.Extent.Z);
-
- //
- // If we can find a base for our team, then add ourselves to it.
- //
- BaseControllerClass *base = BaseControllerClass::Find_Base ( Get_Player_Type() );
- if (base != NULL) {
- base->Add_Building (this);
- }
- return ;
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // Reset_Components
- //
- /////////////////////////////////////////////////////////////////////////////
- void
- BuildingGameObj::Reset_Components (void)
- {
- RefMultiListIterator<StaticPhysClass> mesh_iterator(&InteriorMeshes);
-
- for (mesh_iterator.First(); !mesh_iterator.Is_Done(); mesh_iterator.Next()) {
- WWASSERT(mesh_iterator.Peek_Obj()->Get_Observer() == this);
- mesh_iterator.Peek_Obj()->Set_Observer(NULL);
- }
- for (mesh_iterator.First(&ExteriorMeshes); !mesh_iterator.Is_Done(); mesh_iterator.Next()) {
- WWASSERT(mesh_iterator.Peek_Obj()->Get_Observer() == this);
- mesh_iterator.Peek_Obj()->Set_Observer(NULL);
- }
- RefMultiListIterator<BuildingAggregateClass> agg_iterator(&Aggregates);
- for (agg_iterator.First(); !agg_iterator.Is_Done(); agg_iterator.Next()) {
- WWASSERT(agg_iterator.Peek_Obj()->Get_Observer() == this);
- agg_iterator.Peek_Obj()->Set_Observer(NULL);
- }
-
- InteriorMeshes.Reset_List();
- ExteriorMeshes.Reset_List();
- PowerOnLights.Reset_List();
- PowerOffLights.Reset_List();
- Aggregates.Reset_List();
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // Add_Mesh
- //
- /////////////////////////////////////////////////////////////////////////////
- void
- BuildingGameObj::Add_Mesh (StaticPhysClass * terrain)
- {
- WWASSERT(terrain != NULL);
- if (Is_Interior_Mesh_Name(terrain->Peek_Model()->Get_Name())) {
- WWASSERT(terrain->Get_Observer() == NULL);
- InteriorMeshes.Add(terrain);
- terrain->Set_Observer(this);
- } else if (Is_Exterior_Mesh_Name(terrain->Peek_Model()->Get_Name())) {
- WWASSERT(terrain->Get_Observer() == NULL);
- ExteriorMeshes.Add(terrain);
- terrain->Set_Observer(this);
- }
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // Remove_Mesh
- //
- /////////////////////////////////////////////////////////////////////////////
- void
- BuildingGameObj::Remove_Mesh (StaticPhysClass * terrain)
- {
- WWASSERT(terrain != NULL);
- if (Is_Interior_Mesh_Name(terrain->Peek_Model()->Get_Name())) {
- WWASSERT(terrain->Get_Observer() == this);
- terrain->Set_Observer(NULL);
- InteriorMeshes.Remove(terrain);
- } else if (Is_Exterior_Mesh_Name(terrain->Peek_Model()->Get_Name())) {
- WWASSERT(terrain->Get_Observer() == this);
- terrain->Set_Observer(NULL);
- ExteriorMeshes.Remove(terrain);
- }
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // Add_Aggregate
- //
- /////////////////////////////////////////////////////////////////////////////
- void
- BuildingGameObj::Add_Aggregate (BuildingAggregateClass * aggregate)
- {
- WWASSERT(aggregate != NULL);
- Aggregates.Add(aggregate);
- WWASSERT(aggregate->Get_Observer() == NULL);
- aggregate->Set_Observer(this);
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // Remove_Aggregate
- //
- /////////////////////////////////////////////////////////////////////////////
- void
- BuildingGameObj::Remove_Aggregate (BuildingAggregateClass * aggregate)
- {
- WWASSERT(aggregate != NULL);
- WWASSERT(aggregate->Get_Observer() == this);
- aggregate->Set_Observer(NULL);
- Aggregates.Remove(aggregate);
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // Add_Light
- //
- /////////////////////////////////////////////////////////////////////////////
- void
- BuildingGameObj::Add_Light (LightPhysClass * light)
- {
- WWASSERT(light != NULL);
- if (light->Get_Group_ID() == 0) {
- PowerOnLights.Add(light);
- } else {
- PowerOffLights.Add(light);
- }
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // Enable_Alternate_Materials
- //
- /////////////////////////////////////////////////////////////////////////////
- void
- BuildingGameObj::Enable_Alternate_Materials (RefMultiListClass<StaticPhysClass> & models, bool onoff)
- {
- RefMultiListIterator<StaticPhysClass> it(&models);
- for (it.First(); !it.Is_Done(); it.Next()) {
- Enable_Alternate_Materials(it.Peek_Obj()->Peek_Model(),onoff);
- }
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // Enable_Alternate_Materials
- //
- /////////////////////////////////////////////////////////////////////////////
- void
- BuildingGameObj::Enable_Alternate_Materials (RenderObjClass * model,bool onoff)
- {
- if (model == NULL) return;
- for (int i=0; i<model->Get_Num_Sub_Objects(); i++) {
- RenderObjClass * subobj = model->Get_Sub_Object(i);
- Enable_Alternate_Materials(subobj,onoff);
- REF_PTR_RELEASE(subobj);
- }
- if (model->Class_ID() == RenderObjClass::CLASSID_MESH) {
- MeshModelClass * mesh_model = ((MeshClass *)model)->Get_Model();
- mesh_model->Enable_Alternate_Material_Description(onoff);
- REF_PTR_RELEASE(mesh_model);
- }
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // CnC_Initialize
- //
- /////////////////////////////////////////////////////////////////////////////
- void
- BuildingGameObj::CnC_Initialize (BaseControllerClass *base)
- {
- BaseController = base;
- //
- // Create an observer that we can use to monitor the building's health
- //
- BuildingMonitor = new BuildingMonitorClass;
- BuildingMonitor->Set_Building (this);
- Add_Observer (BuildingMonitor);
- return ;
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // On_Damaged
- //
- /////////////////////////////////////////////////////////////////////////////
- void
- BuildingGameObj::On_Damaged (void)
- {
- //
- // Notify the controller that the building has been damaged
- //
- if (BaseController != NULL) {
- BaseController->On_Building_Damaged (this);
- }
- return ;
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // On_Destroyed
- //
- /////////////////////////////////////////////////////////////////////////////
- void
- BuildingGameObj::On_Destroyed (void)
- {
- IsDestroyed = true;
- //
- // Notify the controller that the building has been destroyed
- //
- if (BaseController != NULL) {
- BaseController->On_Building_Destroyed (this);
- }
-
- //
- // Mark the object as dirty so it's state will be mirrored on the client
- //
- if (CombatManager::I_Am_Server ()) {
- Set_Object_Dirty_Bit (NetworkObjectClass::BIT_RARE, true);
- }
- //
- // Reveal this building to the encyclopedia
- //
- EncyclopediaMgrClass::Reveal_Object (this);
- return ;
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // Import_Rare
- //
- /////////////////////////////////////////////////////////////////////////////
- void
- BuildingGameObj::Import_Rare (BitStreamClass &packet)
- {
- DamageableGameObj::Import_Rare (packet);
- //
- // Read the state information from the server
- //
- bool is_destroyed = IsDestroyed;
- bool is_power_on = IsPowerOn;
- int current_state = CurrentState;
- packet.Get (is_destroyed);
- packet.Get (is_power_on);
- packet.Get (current_state, BITPACK_BUILDING_STATE);
- //
- // Is the power state of the building changing?
- //
- if (is_power_on != IsPowerOn) {
- Enable_Power (is_power_on);
- }
- //
- // Update our health if we are destroyed
- //
- if (is_destroyed) {
- Get_Defense_Object()->Set_Health(0.0f);
- }
- //
- // Recalculate our state (if necessary)
- //
- if (current_state != CurrentState) {
- Update_State ();
- }
- //
- // Become destroyed (if necessary)
- //
- if (is_destroyed && IsDestroyed == false) {
- On_Destroyed ();
- }
- return ;
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // Export_Rare
- //
- /////////////////////////////////////////////////////////////////////////////
- void
- BuildingGameObj::Export_Rare (BitStreamClass &packet)
- {
- DamageableGameObj::Export_Rare (packet);
- //
- // Transmit the state information
- //
- packet.Add (IsDestroyed);
- packet.Add (IsPowerOn);
- packet.Add (CurrentState, BITPACK_BUILDING_STATE);
- return ;
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // Set_Precision
- //
- /////////////////////////////////////////////////////////////////////////////
- void
- BuildingGameObj::Set_Precision (void)
- {
- cEncoderList::Set_Precision (BITPACK_BUILDING_STATE, -1, (int)BuildingStateClass::STATE_COUNT);
- return ;
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // Collect_Building_Components
- //
- /////////////////////////////////////////////////////////////////////////////
- void
- BuildingGameObj::Collect_Building_Components (void)
- {
- Reset_Components ();
- //
- // Iterate through all static objects in the level, assigning the building components to
- // the appropriate building controller
- //
- RefPhysListIterator staticobj_iterator = PhysicsSceneClass::Get_Instance()->Get_Static_Object_Iterator();
- for (staticobj_iterator.First(); !staticobj_iterator.Is_Done(); staticobj_iterator.Next()) {
-
- StaticPhysClass * obj = staticobj_iterator.Peek_Obj()->As_StaticPhysClass ();
- WWASSERT (obj != NULL);
- WWASSERT (obj->Peek_Model() != NULL);
- const char *obj_name = obj->Peek_Model()->Get_Name();
- if (obj->Get_Factory().Chunk_ID() == PHYSICS_CHUNKID_BUILDINGAGGREGATE) {
- //
- // Does this aggregate match the prefix that this building is expecting?
- //
- if (Name_Prefix_Matches_This_Building (obj_name)) {
- //
- // Calculate how far the object is from the center of this building's
- // collection sphere
- //
- Vector3 obj_pos = obj->Peek_Model()->Get_Bounding_Box().Center;
- float dist2 = (CollectionSphere.Center - obj_pos).Length2 ();
- //
- // Is this object within the collection sphere?
- //
- if (dist2 <= (CollectionSphere.Radius * CollectionSphere.Radius)) {
- // Check for an existing building owner
- CombatPhysObserverClass * old_observer = (CombatPhysObserverClass *)obj->Get_Observer();
- BuildingGameObj * existing_building = NULL;
- if ( old_observer != NULL ) {
- existing_building = old_observer->As_BuildingGameObj();
- }
- if ( existing_building != NULL ) {
- // Another building already has this
- float existing_dist2 = (existing_building->CollectionSphere.Center - obj_pos).Length2 ();
- if ( dist2 < existing_dist2 ) {
- // But we are closer, so remove from the existing
- existing_building->Remove_Aggregate ((BuildingAggregateClass *)obj);
- // and Take him
- Add_Aggregate ((BuildingAggregateClass *)obj);
- }
- } else {
- // We are the first/only
- Add_Aggregate ((BuildingAggregateClass *)obj);
- }
- }
- }
- } else if (Is_Interior_Mesh_Name (obj_name) || Is_Exterior_Mesh_Name (obj_name)) {
-
- //
- // Does this mesh match the prefix that this building is expecting?
- //
- if (Name_Prefix_Matches_This_Building (obj_name)) {
- //
- // Calculate how far the object is from the center of this building's
- // collection sphere
- //
- Vector3 obj_pos = obj->Peek_Model()->Get_Bounding_Box().Center;
- float dist2 = (CollectionSphere.Center - obj_pos).Length2 ();
- //
- // Is this object within the collection sphere?
- //
- if (dist2 <= (CollectionSphere.Radius * CollectionSphere.Radius)) {
- // Check for an existing building owner
- CombatPhysObserverClass * old_observer = (CombatPhysObserverClass *)obj->Get_Observer();
- BuildingGameObj * existing_building = NULL;
- if ( old_observer != NULL ) {
- existing_building = old_observer->As_BuildingGameObj();
- }
- if ( existing_building != NULL ) {
- // Another building already has this
- float existing_dist2 = (existing_building->CollectionSphere.Center - obj_pos).Length2 ();
- if ( dist2 < existing_dist2 ) {
- // But we are closer, so remove from the existing
- existing_building->Remove_Mesh (obj);
- // and Take him
- Add_Mesh (obj);
- }
- } else {
- // We are the first/only
- Add_Mesh (obj);
- }
- }
- }
- }
- }
- //
- // Iterate through all static lights in the level, assigning each building light to
- // the appropriate building controller
- //
- RefPhysListIterator staticlight_iterator = PhysicsSceneClass::Get_Instance ()->Get_Static_Light_Iterator ();
- for (staticlight_iterator.First (); !staticlight_iterator.Is_Done (); staticlight_iterator.Next ()) {
-
- LightPhysClass * light = staticlight_iterator.Peek_Obj()->As_LightPhysClass();
- WWASSERT(light != NULL);
- WWASSERT(light->Peek_Model() != NULL);
- //
- // Does this light match the prefix that this building is expecting?
- //
- if (Name_Prefix_Matches_This_Building (light->Get_Name ())) {
- //
- // Calculate how far the light is from the center of this building's
- // collection sphere
- //
- Vector3 light_pos;
- light->Get_Position (&light_pos);
- float dist2 = (CollectionSphere.Center - light_pos).Length2 ();
- //
- // Is this light within the collection sphere?
- //
- if (dist2 <= (CollectionSphere.Radius * CollectionSphere.Radius)) {
- Add_Light (light);
- }
- }
- }
- //
- // Update the building's state
- //
- Initialize_Building ();
- Update_State (true);
- return ;
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // Export_Creation
- //
- /////////////////////////////////////////////////////////////////////////////
- void
- BuildingGameObj::Export_Creation (BitStreamClass &packet)
- {
- DamageableGameObj::Export_Creation (packet);
- //
- // Send the object's position
- //
- Vector3 position (0, 0, 0);
- Get_Position (&position);
- packet.Add (position.X, BITPACK_WORLD_POSITION_X);
- packet.Add (position.Y, BITPACK_WORLD_POSITION_Y);
- packet.Add (position.Z, BITPACK_WORLD_POSITION_Z);
- //
- // Send the collection sphere's definition
- //
- packet.Add (CollectionSphere.Center.X, BITPACK_WORLD_POSITION_X);
- packet.Add (CollectionSphere.Center.Y, BITPACK_WORLD_POSITION_Y);
- packet.Add (CollectionSphere.Center.Z, BITPACK_WORLD_POSITION_Z);
- packet.Add (CollectionSphere.Radius, BITPACK_BUILDING_RADIUS);
- return ;
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // Import_Creation
- //
- /////////////////////////////////////////////////////////////////////////////
- void
- BuildingGameObj::Import_Creation (BitStreamClass &packet)
- {
- DamageableGameObj::Import_Creation (packet);
- //
- // Read the object's position
- //
- Vector3 position (0, 0, 0);
- packet.Get (position.X, BITPACK_WORLD_POSITION_X);
- packet.Get (position.Y, BITPACK_WORLD_POSITION_Y);
- packet.Get (position.Z, BITPACK_WORLD_POSITION_Z);
- Set_Position (position);
- //
- // Read the collection sphere's definition
- //
- packet.Get (CollectionSphere.Center.X, BITPACK_WORLD_POSITION_X);
- packet.Get (CollectionSphere.Center.Y, BITPACK_WORLD_POSITION_Y);
- packet.Get (CollectionSphere.Center.Z, BITPACK_WORLD_POSITION_Z);
- packet.Get (CollectionSphere.Radius, BITPACK_BUILDING_RADIUS);
- //
- // Now initialize the object
- //
- Collect_Building_Components ();
- Update_State ();
- Initialize_Building ();
- return ;
- }
- /*
- ////////////////////////////////////////////////////////////////////////////
- //
- // Compute_Object_Priority
- //
- /////////////////////////////////////////////////////////////////////////////
- float
- BuildingGameObj::Compute_Object_Priority (int client_id, const Vector3 &client_pos)
- {
- float priority = 1.0F;
- if (Get_Object_Dirty_Bit (client_id, BIT_RARE) == false) {
- priority = DamageableGameObj::Compute_Object_Priority (client_id, client_pos);
- }
- //
- // Priority value is cached, update the cached value.
- //
- Set_Cached_Priority(priority);
- return priority;
- }
- */
- ////////////////////////////////////////////////////////////////////////////
- //
- // Get_Description
- //
- /////////////////////////////////////////////////////////////////////////////
- void
- //BuildingGameObj::Get_Extended_Information(StringClass & description)
- BuildingGameObj::Get_Description(StringClass & description)
- {
- //
- // Construct a diagnostic string
- //
- StringClass line(0,true);
- line.Format("ID: %d\n", Get_ID());
- description += line;
- line.Format("Name: %s\n", Get_Definition().Get_Name());
- description += line;
- line.Format("Team: %d\n", Get_Player_Type());
- description += line;
- Vector3 position;
- Get_Position(&position);
- line.Format("POS: %-5.2f, %-5.2f, %-5.2f\n", position.X, position.Y, position.Z);
- description += line;
-
- if (Get_Defense_Object() != NULL) {
- line.Format("HLTH: %-5.2f\n", Get_Defense_Object()->Get_Health());
- description += line;
- }
- line.Format("HIB: %d\n", Is_Hibernating());
- description += line;
- line.Format("Destr: %d\n", IsDestroyed);
- description += line;
- line.Format("Power: %d\n", IsPowerOn);
- description += line;
- line.Format("ISC: %d\n", Get_Import_State_Count());
- description += line;
- }
- ////////////////////////////////////////////////////////////////////////////
- //
- // Find_Closest_Poly_For_Model
- //
- /////////////////////////////////////////////////////////////////////////////
- void
- BuildingGameObj::Find_Closest_Poly_For_Model
- (
- RenderObjClass * model,
- const Vector3 & pos,
- float * distance2
- )
- {
- if (model == NULL) {
- return ;
- }
- //
- // Convert the point from world space to object space
- //
- Vector3 obj_space_point;
- Matrix3D::Inverse_Transform_Vector (model->Get_Transform (), pos, &obj_space_point);
- for (int index = 0; index < model->Get_Num_Sub_Objects (); index++) {
- RenderObjClass *sub_obj = model->Get_Sub_Object (index);
-
- //
- // Recurse into this sub-object
- //
- if (sub_obj != NULL) {
- Find_Closest_Poly_For_Model (sub_obj, pos, distance2);
- }
- REF_PTR_RELEASE (sub_obj);
- }
- //
- // Is this object a mesh? If so, then do a distance check against all its polygons
- //
- if (model->Class_ID () == RenderObjClass::CLASSID_MESH) {
- MeshModelClass *mesh_model = ((MeshClass *)model)->Peek_Model ();
- if (mesh_model != NULL) {
- const TriIndex *tri_array = mesh_model->Get_Polygon_Array ();
- Vector3 *vert_array = mesh_model->Get_Vertex_Array ();
-
- //
- // Check each polygon to see which is the closest
- //
- int poly_count = mesh_model->Get_Polygon_Count ();
- for (index = 0; index < poly_count; index ++) {
-
- int vert1 = tri_array[index][0];
- int vert2 = tri_array[index][1];
- int vert3 = tri_array[index][2];
- //
- // Compute the distance from the center of this polygon to the
- //
- //
- Vector3 poly_center = (vert_array[vert1] + vert_array[vert2] + vert_array[vert3]) * 0.33F;
- Vector3 delta = (poly_center - obj_space_point);
- float dist2 = delta.Length2 ();
- if (dist2 < (*distance2)) {
- (*distance2) = dist2;
- }
- }
- }
- }
- return ;
- }
- ////////////////////////////////////////////////////////////////////////////
- //
- // Find_Closest_Poly
- //
- /////////////////////////////////////////////////////////////////////////////
- void
- BuildingGameObj::Find_Closest_Poly (const Vector3 &pos, float *distance2)
- {
- (*distance2) = 9999.0F;
- RefMultiListIterator<StaticPhysClass> int_iterator (&InteriorMeshes);
- RefMultiListIterator<StaticPhysClass> ext_iterator (&ExteriorMeshes);
- //
- // Check all the interior meshes first
- //
- for (int_iterator.First (); !int_iterator.Is_Done (); int_iterator.Next ()) {
- Find_Closest_Poly_For_Model (int_iterator.Peek_Obj ()->Peek_Model (), pos, distance2);
- }
- //
- // Now, check all the exterior meshes
- //
- for (ext_iterator.First (); !ext_iterator.Is_Done (); ext_iterator.Next ()) {
- Find_Closest_Poly_For_Model (ext_iterator.Peek_Obj ()->Peek_Model (), pos, distance2);
- }
- return ;
- }
|