| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381 |
- /*
- ** Command & Conquer Generals Zero Hour(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- ////////////////////////////////////////////////////////////////////////////////
- // //
- // (c) 2001-2003 Electronic Arts Inc. //
- // //
- ////////////////////////////////////////////////////////////////////////////////
- // FILE: SpecialPower.cpp /////////////////////////////////////////////////////////////////////////
- // Author: Colin Day, April 2002
- // Desc: Special power templates and the system that holds them
- // Edited: Kris Morness -- July 2002 (added BitFlag system)
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- // USER INCLUDES //////////////////////////////////////////////////////////////////////////////////
- #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
- #include "Common/Player.h"
- #include "Common/Science.h"
- #include "Common/SpecialPower.h"
- #include "GameLogic/Object.h"
- #include "Common/BitFlagsIO.h"
- #ifdef _INTERNAL
- // for occasional debugging...
- //#pragma optimize("", off)
- //#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
- #endif
- // GLOBAL /////////////////////////////////////////////////////////////////////////////////////////
- SpecialPowerStore *TheSpecialPowerStore = NULL;
- #define DEFAULT_DEFECTION_DETECTION_PROTECTION_TIME_LIMIT (LOGICFRAMES_PER_SECOND * 10)
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- // Externs ////////////////////////////////////////////////////////////////////////////////////////
- const char* SpecialPowerMaskType::s_bitNameList[] =
- {
- "SPECIAL_INVALID",
- //Superweapons
- "SPECIAL_DAISY_CUTTER",
- "SPECIAL_PARADROP_AMERICA",
- "SPECIAL_CARPET_BOMB",
- "SPECIAL_CLUSTER_MINES",
- "SPECIAL_EMP_PULSE",
- "SPECIAL_NAPALM_STRIKE",
- "SPECIAL_CASH_HACK",
- "SPECIAL_NEUTRON_MISSILE",
- "SPECIAL_SPY_SATELLITE",
- "SPECIAL_DEFECTOR",
- "SPECIAL_TERROR_CELL",
- "SPECIAL_AMBUSH",
- "SPECIAL_BLACK_MARKET_NUKE",
- "SPECIAL_ANTHRAX_BOMB",
- "SPECIAL_SCUD_STORM",
- #ifdef ALLOW_DEMORALIZE
- "SPECIAL_DEMORALIZE",
- #else
- "SPECIAL_DEMORALIZE_OBSOLETE",
- #endif
- "SPECIAL_CRATE_DROP",
- "SPECIAL_A10_THUNDERBOLT_STRIKE",
- "SPECIAL_DETONATE_DIRTY_NUKE",
- "SPECIAL_ARTILLERY_BARRAGE",
- //Special abilities
- "SPECIAL_MISSILE_DEFENDER_LASER_GUIDED_MISSILES",
- "SPECIAL_REMOTE_CHARGES",
- "SPECIAL_TIMED_CHARGES",
- "SPECIAL_HELIX_NAPALM_BOMB",
- "SPECIAL_HACKER_DISABLE_BUILDING",
- "SPECIAL_TANKHUNTER_TNT_ATTACK",
- "SPECIAL_BLACKLOTUS_CAPTURE_BUILDING",
- "SPECIAL_BLACKLOTUS_DISABLE_VEHICLE_HACK",
- "SPECIAL_BLACKLOTUS_STEAL_CASH_HACK",
- "SPECIAL_INFANTRY_CAPTURE_BUILDING",
- "SPECIAL_RADAR_VAN_SCAN",
- "SPECIAL_SPY_DRONE",
- "SPECIAL_DISGUISE_AS_VEHICLE",
- "SPECIAL_BOOBY_TRAP",
- "SPECIAL_REPAIR_VEHICLES",
- "SPECIAL_PARTICLE_UPLINK_CANNON",
- "SPECIAL_CASH_BOUNTY",
- "SPECIAL_CHANGE_BATTLE_PLANS",
- "SPECIAL_CIA_INTELLIGENCE",
- "SPECIAL_CLEANUP_AREA",
- "SPECIAL_LAUNCH_BAIKONUR_ROCKET",
- "SPECIAL_SPECTRE_GUNSHIP",
- "SPECIAL_GPS_SCRAMBLER",
- "SPECIAL_FRENZY",
- "SPECIAL_SNEAK_ATTACK",
- "SPECIAL_CHINA_CARPET_BOMB",
- "EARLY_SPECIAL_CHINA_CARPET_BOMB",
- "SPECIAL_LEAFLET_DROP",
- "EARLY_SPECIAL_LEAFLET_DROP",
- "EARLY_SPECIAL_FRENZY",
- "SPECIAL_COMMUNICATIONS_DOWNLOAD",
- "EARLY_SPECIAL_REPAIR_VEHICLES",
- "SPECIAL_TANK_PARADROP",
- "SUPW_SPECIAL_PARTICLE_UPLINK_CANNON",
- "AIRF_SPECIAL_DAISY_CUTTER",
- "NUKE_SPECIAL_CLUSTER_MINES",
- "NUKE_SPECIAL_NEUTRON_MISSILE",
- "AIRF_SPECIAL_A10_THUNDERBOLT_STRIKE",
- "AIRF_SPECIAL_SPECTRE_GUNSHIP",
- "INFA_SPECIAL_PARADROP_AMERICA",
- "SLTH_SPECIAL_GPS_SCRAMBLER",
- "AIRF_SPECIAL_CARPET_BOMB",
- "SUPR_SPECIAL_CRUISE_MISSILE",
- "LAZR_SPECIAL_PARTICLE_UPLINK_CANNON",
- "SUPW_SPECIAL_NEUTRON_MISSILE",
-
- "SPECIAL_BATTLESHIP_BOMBARDMENT",
- NULL
- };
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- void SpecialPowerStore::parseSpecialPowerDefinition( INI *ini )
- {
- // read the name
- AsciiString name = ini->getNextToken();
- SpecialPowerTemplate* specialPower = TheSpecialPowerStore->findSpecialPowerTemplatePrivate( name );
- if ( ini->getLoadType() == INI_LOAD_CREATE_OVERRIDES )
- {
- if (specialPower)
- {
- SpecialPowerTemplate* child = (SpecialPowerTemplate*)specialPower->friend_getFinalOverride();
- specialPower = newInstance(SpecialPowerTemplate);
- *specialPower = *child;
- child->setNextOverride(specialPower);
- specialPower->markAsOverride();
- //TheSpecialPowerStore->m_specialPowerTemplates.push_back(specialPower); // nope, do NOT do this
- }
- else
- {
- specialPower = newInstance(SpecialPowerTemplate);
- const SpecialPowerTemplate *defaultTemplate = TheSpecialPowerStore->findSpecialPowerTemplate( "DefaultSpecialPower" );
- if( defaultTemplate )
- *specialPower = *defaultTemplate;
- specialPower->friend_setNameAndID(name, ++TheSpecialPowerStore->m_nextSpecialPowerID);
- specialPower->markAsOverride();
- TheSpecialPowerStore->m_specialPowerTemplates.push_back(specialPower);
- }
- }
- else
- {
- if (specialPower)
- {
- throw INI_INVALID_DATA;
- }
- else
- {
- specialPower = newInstance(SpecialPowerTemplate);
- const SpecialPowerTemplate *defaultTemplate = TheSpecialPowerStore->findSpecialPowerTemplate( "DefaultSpecialPower" );
- if( defaultTemplate )
- *specialPower = *defaultTemplate;
- specialPower->friend_setNameAndID(name, ++TheSpecialPowerStore->m_nextSpecialPowerID);
- TheSpecialPowerStore->m_specialPowerTemplates.push_back(specialPower);
- }
- }
- // parse the ini definition
- if (specialPower)
- ini->initFromINI( specialPower, specialPower->getFieldParse() );
- }
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- /* static */ const FieldParse SpecialPowerTemplate::m_specialPowerFieldParse[] =
- {
-
- { "ReloadTime", INI::parseDurationUnsignedInt, NULL, offsetof( SpecialPowerTemplate, m_reloadTime ) },
- { "RequiredScience", INI::parseScience, NULL, offsetof( SpecialPowerTemplate, m_requiredScience ) },
- { "InitiateSound", INI::parseAudioEventRTS, NULL, offsetof( SpecialPowerTemplate, m_initiateSound ) },
- { "InitiateAtLocationSound", INI::parseAudioEventRTS, NULL, offsetof( SpecialPowerTemplate, m_initiateAtLocationSound ) },
- { "PublicTimer", INI::parseBool, NULL, offsetof( SpecialPowerTemplate, m_publicTimer ) },
- { "Enum", INI::parseIndexList, SpecialPowerMaskType::getBitNames(), offsetof( SpecialPowerTemplate, m_type ) },
- { "DetectionTime", INI::parseDurationUnsignedInt, NULL, offsetof( SpecialPowerTemplate, m_detectionTime ) },
- { "SharedSyncedTimer", INI::parseBool, NULL, offsetof( SpecialPowerTemplate, m_sharedNSync ) },
- { "ViewObjectDuration", INI::parseDurationUnsignedInt, NULL, offsetof( SpecialPowerTemplate, m_viewObjectDuration ) },
- { "ViewObjectRange", INI::parseReal, NULL, offsetof( SpecialPowerTemplate, m_viewObjectRange ) },
- { "RadiusCursorRadius", INI::parseReal, NULL, offsetof( SpecialPowerTemplate, m_radiusCursorRadius ) },
- { "ShortcutPower", INI::parseBool, NULL, offsetof( SpecialPowerTemplate, m_shortcutPower ) },
- { "AcademyClassify", INI::parseIndexList, TheAcademyClassificationTypeNames, offsetof( SpecialPowerTemplate, m_academyClassificationType ) },
- { NULL, NULL, NULL, 0 } // keep this last
- };
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- SpecialPowerTemplate::SpecialPowerTemplate()
- {
- m_id = 0;
- m_type = SPECIAL_INVALID;
- m_reloadTime = 0;
- m_requiredScience = SCIENCE_INVALID;
- m_publicTimer = FALSE;
- m_detectionTime = DEFAULT_DEFECTION_DETECTION_PROTECTION_TIME_LIMIT;
- m_sharedNSync = FALSE;
- m_viewObjectDuration = 0;
- m_viewObjectRange = 0;
- m_radiusCursorRadius = 0;
- m_shortcutPower = FALSE;
- } // end SpecialPowerTemplate
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- SpecialPowerTemplate::~SpecialPowerTemplate()
- {
- } // end ~SpecialPowerTemplate
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- SpecialPowerStore::SpecialPowerStore( void )
- {
- m_nextSpecialPowerID = 0;
- } // end SpecialPowerStore
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- SpecialPowerStore::~SpecialPowerStore( void )
- {
- // delete all templates
- for( Int i = 0; i < m_specialPowerTemplates.size(); ++i )
- m_specialPowerTemplates[ i ]->deleteInstance();
- // erase the list
- m_specialPowerTemplates.clear();
- // set our count to zero
- m_nextSpecialPowerID = 0;
- } // end ~SpecialPowerStore
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- SpecialPowerTemplate* SpecialPowerStore::findSpecialPowerTemplatePrivate( AsciiString name )
- {
- // search the template list for matching name
- for( Int i = 0; i < m_specialPowerTemplates.size(); ++i )
- if( m_specialPowerTemplates[ i ]->getName() == name )
- return m_specialPowerTemplates[ i ];
- return NULL; // not found
- }
- //-------------------------------------------------------------------------------------------------
- /** Find a special power template given unique ID */
- //-------------------------------------------------------------------------------------------------
- const SpecialPowerTemplate *SpecialPowerStore::findSpecialPowerTemplateByID( UnsignedInt id )
- {
- // search the template list for matching name
- for( Int i = 0; i < m_specialPowerTemplates.size(); ++i )
- if( m_specialPowerTemplates[ i ]->getID() == id )
- return m_specialPowerTemplates[ i ];
- return NULL; // not found
- }
- //-------------------------------------------------------------------------------------------------
- /** Find a special power template given index (WB) */
- //-------------------------------------------------------------------------------------------------
- const SpecialPowerTemplate *SpecialPowerStore::getSpecialPowerTemplateByIndex( UnsignedInt index )
- {
- if (index >= 0 && index < m_specialPowerTemplates.size())
- return m_specialPowerTemplates[ index ];
- return NULL; // not found
- } // end getSpecialPowerTemplateByIndex
- //-------------------------------------------------------------------------------------------------
- /** Return the size of the store (WB) */
- //-------------------------------------------------------------------------------------------------
- Int SpecialPowerStore::getNumSpecialPowers( void )
- {
- return m_specialPowerTemplates.size();
- } // end getNumSpecialPowers
- //-------------------------------------------------------------------------------------------------
- /** does the object (and therefore the player) meet all the requirements to use this power */
- //-------------------------------------------------------------------------------------------------
- Bool SpecialPowerStore::canUseSpecialPower( Object *obj, const SpecialPowerTemplate *specialPowerTemplate )
- {
- // sanity
- if( obj == NULL || specialPowerTemplate == NULL )
- return FALSE;
- // as a first sanity check, the object must have a module capable of executing the power
- if( obj->getSpecialPowerModule( specialPowerTemplate ) == NULL )
- return FALSE;
- //
- // in order to execute the special powers we have attached special power modules to the objects
- // that can use them. However, just because an object has a module that is capable of
- // doing the power, does not mean the object and the player can actually execute the
- // power because some powers require a specialized science that the player must select and
- // they cannot have all of them.
- //
-
- // check for requried science
- ScienceType requiredScience = specialPowerTemplate->getRequiredScience();
- if( requiredScience != SCIENCE_INVALID )
- {
- Player *player = obj->getControllingPlayer();
- if( player->hasScience( requiredScience ) == FALSE )
- return FALSE;
- } // end if
-
- // I THINK THIS IS WHERE WE BAIL OUT IF A DIFFERENT CONYARD IS ALREADY CHARGIN THIS SPECIAL RIGHT NOW //LORENZEN
- // all is well
- return TRUE;
- } // end canUseSpecialPower
- //-------------------------------------------------------------------------------------------------
- /** Reset */
- //-------------------------------------------------------------------------------------------------
- void SpecialPowerStore::reset( void )
- {
- for (SpecialPowerTemplatePtrVector::iterator it = m_specialPowerTemplates.begin(); it != m_specialPowerTemplates.end(); /*++it*/)
- {
- SpecialPowerTemplate* si = *it;
- Overridable* temp = si->deleteOverrides();
- if (temp == NULL)
- {
- it = m_specialPowerTemplates.erase(it);
- }
- else
- {
- ++it;
- }
- }
- } // end reset
|