PageRenderTime 27ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/Code/GameSDK/GameDll/Effects/GameEffects/EnergyShieldGameEffect.cpp

https://gitlab.com/blackbird91/CS188_AI_Game
C++ | 991 lines | 731 code | 97 blank | 163 comment | 79 complexity | 524dd6ad47185d82c85d9cd32d7cfde3 MD5 | raw file
  1. /*
  2. * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
  3. * its licensors.
  4. *
  5. * For complete copyright and license terms please see the LICENSE at the root of this
  6. * distribution (the "License"). All use of this software is governed by the License,
  7. * or, if provided, by the license below or the license accompanying this file. Do not
  8. * remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
  9. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. *
  11. */
  12. // Original file Copyright Crytek GMBH or its affiliates, used under license.
  13. // Description : Energy Shield Game logic
  14. #include "StdAfx.h"
  15. #include "EnergyShieldGameEffect.h"
  16. #include "ItemParams.h"
  17. #include "Effects/RenderNodes/EnergyShieldGameRenderNode.h"
  18. #include <IRenderAuxGeom.h>
  19. REGISTER_EFFECT_DEBUG_DATA(CEnergyShieldGameEffect::DebugOnInputEvent,CEnergyShieldGameEffect::DebugDisplay,EnergyShield);
  20. REGISTER_DATA_CALLBACKS(CEnergyShieldGameEffect::LoadStaticData,CEnergyShieldGameEffect::ReleaseStaticData,CEnergyShieldGameEffect::ReloadStaticData,EnergyShieldData);
  21. // Soft-coding:
  22. IMPLEMENT_TYPE(CEnergyShieldGameEffect); // Provides the factory creation and access to reflection
  23. //==================================================================================================
  24. // Name: EEnergyShieldGameEffectFlags
  25. // Desc: Energy Shield Game effect flags
  26. // Author: James Chilvers
  27. //==================================================================================================
  28. enum EEnergyShieldGameEffectFlags
  29. {
  30. ENERGY_SHIELD_FADING_IN = (1<<0),
  31. ENERGY_SHIELD_FADING_OUT = (1<<1)
  32. };//------------------------------------------------------------------------------------------------
  33. //--------------------------------------------------------------------------------------------------
  34. // Desc: Static data
  35. //--------------------------------------------------------------------------------------------------
  36. #if DEBUG_GAME_FX_SYSTEM
  37. static float s_debugRadius = 5.0f;
  38. #endif
  39. const char* ENERGY_SHIELD_GAME_EFFECT_NAME = "Energy Shield";
  40. //--------------------------------------------------------------------------------------------------
  41. //--------------------------------------------------------------------------------------------------
  42. // Name: SEnergyShieldGameEffectData
  43. // Desc: Data loaded from xml to control game effect
  44. //--------------------------------------------------------------------------------------------------
  45. struct SEnergyShieldGameEffectData
  46. {
  47. struct SLightParams
  48. {
  49. SLightParams()
  50. {
  51. for(int i=0; i<eMAX_ENERGY_SHIELD_STATUS; i++)
  52. {
  53. color[i].Set(0.0f,0.0f,0.0f);
  54. }
  55. specular = 0.0f;
  56. heightOffsetScale = 0.0f;
  57. radiusScale = 0.0f;
  58. }
  59. Vec3 color[eMAX_ENERGY_SHIELD_STATUS];
  60. float specular;
  61. float heightOffsetScale;
  62. float radiusScale;
  63. };
  64. SEnergyShieldGameEffectData()
  65. {
  66. pDeflectionParticleEffect = NULL;
  67. deflectionParticleEffectScale = 0.0f;
  68. statusTransitionSpeed = 1.0f;
  69. effectAlphaTransitionSpeed = 1.0f;
  70. ambientSoundID = INVALID_AUDIOSIGNAL_ID;
  71. startUpSoundID = INVALID_AUDIOSIGNAL_ID;
  72. explosivePassSoundID = INVALID_AUDIOSIGNAL_ID;
  73. explosiveBounceSoundID = INVALID_AUDIOSIGNAL_ID;
  74. playerPassSoundID = INVALID_AUDIOSIGNAL_ID;
  75. bulletPassSoundID = INVALID_AUDIOSIGNAL_ID;
  76. isInitialised = false;
  77. }
  78. SEnergyShieldGameRenderNodeParams::SStaticParams renderNodeParams;
  79. SLightParams lightParams;
  80. IParticleEffect* pDeflectionParticleEffect;
  81. float deflectionParticleEffectScale;
  82. float statusTransitionSpeed;
  83. float effectAlphaTransitionSpeed;
  84. TAudioSignalID ambientSoundID;
  85. TAudioSignalID startUpSoundID;
  86. TAudioSignalID explosivePassSoundID;
  87. TAudioSignalID explosiveBounceSoundID;
  88. TAudioSignalID playerPassSoundID;
  89. TAudioSignalID bulletPassSoundID;
  90. bool isInitialised;
  91. };
  92. static SEnergyShieldGameEffectData s_energyShieldGEData;
  93. //--------------------------------------------------------------------------------------------------
  94. //--------------------------------------------------------------------------------------------------
  95. // Name: CEnergyShieldGameEffect
  96. // Desc: Constructor
  97. //--------------------------------------------------------------------------------------------------
  98. CEnergyShieldGameEffect::CEnergyShieldGameEffect()
  99. {
  100. GAME_FX_SYSTEM.RegisterGameRenderNode(m_pRenderNode);
  101. m_pLightSource = NULL;
  102. m_radius = 0.0f;
  103. m_bVisualsNeedUpdate = false;
  104. m_oldOwnerStatus = eENERGY_SHIELD_STATUS_NEUTRAL;
  105. m_newOwnerStatus = eENERGY_SHIELD_STATUS_NEUTRAL;
  106. m_statusTransitionScale = 1.0f;
  107. m_effectAlpha = 0.0f;
  108. m_energyShieldFlags = 0;
  109. m_entityId = 0;
  110. }//-------------------------------------------------------------------------------------------------
  111. //--------------------------------------------------------------------------------------------------
  112. // Name: ~CEnergyShieldGameEffect
  113. // Desc: Destructor
  114. //--------------------------------------------------------------------------------------------------
  115. CEnergyShieldGameEffect::~CEnergyShieldGameEffect()
  116. {
  117. GAME_FX_SYSTEM.UnregisterGameRenderNode(m_pRenderNode);
  118. }//-------------------------------------------------------------------------------------------------
  119. //--------------------------------------------------------------------------------------------------
  120. // Name: ReadColorFromXml
  121. // Desc: Reads colors from xml
  122. //--------------------------------------------------------------------------------------------------
  123. void CEnergyShieldGameEffect::ReadColorFromXml(const IItemParamsNode* pColorNode,Vec3* pColorArray)
  124. {
  125. if(pColorNode && pColorArray)
  126. {
  127. pColorNode->GetAttribute("neutral",pColorArray[eENERGY_SHIELD_STATUS_NEUTRAL]);
  128. pColorNode->GetAttribute("friendly",pColorArray[eENERGY_SHIELD_STATUS_FRIENDLY]);
  129. pColorNode->GetAttribute("enemy",pColorArray[eENERGY_SHIELD_STATUS_ENEMY]);
  130. }
  131. }//-------------------------------------------------------------------------------------------------
  132. //--------------------------------------------------------------------------------------------------
  133. // Name: LoadStaticData
  134. // Desc: Loads static data for effect
  135. //--------------------------------------------------------------------------------------------------
  136. void CEnergyShieldGameEffect::LoadStaticData(IItemParamsNode* pRootNode)
  137. {
  138. const IItemParamsNode* pParamNode = pRootNode->GetChild("EnergyShield");
  139. if(pParamNode)
  140. {
  141. SEnergyShieldGameRenderNodeParams::SStaticParams& params = s_energyShieldGEData.renderNodeParams;
  142. // General params
  143. pParamNode->GetAttribute("statusTransitionSpeed",s_energyShieldGEData.statusTransitionSpeed);
  144. pParamNode->GetAttribute("effectAlphaTransitionSpeed",s_energyShieldGEData.effectAlphaTransitionSpeed);
  145. // Sphere params
  146. const IItemParamsNode* pSphereNode = pParamNode->GetChild("sphere");
  147. if(pSphereNode)
  148. {
  149. pSphereNode->GetAttribute("maxViewDistance",params.maxViewDistance);
  150. pSphereNode->GetAttribute("meshSegmentCount",params.xml.sphereMeshSegmentCount);
  151. params.xml.sphereMeshSegmentCount = max(params.xml.sphereMeshSegmentCount,2);
  152. params.pSphereMaterial = LoadMaterial(pSphereNode->GetAttribute("material"));
  153. pSphereNode->GetAttribute("frontFaceAlphaFadeScale",params.xml.frontFaceAlphaFadeScale);
  154. pSphereNode->GetAttribute("animSpeed",params.xml.sphereAnimSpeed);
  155. pSphereNode->GetAttribute("noiseAnimSpeed",params.xml.noiseAnimSpeed);
  156. pSphereNode->GetAttribute("softNoiseAnimSpeed",params.xml.softNoiseAnimSpeed);
  157. ReadColorFromXml(pSphereNode->GetChild("color"),params.xml.sphereColor);
  158. ReadColorFromXml(pSphereNode->GetChild("refractionColor"),params.xml.sphereRefractionColor);
  159. ReadColorFromXml(pSphereNode->GetChild("chromaShiftChannelStrength"),params.xml.chromaShiftChannelStrength);
  160. }
  161. // Hit effect params
  162. const IItemParamsNode* pHitEffectNode = pParamNode->GetChild("hitEffect");
  163. if(pHitEffectNode)
  164. {
  165. pHitEffectNode->GetAttribute("reservedHitEffectCount",params.xml.reservedHitEffectCount);
  166. pHitEffectNode->GetAttribute("hitEffectMeshSegmentCount",params.xml.hitEffectMeshSegmentCount);
  167. params.xml.hitEffectMeshSegmentCount = max(params.xml.hitEffectMeshSegmentCount,1);
  168. pHitEffectNode->GetAttribute("deflectionMeshSegmentCount",params.xml.deflectionMeshSegmentCount);
  169. params.xml.deflectionMeshSegmentCount = max(params.xml.deflectionMeshSegmentCount,1);
  170. pHitEffectNode->GetAttribute("hitEffectDuration",params.xml.hitEffectDuration);
  171. params.xml.hitEffectDuration = max(params.xml.hitEffectDuration,0.001f);
  172. pHitEffectNode->GetAttribute("deflectionDuration",params.xml.deflectionDuration);
  173. params.xml.deflectionDuration = max(params.xml.deflectionDuration,0.001f);
  174. pHitEffectNode->GetAttribute("particleEffectScale",s_energyShieldGEData.deflectionParticleEffectScale);
  175. pHitEffectNode->GetAttribute("hitWaveRefractionColScale",params.xml.hitWaveRefractionColScale);
  176. pHitEffectNode->GetAttribute("deflectWaveRefractionColScale",params.xml.deflectWaveRefractionColScale);
  177. s_energyShieldGEData.pDeflectionParticleEffect = LoadParticleEffect(pHitEffectNode->GetAttribute("particleEffect"));
  178. params.pHitEffectMaterial = LoadMaterial(pHitEffectNode->GetAttribute("material"));
  179. ReadColorFromXml(pHitEffectNode->GetChild("startColor"),params.xml.hitEffectStartColor);
  180. ReadColorFromXml(pHitEffectNode->GetChild("endColor"),params.xml.hitEffectEndColor);
  181. }
  182. // Pulse params
  183. const IItemParamsNode* pPulseNode = pParamNode->GetChild("pulse");
  184. if(pPulseNode)
  185. {
  186. params.pSpherePulseMaterial = LoadMaterial(pPulseNode->GetAttribute("material"));
  187. pPulseNode->GetAttribute("count",params.xml.pulseCount);
  188. pPulseNode->GetAttribute("speed",params.xml.pulseSpeed);
  189. pPulseNode->GetAttribute("radiusScale",params.xml.pulseRadiusScale);
  190. pPulseNode->GetAttribute("alphaScale",params.xml.pulseAlphaScale);
  191. pPulseNode->GetAttribute("alphaSaturation",params.xml.pulseAlphaSaturation);
  192. pPulseNode->GetAttribute("alphaReduction",params.xml.pulseAlphaReduction);
  193. pPulseNode->GetAttribute("highLightScale",params.xml.pulseHighLightScale);
  194. ReadColorFromXml(pPulseNode->GetChild("color"),params.xml.pulseColor);
  195. }
  196. // Pulse params
  197. const IItemParamsNode* pLightNode = pParamNode->GetChild("light");
  198. if(pLightNode)
  199. {
  200. pLightNode->GetAttribute("specular",s_energyShieldGEData.lightParams.specular);
  201. pLightNode->GetAttribute("heightOffsetScale",s_energyShieldGEData.lightParams.heightOffsetScale);
  202. pLightNode->GetAttribute("radiusScale",s_energyShieldGEData.lightParams.radiusScale);
  203. ReadColorFromXml(pLightNode->GetChild("color"),s_energyShieldGEData.lightParams.color);
  204. }
  205. // Sound fx params
  206. if(g_pGame)
  207. {
  208. CGameAudio* pGameAudio = g_pGame->GetGameAudio();
  209. if(pGameAudio)
  210. {
  211. const IItemParamsNode* pSoundFXNode = pParamNode->GetChild("soundFX");
  212. if(pSoundFXNode)
  213. {
  214. s_energyShieldGEData.ambientSoundID = pGameAudio->GetSignalID(pSoundFXNode->GetAttribute("ambient"));
  215. s_energyShieldGEData.startUpSoundID = pGameAudio->GetSignalID(pSoundFXNode->GetAttribute("startUp"));
  216. s_energyShieldGEData.explosivePassSoundID = pGameAudio->GetSignalID(pSoundFXNode->GetAttribute("explosivePass"));
  217. s_energyShieldGEData.explosiveBounceSoundID = pGameAudio->GetSignalID(pSoundFXNode->GetAttribute("explosiveBounce"));
  218. s_energyShieldGEData.playerPassSoundID = pGameAudio->GetSignalID(pSoundFXNode->GetAttribute("playerPass"));
  219. s_energyShieldGEData.bulletPassSoundID = pGameAudio->GetSignalID(pSoundFXNode->GetAttribute("bulletPass"));
  220. }
  221. }
  222. }
  223. s_energyShieldGEData.isInitialised = true;
  224. }
  225. }//-------------------------------------------------------------------------------------------------
  226. //--------------------------------------------------------------------------------------------------
  227. // Name: ReloadStaticData
  228. // Desc: Reloads static data
  229. //--------------------------------------------------------------------------------------------------
  230. void CEnergyShieldGameEffect::ReloadStaticData(IItemParamsNode* pRootNode)
  231. {
  232. ReleaseStaticData();
  233. LoadStaticData(pRootNode);
  234. #if DEBUG_GAME_FX_SYSTEM
  235. // Data has been reloaded, so re-initialse debug effect with new data
  236. CEnergyShieldGameEffect* pDebugEnergyShieldEffect = (CEnergyShieldGameEffect*)GAME_FX_SYSTEM.GetDebugEffect(ENERGY_SHIELD_GAME_EFFECT_NAME);
  237. if(pDebugEnergyShieldEffect && pDebugEnergyShieldEffect->IsFlagSet(GAME_EFFECT_REGISTERED))
  238. {
  239. s_energyShieldGEData.renderNodeParams.xml.reloadedData = true;
  240. SEnergyShieldGameEffectParams params;
  241. pDebugEnergyShieldEffect->GetPos(params.pos);
  242. params.radius = s_debugRadius;
  243. pDebugEnergyShieldEffect->Initialise(&params);
  244. pDebugEnergyShieldEffect->SetAlpha(0.0f);
  245. pDebugEnergyShieldEffect->SetAlpha(1.0f);
  246. pDebugEnergyShieldEffect->UpdateVisuals();
  247. s_energyShieldGEData.renderNodeParams.xml.reloadedData = false;
  248. }
  249. #endif
  250. }//-------------------------------------------------------------------------------------------------
  251. //--------------------------------------------------------------------------------------------------
  252. // Name: ReleaseStaticData
  253. // Desc: Releases static data
  254. //--------------------------------------------------------------------------------------------------
  255. void CEnergyShieldGameEffect::ReleaseStaticData()
  256. {
  257. if(s_energyShieldGEData.isInitialised)
  258. {
  259. SAFE_RELEASE(s_energyShieldGEData.renderNodeParams.pSphereMaterial);
  260. SAFE_RELEASE(s_energyShieldGEData.renderNodeParams.pHitEffectMaterial);
  261. SAFE_RELEASE(s_energyShieldGEData.renderNodeParams.pSpherePulseMaterial);
  262. SAFE_RELEASE(s_energyShieldGEData.pDeflectionParticleEffect);
  263. s_energyShieldGEData.isInitialised = false;
  264. }
  265. }//-------------------------------------------------------------------------------------------------
  266. //--------------------------------------------------------------------------------------------------
  267. // Name: Initialise
  268. // Desc: Initializes game effect
  269. //--------------------------------------------------------------------------------------------------
  270. void CEnergyShieldGameEffect::Initialise(const SGameEffectParams* pGameEffectParams)
  271. {
  272. CGameEffect::Initialise(pGameEffectParams);
  273. if(pGameEffectParams)
  274. {
  275. const SEnergyShieldGameEffectParams* pEnergyShieldParams = static_cast<const SEnergyShieldGameEffectParams*>(pGameEffectParams);
  276. if(m_pRenderNode == NULL)
  277. {
  278. m_pRenderNode = CREATE_GAME_FX_SOFT_CODE_INSTANCE(CEnergyShieldGameRenderNode);
  279. }
  280. if(m_pRenderNode)
  281. {
  282. m_pRenderNode->SetRndFlags(ERF_HIDDEN,true);
  283. SEnergyShieldGameRenderNodeParams renderNodeParams;
  284. renderNodeParams.staticParams = s_energyShieldGEData.renderNodeParams;
  285. renderNodeParams.radius = pEnergyShieldParams->radius;
  286. renderNodeParams.pos = pEnergyShieldParams->pos;
  287. m_pRenderNode->SetParams(&renderNodeParams);
  288. m_pRenderNode->InitialiseGameRenderNode();
  289. }
  290. m_radius = pEnergyShieldParams->radius;
  291. m_entityId = pEnergyShieldParams->entityId;
  292. CreateLightSource();
  293. m_ambientSound.SetSignal(s_energyShieldGEData.ambientSoundID);
  294. }
  295. }//-------------------------------------------------------------------------------------------------
  296. //--------------------------------------------------------------------------------------------------
  297. // Name: Release
  298. // Desc: Releases game effect
  299. //--------------------------------------------------------------------------------------------------
  300. void CEnergyShieldGameEffect::Release()
  301. {
  302. CGameEffect::SetActive(false);
  303. SAFE_DELETE_GAME_RENDER_NODE(m_pRenderNode);
  304. ReleaseLightSource();
  305. CGameEffect::Release();
  306. }//-------------------------------------------------------------------------------------------------
  307. //--------------------------------------------------------------------------------------------------
  308. // Name: CreateLightSource
  309. // Desc: Creates light source
  310. //--------------------------------------------------------------------------------------------------
  311. void CEnergyShieldGameEffect::CreateLightSource()
  312. {
  313. if(m_pLightSource == NULL)
  314. {
  315. m_pLightSource = gEnv->p3DEngine->CreateLightSource();
  316. if(m_pLightSource)
  317. {
  318. m_pLightSource->SetRndFlags(ERF_HIDDEN,true);
  319. const bool bForceLightUpdate = true;
  320. UpdateLightSource(bForceLightUpdate); // Light source must be valid before registering
  321. gEnv->p3DEngine->RegisterEntity(m_pLightSource);
  322. }
  323. }
  324. }//-------------------------------------------------------------------------------------------------
  325. //--------------------------------------------------------------------------------------------------
  326. // Name: ReleaseLightSource
  327. // Desc: Releases light source
  328. //--------------------------------------------------------------------------------------------------
  329. void CEnergyShieldGameEffect::ReleaseLightSource()
  330. {
  331. if(m_pLightSource)
  332. {
  333. gEnv->p3DEngine->UnRegisterEntity(m_pLightSource);
  334. gEnv->p3DEngine->DeleteLightSource(m_pLightSource);
  335. m_pLightSource = NULL;
  336. }
  337. }//-------------------------------------------------------------------------------------------------
  338. //--------------------------------------------------------------------------------------------------
  339. // Name: SetActive
  340. // Desc: Sets active status of effect
  341. //--------------------------------------------------------------------------------------------------
  342. void CEnergyShieldGameEffect::SetActive(bool isActive)
  343. {
  344. if(s_energyShieldGEData.isInitialised)
  345. {
  346. if(isActive)
  347. {
  348. Start();
  349. }
  350. else
  351. {
  352. Stop();
  353. }
  354. }
  355. }//-------------------------------------------------------------------------------------------------
  356. //--------------------------------------------------------------------------------------------------
  357. // Name: Start
  358. // Desc: Starts effect
  359. //--------------------------------------------------------------------------------------------------
  360. void CEnergyShieldGameEffect::Start()
  361. {
  362. if(IsFlagSet(GAME_EFFECT_ACTIVE) == false)
  363. {
  364. CGameEffect::SetActive(true);
  365. SET_FLAG(m_energyShieldFlags,ENERGY_SHIELD_FADING_IN,true);
  366. SET_FLAG(m_energyShieldFlags,ENERGY_SHIELD_FADING_OUT,false);
  367. m_ambientSound.Play(m_entityId);
  368. Vec3 pos(ZERO);
  369. GetPos(pos);
  370. CAudioSignalPlayer::JustPlay(s_energyShieldGEData.startUpSoundID,pos);
  371. }
  372. }//-------------------------------------------------------------------------------------------------
  373. //--------------------------------------------------------------------------------------------------
  374. // Name: Stop
  375. // Desc: Stops effect
  376. //--------------------------------------------------------------------------------------------------
  377. void CEnergyShieldGameEffect::Stop()
  378. {
  379. if(IsFlagSet(GAME_EFFECT_ACTIVE))
  380. {
  381. SET_FLAG(m_energyShieldFlags,ENERGY_SHIELD_FADING_IN,false);
  382. SET_FLAG(m_energyShieldFlags,ENERGY_SHIELD_FADING_OUT,true);
  383. m_ambientSound.Stop(m_entityId);
  384. }
  385. }//-------------------------------------------------------------------------------------------------
  386. //--------------------------------------------------------------------------------------------------
  387. // Name: GetName
  388. // Desc: Gets effect's name
  389. //--------------------------------------------------------------------------------------------------
  390. const char* CEnergyShieldGameEffect::GetName() const
  391. {
  392. return ENERGY_SHIELD_GAME_EFFECT_NAME;
  393. }//-------------------------------------------------------------------------------------------------
  394. //--------------------------------------------------------------------------------------------------
  395. // Name: Update
  396. // Desc: Updates effect
  397. //--------------------------------------------------------------------------------------------------
  398. void CEnergyShieldGameEffect::Update(float frameTime)
  399. {
  400. CGameEffect::Update(frameTime);
  401. UpdateEffectAlpha(frameTime);
  402. if(m_oldOwnerStatus != m_newOwnerStatus)
  403. {
  404. m_bVisualsNeedUpdate = true;
  405. m_statusTransitionScale += (frameTime * s_energyShieldGEData.statusTransitionSpeed);
  406. if(m_statusTransitionScale >= 1.0f)
  407. {
  408. m_statusTransitionScale = 1.0f;
  409. m_oldOwnerStatus = m_newOwnerStatus;
  410. }
  411. }
  412. if(m_bVisualsNeedUpdate)
  413. {
  414. UpdateVisuals();
  415. }
  416. }//-------------------------------------------------------------------------------------------------
  417. //--------------------------------------------------------------------------------------------------
  418. // Name: UpdateLightSource
  419. // Desc: Updates light source
  420. //--------------------------------------------------------------------------------------------------
  421. void CEnergyShieldGameEffect::UpdateLightSource(bool bForceUpdate)
  422. {
  423. if(m_pLightSource)
  424. {
  425. if((m_effectAlpha > 0.0f) || bForceUpdate)
  426. {
  427. Vec3 pos;
  428. GetPos(pos);
  429. // Offset height so above ground level
  430. pos.z += (m_radius * s_energyShieldGEData.lightParams.heightOffsetScale);
  431. // Lerp color
  432. const Vec3& oldColor = s_energyShieldGEData.lightParams.color[m_oldOwnerStatus];
  433. const Vec3& newColor = s_energyShieldGEData.lightParams.color[m_newOwnerStatus];
  434. ColorF lightColor = Vec3::CreateLerp(oldColor,newColor,m_statusTransitionScale) * m_effectAlpha;
  435. CDLight lightParams;
  436. lightParams.SetLightColor(lightColor);
  437. lightParams.SetSpecularMult(s_energyShieldGEData.lightParams.specular);
  438. lightParams.m_fRadius = m_radius * s_energyShieldGEData.lightParams.radiusScale;
  439. lightParams.m_Flags |= DLF_POINT;
  440. lightParams.m_sName = "Energy Shield Light";
  441. m_pLightSource->SetLightProperties(lightParams);
  442. Matrix34 worldMatrix;
  443. worldMatrix.SetIdentity();
  444. worldMatrix.SetTranslation(pos);
  445. m_pLightSource->SetMatrix(worldMatrix);
  446. }
  447. }
  448. }//-------------------------------------------------------------------------------------------------
  449. //--------------------------------------------------------------------------------------------------
  450. // Name: UpdateEffectAlpha
  451. // Desc: Updates effect alpha
  452. //--------------------------------------------------------------------------------------------------
  453. void CEnergyShieldGameEffect::UpdateEffectAlpha(float frameTime)
  454. {
  455. if(IS_FLAG_SET(m_energyShieldFlags,ENERGY_SHIELD_FADING_IN))
  456. {
  457. float newAlpha = m_effectAlpha + (frameTime*s_energyShieldGEData.effectAlphaTransitionSpeed);
  458. if(newAlpha >= 1.0f)
  459. {
  460. newAlpha = 1.0f;
  461. SET_FLAG(m_energyShieldFlags,ENERGY_SHIELD_FADING_IN,false);
  462. }
  463. SetAlpha(newAlpha);
  464. }
  465. else if(IS_FLAG_SET(m_energyShieldFlags,ENERGY_SHIELD_FADING_OUT))
  466. {
  467. float newAlpha = m_effectAlpha - (frameTime*s_energyShieldGEData.effectAlphaTransitionSpeed);
  468. if(newAlpha <= 0.0f)
  469. {
  470. newAlpha = 0.0f;
  471. SET_FLAG(m_energyShieldFlags,ENERGY_SHIELD_FADING_OUT,false);
  472. CGameEffect::SetActive(false);
  473. }
  474. SetAlpha(newAlpha);
  475. }
  476. }//-------------------------------------------------------------------------------------------------
  477. //--------------------------------------------------------------------------------------------------
  478. // Name: SetAlpha
  479. // Desc: Sets effect alpha
  480. //--------------------------------------------------------------------------------------------------
  481. void CEnergyShieldGameEffect::SetAlpha(float newAlpha)
  482. {
  483. if(m_effectAlpha != newAlpha)
  484. {
  485. m_bVisualsNeedUpdate = true;
  486. const bool bHidden = (newAlpha > 0.0f) ? false : true;
  487. if(m_pRenderNode)
  488. {
  489. m_pRenderNode->SetRndFlags(ERF_HIDDEN,bHidden);
  490. }
  491. if(m_pLightSource)
  492. {
  493. m_pLightSource->SetRndFlags(ERF_HIDDEN,bHidden);
  494. }
  495. }
  496. m_effectAlpha = newAlpha;
  497. }//-------------------------------------------------------------------------------------------------
  498. //--------------------------------------------------------------------------------------------------
  499. // Name: SetRadius
  500. // Desc: Sets effect radius
  501. //--------------------------------------------------------------------------------------------------
  502. void CEnergyShieldGameEffect::SetRadius(float newRadius)
  503. {
  504. m_bVisualsNeedUpdate = true;
  505. m_radius = newRadius;
  506. }//-------------------------------------------------------------------------------------------------
  507. //--------------------------------------------------------------------------------------------------
  508. // Name: AddHit
  509. // Desc: Adds a hit effect
  510. //--------------------------------------------------------------------------------------------------
  511. void CEnergyShieldGameEffect::AddHit(const Vec3& pos,const Vec3& vel,float projectileRadius,uint8 flags)
  512. {
  513. if(m_pRenderNode)
  514. {
  515. const bool bIsProjectile = IS_FLAG_SET(flags,ESHF_PROJECTILE);
  516. if(bIsProjectile)
  517. {
  518. SEnergyShieldHitData newHitData;
  519. newHitData.pos = pos;
  520. newHitData.spawnTime = gEnv->pTimer->GetCurrTime(ITimer::ETIMER_GAME);
  521. newHitData.speed = vel.GetLength();
  522. newHitData.bounceSpeed = vel;
  523. newHitData.bDeflected = IS_FLAG_SET(flags,ESHF_DEFLECTED);
  524. SEnergyShieldGameRenderNodeParams renderNodeParams;
  525. renderNodeParams.pNewHitEffect = &newHitData;
  526. m_pRenderNode->SetParams(&renderNodeParams);
  527. if(newHitData.bDeflected)
  528. {
  529. SpawnDeflectionParticleEffect(pos,vel);
  530. CAudioSignalPlayer::JustPlay(s_energyShieldGEData.explosiveBounceSoundID,pos);
  531. }
  532. else
  533. {
  534. const bool bInSideShield = IS_FLAG_SET(flags,ESHF_INSIDE_SHIELD);
  535. const bool bExplosive = IS_FLAG_SET(flags,ESHF_EXPLOSIVE);
  536. TAudioSignalID soundId = INVALID_AUDIOSIGNAL_ID;
  537. if(bInSideShield && bExplosive)
  538. {
  539. soundId = s_energyShieldGEData.explosivePassSoundID;
  540. }
  541. else
  542. {
  543. soundId = s_energyShieldGEData.bulletPassSoundID;
  544. }
  545. CAudioSignalPlayer::JustPlay(soundId,pos);
  546. }
  547. }
  548. else
  549. {
  550. CAudioSignalPlayer::JustPlay(s_energyShieldGEData.playerPassSoundID,pos);
  551. }
  552. }
  553. }//-------------------------------------------------------------------------------------------------
  554. //--------------------------------------------------------------------------------------------------
  555. // Name: SpawnDeflectionParticleEffect
  556. // Desc: Spawns deflection particle effect
  557. //--------------------------------------------------------------------------------------------------
  558. void CEnergyShieldGameEffect::SpawnDeflectionParticleEffect(const Vec3& pos, const Vec3& vel)
  559. {
  560. if(s_energyShieldGEData.pDeflectionParticleEffect)
  561. {
  562. Vec3 dir = vel;
  563. dir.Normalize();
  564. const float scale = s_energyShieldGEData.deflectionParticleEffectScale * m_radius;
  565. const bool bIndependent = false;
  566. IParticleEmitter* pParticleEmitter = s_energyShieldGEData.pDeflectionParticleEffect->Spawn(bIndependent,IParticleEffect::ParticleLoc(pos, dir, scale));
  567. if(pParticleEmitter)
  568. {
  569. // Use emitter strength to control emitter particle color
  570. // The only other way to control the color is by have 3 particle effects
  571. const float friendlyStrength = 0.3333f;
  572. const float enemyStrength = 0.6666f;
  573. float emitterStrength = 0.0f;
  574. if(m_newOwnerStatus == m_oldOwnerStatus)
  575. {
  576. switch(m_newOwnerStatus)
  577. {
  578. case eENERGY_SHIELD_STATUS_FRIENDLY:
  579. {
  580. // Friendly
  581. emitterStrength = friendlyStrength;
  582. break;
  583. }
  584. case eENERGY_SHIELD_STATUS_ENEMY:
  585. {
  586. // Enemy
  587. emitterStrength = enemyStrength;
  588. break;
  589. }
  590. }
  591. }
  592. else
  593. {
  594. // Transition between state colors
  595. emitterStrength = m_statusTransitionScale * friendlyStrength;
  596. switch(m_newOwnerStatus)
  597. {
  598. case eENERGY_SHIELD_STATUS_NEUTRAL:
  599. {
  600. if(m_oldOwnerStatus == eENERGY_SHIELD_STATUS_FRIENDLY)
  601. {
  602. emitterStrength = friendlyStrength - emitterStrength; // Friendly to Neutral
  603. }
  604. else
  605. {
  606. emitterStrength = enemyStrength + emitterStrength; // Enemy to Neutral
  607. }
  608. break;
  609. }
  610. case eENERGY_SHIELD_STATUS_FRIENDLY:
  611. {
  612. if(m_oldOwnerStatus == eENERGY_SHIELD_STATUS_ENEMY)
  613. {
  614. emitterStrength = enemyStrength - emitterStrength; // Enemy to Friendly
  615. }
  616. else
  617. {
  618. emitterStrength = emitterStrength; // Neutral to Friendly
  619. }
  620. break;
  621. }
  622. case eENERGY_SHIELD_STATUS_ENEMY:
  623. {
  624. if(m_oldOwnerStatus == eENERGY_SHIELD_STATUS_FRIENDLY)
  625. {
  626. emitterStrength = friendlyStrength + emitterStrength; // Friendly to Enemy
  627. }
  628. else
  629. {
  630. emitterStrength = 1.0f - emitterStrength; // Neutral to Enemy
  631. }
  632. break;
  633. }
  634. }
  635. }
  636. SpawnParams spawnParams;
  637. pParticleEmitter->GetSpawnParams(spawnParams);
  638. spawnParams.fStrength = emitterStrength;
  639. pParticleEmitter->SetSpawnParams(spawnParams);
  640. }
  641. }
  642. }//-------------------------------------------------------------------------------------------------
  643. //--------------------------------------------------------------------------------------------------
  644. // Name: GetPos
  645. // Desc: Gets effect positions
  646. //--------------------------------------------------------------------------------------------------
  647. void CEnergyShieldGameEffect::GetPos(Vec3& posOut) const
  648. {
  649. if(m_pRenderNode)
  650. {
  651. posOut = m_pRenderNode->GetPos();
  652. }
  653. }//-------------------------------------------------------------------------------------------------
  654. //--------------------------------------------------------------------------------------------------
  655. // Name: SetPos
  656. // Desc: Sets effect positions
  657. //--------------------------------------------------------------------------------------------------
  658. void CEnergyShieldGameEffect::SetPos(const Vec3& newPos)
  659. {
  660. if(m_pRenderNode)
  661. {
  662. // Set matrix
  663. Matrix34 matrix;
  664. matrix.SetIdentity();
  665. matrix.SetTranslation(newPos);
  666. m_pRenderNode->SetMatrix(matrix);
  667. }
  668. }//-------------------------------------------------------------------------------------------------
  669. //--------------------------------------------------------------------------------------------------
  670. // Name: SetShieldOwnerStatus
  671. // Desc: Sets shield owner status
  672. //--------------------------------------------------------------------------------------------------
  673. void CEnergyShieldGameEffect::SetShieldOwnerStatus( EEnergyShieldStatus newOwnerStatus )
  674. {
  675. m_oldOwnerStatus = m_newOwnerStatus;
  676. m_newOwnerStatus = newOwnerStatus;
  677. m_statusTransitionScale = 0.0f;
  678. }//-------------------------------------------------------------------------------------------------
  679. //--------------------------------------------------------------------------------------------------
  680. // Name: UpdateVisuals
  681. // Desc: Updates visual parts of effect
  682. //--------------------------------------------------------------------------------------------------
  683. void CEnergyShieldGameEffect::UpdateVisuals()
  684. {
  685. if(m_pRenderNode)
  686. {
  687. SEnergyShieldGameRenderNodeParams renderNodeParams;
  688. renderNodeParams.radius = m_radius;
  689. renderNodeParams.pos = m_pRenderNode->GetPos();
  690. renderNodeParams.oldStatus = m_oldOwnerStatus;
  691. renderNodeParams.newStatus = m_newOwnerStatus;
  692. renderNodeParams.statusTransitionScale = m_statusTransitionScale;
  693. renderNodeParams.effectAlpha = m_effectAlpha;
  694. m_pRenderNode->SetParams(&renderNodeParams);
  695. }
  696. UpdateLightSource();
  697. m_bVisualsNeedUpdate = false;
  698. }//-------------------------------------------------------------------------------------------------
  699. #if DEBUG_GAME_FX_SYSTEM
  700. //--------------------------------------------------------------------------------------------------
  701. // Name: DebugOnInputEvent
  702. // Desc: Called when input events happen in debug builds
  703. //--------------------------------------------------------------------------------------------------
  704. void CEnergyShieldGameEffect::DebugOnInputEvent(int keyId)
  705. {
  706. if(s_energyShieldGEData.isInitialised)
  707. {
  708. CEnergyShieldGameEffect* pEnergyShieldEffect = (CEnergyShieldGameEffect*)GAME_FX_SYSTEM.GetDebugEffect(ENERGY_SHIELD_GAME_EFFECT_NAME);
  709. // Read input
  710. switch(keyId)
  711. {
  712. case eKI_NP_1:
  713. {
  714. // Create debug effect for development
  715. if(pEnergyShieldEffect == NULL)
  716. {
  717. pEnergyShieldEffect = CREATE_GAME_FX_SOFT_CODE_INSTANCE(CEnergyShieldGameEffect);
  718. if(pEnergyShieldEffect)
  719. {
  720. SEnergyShieldGameEffectParams params;
  721. params.pos = gEnv->pRenderer->GetCamera().GetPosition();
  722. params.radius = s_debugRadius;
  723. EntityId entityId = 0;
  724. SEntitySpawnParams entitySpawnParams;
  725. entitySpawnParams.pClass = gEnv->pEntitySystem->GetClassRegistry()->GetDefaultClass();
  726. entitySpawnParams.sName = "EnergyShield";
  727. entitySpawnParams.nFlags = ENTITY_FLAG_NO_PROXIMITY | ENTITY_FLAG_CLIENT_ONLY | ENTITY_FLAG_NO_SAVE;
  728. IEntity *pEntity=gEnv->pEntitySystem->SpawnEntity(entitySpawnParams);
  729. if(pEntity)
  730. {
  731. pEntity->SetPos(params.pos);
  732. params.entityId = pEntity->GetId();
  733. }
  734. pEnergyShieldEffect->Initialise(&params);
  735. pEnergyShieldEffect->SetFlag(GAME_EFFECT_DEBUG_EFFECT,true);
  736. }
  737. }
  738. break;
  739. }
  740. case eKI_NP_2:
  741. {
  742. if(pEnergyShieldEffect && pEnergyShieldEffect->m_entityId!=0)
  743. {
  744. gEnv->pEntitySystem->RemoveEntity(pEnergyShieldEffect->m_entityId);
  745. }
  746. // Delete effect
  747. SAFE_DELETE_GAME_EFFECT(pEnergyShieldEffect);
  748. break;
  749. }
  750. case eKI_NP_3:
  751. {
  752. // Toggle active status
  753. if(pEnergyShieldEffect)
  754. {
  755. pEnergyShieldEffect->SetActive(!pEnergyShieldEffect->IsFlagSet(GAME_EFFECT_ACTIVE));
  756. }
  757. break;
  758. }
  759. case eKI_NP_4:
  760. {
  761. // Hit Effect test
  762. if(pEnergyShieldEffect)
  763. {
  764. Vec3 pos;
  765. Vec3 vel(0.0f,0.0f,0.0f);
  766. float projectileRadius = 1.0f;
  767. pEnergyShieldEffect->GetPos(pos);
  768. Vec3 randomPosOnSphere;
  769. randomPosOnSphere.SetRandomDirection();
  770. randomPosOnSphere *= s_debugRadius;
  771. pos += randomPosOnSphere;
  772. pEnergyShieldEffect->AddHit(pos,vel,projectileRadius);
  773. }
  774. break;
  775. }
  776. case eKI_NP_5:
  777. {
  778. // Deflection test
  779. if(pEnergyShieldEffect)
  780. {
  781. Vec3 pos;
  782. Vec3 vel(0.0f,0.0f,0.0f);
  783. float projectileRadius = 1.0f;
  784. pEnergyShieldEffect->GetPos(pos);
  785. Vec3 randomPosOnSphere;
  786. randomPosOnSphere.SetRandomDirection();
  787. vel = randomPosOnSphere;
  788. randomPosOnSphere *= s_debugRadius;
  789. pos += randomPosOnSphere;
  790. pEnergyShieldEffect->AddHit(pos,vel,projectileRadius,ESHF_DEFLECTED);
  791. }
  792. break;
  793. }
  794. case eKI_NP_6:
  795. {
  796. // Extreme hit effect test
  797. if(pEnergyShieldEffect)
  798. {
  799. static uint32 spawnHitCount = 300;
  800. bool bDeflected = true;
  801. Vec3 effectPos;
  802. Vec3 hitPos;
  803. float projectileRadius = 1.0f;
  804. pEnergyShieldEffect->GetPos(effectPos);
  805. Vec3 randomPosOnSphere;
  806. for(uint32 i=0; i<spawnHitCount; i++)
  807. {
  808. bDeflected = (cry_frand() > 0.5f) ? true : false;
  809. uint8 flags = 0;
  810. SET_FLAG(flags,ESHF_DEFLECTED,bDeflected);
  811. randomPosOnSphere.SetRandomDirection();
  812. randomPosOnSphere *= s_debugRadius;
  813. hitPos = effectPos + randomPosOnSphere;
  814. pEnergyShieldEffect->AddHit(hitPos,randomPosOnSphere,projectileRadius,flags);
  815. }
  816. }
  817. break;
  818. }
  819. case eKI_NP_7:
  820. {
  821. // Set Neutral
  822. if(pEnergyShieldEffect)
  823. pEnergyShieldEffect->SetShieldOwnerStatus(eENERGY_SHIELD_STATUS_NEUTRAL);
  824. break;
  825. }
  826. case eKI_NP_8:
  827. {
  828. // Set Friendly
  829. if(pEnergyShieldEffect)
  830. pEnergyShieldEffect->SetShieldOwnerStatus(eENERGY_SHIELD_STATUS_FRIENDLY);
  831. break;
  832. }
  833. case eKI_NP_9:
  834. {
  835. // Set Enemy
  836. if(pEnergyShieldEffect)
  837. pEnergyShieldEffect->SetShieldOwnerStatus(eENERGY_SHIELD_STATUS_ENEMY);
  838. break;
  839. }
  840. case eKI_NP_Multiply:
  841. {
  842. // Increase shield radius
  843. s_debugRadius += 0.1f;
  844. if(pEnergyShieldEffect)
  845. pEnergyShieldEffect->SetRadius(s_debugRadius);
  846. break;
  847. }
  848. case eKI_NP_Divide:
  849. {
  850. // Decrease shield radius
  851. s_debugRadius = max(s_debugRadius-0.1f,0.0f);
  852. if(pEnergyShieldEffect)
  853. pEnergyShieldEffect->SetRadius(s_debugRadius);
  854. break;
  855. }
  856. }
  857. }
  858. }//-------------------------------------------------------------------------------------------------
  859. //--------------------------------------------------------------------------------------------------
  860. // Name: DebugDisplay
  861. // Desc: Display when this effect is selected to debug through the game effects system
  862. //--------------------------------------------------------------------------------------------------
  863. void CEnergyShieldGameEffect::DebugDisplay(const Vec2& textStartPos,float textSize,float textYStep)
  864. {
  865. ColorF textCol(1.0f,1.0f,0.0f,1.0f);
  866. Vec2 currentTextPos = textStartPos;
  867. if(s_energyShieldGEData.isInitialised)
  868. {
  869. gEnv->pRenderer->Draw2dLabel(currentTextPos.x,currentTextPos.y,textSize,&textCol.r,false,"Create: NumPad 1");
  870. currentTextPos.y += textYStep;
  871. gEnv->pRenderer->Draw2dLabel(currentTextPos.x,currentTextPos.y,textSize,&textCol.r,false,"Destroy: NumPad 2");
  872. currentTextPos.y += textYStep;
  873. gEnv->pRenderer->Draw2dLabel(currentTextPos.x,currentTextPos.y,textSize,&textCol.r,false,"Toggle Active: NumPad 3");
  874. currentTextPos.y += textYStep;
  875. gEnv->pRenderer->Draw2dLabel(currentTextPos.x,currentTextPos.y,textSize,&textCol.r,false,"Add random hit: NumPad 4");
  876. currentTextPos.y += textYStep;
  877. gEnv->pRenderer->Draw2dLabel(currentTextPos.x,currentTextPos.y,textSize,&textCol.r,false,"Add random deflection hit: NumPad 5");
  878. currentTextPos.y += textYStep;
  879. gEnv->pRenderer->Draw2dLabel(currentTextPos.x,currentTextPos.y,textSize,&textCol.r,false,"Extreme test: NumPad 6");
  880. currentTextPos.y += textYStep;
  881. gEnv->pRenderer->Draw2dLabel(currentTextPos.x,currentTextPos.y,textSize,&textCol.r,false,"Set Neutral: 7");
  882. currentTextPos.y += textYStep;
  883. gEnv->pRenderer->Draw2dLabel(currentTextPos.x,currentTextPos.y,textSize,&textCol.r,false,"Set Friendly: 8");
  884. currentTextPos.y += textYStep;
  885. gEnv->pRenderer->Draw2dLabel(currentTextPos.x,currentTextPos.y,textSize,&textCol.r,false,"Set Enemy: 9");
  886. currentTextPos.y += textYStep;
  887. gEnv->pRenderer->Draw2dLabel(currentTextPos.x,currentTextPos.y,textSize,&textCol.r,false,"Add/Decrease radius: NumPad */ = %f",s_debugRadius);
  888. }
  889. else
  890. {
  891. gEnv->pRenderer->Draw2dLabel(currentTextPos.x,currentTextPos.y,textSize,&textCol.r,false,"Effect failed to load data");
  892. }
  893. }//-------------------------------------------------------------------------------------------------
  894. #endif