CrushDie.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. /*
  2. ** Command & Conquer Generals(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: CrushDie.cpp ///////////////////////////////////////////////////////////////////////////
  24. // Author: Colin Day, November 2001
  25. // Desc: Crush Die module
  26. ///////////////////////////////////////////////////////////////////////////////////////////////////
  27. // INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
  28. #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
  29. #include "Common/Player.h"
  30. #include "Common/PlayerList.h"
  31. #include "Common/RandomValue.h"
  32. #include "Common/ThingFactory.h"
  33. #include "Common/ThingTemplate.h"
  34. #include "Common/Xfer.h"
  35. #include "GameClient/Drawable.h"
  36. #include "GameLogic/GameLogic.h"
  37. #include "GameLogic/Object.h"
  38. #include "GameLogic/Module/BodyModule.h"
  39. #include "GameLogic/Module/CrushDie.h"
  40. //-------------------------------------------------------------------------------------------------
  41. // Figure out which crush point was hit so the correct crushed object can be swapped in
  42. // Figure out which crush point was hit so the correct crushed object can be swapped in
  43. static CrushEnum crushLocationCheck( Object* crusherObject, Object* victimObject )
  44. {
  45. if( (crusherObject == NULL) || (victimObject == NULL) )
  46. return NO_CRUSH;
  47. Bool frontCrushed = victimObject->getBodyModule()->getFrontCrushed();
  48. Bool backCrushed = victimObject->getBodyModule()->getBackCrushed();
  49. // const Coord3D *dir = crusherObject->getUnitDirectionVector2D();
  50. const Coord3D *otherDir = victimObject->getUnitDirectionVector2D();
  51. const Coord3D *pos = crusherObject->getPosition();
  52. const Coord3D *otherPos = victimObject->getPosition();
  53. Real crushPointOffsetDistance = victimObject->getGeometryInfo().getMajorRadius() * 0.5;
  54. Coord3D crushPointOffset;
  55. crushPointOffset.x = otherDir->x * crushPointOffsetDistance;
  56. crushPointOffset.y = otherDir->y * crushPointOffsetDistance;
  57. crushPointOffset.z = 0;
  58. Coord3D comparisonCoord;
  59. Real dx, dy;
  60. CrushEnum retval = NO_CRUSH;
  61. Real bestDist = 99999;
  62. // PhysicsCollide has already done the logic of which point to smoosh and waited until we crossed that point
  63. // so at this point we just need to know which crush point is closest.
  64. if( !frontCrushed && !backCrushed )
  65. {
  66. // Check the middle crush point
  67. comparisonCoord = *otherPos;//copy so can move to each crush point
  68. dx = comparisonCoord.x - pos->x;
  69. dy = comparisonCoord.y - pos->y;
  70. Real dist = (Real)( dx*dx + dy*dy );
  71. //otherwise we want to make sure we get the closest valid crush point
  72. retval = TOTAL_CRUSH;
  73. bestDist = dist;
  74. }
  75. if( !frontCrushed )
  76. {
  77. // Check the front point.
  78. comparisonCoord = *otherPos;
  79. comparisonCoord.x += crushPointOffset.x;
  80. comparisonCoord.y += crushPointOffset.y;
  81. dx = comparisonCoord.x - pos->x;
  82. dy = comparisonCoord.y - pos->y;
  83. Real dist = (Real)( dx*dx + dy*dy );
  84. if( dist < bestDist )//closer
  85. {
  86. if( backCrushed )
  87. {
  88. retval = TOTAL_CRUSH;
  89. bestDist = dist;
  90. }
  91. else
  92. {
  93. retval = FRONT_END_CRUSH;
  94. bestDist = dist;
  95. }
  96. }
  97. }
  98. if( !backCrushed )
  99. {
  100. // Check back point
  101. comparisonCoord = *otherPos;
  102. comparisonCoord.x -= crushPointOffset.x;
  103. comparisonCoord.y -= crushPointOffset.y;
  104. dx = comparisonCoord.x - pos->x;
  105. dy = comparisonCoord.y - pos->y;
  106. Real dist = (Real)( dx*dx + dy*dy );
  107. if( dist < bestDist )//closer
  108. {
  109. if( frontCrushed )
  110. {
  111. retval = TOTAL_CRUSH;
  112. bestDist = dist;
  113. }
  114. else
  115. {
  116. retval = BACK_END_CRUSH;
  117. bestDist = dist;
  118. }
  119. }
  120. }
  121. return retval;
  122. }
  123. //-------------------------------------------------------------------------------------------------
  124. //-------------------------------------------------------------------------------------------------
  125. CrushDie::CrushDie( Thing *thing, const ModuleData* moduleData ) : DieModule( thing, moduleData )
  126. {
  127. }
  128. //-------------------------------------------------------------------------------------------------
  129. //-------------------------------------------------------------------------------------------------
  130. CrushDie::~CrushDie( void )
  131. {
  132. }
  133. //-------------------------------------------------------------------------------------------------
  134. /** The die callback. */
  135. //-------------------------------------------------------------------------------------------------
  136. void CrushDie::onDie( const DamageInfo * damageInfo )
  137. {
  138. if (!isDieApplicable(damageInfo))
  139. return;
  140. DEBUG_ASSERTCRASH(damageInfo->in.m_damageType == DAMAGE_CRUSH, ("this should only be used for crush damage\n"));
  141. if (damageInfo->in.m_damageType != DAMAGE_CRUSH)
  142. return;
  143. Object *damageDealer = TheGameLogic->findObjectByID( damageInfo->in.m_sourceID );
  144. DEBUG_ASSERTCRASH(damageDealer,("You must have a damageDealer source for this effect"));
  145. CrushEnum crushType = damageDealer ? crushLocationCheck(damageDealer, getObject()) : TOTAL_CRUSH;
  146. if (crushType != NO_CRUSH)
  147. {
  148. if (getCrushDieModuleData()->m_crushSounds[crushType].getEventName().isEmpty() == false)
  149. {
  150. // be sure that 0==never, 100==always
  151. // MDC: moving to GameLogicRandomValue. This does not need to be synced, but having it so makes searches *so* much nicer.
  152. if (GameLogicRandomValue(0, 99) < getCrushDieModuleData()->m_crushSoundPercent[crushType])
  153. {
  154. AudioEventRTS crushSound(getCrushDieModuleData()->m_crushSounds[crushType]);
  155. crushSound.setObjectID(getObject()->getID());
  156. TheAudio->addAudioEvent(&crushSound);
  157. }
  158. }
  159. {
  160. Object *me = getObject();
  161. if (me)
  162. {
  163. me->getBodyModule()->setFrontCrushed(crushType == TOTAL_CRUSH || crushType == FRONT_END_CRUSH);
  164. me->getBodyModule()->setBackCrushed(crushType == TOTAL_CRUSH || crushType == BACK_END_CRUSH);
  165. ModelConditionFlags newCrushed;
  166. newCrushed.set(MODELCONDITION_FRONTCRUSHED, (crushType == TOTAL_CRUSH || crushType == FRONT_END_CRUSH));
  167. newCrushed.set(MODELCONDITION_BACKCRUSHED, crushType == TOTAL_CRUSH || crushType == BACK_END_CRUSH);
  168. me->getDrawable()->clearAndSetModelConditionFlags(
  169. MAKE_MODELCONDITION_MASK2(MODELCONDITION_BACKCRUSHED, MODELCONDITION_FRONTCRUSHED),
  170. newCrushed);
  171. }
  172. }
  173. }
  174. }
  175. // ------------------------------------------------------------------------------------------------
  176. /** CRC */
  177. // ------------------------------------------------------------------------------------------------
  178. void CrushDie::crc( Xfer *xfer )
  179. {
  180. // extend base class
  181. DieModule::crc( xfer );
  182. } // end crc
  183. // ------------------------------------------------------------------------------------------------
  184. /** Xfer method
  185. * Version Info:
  186. * 1: Initial version */
  187. // ------------------------------------------------------------------------------------------------
  188. void CrushDie::xfer( Xfer *xfer )
  189. {
  190. // version
  191. XferVersion currentVersion = 1;
  192. XferVersion version = currentVersion;
  193. xfer->xferVersion( &version, currentVersion );
  194. // extend base class
  195. DieModule::xfer( xfer );
  196. } // end xfer
  197. // ------------------------------------------------------------------------------------------------
  198. /** Load post process */
  199. // ------------------------------------------------------------------------------------------------
  200. void CrushDie::loadPostProcess( void )
  201. {
  202. // extend base class
  203. DieModule::loadPostProcess();
  204. } // end loadPostProcess