CrateCollide.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. /*
  2. ** Command & Conquer Generals Zero Hour(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. ////////////////////////////////////////////////////////////////////////////////
  19. // //
  20. // (c) 2001-2003 Electronic Arts Inc. //
  21. // //
  22. ////////////////////////////////////////////////////////////////////////////////
  23. // FILE: CrateCollide.cpp ///////////////////////////////////////////////////////////////////////
  24. // Author: Graham Smallwood, March 2002
  25. // Desc: Abstract base Class Crate Collide
  26. ///////////////////////////////////////////////////////////////////////////////////////////////////
  27. // INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
  28. #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
  29. #include "Common/BitFlagsIO.h"
  30. #include "Common/Player.h"
  31. #include "Common/Xfer.h"
  32. #include "Common/GameAudio.h"
  33. #include "Common/MiscAudio.h"
  34. #include "GameClient/Anim2D.h"
  35. #include "GameClient/FXList.h"
  36. #include "GameClient/InGameUI.h"
  37. #include "GameClient/Drawable.h"
  38. #include "GameLogic/GameLogic.h"
  39. #include "GameLogic/Object.h"
  40. #include "GameLogic/Module/CrateCollide.h"
  41. #ifdef _INTERNAL
  42. // for occasional debugging...
  43. //#pragma optimize("", off)
  44. //#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
  45. #endif
  46. //-------------------------------------------------------------------------------------------------
  47. //-------------------------------------------------------------------------------------------------
  48. CrateCollideModuleData::CrateCollideModuleData()
  49. {
  50. m_isForbidOwnerPlayer = FALSE;
  51. m_executeAnimationDisplayTimeInSeconds = 0.0f;
  52. m_executeAnimationZRisePerSecond = 0.0f;
  53. m_executeAnimationFades = TRUE;
  54. m_isBuildingPickup = FALSE;
  55. m_isHumanOnlyPickup = FALSE;
  56. m_executeFX = NULL;
  57. m_pickupScience = SCIENCE_INVALID;
  58. // Added By Sadullah Nader
  59. // Initializations missing and needed
  60. m_executionAnimationTemplate = AsciiString::TheEmptyString;
  61. // End Add
  62. }
  63. //-------------------------------------------------------------------------------------------------
  64. //-------------------------------------------------------------------------------------------------
  65. void CrateCollideModuleData::buildFieldParse(MultiIniFieldParse& p)
  66. {
  67. ModuleData::buildFieldParse(p);
  68. static const FieldParse dataFieldParse[] =
  69. {
  70. { "RequiredKindOf", KindOfMaskType::parseFromINI, NULL, offsetof( CrateCollideModuleData, m_kindof ) },
  71. { "ForbiddenKindOf", KindOfMaskType::parseFromINI, NULL, offsetof( CrateCollideModuleData, m_kindofnot ) },
  72. { "ForbidOwnerPlayer", INI::parseBool, NULL, offsetof( CrateCollideModuleData, m_isForbidOwnerPlayer ) },
  73. { "BuildingPickup", INI::parseBool, NULL, offsetof( CrateCollideModuleData, m_isBuildingPickup ) },
  74. { "HumanOnly", INI::parseBool, NULL, offsetof( CrateCollideModuleData, m_isHumanOnlyPickup ) },
  75. { "PickupScience", INI::parseScience, NULL, offsetof( CrateCollideModuleData, m_pickupScience ) },
  76. { "ExecuteFX", INI::parseFXList, NULL, offsetof( CrateCollideModuleData, m_executeFX ) },
  77. { "ExecuteAnimation", INI::parseAsciiString, NULL, offsetof( CrateCollideModuleData, m_executionAnimationTemplate ) },
  78. { "ExecuteAnimationTime", INI::parseReal, NULL, offsetof( CrateCollideModuleData, m_executeAnimationDisplayTimeInSeconds ) },
  79. { "ExecuteAnimationZRise", INI::parseReal, NULL, offsetof( CrateCollideModuleData, m_executeAnimationZRisePerSecond ) },
  80. { "ExecuteAnimationFades", INI::parseBool, NULL, offsetof( CrateCollideModuleData, m_executeAnimationFades ) },
  81. { 0, 0, 0, 0 }
  82. };
  83. p.add(dataFieldParse);
  84. }
  85. //-------------------------------------------------------------------------------------------------
  86. //-------------------------------------------------------------------------------------------------
  87. CrateCollide::CrateCollide( Thing *thing, const ModuleData* moduleData ) : CollideModule( thing, moduleData )
  88. {
  89. }
  90. //-------------------------------------------------------------------------------------------------
  91. //-------------------------------------------------------------------------------------------------
  92. CrateCollide::~CrateCollide( void )
  93. {
  94. }
  95. //-------------------------------------------------------------------------------------------------
  96. /** The collide event.
  97. * Note that when other is NULL it means "collide with ground" */
  98. //-------------------------------------------------------------------------------------------------
  99. void CrateCollide::onCollide( Object *other, const Coord3D *, const Coord3D * )
  100. {
  101. const CrateCollideModuleData *modData = getCrateCollideModuleData();
  102. // If the crate can be picked up, perform the game logic and destroy the crate.
  103. if( isValidToExecute( other ) )
  104. {
  105. if( executeCrateBehavior( other ) )
  106. {
  107. if( modData->m_executeFX != NULL )
  108. {
  109. // Note: We pass in other here, because the crate is owned by the neutral player, and
  110. // we want to do things that only the other person can see.
  111. FXList::doFXObj( modData->m_executeFX, other );
  112. }
  113. TheGameLogic->destroyObject( getObject() );
  114. }
  115. // play animation in the world at this spot if there is one
  116. if( TheAnim2DCollection && modData->m_executionAnimationTemplate.isEmpty() == FALSE && TheGameLogic->getDrawIconUI() )
  117. {
  118. Anim2DTemplate *animTemplate = TheAnim2DCollection->findTemplate( modData->m_executionAnimationTemplate );
  119. TheInGameUI->addWorldAnimation( animTemplate,
  120. getObject()->getPosition(),
  121. WORLD_ANIM_FADE_ON_EXPIRE,
  122. modData->m_executeAnimationDisplayTimeInSeconds,
  123. modData->m_executeAnimationZRisePerSecond );
  124. }
  125. }
  126. }
  127. //-------------------------------------------------------------------------------------------------
  128. Bool CrateCollide::isValidToExecute( const Object *other ) const
  129. {
  130. //The ground never picks up a crate
  131. if( other == NULL )
  132. return FALSE;
  133. //Nothing Neutral can pick up any type of crate
  134. if( other->isNeutralControlled() )
  135. return FALSE;
  136. const CrateCollideModuleData* md = getCrateCollideModuleData();
  137. Bool validBuildingAttempt = md->m_isBuildingPickup && other->isKindOf( KINDOF_STRUCTURE );
  138. // Must be a "Unit" type thing. Real Game Object, not just Object
  139. if( other->getAIUpdateInterface() == NULL && !validBuildingAttempt )// Building exception flag for Drop Zone
  140. return FALSE;
  141. // must match our kindof flags (if any)
  142. if (md && !other->isKindOfMulti(md->m_kindof, md->m_kindofnot))
  143. return FALSE;
  144. if( other->isEffectivelyDead() )
  145. return FALSE;
  146. // crates cannot be claimed while in the air, except by buildings
  147. if( getObject()->isAboveTerrain() && !validBuildingAttempt )
  148. return FALSE;
  149. if( md->m_isForbidOwnerPlayer && (getObject()->getControllingPlayer() == other->getControllingPlayer()) )
  150. return FALSE; // Design has decreed this to not be picked up by the dead guy's team.
  151. if( md->m_isHumanOnlyPickup && other->getControllingPlayer() && (other->getControllingPlayer()->getPlayerType() != PLAYER_HUMAN) )
  152. return FALSE; // Human only mission crate
  153. if( (md->m_pickupScience != SCIENCE_INVALID) && other->getControllingPlayer() && !other->getControllingPlayer()->hasScience(md->m_pickupScience) )
  154. return FALSE; // Science required to pick this up
  155. if( other->isKindOf( KINDOF_PARACHUTE ) )
  156. return FALSE;
  157. return TRUE;
  158. }
  159. void CrateCollide::doSabotageFeedbackFX( const Object *other, SabotageVictimType type )
  160. {
  161. if ( ! getObject() )
  162. return;
  163. if ( ! other )
  164. return;
  165. AudioEventRTS soundToPlay;
  166. switch ( type )
  167. {
  168. case CrateCollide::SAB_VICTIM_FAKE_BUILDING:
  169. {
  170. return; // THIS NEEDS NO ADD'L FEEDBACK
  171. }
  172. case CrateCollide::SAB_VICTIM_COMMAND_CENTER:
  173. case CrateCollide::SAB_VICTIM_SUPERWEAPON:
  174. {
  175. soundToPlay = TheAudio->getMiscAudio()->m_sabotageResetTimerBuilding;
  176. break;
  177. }
  178. case CrateCollide::SAB_VICTIM_DROP_ZONE:
  179. case CrateCollide::SAB_VICTIM_SUPPLY_CENTER:
  180. {
  181. soundToPlay = TheAudio->getMiscAudio()->m_moneyWithdrawSound;
  182. break;
  183. }
  184. case CrateCollide::SAB_VICTIM_INTERNET_CENTER:
  185. case CrateCollide::SAB_VICTIM_MILITARY_FACTORY:
  186. case CrateCollide::SAB_VICTIM_POWER_PLANT:
  187. default:
  188. {
  189. soundToPlay = TheAudio->getMiscAudio()->m_sabotageShutDownBuilding;
  190. break;
  191. }
  192. }
  193. soundToPlay.setPosition( other->getPosition() );
  194. TheAudio->addAudioEvent( &soundToPlay );
  195. Drawable *draw = other->getDrawable();
  196. if ( draw )
  197. draw->flashAsSelected();
  198. }
  199. // ------------------------------------------------------------------------------------------------
  200. /** CRC */
  201. // ------------------------------------------------------------------------------------------------
  202. void CrateCollide::crc( Xfer *xfer )
  203. {
  204. // extend base class
  205. CollideModule::crc( xfer );
  206. } // end crc
  207. // ------------------------------------------------------------------------------------------------
  208. /** Xfer Method
  209. * Version Info:
  210. * 1: Initial version */
  211. // ------------------------------------------------------------------------------------------------
  212. void CrateCollide::xfer( Xfer *xfer )
  213. {
  214. // version
  215. XferVersion currentVersion = 1;
  216. XferVersion version = currentVersion;
  217. xfer->xferVersion( &version, currentVersion );
  218. // extend base class
  219. CollideModule::xfer( xfer );
  220. } // end xfer
  221. // ------------------------------------------------------------------------------------------------
  222. /** Load post process */
  223. // ------------------------------------------------------------------------------------------------
  224. void CrateCollide::loadPostProcess( void )
  225. {
  226. // extend base class
  227. CollideModule::loadPostProcess();
  228. } // end loadPostProcess