| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284 |
- /*
- ** 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: CrateCollide.cpp ///////////////////////////////////////////////////////////////////////
- // Author: Graham Smallwood, March 2002
- // Desc: Abstract base Class Crate Collide
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- // INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
- #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
- #include "Common/BitFlagsIO.h"
- #include "Common/Player.h"
- #include "Common/Xfer.h"
- #include "Common/GameAudio.h"
- #include "Common/MiscAudio.h"
- #include "GameClient/Anim2D.h"
- #include "GameClient/FXList.h"
- #include "GameClient/InGameUI.h"
- #include "GameClient/Drawable.h"
- #include "GameLogic/GameLogic.h"
- #include "GameLogic/Object.h"
- #include "GameLogic/Module/CrateCollide.h"
- #ifdef _INTERNAL
- // for occasional debugging...
- //#pragma optimize("", off)
- //#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
- #endif
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- CrateCollideModuleData::CrateCollideModuleData()
- {
- m_isForbidOwnerPlayer = FALSE;
- m_executeAnimationDisplayTimeInSeconds = 0.0f;
- m_executeAnimationZRisePerSecond = 0.0f;
- m_executeAnimationFades = TRUE;
- m_isBuildingPickup = FALSE;
- m_isHumanOnlyPickup = FALSE;
- m_executeFX = NULL;
- m_pickupScience = SCIENCE_INVALID;
- // Added By Sadullah Nader
- // Initializations missing and needed
-
- m_executionAnimationTemplate = AsciiString::TheEmptyString;
-
- // End Add
- }
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- void CrateCollideModuleData::buildFieldParse(MultiIniFieldParse& p)
- {
- ModuleData::buildFieldParse(p);
- static const FieldParse dataFieldParse[] =
- {
- { "RequiredKindOf", KindOfMaskType::parseFromINI, NULL, offsetof( CrateCollideModuleData, m_kindof ) },
- { "ForbiddenKindOf", KindOfMaskType::parseFromINI, NULL, offsetof( CrateCollideModuleData, m_kindofnot ) },
- { "ForbidOwnerPlayer", INI::parseBool, NULL, offsetof( CrateCollideModuleData, m_isForbidOwnerPlayer ) },
- { "BuildingPickup", INI::parseBool, NULL, offsetof( CrateCollideModuleData, m_isBuildingPickup ) },
- { "HumanOnly", INI::parseBool, NULL, offsetof( CrateCollideModuleData, m_isHumanOnlyPickup ) },
- { "PickupScience", INI::parseScience, NULL, offsetof( CrateCollideModuleData, m_pickupScience ) },
- { "ExecuteFX", INI::parseFXList, NULL, offsetof( CrateCollideModuleData, m_executeFX ) },
- { "ExecuteAnimation", INI::parseAsciiString, NULL, offsetof( CrateCollideModuleData, m_executionAnimationTemplate ) },
- { "ExecuteAnimationTime", INI::parseReal, NULL, offsetof( CrateCollideModuleData, m_executeAnimationDisplayTimeInSeconds ) },
- { "ExecuteAnimationZRise", INI::parseReal, NULL, offsetof( CrateCollideModuleData, m_executeAnimationZRisePerSecond ) },
- { "ExecuteAnimationFades", INI::parseBool, NULL, offsetof( CrateCollideModuleData, m_executeAnimationFades ) },
- { 0, 0, 0, 0 }
- };
- p.add(dataFieldParse);
- }
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- CrateCollide::CrateCollide( Thing *thing, const ModuleData* moduleData ) : CollideModule( thing, moduleData )
- {
- }
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- CrateCollide::~CrateCollide( void )
- {
- }
- //-------------------------------------------------------------------------------------------------
- /** The collide event.
- * Note that when other is NULL it means "collide with ground" */
- //-------------------------------------------------------------------------------------------------
- void CrateCollide::onCollide( Object *other, const Coord3D *, const Coord3D * )
- {
- const CrateCollideModuleData *modData = getCrateCollideModuleData();
- // If the crate can be picked up, perform the game logic and destroy the crate.
- if( isValidToExecute( other ) )
- {
- if( executeCrateBehavior( other ) )
- {
- if( modData->m_executeFX != NULL )
- {
- // Note: We pass in other here, because the crate is owned by the neutral player, and
- // we want to do things that only the other person can see.
- FXList::doFXObj( modData->m_executeFX, other );
- }
- TheGameLogic->destroyObject( getObject() );
- }
- // play animation in the world at this spot if there is one
- if( TheAnim2DCollection && modData->m_executionAnimationTemplate.isEmpty() == FALSE && TheGameLogic->getDrawIconUI() )
- {
- Anim2DTemplate *animTemplate = TheAnim2DCollection->findTemplate( modData->m_executionAnimationTemplate );
- TheInGameUI->addWorldAnimation( animTemplate,
- getObject()->getPosition(),
- WORLD_ANIM_FADE_ON_EXPIRE,
- modData->m_executeAnimationDisplayTimeInSeconds,
- modData->m_executeAnimationZRisePerSecond );
- }
- }
- }
- //-------------------------------------------------------------------------------------------------
- Bool CrateCollide::isValidToExecute( const Object *other ) const
- {
- //The ground never picks up a crate
- if( other == NULL )
- return FALSE;
- //Nothing Neutral can pick up any type of crate
- if( other->isNeutralControlled() )
- return FALSE;
- const CrateCollideModuleData* md = getCrateCollideModuleData();
- Bool validBuildingAttempt = md->m_isBuildingPickup && other->isKindOf( KINDOF_STRUCTURE );
- // Must be a "Unit" type thing. Real Game Object, not just Object
- if( other->getAIUpdateInterface() == NULL && !validBuildingAttempt )// Building exception flag for Drop Zone
- return FALSE;
- // must match our kindof flags (if any)
- if (md && !other->isKindOfMulti(md->m_kindof, md->m_kindofnot))
- return FALSE;
- if( other->isEffectivelyDead() )
- return FALSE;
- // crates cannot be claimed while in the air, except by buildings
- if( getObject()->isAboveTerrain() && !validBuildingAttempt )
- return FALSE;
- if( md->m_isForbidOwnerPlayer && (getObject()->getControllingPlayer() == other->getControllingPlayer()) )
- return FALSE; // Design has decreed this to not be picked up by the dead guy's team.
- if( md->m_isHumanOnlyPickup && other->getControllingPlayer() && (other->getControllingPlayer()->getPlayerType() != PLAYER_HUMAN) )
- return FALSE; // Human only mission crate
- if( (md->m_pickupScience != SCIENCE_INVALID) && other->getControllingPlayer() && !other->getControllingPlayer()->hasScience(md->m_pickupScience) )
- return FALSE; // Science required to pick this up
- if( other->isKindOf( KINDOF_PARACHUTE ) )
- return FALSE;
- return TRUE;
- }
- void CrateCollide::doSabotageFeedbackFX( const Object *other, SabotageVictimType type )
- {
- if ( ! getObject() )
- return;
- if ( ! other )
- return;
- AudioEventRTS soundToPlay;
- switch ( type )
- {
- case CrateCollide::SAB_VICTIM_FAKE_BUILDING:
- {
- return; // THIS NEEDS NO ADD'L FEEDBACK
- }
- case CrateCollide::SAB_VICTIM_COMMAND_CENTER:
- case CrateCollide::SAB_VICTIM_SUPERWEAPON:
- {
- soundToPlay = TheAudio->getMiscAudio()->m_sabotageResetTimerBuilding;
- break;
- }
- case CrateCollide::SAB_VICTIM_DROP_ZONE:
- case CrateCollide::SAB_VICTIM_SUPPLY_CENTER:
- {
- soundToPlay = TheAudio->getMiscAudio()->m_moneyWithdrawSound;
- break;
- }
- case CrateCollide::SAB_VICTIM_INTERNET_CENTER:
- case CrateCollide::SAB_VICTIM_MILITARY_FACTORY:
- case CrateCollide::SAB_VICTIM_POWER_PLANT:
- default:
- {
- soundToPlay = TheAudio->getMiscAudio()->m_sabotageShutDownBuilding;
- break;
- }
- }
- soundToPlay.setPosition( other->getPosition() );
- TheAudio->addAudioEvent( &soundToPlay );
- Drawable *draw = other->getDrawable();
- if ( draw )
- draw->flashAsSelected();
- }
- // ------------------------------------------------------------------------------------------------
- /** CRC */
- // ------------------------------------------------------------------------------------------------
- void CrateCollide::crc( Xfer *xfer )
- {
- // extend base class
- CollideModule::crc( xfer );
- } // end crc
- // ------------------------------------------------------------------------------------------------
- /** Xfer Method
- * Version Info:
- * 1: Initial version */
- // ------------------------------------------------------------------------------------------------
- void CrateCollide::xfer( Xfer *xfer )
- {
- // version
- XferVersion currentVersion = 1;
- XferVersion version = currentVersion;
- xfer->xferVersion( &version, currentVersion );
- // extend base class
- CollideModule::xfer( xfer );
- } // end xfer
- // ------------------------------------------------------------------------------------------------
- /** Load post process */
- // ------------------------------------------------------------------------------------------------
- void CrateCollide::loadPostProcess( void )
- {
- // extend base class
- CollideModule::loadPostProcess();
- } // end loadPostProcess
|