boatscript.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715
  1. enum EBoatEffects
  2. {
  3. PTC_FRONT = 0,
  4. PTC_BACK,
  5. PTC_SIDE_L,
  6. PTC_SIDE_R
  7. }
  8. enum EBoatEngineSoundState
  9. {
  10. NONE,
  11. START_OK,
  12. START_NO_FUEL,
  13. STOP_OK,
  14. STOP_NO_FUEL
  15. }
  16. class BoatScriptOwnerState : BoatOwnerState
  17. {
  18. };
  19. class BoatScriptMove : BoatMove
  20. {
  21. };
  22. class BoatScript : Boat
  23. {
  24. protected const float SOUND_ENGINE_FADE = 0.2;
  25. protected const float SPLASH_THRESHOLD_CONDITION = 0.08; // diff between sea surface and propeller pos which determines if the splash should happen
  26. protected const float SPLASH_THRESHOLD = 0.18; // diff between sea surface and propeller pos which determines when the splash happens
  27. private static ref map<typename, ref TInputActionMap> m_BoatTypeActionsMap = new map<typename, ref TInputActionMap>();
  28. private TInputActionMap m_InputActionMap;
  29. private bool m_ActionsInitialized;
  30. protected vector m_VelocityPrevTick;
  31. protected float m_MomentumPrevTick;
  32. protected ref VehicleContactData m_ContactData;
  33. // particles
  34. protected bool m_UpdateParticles;
  35. protected ref EffectBoatWaterBase m_WaterEffects[4];
  36. // sounds
  37. protected bool m_SplashIncoming; // boat is high enough for the splash to trigger when it falls back down to sea level
  38. protected bool m_PlaySoundEngineStopNoFuel;
  39. protected bool m_PlaySoundImpactLight;
  40. protected bool m_PlaySoundImpactHeavy;
  41. protected bool m_PlaySoundPushBoat;
  42. protected bool m_IsEngineSoundFading;
  43. protected bool m_EngineFadeDirection; // true>in | false>out
  44. protected float m_EngineFadeTime;
  45. protected string m_SoundImpactLight;
  46. protected string m_SoundImpactHeavy;
  47. protected string m_SoundPushBoat;
  48. protected string m_SoundWaterSplash;
  49. protected ref EffectSound m_SoundImpactLightEffect;
  50. protected ref EffectSound m_SoundImpactHeavyEffect;
  51. protected ref EffectSound m_SoundPushBoatEffect;
  52. protected ref EffectSound m_SoundWaterSplashEffect;
  53. void BoatScript()
  54. {
  55. SetEventMask(EntityEvent.POSTSIMULATE);
  56. SetEventMask(EntityEvent.FRAME);
  57. m_PlaySoundImpactLight = false;
  58. m_PlaySoundImpactHeavy = false;
  59. RegisterNetSyncVariableBool("m_PlaySoundEngineStopNoFuel");
  60. RegisterNetSyncVariableBool("m_PlaySoundPushBoat");
  61. RegisterNetSyncVariableBoolSignal("m_PlaySoundImpactLight");
  62. RegisterNetSyncVariableBoolSignal("m_PlaySoundImpactHeavy");
  63. m_SoundImpactHeavy = "boat_01_hit_light_SoundSet";
  64. m_SoundImpactLight = "boat_01_hit_heavy_SoundSet";
  65. m_SoundPushBoat = "boat_01_push_SoundSet";
  66. m_SoundWaterSplash = "boat_01_splash_SoundSet";
  67. if (GetGame().IsDedicatedServer())
  68. return;
  69. m_WaterEffects[EBoatEffects.PTC_FRONT] = new EffectBoatWaterFront();
  70. m_WaterEffects[EBoatEffects.PTC_BACK] = new EffectBoatWaterBack();
  71. m_WaterEffects[EBoatEffects.PTC_SIDE_L] = new EffectBoatWaterSide();
  72. m_WaterEffects[EBoatEffects.PTC_SIDE_R] = new EffectBoatWaterSide();
  73. if (MemoryPointExists("ptcFxFront"))
  74. m_WaterEffects[EBoatEffects.PTC_FRONT].AttachTo(this, GetMemoryPointPos("ptcFxFront"));
  75. if (MemoryPointExists("ptcFxBack"))
  76. m_WaterEffects[EBoatEffects.PTC_BACK].AttachTo(this, GetMemoryPointPos("ptcFxBack"));
  77. if (MemoryPointExists("ptcFxSide1"))
  78. m_WaterEffects[EBoatEffects.PTC_SIDE_L].AttachTo(this, GetMemoryPointPos("ptcFxSide1"));
  79. if (MemoryPointExists("ptcFxSide2"))
  80. m_WaterEffects[EBoatEffects.PTC_SIDE_R].AttachTo(this, GetMemoryPointPos("ptcFxSide2"));
  81. }
  82. void ~BoatScript()
  83. {
  84. #ifndef SERVER
  85. CleanupEffects();
  86. #endif
  87. }
  88. override void EEDelete(EntityAI parent)
  89. {
  90. if (!GetGame().IsDedicatedServer())
  91. CleanupEffects();
  92. }
  93. void InitializeActions()
  94. {
  95. m_InputActionMap = m_BoatTypeActionsMap.Get(this.Type());
  96. if (!m_InputActionMap)
  97. {
  98. TInputActionMap iam = new TInputActionMap();
  99. m_InputActionMap = iam;
  100. SetActions();
  101. m_BoatTypeActionsMap.Insert(this.Type(), m_InputActionMap);
  102. }
  103. }
  104. override void GetActions(typename action_input_type, out array<ActionBase_Basic> actions)
  105. {
  106. if (!m_ActionsInitialized)
  107. {
  108. m_ActionsInitialized = true;
  109. InitializeActions();
  110. }
  111. actions = m_InputActionMap.Get(action_input_type);
  112. }
  113. override bool DisableVicinityIcon()
  114. {
  115. return true;
  116. }
  117. override string GetVehicleType()
  118. {
  119. return "VehicleTypeBoat";
  120. }
  121. override bool IsInventoryVisible()
  122. {
  123. return (GetGame().GetPlayer() && (!GetGame().GetPlayer().GetCommand_Vehicle() || GetGame().GetPlayer().GetCommand_Vehicle().GetTransport() == this));
  124. }
  125. override float GetTransportCameraDistance()
  126. {
  127. return 4.5;
  128. }
  129. override vector GetTransportCameraOffset()
  130. {
  131. return "0 1.4 0";
  132. }
  133. override int GetAnimInstance()
  134. {
  135. return VehicleAnimInstances.ZODIAC;
  136. }
  137. override int Get3rdPersonCameraType()
  138. {
  139. return DayZPlayerCameras.DAYZCAMERA_3RD_VEHICLE;
  140. }
  141. override bool CrewCanGetThrough(int posIdx)
  142. {
  143. return true;
  144. }
  145. override bool CanReachSeatFromSeat(int currentSeat, int nextSeat)
  146. {
  147. return true;
  148. }
  149. override bool CanReachSeatFromDoors(string pSeatSelection, vector pFromPos, float pDistance = 1.0)
  150. {
  151. return true;
  152. }
  153. override bool CanReachDoorsFromSeat(string pDoorsSelection, int pCurrentSeat)
  154. {
  155. return true;
  156. }
  157. override bool IsAreaAtDoorFree(int currentSeat, float maxAllowedObjHeight, inout vector extents, out vector transform[4])
  158. {
  159. return super.IsAreaAtDoorFree(currentSeat, maxAllowedObjHeight, extents, transform);
  160. }
  161. override bool OnBeforeEngineStart()
  162. {
  163. if (GetFluidFraction(BoatFluid.FUEL) <= 0)
  164. {
  165. HandleEngineSound(EBoatEngineSoundState.START_NO_FUEL);
  166. return false;
  167. }
  168. return true;
  169. }
  170. override void OnEngineStart()
  171. {
  172. super.OnEngineStart();
  173. if (GetGame().IsDedicatedServer())
  174. return;
  175. FadeEngineSound(true);
  176. HandleEngineSound(EBoatEngineSoundState.START_OK);
  177. ClearWaterEffects(); // in case they are still active
  178. }
  179. override void OnEngineStop()
  180. {
  181. super.OnEngineStop();
  182. if (GetGame().IsDedicatedServer())
  183. return;
  184. FadeEngineSound(false);
  185. HandleEngineSound(EBoatEngineSoundState.STOP_OK);
  186. vector mat[4];
  187. dBodyGetWorldTransform(this, mat);
  188. vector pos = mat[3] + VectorToParent(PropellerGetPosition());
  189. if (GetGame().GetWaterDepth(pos) < 0) // stop instantly
  190. StopParticleUpdate();
  191. else
  192. GetGame().GetCallQueue(CALL_CATEGORY_SYSTEM).CallLater(StopParticleUpdate, 3000);
  193. }
  194. override void EEOnCECreate()
  195. {
  196. float maxVolume = GetFluidCapacity(BoatFluid.FUEL);
  197. float amount = Math.RandomFloat(0.0, maxVolume * 0.35);
  198. Fill(BoatFluid.FUEL, amount);
  199. }
  200. override void EOnPostSimulate(IEntity other, float timeSlice)
  201. {
  202. if (GetGame().IsServer())
  203. {
  204. HandleByCrewMemberState(ECrewMemberState.UNCONSCIOUS);
  205. HandleByCrewMemberState(ECrewMemberState.DEAD);
  206. if (EngineIsOn())
  207. {
  208. if (GetFluidFraction(BoatFluid.FUEL) <= 0)
  209. {
  210. m_PlaySoundEngineStopNoFuel = true;
  211. SetSynchDirty();
  212. m_PlaySoundEngineStopNoFuel = false;
  213. EngineStop();
  214. }
  215. }
  216. CheckContactCache();
  217. m_VelocityPrevTick = GetVelocity(this);
  218. m_MomentumPrevTick = GetMomentum();
  219. }
  220. else if (EngineIsOn())
  221. m_UpdateParticles = true;
  222. if (!GetGame().IsDedicatedServer() && m_UpdateParticles)
  223. HandleBoatSplashSound();
  224. }
  225. override void EOnSimulate(IEntity other, float timeSlice)
  226. {
  227. if (!IsProxy())
  228. {
  229. if (EngineIsOn())
  230. {
  231. vector mat[4];
  232. dBodyGetWorldTransform(this, mat);
  233. vector pos = mat[3] + VectorToParent(PropellerGetPosition());
  234. if (GetGame().GetWaterDepth(pos) < -0.2)
  235. EngineStop();
  236. }
  237. }
  238. }
  239. override void EOnFrame(IEntity other, float timeSlice)
  240. {
  241. if (!GetGame().IsDedicatedServer())
  242. {
  243. if (m_UpdateParticles)
  244. UpdateParticles();
  245. if (m_IsEngineSoundFading)
  246. {
  247. m_EngineFadeTime -= timeSlice;
  248. if (m_EngineFadeTime < 0)
  249. m_IsEngineSoundFading = false;
  250. }
  251. }
  252. }
  253. override void EOnContact(IEntity other, Contact extra)
  254. {
  255. if (GetGame().IsServer())
  256. {
  257. if (m_ContactData)
  258. return;
  259. float momentumDelta = GetMomentum() - m_MomentumPrevTick;
  260. float dot = vector.Dot(m_VelocityPrevTick.Normalized(), GetVelocity(this).Normalized());
  261. if (dot < 0)
  262. momentumDelta = m_MomentumPrevTick;
  263. m_ContactData = new VehicleContactData();
  264. m_ContactData.SetData(extra.Position, other, momentumDelta); // change to local pos
  265. if (EngineIsOn() && !CheckOperationalState())
  266. EngineStop();
  267. }
  268. }
  269. override void EEHitBy(TotalDamageResult damageResult, int damageType, EntityAI source, int component, string dmgZone, string ammo, vector modelPos, float speedCoef)
  270. {
  271. super.EEHitBy(damageResult, damageType, source, component, dmgZone, ammo, modelPos, speedCoef);
  272. if (GetGame().IsServer())
  273. {
  274. if (EngineIsOn() && !CheckOperationalState())
  275. EngineStop();
  276. }
  277. }
  278. override void OnVariablesSynchronized()
  279. {
  280. super.OnVariablesSynchronized();
  281. if (m_PlaySoundImpactHeavy)
  282. {
  283. PlaySound(m_SoundImpactHeavy, m_SoundImpactHeavyEffect);
  284. m_PlaySoundImpactHeavy = false;
  285. }
  286. if (m_PlaySoundImpactLight)
  287. {
  288. PlaySound(m_SoundImpactLight, m_SoundImpactLightEffect);
  289. m_PlaySoundImpactLight = false;
  290. }
  291. if (m_PlaySoundPushBoat)
  292. PlaySound(m_SoundPushBoat, m_SoundPushBoatEffect);
  293. else if (m_SoundPushBoatEffect && m_SoundPushBoatEffect.IsPlaying())
  294. m_SoundPushBoatEffect.Stop();
  295. if (m_PlaySoundEngineStopNoFuel)
  296. {
  297. HandleEngineSound(EBoatEngineSoundState.STOP_NO_FUEL);
  298. m_PlaySoundEngineStopNoFuel = false;
  299. }
  300. }
  301. override float OnSound(BoatSoundCtrl ctrl, float oldValue)
  302. {
  303. if (m_IsEngineSoundFading)
  304. {
  305. if (m_EngineFadeDirection)
  306. oldValue = Math.InverseLerp(SOUND_ENGINE_FADE, 0, m_EngineFadeTime);
  307. else
  308. oldValue = Math.InverseLerp(0, SOUND_ENGINE_FADE, m_EngineFadeTime);
  309. return oldValue;
  310. }
  311. return super.OnSound(ctrl, oldValue);
  312. }
  313. override void HandleByCrewMemberState(ECrewMemberState state)
  314. {
  315. switch (state)
  316. {
  317. case ECrewMemberState.UNCONSCIOUS:
  318. foreach (int unconsciousCrewMemberIndex : m_UnconsciousCrewMemberIndices)
  319. {
  320. if (unconsciousCrewMemberIndex == DayZPlayerConstants.VEHICLESEAT_DRIVER)
  321. EngineStop();
  322. m_UnconsciousCrewMemberIndices.RemoveItem(unconsciousCrewMemberIndex);
  323. }
  324. break;
  325. case ECrewMemberState.DEAD:
  326. foreach (int deadCrewMemberIndex : m_DeadCrewMemberIndices)
  327. {
  328. if (deadCrewMemberIndex == DayZPlayerConstants.VEHICLESEAT_DRIVER)
  329. EngineStop();
  330. m_DeadCrewMemberIndices.RemoveItem(deadCrewMemberIndex);
  331. }
  332. break;
  333. }
  334. }
  335. bool CheckOperationalState()
  336. {
  337. if (GetHealthLevel("") >= GameConstants.STATE_RUINED || GetHealthLevel("Engine") >= GameConstants.STATE_RUINED)
  338. return false;
  339. if (IsVitalSparkPlug())
  340. {
  341. EntityAI item = FindAttachmentBySlotName("SparkPlug");
  342. if (!item || (item && item.IsRuined()))
  343. return false;
  344. }
  345. return true;
  346. }
  347. // Server side event for jump out processing
  348. void OnVehicleJumpOutServer(GetOutTransportActionData data)
  349. {
  350. vector posMS = data.m_Player.WorldToModel(data.m_Player.GetPosition());
  351. float healthCoef = Math.InverseLerp(ActionGetOutTransport.HEALTH_LOW_SPEED_VALUE, ActionGetOutTransport.HEALTH_HIGH_SPEED_VALUE, data.m_Speed) * 0.5;
  352. healthCoef = Math.Clamp(healthCoef, 0.0, 1.0);
  353. data.m_Player.ProcessDirectDamage(DamageType.CUSTOM, data.m_Player, "", "FallDamageHealth", posMS, healthCoef);
  354. }
  355. protected void HandleEngineSound(EBoatEngineSoundState state)
  356. {
  357. if (GetGame().IsDedicatedServer())
  358. return;
  359. EffectSound sound = null;
  360. switch (state)
  361. {
  362. case EBoatEngineSoundState.START_OK:
  363. sound = SEffectManager.PlaySound("boat_01_engine_start_SoundSet", ModelToWorld(PropellerGetPosition()));
  364. sound.SetAttachmentParent(this);
  365. sound.SetAutodestroy(true);
  366. break;
  367. case EBoatEngineSoundState.STOP_OK:
  368. sound = SEffectManager.PlaySound("boat_01_engine_stop_SoundSet", ModelToWorld(PropellerGetPosition()));
  369. sound.SetAttachmentParent(this);
  370. sound.SetAutodestroy(true);
  371. break;
  372. case EBoatEngineSoundState.START_NO_FUEL:
  373. sound = SEffectManager.PlaySound("boat_01_engine_start_no_fuel_SoundSet", ModelToWorld(PropellerGetPosition()));
  374. sound.SetAttachmentParent(this);
  375. sound.SetAutodestroy(true);
  376. break;
  377. case EBoatEngineSoundState.STOP_NO_FUEL:
  378. sound = SEffectManager.PlaySound("boat_01_engine_stop_no_fuel_SoundSet", ModelToWorld(PropellerGetPosition()));
  379. sound.SetAttachmentParent(this);
  380. sound.SetAutodestroy(true);
  381. break;
  382. }
  383. }
  384. protected void PlaySound(string soundset, inout EffectSound sound)
  385. {
  386. #ifndef SERVER
  387. //Print(this.GetPosition().ToString() + " playing " + soundset + " using "+ sound);
  388. if (!sound)
  389. {
  390. sound = SEffectManager.PlaySoundCachedParams(soundset, GetPosition());
  391. sound.SetAttachmentParent(this);
  392. sound.SetAutodestroy(true); // SoundWaveObjects tend to null themselves for unknown reasons, breaking the effect in the process
  393. }
  394. else
  395. {
  396. if (!sound.IsSoundPlaying())
  397. {
  398. sound.SetCurrentPosition(GetPosition());
  399. sound.SoundPlay();
  400. }
  401. }
  402. #endif
  403. }
  404. protected void HandleBoatSplashSound()
  405. {
  406. float propPosRelative = GetGame().SurfaceGetSeaLevel() - CoordToParent(PropellerGetPosition())[1];
  407. if (propPosRelative < SPLASH_THRESHOLD_CONDITION)
  408. m_SplashIncoming = true;
  409. if (m_SplashIncoming && propPosRelative > SPLASH_THRESHOLD)
  410. {
  411. m_SoundWaterSplashEffect = SEffectManager.CreateSound(m_SoundWaterSplash, GetPosition());
  412. m_SoundWaterSplashEffect.SetAttachmentParent(this);
  413. m_SoundWaterSplashEffect.SetLocalPosition(PropellerGetPosition());
  414. m_SoundWaterSplashEffect.SetAutodestroy(true);
  415. vector velocity = dBodyGetVelocityAt(this, CoordToParent(PropellerGetPosition()));
  416. float speed = velocity.Normalize() * 3.6; // to km/h
  417. float lerp = Math.InverseLerp(0, 30, speed);
  418. m_SoundWaterSplashEffect.SetSoundVolume(lerp);
  419. m_SoundWaterSplashEffect.Start();
  420. m_SplashIncoming = false;
  421. }
  422. }
  423. protected void SyncSoundImpactLight()
  424. {
  425. if (!m_PlaySoundImpactLight)
  426. {
  427. m_PlaySoundImpactLight = true;
  428. SetSynchDirty();
  429. }
  430. }
  431. protected void SyncSoundImpactHeavy()
  432. {
  433. if (!m_PlaySoundImpactHeavy)
  434. {
  435. m_PlaySoundImpactHeavy = true;
  436. SetSynchDirty();
  437. }
  438. }
  439. void SyncSoundPushBoat(bool play)
  440. {
  441. if (m_PlaySoundPushBoat != play)
  442. {
  443. m_PlaySoundPushBoat = play;
  444. SetSynchDirty();
  445. }
  446. }
  447. // Set engine sound to fade on start/stop
  448. protected void FadeEngineSound(bool fadeIn)
  449. {
  450. m_IsEngineSoundFading = true;
  451. m_EngineFadeDirection = fadeIn;
  452. m_EngineFadeTime = SOUND_ENGINE_FADE;
  453. }
  454. protected void CheckContactCache()
  455. {
  456. if (!m_ContactData)
  457. return;
  458. float impulse = Math.AbsInt(m_ContactData.m_Impulse);
  459. m_ContactData = null;
  460. if (impulse < GameConstants.CARS_CONTACT_DMG_MIN)
  461. return;
  462. else if (impulse < GameConstants.CARS_CONTACT_DMG_THRESHOLD)
  463. SyncSoundImpactLight();
  464. else
  465. SyncSoundImpactHeavy();
  466. }
  467. protected void SetActions()
  468. {
  469. AddAction(ActionGetInTransport);
  470. AddAction(ActionPushBoat);
  471. }
  472. void AddAction(typename actionName)
  473. {
  474. ActionBase action = ActionManagerBase.GetAction(actionName);
  475. if (!action)
  476. {
  477. Debug.LogError("Action " + actionName + " dosn't exist!");
  478. return;
  479. }
  480. typename ai = action.GetInputType();
  481. if (!ai)
  482. {
  483. m_ActionsInitialized = false;
  484. return;
  485. }
  486. array<ActionBase_Basic> actionArray = m_InputActionMap.Get(ai);
  487. if (!actionArray)
  488. {
  489. actionArray = new array<ActionBase_Basic>;
  490. m_InputActionMap.Insert(ai, actionArray);
  491. }
  492. if (LogManager.IsActionLogEnable())
  493. {
  494. Debug.ActionLog(action.ToString() + " -> " + ai, this.ToString() , "n/a", "Add action" );
  495. }
  496. actionArray.Insert(action);
  497. }
  498. void RemoveAction(typename actionName)
  499. {
  500. PlayerBase player = PlayerBase.Cast(GetGame().GetPlayer());
  501. ActionBase action = player.GetActionManager().GetAction(actionName);
  502. typename ai = action.GetInputType();
  503. array<ActionBase_Basic> actionArray = m_InputActionMap.Get(ai);
  504. if (actionArray)
  505. {
  506. actionArray.RemoveItem(action);
  507. }
  508. }
  509. protected void UpdateParticles()
  510. {
  511. for (int i; i < 4; i++)
  512. {
  513. m_WaterEffects[i].Update();
  514. }
  515. }
  516. protected void StopParticleUpdate()
  517. {
  518. m_UpdateParticles = false;
  519. ClearWaterEffects();
  520. }
  521. protected void ClearWaterEffects()
  522. {
  523. GetGame().GetCallQueue(CALL_CATEGORY_SYSTEM).Remove(StopParticleUpdate);
  524. for (int i; i < 4; i++)
  525. {
  526. if (m_WaterEffects[i].IsPlaying())
  527. {
  528. if (m_WaterEffects[i].GetParticle())
  529. {
  530. m_WaterEffects[i].GetParticle().SetParticleParam(EmitorParam.BIRTH_RATE, 0);
  531. m_WaterEffects[i].GetParticle().SetParticleParam(EmitorParam.BIRTH_RATE_RND, 0);
  532. }
  533. m_WaterEffects[i].Stop();
  534. }
  535. }
  536. }
  537. // Called on destroy/stream out
  538. protected void CleanupEffects()
  539. {
  540. for (int i; i < 4; i++)
  541. {
  542. if (m_WaterEffects[i].IsRegistered())
  543. {
  544. m_WaterEffects[i].Stop();
  545. SEffectManager.EffectUnregisterEx(m_WaterEffects[i]);
  546. }
  547. }
  548. SEffectManager.DestroyEffect(m_SoundImpactLightEffect);
  549. SEffectManager.DestroyEffect(m_SoundImpactHeavyEffect);
  550. SEffectManager.DestroyEffect(m_SoundPushBoatEffect);
  551. SEffectManager.DestroyEffect(m_SoundWaterSplashEffect);
  552. }
  553. override void GetDebugActions(out TSelectableActionInfoArrayEx outputList)
  554. {
  555. super.GetDebugActions(outputList);
  556. outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.SEPARATOR, "___________________________", FadeColors.RED));
  557. outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.DELETE, "Delete", FadeColors.RED));
  558. }
  559. override bool OnAction(int action_id, Man player, ParamsReadContext ctx)
  560. {
  561. if (super.OnAction(action_id, player, ctx))
  562. return true;
  563. if (!GetGame().IsServer())
  564. {
  565. return false;
  566. }
  567. switch (action_id)
  568. {
  569. case EActions.DELETE:
  570. Delete();
  571. return true;
  572. }
  573. return false;
  574. }
  575. protected override event typename GetOwnerStateType()
  576. {
  577. return BoatScriptOwnerState;
  578. }
  579. protected override event typename GetMoveType()
  580. {
  581. return BoatScriptMove;
  582. }
  583. #ifdef DIAG_DEVELOPER
  584. override void FixEntity()
  585. {
  586. super.FixEntity();
  587. if (GetGame().IsServer())
  588. Fill(BoatFluid.FUEL, GetFluidCapacity(BoatFluid.FUEL));
  589. }
  590. #endif
  591. }