| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411 |
- /*
- ** 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/damage.cpp $*
- * *
- * $Author:: Greg_h $*
- * *
- * $Modtime:: 6/21/02 2:42p $*
- * *
- * $Revision:: 114 $*
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- /*
- ** Includes
- */
- #include "damage.h"
- #include "assets.h"
- #include "debug.h"
- #include "smartgameobj.h"
- #include "combat.h"
- #include "slist.h"
- #include "wwpacket.h"
- #include "playerdata.h"
- #include "soldier.h"
- #include "weapons.h"
- #include "diaglog.h"
- #include "playertype.h"
- #include <string.h>
- #include <stdio.h>
- #include "wwmath.h"
- #include "encoderlist.h"
- #include "bitpackids.h"
- #include "gametype.h"
- #include "csdamageevent.h"
- #ifdef WWDEBUG
- bool DefenseObjectClass::OneShotKills = false;
- #endif // _WWDEBUG
- ArmorWarheadManager ArmorManagerObject;
- DynamicVectorClass<StringClass> ArmorNames;
- DynamicVectorClass<StringClass> WarheadNames;
- DynamicVectorClass<int> ArmorSaveIDs;
- DynamicVectorClass<int> WarheadSaveIDs;
- DynamicVectorClass<bool> SoftArmorTable;
- // For each Warhead
- DynamicVectorClass<int> SpecialDamageTypes;
- DynamicVectorClass<float> SpecialDamageProbability;
- DynamicVectorClass<float> VisceroidProbability;
- // For each special damage type
- int SpecialDamageWarhead[ArmorWarheadManager::NUM_SPECIAL_DAMAGE_TYPES];
- float SpecialDamageDuration[ArmorWarheadManager::NUM_SPECIAL_DAMAGE_TYPES];
- float SpecialDamageScale[ArmorWarheadManager::NUM_SPECIAL_DAMAGE_TYPES];
- StringClass SpecialDamageExplosion[ArmorWarheadManager::NUM_SPECIAL_DAMAGE_TYPES];
- // Skins that are imprevious to special damage
- DynamicVectorClass<ArmorType> ImperviousSkins[ArmorWarheadManager::NUM_SPECIAL_DAMAGE_TYPES];
- safe_float * ArmorWarheadManager::Multipliers = NULL;
- safe_float * ArmorWarheadManager::Absorbsion = NULL;
- #define ARMOR_INI_FILENAME "armor.ini"
- #define SECTION_SOFT_ARMOR_TYPES "Soft_Armor_Types"
- #define SECTION_HARD_ARMOR_TYPES "Hard_Armor_Types"
- #define SECTION_ARMOR_TYPES "Armor_Types"
- #define SECTION_WARHEAD_TYPES "Warhead_Types"
- #define SECTION_SCALE "Scale_%s"
- #define SECTION_SHIELD "Shield_%s"
- #define SECTION_ARMOR_SAVE_IDS "Armor_Save_IDs"
- #define SECTION_WARHEAD_SAVE_IDS "Warhead_Save_IDs"
- #define SECTION_SOFT_ARMOR "Soft_Armor"
- #define SECTION_SPECIAL_DAMAGE_TYPE "Special_Damage_Type"
- #define SECTION_SPECIAL_DAMAGE_PROBABILITY "Special_Damage_Probability"
- #define SECTION_VISCEROID_PROBABILITY "Visceroid_Probability"
- #define ENTRY_WARHEAD "Warhead"
- #define ENTRY_DURATION "Duration"
- #define ENTRY_SCALE "Scale"
- #define ENTRY_EXPLOSION "Explosion"
- /*
- **
- */
- void ArmorWarheadManager::Init( void )
- {
- Shutdown();
- INIClass * armorINI = Get_INI( ARMOR_INI_FILENAME );
- if (armorINI != NULL) {
- WWASSERT( armorINI && armorINI->Section_Count() > 0 );
- int count, entry;
- // Load Armor Types
- count = armorINI->Entry_Count( SECTION_ARMOR_TYPES );
- for ( entry = 0; entry < count; entry++ ) {
- char entry_name[80];
- armorINI->Get_String( SECTION_ARMOR_TYPES,
- armorINI->Get_Entry( SECTION_ARMOR_TYPES, entry),
- "", entry_name, sizeof( entry_name ) );
- ArmorNames.Add( entry_name );
- ArmorSaveIDs.Add( entry );
- SoftArmorTable.Add( false );
- }
- // Load Warhead Types
- count = armorINI->Entry_Count( SECTION_WARHEAD_TYPES );
- for ( entry = 0; entry < count; entry++ ) {
- char entry_name[80];
- armorINI->Get_String( SECTION_WARHEAD_TYPES,
- armorINI->Get_Entry( SECTION_WARHEAD_TYPES, entry),
- "", entry_name, sizeof( entry_name ) );
- WarheadNames.Add( entry_name );
- WarheadSaveIDs.Add( entry );
- }
- int armor_num;
- // Load Armor Save IDs
- for ( armor_num = 0; armor_num < ArmorNames.Count(); armor_num++ ) {
- int id = armorINI->Get_Int( SECTION_ARMOR_SAVE_IDS, ArmorNames[armor_num], -100 );
- if ( id == -100 ) {
- Debug_Say(( "Missing Armor_Save_ID for %s\n", ArmorNames[armor_num] ));
- }
- ArmorSaveIDs[ armor_num ] = id;
- }
- // Load Warhead Save IDs
- int warhead_num;
- for ( warhead_num = 0; warhead_num < WarheadNames.Count(); warhead_num++ ) {
- int id = armorINI->Get_Int( SECTION_WARHEAD_SAVE_IDS, WarheadNames[warhead_num], -100 );
- if ( id == -100 ) {
- Debug_Say(( "Missing Warhead_Save_ID for %s\n", WarheadNames[warhead_num] ));
- }
- WarheadSaveIDs[ warhead_num ] = id;
- }
- // Load Soft Armor Table
- count = armorINI->Entry_Count( SECTION_SOFT_ARMOR );
- for ( entry = 0; entry < count; entry++ ) {
- char entry_name[80];
- armorINI->Get_String( SECTION_SOFT_ARMOR,
- armorINI->Get_Entry( SECTION_SOFT_ARMOR, entry),
- "", entry_name, sizeof( entry_name ) );
- ArmorType type = Get_Armor_Type( entry_name );
- SoftArmorTable[ type ] = true;
- }
- // Load Multipliers
- Multipliers = new safe_float[ Get_Num_Armor_Types() * Get_Num_Warhead_Types() ];
- for ( armor_num = 0; armor_num < ArmorNames.Count(); armor_num++ ) {
- char section_name[80];
- sprintf( section_name, SECTION_SCALE, ArmorNames[armor_num] );
- for ( int warhead_num = 0; warhead_num < WarheadNames.Count(); warhead_num++ ) {
- Multipliers[ armor_num * Get_Num_Warhead_Types() + warhead_num ] =
- armorINI->Get_Float( section_name, WarheadNames[warhead_num], 1.0f );
- }
- }
- // Load Shield Absorbsion
- Absorbsion = new safe_float[ Get_Num_Armor_Types() * Get_Num_Warhead_Types() ];
- for ( armor_num = 0; armor_num < ArmorNames.Count(); armor_num++ ) {
- char section_name[80];
- sprintf( section_name, SECTION_SHIELD, ArmorNames[armor_num] );
- for ( int warhead_num = 0; warhead_num < WarheadNames.Count(); warhead_num++ ) {
- Absorbsion[ armor_num * Get_Num_Warhead_Types() + warhead_num ] =
- armorINI->Get_Float( section_name, WarheadNames[warhead_num], 0.0f );
- }
- }
- // Load Warhead Special Damage
- for ( warhead_num = 0; warhead_num < WarheadNames.Count(); warhead_num++ ) {
- SpecialDamageTypes.Add( SPECIAL_DAMAGE_TYPE_NONE );
- SpecialDamageProbability.Add( 0 );
- VisceroidProbability.Add( 0 );
- StringClass special_damage_type(0,true);
- armorINI->Get_String(special_damage_type, SECTION_SPECIAL_DAMAGE_TYPE, WarheadNames[warhead_num] );
- if ( !special_damage_type.Is_Empty() ) {
- if ( !stricmp( special_damage_type, "FIRE" ) ) {
- SpecialDamageTypes[warhead_num] = SPECIAL_DAMAGE_TYPE_FIRE;
- }
- if ( !stricmp( special_damage_type, "CHEM" ) ) {
- SpecialDamageTypes[warhead_num] = SPECIAL_DAMAGE_TYPE_CHEM;
- }
- if ( !stricmp( special_damage_type, "CNC_FIRE" ) ) {
- SpecialDamageTypes[warhead_num] = SPECIAL_DAMAGE_TYPE_CNC_FIRE;
- }
- if ( !stricmp( special_damage_type, "CNC_CHEM" ) ) {
- SpecialDamageTypes[warhead_num] = SPECIAL_DAMAGE_TYPE_CNC_CHEM;
- }
- if ( !stricmp( special_damage_type, "ELECTRIC" ) ) {
- SpecialDamageTypes[warhead_num] = SPECIAL_DAMAGE_TYPE_ELECTRIC;
- }
- }
- SpecialDamageProbability[warhead_num] =
- armorINI->Get_Float( SECTION_SPECIAL_DAMAGE_PROBABILITY, WarheadNames[warhead_num], 0.0f );
- VisceroidProbability[warhead_num] =
- armorINI->Get_Float( SECTION_VISCEROID_PROBABILITY, WarheadNames[warhead_num], 0.0f );
- // Debug_Say(( "Warhead %s %d %f\n", WarheadNames[warhead_num],
- // SpecialDamageTypes[warhead_num], SpecialDamageProbability[warhead_num] ));
- }
- int i;
- for ( i = 0; i < NUM_SPECIAL_DAMAGE_TYPES; i++ ) {
- SpecialDamageWarhead[i] = 0;
- SpecialDamageDuration[i] = 0;
- SpecialDamageScale[i] = 0;
- SpecialDamageExplosion[i] = "";
- }
- StringClass temp_string(0,true);
- for ( i = SPECIAL_DAMAGE_TYPE_FIRE; i < NUM_SPECIAL_DAMAGE_TYPES; i++ ) {
- const char * SpecialDamageSectionNames[NUM_SPECIAL_DAMAGE_TYPES] = {
- "Special_Damage_None",
- "Special_Damage_Fire",
- "Special_Damage_Chem",
- "Special_Damage_Electric",
- "Special_Damage_CNC_Fire",
- "Special_Damage_CNC_Chem",
- };
- StringClass section(SpecialDamageSectionNames[i],true);
- SpecialDamageWarhead[i] = Get_Warhead_Type( armorINI->Get_String( temp_string, section, ENTRY_WARHEAD ) );
- SpecialDamageDuration[i] = armorINI->Get_Float( section, ENTRY_DURATION, 0 );
- SpecialDamageScale[i] = armorINI->Get_Float( section, ENTRY_SCALE, 1 );
- SpecialDamageExplosion[i] = armorINI->Get_String( temp_string, section, ENTRY_EXPLOSION );
- }
- //
- // Copy fire into super fire
- //
- SpecialDamageWarhead[SPECIAL_DAMAGE_TYPE_SUPER_FIRE] = SpecialDamageWarhead[SPECIAL_DAMAGE_TYPE_FIRE];
- SpecialDamageDuration[SPECIAL_DAMAGE_TYPE_SUPER_FIRE] = SpecialDamageDuration[SPECIAL_DAMAGE_TYPE_FIRE];
- SpecialDamageScale[SPECIAL_DAMAGE_TYPE_SUPER_FIRE] = SpecialDamageScale[SPECIAL_DAMAGE_TYPE_FIRE];
- SpecialDamageExplosion[SPECIAL_DAMAGE_TYPE_SUPER_FIRE] = SpecialDamageExplosion[SPECIAL_DAMAGE_TYPE_FIRE];
- // Load Impervious skin
- for ( int damage = SPECIAL_DAMAGE_TYPE_FIRE; damage < NUM_SPECIAL_DAMAGE_TYPES; damage++ ) {
- const char * ImperviousSectionNames[NUM_SPECIAL_DAMAGE_TYPES] = {
- "Impervious_None",
- "Impervious_Fire",
- "Impervious_Chem",
- "Impervious_Electric",
- "Impervious_CNC_Fire",
- "Impervious_CNC_Chem",
- };
- StringClass section = ImperviousSectionNames[damage];
- int count = armorINI->Entry_Count( section );
- for ( entry = 0; entry < count; entry++ ) {
- StringClass entry_name = armorINI->Get_String( temp_string, section, armorINI->Get_Entry( section, entry) );
- if ( !entry_name.Is_Empty() ) {
- ImperviousSkins[damage].Add( Get_Armor_Type( entry_name ) );
- }
- }
- // for ( int i = 0; i < ImperviousSkins[damage].Count(); i++ ) {
- // Debug_Say(( "Loaded %s %d\n", (const char *)section, ImperviousSkins[damage][i] ));
- // }
- }
- Release_INI( armorINI );
- } else {
- Debug_Say(("ArmorWarheadManager::Init - Unable to load %s\n", ARMOR_INI_FILENAME));
- }
- }
- void ArmorWarheadManager::Shutdown( void )
- {
- if ( Multipliers != NULL ) {
- delete [] Multipliers;
- Multipliers = NULL;
- }
- if ( Absorbsion != NULL ) {
- delete [] Absorbsion;
- Absorbsion = NULL;
- }
- ArmorNames.Delete_All();
- WarheadNames.Delete_All();
- ArmorSaveIDs.Delete_All();
- WarheadSaveIDs.Delete_All();
- SoftArmorTable.Delete_All();
- SpecialDamageTypes.Delete_All();
- SpecialDamageProbability.Delete_All();
- VisceroidProbability.Delete_All();
- for (int i=0; i<ArmorWarheadManager::NUM_SPECIAL_DAMAGE_TYPES; i++) {
- ImperviousSkins[i].Delete_All();
- }
- }
- int ArmorWarheadManager::Get_Num_Armor_Types( void )
- {
- return ArmorNames.Count();
- }
- int ArmorWarheadManager::Get_Num_Warhead_Types( void )
- {
- return WarheadNames.Count();
- }
- ArmorType ArmorWarheadManager::Get_Armor_Type( const char *name )
- {
- for ( int index = 0; index < ArmorNames.Count(); index++ ) {
- if ( !stricmp( ArmorNames[index], name ) ) {
- return index;
- }
- }
- Debug_Say(( "Armor %s Not Found\n", name ));
- // WWASSERT( 0 ); //Armor type not found!
- return 0;
- }
- WarheadType ArmorWarheadManager::Get_Warhead_Type( const char *name )
- {
- for ( int index = 0; index < WarheadNames.Count(); index++ ) {
- if ( !stricmp( WarheadNames[index], name ) ) {
- return index;
- }
- }
- Debug_Say(( "Warhead %s Not Found\n", name ));
- // WWASSERT( 0 ); //Warhead type not found!
- return 0;
- }
- const char * ArmorWarheadManager::Get_Armor_Name( ArmorType type )
- {
- WWASSERT( (int)type >= 0 );
- WWASSERT( (int)type < Get_Num_Armor_Types() );
- return ArmorNames[type];
- }
- const char * ArmorWarheadManager::Get_Warhead_Name( WarheadType type )
- {
- WWASSERT( (int)type >= 0 );
- WWASSERT( (int)type < Get_Num_Warhead_Types() );
- return WarheadNames[type];
- }
- float ArmorWarheadManager::Get_Damage_Multiplier( ArmorType armor, WarheadType warhead )
- {
- WWASSERT( (int)armor >= 0 );
- WWASSERT( (int)armor < Get_Num_Armor_Types() );
- WWASSERT( (int)warhead >= 0 );
- WWASSERT( (int)warhead < Get_Num_Warhead_Types() );
- return( Multipliers[ (unsigned int)armor * Get_Num_Warhead_Types() + (unsigned int)warhead ] );
- /*
- int index = armor * Get_Num_Warhead_Types() + warhead;
- float multiplier = Multipliers[index];
- WWASSERT(WWMath::Is_Valid_Float(multiplier));
- Debug_Say(("index = %d, armor = %d, warhead = %d, multiplier = %5.2f\n",
- index, armor, warhead, multiplier));
- return multiplier;
- */
- }
- float ArmorWarheadManager::Get_Shield_Absorbsion( ArmorType armor, WarheadType warhead )
- {
- WWASSERT( (int)armor >= 0 );
- WWASSERT( (int)armor < Get_Num_Armor_Types() );
- WWASSERT( (int)warhead >= 0 );
- WWASSERT( (int)warhead < Get_Num_Warhead_Types() );
- return( Absorbsion[ (unsigned int)armor * Get_Num_Warhead_Types() + (unsigned int)warhead ] );
- }
- bool ArmorWarheadManager::Is_Armor_Soft( ArmorType armor )
- {
- return SoftArmorTable[armor];
- }
- int ArmorWarheadManager::Get_Armor_Save_ID( ArmorType type )
- {
- return ArmorSaveIDs[ type ];
- }
- ArmorType ArmorWarheadManager::Find_Armor_Save_ID( int id )
- {
- for ( int index = 0; index < ArmorSaveIDs.Count(); index++ ) {
- if ( ArmorSaveIDs[ index ] == id ) {
- return index;
- }
- }
- //Debug_Say(( "FAILED to find ARMOR_SAVE_ID for %d\n", id ));
- return 0;
- }
- int ArmorWarheadManager::Get_Warhead_Save_ID( WarheadType type )
- {
- return WarheadSaveIDs[ type ];
- }
- ArmorType ArmorWarheadManager::Find_Warhead_Save_ID( int id )
- {
- for ( int index = 0; index < WarheadSaveIDs.Count(); index++ ) {
- if ( WarheadSaveIDs[ index ] == id ) {
- return index;
- }
- }
- Debug_Say(( "FAILED to find WARHEAD_SAVE_ID for %d\n", id ));
- return 0;
- }
- ArmorWarheadManager::SpecialDamageType ArmorWarheadManager::Get_Special_Damage_Type( WarheadType type )
- {
- WWASSERT( (int)type >= 0 );
- WWASSERT( (int)type < Get_Num_Warhead_Types() );
- return (SpecialDamageType)SpecialDamageTypes[type];
- }
- float ArmorWarheadManager::Get_Special_Damage_Probability( WarheadType type )
- {
- WWASSERT( (int)type >= 0 );
- WWASSERT( (int)type < Get_Num_Warhead_Types() );
- return SpecialDamageProbability[type];
- }
- WarheadType ArmorWarheadManager::Get_Special_Damage_Warhead( SpecialDamageType type )
- {
- WWASSERT( (int)type >= 0 );
- WWASSERT( (int)type < NUM_SPECIAL_DAMAGE_TYPES );
- return SpecialDamageWarhead[type];
- }
- float ArmorWarheadManager::Get_Special_Damage_Duration( SpecialDamageType type )
- {
- WWASSERT( (int)type >= 0 );
- WWASSERT( (int)type < NUM_SPECIAL_DAMAGE_TYPES );
- return SpecialDamageDuration[type];
- }
- float ArmorWarheadManager::Get_Special_Damage_Scale( SpecialDamageType type )
- {
- WWASSERT( (int)type >= 0 );
- WWASSERT( (int)type < NUM_SPECIAL_DAMAGE_TYPES );
- return SpecialDamageScale[type];
- }
- const char * ArmorWarheadManager::Get_Special_Damage_Explosion( SpecialDamageType type )
- {
- WWASSERT( (int)type >= 0 );
- WWASSERT( (int)type < NUM_SPECIAL_DAMAGE_TYPES );
- return SpecialDamageExplosion[type];
- }
- float ArmorWarheadManager::Get_Visceroid_Probability( WarheadType type )
- {
- WWASSERT( (int)type >= 0 );
- WWASSERT( (int)type < Get_Num_Warhead_Types() );
- return VisceroidProbability[type];
- }
- bool ArmorWarheadManager::Is_Skin_Impervious( SpecialDamageType type, ArmorType skin )
- {
- WWASSERT( (int)type >= 0 );
- WWASSERT( (int)type < NUM_SPECIAL_DAMAGE_TYPES );
- for ( int i = 0; i < ImperviousSkins[type].Count(); i++ ) {
- if ( ImperviousSkins[type][i] == skin ) {
- return true;
- }
- }
- return false;
- }
- /*
- **
- */
- OffenseObjectClass::OffenseObjectClass( const OffenseObjectClass & base ) :
- Damage( base.Damage ),
- Warhead( base.Warhead )
- {
- Set_Owner( base.Get_Owner() );
- }
- /*
- ** Save and Load
- */
- enum {
- CHUNKID_VARIABLES = 914991020,
- CHUNKID_OWNER,
- MICROCHUNKID_WARHEAD = 1,
- MICROCHUNKID_DAMAGE,
- MICROCHUNKID_HEALTH,
- MICROCHUNKID_HEALTH_MAX,
- MICROCHUNKID_SKIN,
- MICROCHUNKID_SHIELD_STRENGTH,
- MICROCHUNKID_SHIELD_STRENGTH_MAX,
- MICROCHUNKID_SHIELD_TYPE,
- XXXMICROCHUNKID_LAST_HEALTH,
- XXXMICROCHUNKID_LAST_SKIN,
- XXXMICROCHUNKID_LAST_SHIELD_STRENGTH,
- XXXMICROCHUNKID_LAST_SHIELD_TYPE,
- MICROCHUNKID_DAMAGE_POINTS,
- MICROCHUNKID_DEATH_POINTS,
- };
- bool OffenseObjectClass::Save( ChunkSaveClass & csave )
- {
- csave.Begin_Chunk( CHUNKID_VARIABLES );
- int save_id = ArmorWarheadManager::Get_Warhead_Save_ID( Warhead );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_WARHEAD, save_id );
- WRITE_SAFE_MICRO_CHUNK( csave, MICROCHUNKID_DAMAGE, Damage, float );
- csave.End_Chunk();
- csave.Begin_Chunk( CHUNKID_OWNER );
- Owner.Save( csave );
- csave.End_Chunk();
- return true;
- }
- bool OffenseObjectClass::Load( ChunkLoadClass &cload )
- {
- int save_id = -2;
- while (cload.Open_Chunk()) {
- switch(cload.Cur_Chunk_ID()) {
- case CHUNKID_VARIABLES:
- while (cload.Open_Micro_Chunk()) {
- switch(cload.Cur_Micro_Chunk_ID()) {
- READ_MICRO_CHUNK( cload, MICROCHUNKID_WARHEAD, save_id );
- READ_SAFE_MICRO_CHUNK( cload, MICROCHUNKID_DAMAGE, Damage, float);
- default:
- Debug_Say(( "Unrecognized Offense Variable chunkID\n" ));
- break;
- }
- cload.Close_Micro_Chunk();
- }
- break;
- case CHUNKID_OWNER:
- Owner.Load( cload );
- break;
- default:
- Debug_Say(( "Unrecognized Offense chunkID\n" ));
- break;
- }
- cload.Close_Chunk();
- }
- Warhead = ArmorWarheadManager::Find_Warhead_Save_ID( save_id );
- return true;
- }
- void DefenseObjectClass::Init( const DefenseObjectDefClass & def, DamageableGameObj * owner )
- {
- Health = def.Health;
- HealthMax = def.HealthMax;
- Skin = def.Skin;
- ShieldStrength = def.ShieldStrength;
- ShieldStrengthMax = def.ShieldStrengthMax;
- ShieldType = def.ShieldType;
- DamagePoints = def.DamagePoints;
- DeathPoints = def.DeathPoints;
- Set_Owner( owner );
- }
- bool DefenseObjectClass::Save( ChunkSaveClass & csave )
- {
- csave.Begin_Chunk( CHUNKID_VARIABLES );
- WRITE_SAFE_MICRO_CHUNK( csave, MICROCHUNKID_HEALTH, Health, float );
- WRITE_SAFE_MICRO_CHUNK( csave, MICROCHUNKID_HEALTH_MAX, HealthMax, float );
- int skin_save_id = ArmorWarheadManager::Get_Armor_Save_ID( Skin );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_SKIN, skin_save_id );
- WRITE_SAFE_MICRO_CHUNK( csave, MICROCHUNKID_SHIELD_STRENGTH, ShieldStrength, float );
- WRITE_SAFE_MICRO_CHUNK( csave, MICROCHUNKID_SHIELD_STRENGTH_MAX, ShieldStrengthMax, float );
- int shield_save_id = ArmorWarheadManager::Get_Armor_Save_ID( ShieldType );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_SHIELD_TYPE, shield_save_id );
- WRITE_SAFE_MICRO_CHUNK( csave, MICROCHUNKID_DAMAGE_POINTS, DamagePoints, float );
- WRITE_SAFE_MICRO_CHUNK( csave, MICROCHUNKID_DEATH_POINTS, DeathPoints, float );
- csave.End_Chunk();
- csave.Begin_Chunk( CHUNKID_OWNER );
- Owner.Save( csave );
- csave.End_Chunk();
- return true;
- }
- bool DefenseObjectClass::Load( ChunkLoadClass &cload )
- {
- int skin_save_id = -2;
- int shield_save_id = -2;
- while (cload.Open_Chunk()) {
- switch(cload.Cur_Chunk_ID()) {
- case CHUNKID_VARIABLES:
- while (cload.Open_Micro_Chunk()) {
- switch(cload.Cur_Micro_Chunk_ID()) {
- READ_SAFE_MICRO_CHUNK( cload, MICROCHUNKID_HEALTH, Health, float );
- READ_SAFE_MICRO_CHUNK( cload, MICROCHUNKID_HEALTH_MAX, HealthMax, float );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_SKIN, skin_save_id );
- READ_SAFE_MICRO_CHUNK( cload, MICROCHUNKID_SHIELD_STRENGTH, ShieldStrength, float );
- READ_SAFE_MICRO_CHUNK( cload, MICROCHUNKID_SHIELD_STRENGTH_MAX, ShieldStrengthMax, float );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_SHIELD_TYPE, shield_save_id );
- READ_SAFE_MICRO_CHUNK( cload, MICROCHUNKID_DAMAGE_POINTS, DamagePoints, float );
- READ_SAFE_MICRO_CHUNK( cload, MICROCHUNKID_DEATH_POINTS, DeathPoints, float );
- default:
- Debug_Say(( "Unrecognized Defense Variable chunkID\n" ));
- break;
- }
- cload.Close_Micro_Chunk();
- }
- break;
- case CHUNKID_OWNER:
- Owner.Load( cload );
- break;
- default:
- Debug_Say(( "Unrecognized Defense chunkID\n" ));
- break;
- }
- cload.Close_Chunk();
- }
- Skin = ArmorWarheadManager::Find_Armor_Save_ID( skin_save_id );
- ShieldType = ArmorWarheadManager::Find_Armor_Save_ID( shield_save_id );
- return true;
- }
- bool DefenseObjectClass::Is_Soft( void )
- {
- if ( !ArmorWarheadManager::Is_Armor_Soft( Skin ) ) {
- return false;
- }
- if ( ( (float)ShieldStrength > 0 ) && ( !ArmorWarheadManager::Is_Armor_Soft( ShieldType ) ) ) {
- return false;
- }
- return true;
- }
- /*
- **
- */
- float DefenseObjectClass::Apply_Damage( const OffenseObjectClass & offense, float scale, int alternate_skin )
- {
- #if 1
- // If singleplay or non trusted clients, just apply damage normally, if server
- bool normal = IS_SOLOPLAY || !cCsDamageEvent::Get_Are_Clients_Trusted();
- DamageableGameObj * owner = Get_Owner();
- // Buildings have no owner
- if ( owner == NULL || owner->As_BuildingGameObj() ) {
- normal = true;
- }
- if ( offense.ForceServerDamage || !offense.EnableClientDamage ) {
- normal = true;
- }
- if ( normal ) {
- if ( CombatManager::I_Am_Server() ) {
- return Do_Damage( offense, scale, alternate_skin );
- } else {
- return Health;
- }
- }
- // Client Damage
- // If I am a client, and damager is my guy, tell the server that damage should apply
- // If I am a server, and the damager has a client, ignore the damage
- bool has_client = false;
- bool my_client = false;
- if ( offense.Get_Owner() != NULL && offense.Get_Owner()->As_SmartGameObj() ) {
- int control_owner = offense.Get_Owner()->As_SmartGameObj()->Get_Control_Owner();
- has_client = control_owner > 0;
- my_client = control_owner == CombatManager::Get_My_Id();
- }
- if ( CombatManager::I_Am_Server() ) {
- if ( my_client || !has_client ) {
- return Do_Damage( offense, scale, alternate_skin );
- } else {
- return Health; // assume we will be notified by the owner Don't apply the damage
- }
- }
- // I am a client. If this is my object, request damage
- if ( my_client ) {
- Request_Damage( offense, scale );
- }
- return Health; // Don't apply the damage
- #else
- // Client Authorative damage is no longer done here.
- if ( CombatManager::I_Am_Server() ) {
- return Do_Damage( offense, scale, alternate_skin );
- } else {
- return Health;
- }
- #endif
- }
- /*
- **
- */
- void DefenseObjectClass::Request_Damage( const OffenseObjectClass & offense, float scale )
- {
- WWASSERT(CombatManager::I_Am_Only_Client());
- WWASSERT(cCsDamageEvent::Get_Are_Clients_Trusted() == true);
- cCsDamageEvent * event = new cCsDamageEvent();
- if ( event ) {
- int damager_id = 0;
- if ( offense.Get_Owner() ) {
- damager_id = offense.Get_Owner()->Get_ID();
- }
- int damagee_id = 0;
- if ( Get_Owner() ) {
- damagee_id = Get_Owner()->Get_ID();
- }
- int warhead = offense.Get_Warhead();
- float damage = offense.Get_Damage() * scale;
- event->Init( damager_id, damagee_id, damage, warhead );
- // Debug_Say(( "Requesting damage of %f from %d to %d\n", damage, damager_id, damagee_id ));
- }
- }
- /*
- **
- */
- float DefenseObjectClass::Do_Damage( const OffenseObjectClass & offense, float scale, int alternate_skin )
- {
- SmartGameObj * smart = NULL;
- if ( offense.Get_Owner() != NULL ) {
- smart = offense.Get_Owner()->As_SmartGameObj();
- }
- //TSS102201
- //
- // Keep track of who is attempting to damage who. This is used as a server
- // heuristic used in network priority calculations. It doesn't matter whether
- // or not damage is actually done.
- //
- int damager_id = -1;
- int damagee_id = -1;
- if (offense.Get_Owner() != NULL) {
- damager_id = offense.Get_Owner()->Get_Network_ID();
- }
-
- if (Get_Owner() != NULL) {
- damagee_id = Get_Owner()->Get_Network_ID();
- }
- if (offense.Get_Owner() != NULL && damagee_id != -1) {
- offense.Get_Owner()->Set_Last_Object_Id_I_Damaged(damagee_id);
- }
- if (Get_Owner() != NULL && damager_id != -1) {
- Get_Owner()->Set_Last_Object_Id_I_Got_Damaged_By(damager_id);
- }
- float damage = offense.Get_Damage() * scale;
- // Scale damage by difficulty if star is applying
- if ( IS_MISSION && offense.Get_Owner() == COMBAT_STAR ) {
- switch ( CombatManager::Get_Difficulty_Level() ) {
- case 0: damage *= 2.0f; break;
- case 1: damage *= 1.333f; break;
- case 2: damage *= 1.0f; break;
- };
- }
- float shield_damage = 0;
- float damage_scale = 1;
- float shield_damage_scale = 1;
- if (alternate_skin != -1) {
- damage_scale = ArmorWarheadManager::Get_Damage_Multiplier( alternate_skin, offense.Get_Warhead() );
- shield_damage_scale = 0;
- } else {
- damage_scale = ArmorWarheadManager::Get_Damage_Multiplier( Skin, offense.Get_Warhead() );
- shield_damage_scale = ArmorWarheadManager::Get_Damage_Multiplier( ShieldType, offense.Get_Warhead() );
- }
- // check for punish = no more damage
- if ( smart != NULL && smart->Get_Player_Data() ) {
- #define PUNISH_DELAY 60
- if ( smart->Get_Player_Data()->Get_Punish_Timer() > PUNISH_DELAY ) {
- damage_scale = 0;
- shield_damage_scale = 0;
- smart->Get_Player_Data()->Set_Money( 0 );
- smart->Get_Player_Data()->Set_Score( 0 );
- }
- }
- bool is_repair = false;
- // check for repair on either health of shield
- // Note: humans don't repair health, but vehicles do.
- if ( (damage * damage_scale < 0) || (damage * shield_damage_scale < 0) ) { // We are repairing
- is_repair = true;
- Mark_Owner_Dirty();
- // Apply first to health, then to shield
- if ( Health < HealthMax && (damage_scale != 0) ) {
- damage *= damage_scale;
- float min_damage = (float)Health - (float)HealthMax;
- damage = WWMath::Clamp( damage, min_damage, 0 );
- //Debug_Say(( "Repairing %f health\n", damage ));
- Health = (float)Health - damage;
- } else {
- damage *= shield_damage_scale;
- shield_damage = damage;
- damage = 0;
- float min_shield_damage = (float)ShieldStrength - (float)ShieldStrengthMax;
- shield_damage = WWMath::Clamp( shield_damage, min_shield_damage, 0 );
- //Debug_Say(( "Repairing %f shield\n", shield_damage ));
- ShieldStrength = (float)ShieldStrength - shield_damage;
- }
- } else {
- if ( smart && Get_Owner() &&
- (smart != Get_Owner() ) &&
- smart->Is_Teammate( Get_Owner() ) ) {
- // This is friendly fire!!
- if ( !CombatManager::Is_Friendly_Fire_Permitted() ) {
- // damage = 0;
- return Health;
- }
- }
- if ( damage != 0 ) {
- Mark_Owner_Dirty();
- }
- // if we have a shield, redirect a fraction of our damage;
- // If alternate skin (MCT) ignore sheild damage;
- if ( (float)ShieldStrength > 0.0f && alternate_skin == -1 ) {
- shield_damage = damage * ArmorWarheadManager::Get_Shield_Absorbsion( ShieldType, offense.Get_Warhead() );
- damage -= shield_damage;
- shield_damage *= shield_damage_scale;
- float shield_damage_to_apply = shield_damage; // how much scaled damage to apply
- if ( shield_damage > (float)ShieldStrength ) {
- shield_damage = ShieldStrength;
- }
- ShieldStrength = (float)ShieldStrength - shield_damage;
- if ( shield_damage_scale != 0 ) {
- shield_damage /= shield_damage_scale; // how much un scaled damage did we apply
- shield_damage_to_apply /= shield_damage_scale; // how much scaled damage did we try to apply
- }
- damage += shield_damage_to_apply - shield_damage;
- // Clamp Shield Strength
- ShieldStrength = WWMath::Clamp( (float)ShieldStrength, 0, (float)ShieldStrengthMax );
- }
- // scale the (remaining) damage
- // (gth) added alternate_skin feature which is used by buildings when their MCT is being damaged.
- damage *= damage_scale;
- if ( (float)Health < damage ) {
- damage = Health;
- }
- #ifdef WWDEBUG
- //
- // TSS090601
- //
- if (OneShotKills) {
- damage = Health;
- }
- #endif // _WWDEBUG
- Health = (float)Health - damage;
-
- //
- // Don't allow this object to die (if necessary)
- //
- if ( CanObjectDie == false ) {
- Health = max ( (float)Health, 1.0F );
- }
- }
- if ( COMBAT_STAR != NULL && // dedicated server test
- Get_Owner() == COMBAT_STAR ) {
- Vector3 pos;
- Get_Owner()->Get_Position( &pos );
- int hitter_id = 0;
- const char * weapon_name = "";
- if ( offense.Get_Owner() ) {
- hitter_id = offense.Get_Owner()->Get_ID();
- if ( offense.Get_Owner()->Get_Weapon() ) {
- weapon_name = offense.Get_Owner()->Get_Weapon()->Get_Definition()->Get_Name();
- }
- }
- float points = damage;
- float armor = Get_Shield_Strength();
- DIAG_LOG(( "DRCV", "%s; %d; %1.2f; %1.2f; %1.2f; %1.2f; %1.2f; %1.2f", weapon_name, hitter_id, points, armor, Health, pos.X, pos.Y, pos.Z ));
- }
- if (( smart == COMBAT_STAR ) && ( smart != NULL )) {
- Vector3 pos;
- smart->Get_Position( &pos );
- const char * weapon_name = "";
- int ammo = 0;
- if ( smart->Get_Weapon() ) {
- weapon_name = smart->Get_Weapon()->Get_Definition()->Get_Name();
- ammo = smart->Get_Weapon()->Get_Total_Rounds();
- }
- int hittee_id = 0;
- Vector3 victim_pos(0,0,0);
- const char * team_name = "";
- if ( Get_Owner() ) {
- hittee_id = Get_Owner()->Get_ID();
- Get_Owner()->Get_Position( &victim_pos );
- team_name = Player_Type_Name( Get_Owner()->Get_Player_Type() );
- }
- float points = damage;
- float armor = Get_Shield_Strength();
- DIAG_LOG(( "DEFC", "%1.2f; %1.2f; %1.2f; %s; %d; %d; %1.2f; %1.2f; %1.2f; %1.2f; %1.2f; %1.2f; %s ", pos.X, pos.Y, pos.Z, weapon_name, ammo, hittee_id, points, armor, Health, victim_pos.X, victim_pos.Y, victim_pos.Z, team_name ));
- }
- // Clamp Health to Max
- Health = WWMath::Clamp( (float)Health, 0, (float)HealthMax );
- if ( damage > 0 && (float)Health <= 0 ) {
- int victim_id = 0;
- Vector3 victim_pos(0,0,0);
- if ( Get_Owner() != NULL ) {
- victim_id = Get_Owner()->Get_ID();
- Get_Owner()->Get_Position( &victim_pos );
- }
- int killer_id = 0;
- Vector3 killer_pos(0,0,0);
- const char * weapon_name = "";
- if ( smart != NULL ) {
- killer_id = smart->Get_ID();
- smart->Get_Position( &killer_pos );
- if ( smart->Get_Weapon() ) {
- weapon_name = smart->Get_Weapon()->Get_Definition()->Get_Name();
- }
- }
- DIAG_LOG(( "OBDE", "%d; %1.2f; %1.2f; %1.2f; %d; %1.2f; %1.2f; %1.2f; %s", victim_id, victim_pos.X, victim_pos.Y, victim_pos.Z, killer_id, killer_pos.X, killer_pos.Y, killer_pos.Z, weapon_name ));
- if ( Get_Owner() == COMBAT_STAR ) {
- DIAG_LOG(( "STDE", "%1.2f; %1.2f; %1.2f; %d; %1.2f; %1.2f; %1.2f; %s", victim_pos.X, victim_pos.Y, victim_pos.Z, killer_id, killer_pos.X, killer_pos.Y, killer_pos.Z, weapon_name ));
- }
- }
- if (damage > 0 &&
- (float) Health <= 0 &&
- smart != NULL &&
- smart->As_SoldierGameObj() != NULL &&
- Get_Owner() != NULL &&
- Get_Owner()->As_SoldierGameObj() != NULL) {
- CombatManager::On_Soldier_Kill(smart->As_SoldierGameObj(), Get_Owner()->As_SoldierGameObj());
- }
- // Apply Points for damage/death
- if ( smart != NULL && smart->Get_Player_Data() ) {
- float points_dir = 1;
- // If same team, make the points negative
- if ( Get_Owner() ) {
- if ( smart->Is_Teammate( Get_Owner() ) ) {
- points_dir = -1;
- } else if ( !smart->Is_Enemy( Get_Owner() ) ) {
- // No points for neutrals
- points_dir = 0;
- }
- }
- if (offense.Get_Owner() != Get_Owner()) {
- float points = (float)DamagePoints;
- if ( is_repair ) { // half points for repair
- points *= 0.5f;
- }
- smart->Get_Player_Data()->Apply_Damage_Points( points_dir * (damage + shield_damage) * points, Get_Owner() );
- }
- if ( damage > 0 && (float)Health <= 0 ) {
-
- if (offense.Get_Owner() != Get_Owner()) {
- smart->Get_Player_Data()->Apply_Death_Points( points_dir * (float)DeathPoints, Get_Owner() );
- }
- }
- }
- return Health;
- }
- bool DefenseObjectClass::Is_Repair( const OffenseObjectClass & offense, float scale )
- {
- float damage = offense.Get_Damage() * scale;
- float damage_scale = ArmorWarheadManager::Get_Damage_Multiplier( Skin, offense.Get_Warhead() );
- float shield_damage_scale = ArmorWarheadManager::Get_Damage_Multiplier( ShieldType, offense.Get_Warhead() );
- // check for repair on either health of shield
- return ( (damage * damage_scale < 0) || (damage * shield_damage_scale < 0) );
- }
- bool DefenseObjectClass::Would_Damage( const OffenseObjectClass & offense, float scale )
- {
- float damage = offense.Get_Damage() * scale;
- float damage_scale = ArmorWarheadManager::Get_Damage_Multiplier( Skin, offense.Get_Warhead() );
- float shield_damage_scale = ArmorWarheadManager::Get_Damage_Multiplier( ShieldType, offense.Get_Warhead() );
- SmartGameObj * smart = NULL;
- if ( offense.Get_Owner() != NULL ) {
- smart = offense.Get_Owner()->As_SmartGameObj();
- }
- if ( smart && Get_Owner() &&
- smart->Is_Teammate( Get_Owner() ) &&
- (smart != Get_Owner() ) ) {
- // This is friendly fire!!
- if ( !CombatManager::Is_Friendly_Fire_Permitted() ) {
- return false;
- }
- }
- if ( damage * damage_scale > 0 && (float)Health > 0 ) {
- return true;
- }
- if ( damage * shield_damage_scale > 0 && (float)ShieldStrength > 0 ) {
- return true;
- }
- return false;
- }
- void DefenseObjectClass::Import(BitStreamClass & packet)
- {
- bool is_health_zero = packet.Get(is_health_zero);
- int health = packet.Get(health, BITPACK_HEALTH);
- int shield_strength = packet.Get(shield_strength, BITPACK_SHIELD_STRENGTH);
- unsigned int shield_type;
- packet.Get(shield_type, BITPACK_SHIELD_TYPE);
- ShieldType = shield_type;
- Health = (float)health;
- ShieldStrength = (float)shield_strength;
- if (is_health_zero) {
- Health = 0;
- } else {
- Health = WWMath::Max(Health, 0.01f);
- }
- //WWASSERT(WWMath::Is_Valid_Float(ShieldStrength));
- //WWASSERT(packet.Is_Flushed());
- }
- void DefenseObjectClass::Export(BitStreamClass & packet)
- {
- //
- // N.B. The funky syntax is to prevent datasafe asserts
- //
- int health = cMathUtil::Round((double) (float)Health);
- int shield_strength = cMathUtil::Round((double) (float)ShieldStrength);
- //TSS012202
- //packet.Add((bool)(health == 0));
- packet.Add((bool)(((float)Health) == 0));
- packet.Add(health, BITPACK_HEALTH);
- packet.Add(shield_strength, BITPACK_SHIELD_STRENGTH);
- packet.Add((unsigned long)ShieldType, BITPACK_SHIELD_TYPE);
- //LastSentHealth = Health;
- //LastSentSkin = Skin;
- //LastSentShieldStrength = ShieldStrength;
- //LastSentShieldType = ShieldType;
- }
- /*
- //
- // This was only valid with 1 client. We would need dirty tests for every client.
- //
- bool DefenseObjectClass::Is_Defense_State_Dirty(void)
- {
- return (
- fabs(Health - LastSentHealth) > MISCUTIL_EPSILON ||
- Skin != LastSentSkin ||
- fabs(ShieldStrength - LastSentShieldStrength) > MISCUTIL_EPSILON ||
- ShieldType != LastSentShieldType);
- }
- */
- /*****************************************************************************************
- **
- ** DefenseObjectDefClass Implementation
- **
- *****************************************************************************************/
- enum
- {
- DEFENSEOBJECTDEF_CHUNK_VARIABLES = 7311607,
- DEFENSEOBJECTDEF_VARIABLE_HEALTH = 0x00,
- DEFENSEOBJECTDEF_VARIABLE_HEALTHMAX,
- DEFENSEOBJECTDEF_VARIABLE_SKIN,
- DEFENSEOBJECTDEF_VARIABLE_SHIELDSTRENGTH,
- DEFENSEOBJECTDEF_VARIABLE_SHIELDSTRENGTHMAX,
- DEFENSEOBJECTDEF_VARIABLE_SHIELDTYPE,
- DEFENSEOBJECTDEF_VARIABLE_DAMAGE_POINTS,
- DEFENSEOBJECTDEF_VARIABLE_DEATH_POINTS,
- };
- DefenseObjectDefClass::DefenseObjectDefClass(void) :
- Health( 100.0f ),
- HealthMax( 100.0f ),
- Skin( 0 ),
- ShieldStrength( 0 ),
- ShieldStrengthMax( 0 ),
- ShieldType( 0 ),
- DamagePoints( 0 ),
- DeathPoints( 0 )
- {
- }
- DefenseObjectDefClass::~DefenseObjectDefClass(void)
- {
- }
- bool DefenseObjectDefClass::Save(ChunkSaveClass &csave)
- {
- csave.Begin_Chunk(DEFENSEOBJECTDEF_CHUNK_VARIABLES);
- WRITE_SAFE_MICRO_CHUNK(csave,DEFENSEOBJECTDEF_VARIABLE_HEALTH, Health, float);
- WRITE_SAFE_MICRO_CHUNK(csave,DEFENSEOBJECTDEF_VARIABLE_HEALTHMAX,HealthMax, float);
- int skin_save_id = ArmorWarheadManager::Get_Armor_Save_ID( Skin );
- WRITE_MICRO_CHUNK(csave,DEFENSEOBJECTDEF_VARIABLE_SKIN,skin_save_id);
- WRITE_SAFE_MICRO_CHUNK(csave,DEFENSEOBJECTDEF_VARIABLE_SHIELDSTRENGTH, ShieldStrength, float);
- WRITE_SAFE_MICRO_CHUNK(csave,DEFENSEOBJECTDEF_VARIABLE_SHIELDSTRENGTHMAX, ShieldStrengthMax, float);
- int shield_save_id = ArmorWarheadManager::Get_Armor_Save_ID( ShieldType );
- WRITE_MICRO_CHUNK(csave,DEFENSEOBJECTDEF_VARIABLE_SHIELDTYPE,shield_save_id);
- WRITE_SAFE_MICRO_CHUNK(csave,DEFENSEOBJECTDEF_VARIABLE_DAMAGE_POINTS,DamagePoints, float);
- WRITE_SAFE_MICRO_CHUNK(csave,DEFENSEOBJECTDEF_VARIABLE_DEATH_POINTS,DeathPoints, float);
- csave.End_Chunk();
- return true;
- }
- bool DefenseObjectDefClass::Load(ChunkLoadClass &cload)
- {
- int skin_save_id = -2;
- int shield_save_id = -2;
- while (cload.Open_Chunk()) {
- switch(cload.Cur_Chunk_ID())
- {
- case DEFENSEOBJECTDEF_CHUNK_VARIABLES:
- while (cload.Open_Micro_Chunk()) {
- switch(cload.Cur_Micro_Chunk_ID()) {
- READ_SAFE_MICRO_CHUNK(cload,DEFENSEOBJECTDEF_VARIABLE_HEALTH,Health,float);
- READ_SAFE_MICRO_CHUNK(cload,DEFENSEOBJECTDEF_VARIABLE_HEALTHMAX,HealthMax,float);
- READ_MICRO_CHUNK(cload,DEFENSEOBJECTDEF_VARIABLE_SKIN,skin_save_id);
- READ_SAFE_MICRO_CHUNK(cload,DEFENSEOBJECTDEF_VARIABLE_SHIELDSTRENGTH,ShieldStrength,float);
- READ_SAFE_MICRO_CHUNK(cload,DEFENSEOBJECTDEF_VARIABLE_SHIELDSTRENGTHMAX,ShieldStrengthMax,float);
- READ_MICRO_CHUNK(cload,DEFENSEOBJECTDEF_VARIABLE_SHIELDTYPE,shield_save_id);
- READ_SAFE_MICRO_CHUNK(cload,DEFENSEOBJECTDEF_VARIABLE_DAMAGE_POINTS,DamagePoints,float);
- READ_SAFE_MICRO_CHUNK(cload,DEFENSEOBJECTDEF_VARIABLE_DEATH_POINTS,DeathPoints,float);
- }
- cload.Close_Micro_Chunk();
- }
- break;
- default:
- WWDEBUG_SAY(("Unhandled Chunk: 0x%X File: %s Line: %d\r\n",cload.Cur_Chunk_ID(),__FILE__,__LINE__));
- break;
- };
- cload.Close_Chunk();
- }
- Skin = ArmorWarheadManager::Find_Armor_Save_ID( skin_save_id );
- ShieldType = ArmorWarheadManager::Find_Armor_Save_ID( shield_save_id );
- return true;
- }
- void DefenseObjectClass::Set_Health(float health)
- {
- float old_health = Health;
- Health = WWMath::Clamp(health, 0, HealthMax);
- if ( old_health != (float)Health ) {
- Mark_Owner_Dirty();
- }
- }
- void DefenseObjectClass::Add_Health(float add_health)
- {
- Set_Health( WWMath::Clamp((float)Health + add_health, 0, HealthMax) );
- }
- float DefenseObjectClass::Get_Health(void) const
- {
- return Health;
- }
- void DefenseObjectClass::Set_Health_Max(float health)
- {
- HealthMax = WWMath::Clamp(health, 0, MAX_MAX_HEALTH);
- Mark_Owner_Dirty();
- }
- float DefenseObjectClass::Get_Health_Max(void) const
- {
- return HealthMax;
- }
- void DefenseObjectClass::Set_Shield_Strength(float str)
- {
- float old = ShieldStrength;
- ShieldStrength = WWMath::Clamp(str, 0, ShieldStrengthMax);
- if ( old != (float)ShieldStrength ) {
- Mark_Owner_Dirty();
- }
- }
- void DefenseObjectClass::Add_Shield_Strength(float str)
- {
- Set_Shield_Strength( WWMath::Clamp((float)ShieldStrength + str, 0, ShieldStrengthMax) );
- }
- float DefenseObjectClass::Get_Shield_Strength(void) const
- {
- return ShieldStrength;
- }
- void DefenseObjectClass::Set_Shield_Strength_Max(float str)
- {
- ShieldStrengthMax = WWMath::Clamp(str, 0, MAX_MAX_SHIELD_STRENGTH);
- Mark_Owner_Dirty();
- }
- float DefenseObjectClass::Get_Shield_Strength_Max(void) const
- {
- return ShieldStrengthMax;
- }
- void DefenseObjectClass::Set_Precision(void)
- {
- //
- // This static function needs to be called after ArmorWarheadManager::Init
- // has done its work.
- //
- cEncoderList::Set_Precision(BITPACK_HEALTH, 0, (int) MAX_MAX_HEALTH);
- cEncoderList::Set_Precision(BITPACK_SHIELD_STRENGTH, 0, (int) MAX_MAX_SHIELD_STRENGTH);
- cEncoderList::Set_Precision(BITPACK_SHIELD_TYPE, 0,
- //ArmorWarheadManager::Get_Num_Armor_Types(), 1);
- ArmorWarheadManager::Get_Num_Armor_Types());
- }
- /*
- **
- */
- void DefenseObjectClass::Mark_Owner_Dirty( void )
- {
- if ( Get_Owner() != NULL ) {
- Get_Owner()->Set_Object_Dirty_Bit( NetworkObjectClass::BIT_OCCASIONAL, true );
- }
- }
- /*
- **
- */
- void DefenseObjectClass::Set_Shield_Type( ArmorType type )
- {
- ShieldType = type;
- Mark_Owner_Dirty();
- }
- //
- // Do extra stuff when somebody kills somebody
- //
- /*
- if ( Get_Owner() != NULL &&
- Get_Owner()->As_SmartGameObj() &&
- Get_Owner()->As_SmartGameObj()->Has_Player() ) {
- int victim_id = Get_Owner()->As_SmartGameObj()->Get_Control_Owner();
- smart->Get_Player_Data()->On_Kill(victim_id);
- }
- */
- /*
- if ( Get_Owner() != NULL &&
- Get_Owner()->As_DamageableGameObj() != NULL &&
- Get_Owner()->As_DamageableGameObj()->As_PhysicalGameObj() != NULL &&
- Get_Owner()->As_DamageableGameObj()->As_PhysicalGameObj()->As_SoldierGameObj() != NULL &&
- Get_Owner()->As_SmartGameObj() != smart) {
- int victim_id = Get_Owner()->As_SmartGameObj()->Get_Control_Owner();
- int victim_team = Get_Owner()->As_SmartGameObj()->Get_Player_Type();
- smart->Get_Player_Data()->On_Kill(victim_id, victim_team);
- }
- */
- /*
- if ( Get_Owner() != NULL &&
- Get_Owner()->As_SoldierGameObj != NULL &&
- Get_Owner()->As_SmartGameObj() != smart) {
- WWASSERT(Get_Owner()->As_SmartGameObj() != NULL);
- int victim_id = Get_Owner()->As_SmartGameObj()->Get_Control_Owner();
- int victim_team = Get_Owner()->As_SmartGameObj()->Get_Player_Type();
- smart->Get_Player_Data()->On_Kill(victim_id, victim_team);
- }
- */
|