trapspawnbase.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907
  1. class TrapSpawnBase extends ItemBase
  2. {
  3. bool m_IsFoldable;
  4. bool m_CanCatch = false;
  5. //configurable stuff
  6. bool m_NeedInstalation;
  7. int m_InitWaitTimeMin;
  8. int m_InitWaitTimeMax;
  9. int m_UpdateWaitTime; //! Catch evaluation interval
  10. int m_SpawnUpdateWaitTime; //! Catch spawn and player check interval (expensive-ish)
  11. int m_MaxActiveTime; //! Max time of trap activity (seconds)
  12. float m_BaitLossFraction; //! Normalized bait qty reduction on unsuccessful catch
  13. float m_DefectRate; //! Absolute damage dealt to trap when used
  14. float m_MinimalDistanceFromPlayersToCatch; //! duh
  15. //derived stuff
  16. private int m_InitWaitTime; //! After this time after deployment, the trap is activated
  17. private int m_AdjustedMaxActiveTime; //! Adjusted by init wait time, when appropriate
  18. private int m_ElapsedTime;
  19. private int m_ActivationTime;
  20. private int m_RollSuccessTime;
  21. private float m_CurrentMinimalDistance;
  22. private float m_CurrentlyUsedDelta;
  23. private bool m_IsCatchSuccessful;
  24. private int m_CatchEnviroMask = 0;
  25. private int m_YieldItemIdxLocal = -1;
  26. private int m_YieldItemIdx = -1;
  27. private int m_CatchParticleEffecterId = -1;
  28. vector m_PreyPos; // The position where prey will be spawned -> Will be overriden later
  29. protected bool m_IsActive;
  30. protected bool m_IsPastWaitingTime;
  31. protected bool m_IsDeployed;
  32. ref Timer m_Timer;
  33. string m_AnimationPhaseSet;
  34. string m_AnimationPhaseTriggered;
  35. string m_AnimationPhaseUsed;
  36. protected ref array<string> m_PlaceableWaterSurfaceList;
  37. protected ref CatchingContextTrapsBase m_CatchingContext;
  38. #ifdef DEVELOPER
  39. int m_dbgAttemptCount = 0;
  40. #endif
  41. void TrapSpawnBase()
  42. {
  43. InitTrapValues();
  44. RegisterNetSyncVariableBool("m_IsActive");
  45. RegisterNetSyncVariableBool("m_IsDeployed");
  46. RegisterNetSyncVariableInt("m_YieldItemIdx");
  47. //DEPRECATED stuff below, legacy reasons only
  48. m_CatchesPond = new multiMap<string, float>; //yields now in WorldData.InitYieldBank
  49. m_CatchesSea = new multiMap<string, float>; //yields now in WorldData.InitYieldBank
  50. m_CatchesGroundAnimal = new multiMap<string, float>; //yields now in WorldData.InitYieldBank
  51. }
  52. void ~TrapSpawnBase()
  53. {
  54. if (m_Timer)
  55. {
  56. m_Timer.Stop();
  57. delete m_Timer;
  58. }
  59. ClearCatchingComponent();
  60. }
  61. void InitTrapValues()
  62. {
  63. m_DefectRate = 10; //Added damage after trap activation
  64. m_BaitLossFraction = 0.2;
  65. m_UpdateWaitTime = 60;
  66. m_SpawnUpdateWaitTime = 30;
  67. m_InitWaitTimeMin = 10;
  68. m_InitWaitTimeMax = 10;
  69. m_MaxActiveTime = 1200;
  70. m_NeedInstalation = true;
  71. m_IsFoldable = false;
  72. m_IsCatchSuccessful = false;
  73. m_MinimalDistanceFromPlayersToCatch = 0;
  74. m_AnimationPhaseSet = "";
  75. m_AnimationPhaseTriggered = "";
  76. m_AnimationPhaseUsed = "";
  77. m_PlaceableWaterSurfaceList = new array<string>();
  78. m_PlaceableWaterSurfaceList.Insert(UAWaterType.SEA);
  79. m_PlaceableWaterSurfaceList.Insert(UAWaterType.FRESH);
  80. }
  81. override void OnStoreSave( ParamsWriteContext ctx )
  82. {
  83. super.OnStoreSave( ctx );
  84. ctx.Write( m_IsActive );
  85. ctx.Write( m_IsDeployed );
  86. ctx.Write(m_CatchEnviroMask);
  87. }
  88. override bool OnStoreLoad( ParamsReadContext ctx, int version )
  89. {
  90. if ( !super.OnStoreLoad(ctx, version) )
  91. return false;
  92. m_IsStoreLoad = true;
  93. bool b_is_active = false;
  94. if ( !ctx.Read( b_is_active ) )
  95. b_is_active = false;
  96. bool b_is_in_progress = false;
  97. if (version < 139)
  98. {
  99. if ( !ctx.Read( b_is_in_progress ) )
  100. b_is_in_progress = false;
  101. }
  102. bool b_is_deployed = false;
  103. if ( !ctx.Read( b_is_deployed ) )
  104. b_is_deployed = false;
  105. if (version >= 139)
  106. {
  107. int enviroMask;
  108. if (ctx.Read(enviroMask))
  109. m_CatchEnviroMask = enviroMask;
  110. }
  111. if (b_is_active)
  112. {
  113. InitCatchingComponent();
  114. SetActive();
  115. }
  116. SetDeployed( b_is_deployed );
  117. m_IsStoreLoad = false;
  118. return true;
  119. }
  120. //! this event is called all variables are synchronized on client
  121. override void OnVariablesSynchronized()
  122. {
  123. super.OnVariablesSynchronized();
  124. if (m_YieldItemIdx != m_YieldItemIdxLocal)
  125. {
  126. m_YieldItemIdxLocal = m_YieldItemIdx;
  127. if (m_YieldItemIdxLocal != -1)
  128. OnCatchSpawnClient();
  129. }
  130. }
  131. bool IsActive()
  132. {
  133. return m_IsActive;
  134. }
  135. bool IsDeployed()
  136. {
  137. return m_IsDeployed;
  138. }
  139. void SetDeployed( bool newState )
  140. {
  141. m_IsDeployed = newState;
  142. if ( newState == true )
  143. {
  144. if ( m_AnimationPhaseSet != "" && m_AnimationPhaseTriggered != "" )
  145. {
  146. SetAnimationPhase( m_AnimationPhaseSet, 1 );
  147. SetAnimationPhase( m_AnimationPhaseTriggered, 0 );
  148. SetAnimationPhase( m_AnimationPhaseUsed, 1 );
  149. }
  150. }
  151. else
  152. {
  153. if ( m_AnimationPhaseSet != "" && m_AnimationPhaseTriggered != "" )
  154. {
  155. SetAnimationPhase( m_AnimationPhaseSet, 0 );
  156. SetAnimationPhase( m_AnimationPhaseTriggered, 1 );
  157. SetAnimationPhase( m_AnimationPhaseUsed, 1 );
  158. }
  159. }
  160. SetSynchDirty();
  161. }
  162. override bool IsTakeable()
  163. {
  164. return true;
  165. }
  166. bool IsPlaceableAtPosition( vector position )
  167. {
  168. string surface_type;
  169. GetGame().SurfaceGetType3D( position[0], position[1], position[2], surface_type);
  170. // check surface
  171. return GetGame().IsSurfaceDigable(surface_type);
  172. }
  173. void SetupTrap()
  174. {
  175. if ( GetGame().IsServer() )
  176. {
  177. if ( GetHierarchyRootPlayer() && GetHierarchyRootPlayer().CanDropEntity( this ) )
  178. {
  179. SetupTrapPlayer( PlayerBase.Cast( GetHierarchyRootPlayer() ) );
  180. }
  181. }
  182. }
  183. void SetupTrapPlayer( PlayerBase player, bool set_position = true )
  184. {
  185. if ( GetGame().IsServer() )
  186. {
  187. if ( set_position )
  188. {
  189. vector trapPos = player.GetPosition() + ( player.GetDirection() * 0.5 );
  190. trapPos[1] = GetGame().SurfaceRoadY( trapPos[0], trapPos[2] );
  191. SetPosition( trapPos );
  192. }
  193. SetDeployed( true );
  194. }
  195. }
  196. void UpdatePreyPos()
  197. {
  198. m_PreyPos = GetPosition();
  199. if (MemoryPointExists("Prey_Position"))
  200. m_PreyPos = ModelToWorld(GetMemoryPointPos("Prey_Position"));
  201. }
  202. void Fold()
  203. {
  204. if ( GetGame().IsServer() && m_IsFoldable == true )
  205. {
  206. SetInactive();
  207. }
  208. }
  209. // Deal damage to trap on specific events
  210. void AddDefect()
  211. {
  212. if ( GetGame().IsServer() )
  213. {
  214. DecreaseHealth( "", "", m_DefectRate );
  215. }
  216. }
  217. void StartActivate( PlayerBase player ) { }
  218. // IsTakeable is used to hide tooltips as well, so we use a custom method instead
  219. // Used to prevent players from taking traps which should be set for catching
  220. bool CanBeTaken()
  221. {
  222. if ( !IsDeployed() || ( GetInventory().AttachmentCount() == 0 && IsDeployed() ) )
  223. {
  224. return true;
  225. }
  226. return false;
  227. }
  228. override bool CanPutInCargo( EntityAI parent )
  229. {
  230. super.CanPutInCargo( parent );
  231. return CanBeTaken();
  232. }
  233. override bool CanPutIntoHands( EntityAI parent )
  234. {
  235. super.CanPutIntoHands( parent );
  236. return CanBeTaken();
  237. }
  238. void ResetActiveProgress()
  239. {
  240. m_ActivationTime = GetGame().GetTickTime();
  241. m_ElapsedTime = 0;
  242. m_CurrentMinimalDistance = m_MinimalDistanceFromPlayersToCatch;
  243. #ifdef DEVELOPER
  244. m_dbgAttemptCount = 0;
  245. #endif
  246. }
  247. void ResetRunningTimerProgress()
  248. {
  249. if (m_IsPastWaitingTime)
  250. {
  251. m_AdjustedMaxActiveTime = m_MaxActiveTime;
  252. RunTrappingTimer(m_UpdateWaitTime,"EvaluateCatch");
  253. }
  254. else
  255. {
  256. m_AdjustedMaxActiveTime = m_MaxActiveTime + m_InitWaitTime;
  257. RunTrappingTimer(m_InitWaitTime + m_UpdateWaitTime,"EvaluateCatch");
  258. }
  259. }
  260. //! generic trapping launcher for traps, use this to store delta info
  261. void RunTrappingTimer(float duration, string fnName)
  262. {
  263. if (!m_Timer)
  264. m_Timer = new Timer(CALL_CATEGORY_SYSTEM);
  265. else
  266. m_Timer.Stop();
  267. #ifdef DEVELOPER
  268. if (IsCLIParam("trapsQuick"))
  269. {
  270. m_CurrentlyUsedDelta = 1;
  271. m_Timer.Run(1, this, fnName);
  272. }
  273. else
  274. #endif
  275. {
  276. m_CurrentlyUsedDelta = duration;
  277. m_Timer.Run(duration, this, fnName);
  278. }
  279. }
  280. // Set animation phases according to state
  281. void SetActive()
  282. {
  283. UpdatePreyPos();
  284. if ( GetGame().IsServer() && !IsActive() )
  285. {
  286. SetCatchSuccessful(false);
  287. m_IsActive = true;
  288. m_IsPastWaitingTime = false;
  289. m_YieldItemIdx = -1;
  290. if (m_CatchParticleEffecterId >= 0)
  291. SEffectManager.DestroyEffecterParticleServer(m_CatchParticleEffecterId);
  292. m_CatchParticleEffecterId = -1;
  293. SetSynchDirty();
  294. if ( m_AnimationPhaseSet != "" && m_AnimationPhaseTriggered != "" )
  295. {
  296. SetAnimationPhase( m_AnimationPhaseSet, 1 );
  297. SetAnimationPhase( m_AnimationPhaseTriggered, 0 );
  298. SetAnimationPhase( m_AnimationPhaseUsed, 1 );
  299. }
  300. ResetActiveProgress();
  301. m_InitWaitTime = Math.RandomFloatInclusive(m_InitWaitTimeMin,m_InitWaitTimeMax);
  302. if (!m_IsStoreLoad) //presumably activated by the player, store load initializes component separately
  303. {
  304. InitCatchingComponent();
  305. UpdateTrapEnviroMask();
  306. RunTrappingTimer(m_InitWaitTime + m_UpdateWaitTime,"EvaluateCatch");
  307. m_AdjustedMaxActiveTime = m_MaxActiveTime + m_InitWaitTime;
  308. }
  309. else //presumed store load
  310. {
  311. SetTrapEnviroMask(m_CatchEnviroMask);
  312. RunTrappingTimer(m_UpdateWaitTime,"EvaluateCatch");
  313. m_AdjustedMaxActiveTime = m_MaxActiveTime;
  314. }
  315. }
  316. }
  317. void SetInactive()
  318. {
  319. if ( GetGame().IsServer() )
  320. {
  321. // We stop timers as the trap is no longer active, then update visuals
  322. m_IsActive = false;
  323. ClearCatchingComponent();
  324. if ( m_Timer )
  325. {
  326. m_Timer.Stop();
  327. }
  328. m_IsPastWaitingTime = false;
  329. SetDeployed( false );
  330. SetSynchDirty();
  331. }
  332. }
  333. void SetUsed()
  334. {
  335. if ( GetGame().IsServer() )
  336. {
  337. // We updated state, visuals and stop timers
  338. m_IsActive = false;
  339. m_IsDeployed = false;
  340. // Deal damage to trap
  341. AddDefect();
  342. HandleBaitLoss();
  343. DetachAllAttachments();
  344. ClearCatchingComponent();
  345. if ( m_Timer )
  346. {
  347. m_Timer.Stop();
  348. }
  349. m_IsPastWaitingTime = false;
  350. if ( m_AnimationPhaseSet != "" && m_AnimationPhaseTriggered != "" )
  351. {
  352. SetAnimationPhase( m_AnimationPhaseSet, 1 );
  353. SetAnimationPhase( m_AnimationPhaseTriggered, 1 );
  354. SetAnimationPhase( m_AnimationPhaseUsed, 0 );
  355. }
  356. m_CatchingContext = null;
  357. SetSynchDirty();
  358. }
  359. }
  360. void IncreaseElapsedTime()
  361. {
  362. m_ElapsedTime += m_CurrentlyUsedDelta;
  363. #ifdef DEVELOPER
  364. if (IsCLIParam("catchingLogs"))
  365. {
  366. Print("dbgTrapz | delta: " + m_CurrentlyUsedDelta);
  367. Print("dbgTrapz | m_ElapsedTime: " + m_ElapsedTime);
  368. Print("dbgTrapz | m_AdjustedMaxActiveTime: " + m_AdjustedMaxActiveTime);
  369. }
  370. #endif
  371. }
  372. void AdjustDetectionRange()
  373. {
  374. if (m_CurrentMinimalDistance > 0)
  375. {
  376. float time = m_ElapsedTime - m_RollSuccessTime;
  377. float timeLimit = m_AdjustedMaxActiveTime - m_RollSuccessTime;
  378. time = Math.InverseLerp(0,timeLimit,time);
  379. time = Easing.EaseInQuad(time);
  380. m_CurrentMinimalDistance = Math.Lerp(m_MinimalDistanceFromPlayersToCatch,0,time);
  381. m_CurrentMinimalDistance = Math.Clamp(m_CurrentMinimalDistance,0,m_MinimalDistanceFromPlayersToCatch);
  382. #ifdef DEVELOPER
  383. if (IsCLIParam("catchingLogs"))
  384. {
  385. Print("dbgTrapz | adjusted distance: " + m_CurrentMinimalDistance + "/" + m_MinimalDistanceFromPlayersToCatch + " | LERP progress: " + time);
  386. }
  387. #endif
  388. }
  389. }
  390. void EvaluateCatch()
  391. {
  392. #ifdef DEVELOPER
  393. m_dbgAttemptCount++;
  394. #endif
  395. m_IsPastWaitingTime = true;
  396. IncreaseElapsedTime();
  397. #ifdef DEVELOPER
  398. if (IsCLIParam("catchingLogs"))
  399. {
  400. Print("dbgTrapz | m_dbgAttemptCount: " + m_dbgAttemptCount + "/" + (m_MaxActiveTime/m_UpdateWaitTime));
  401. }
  402. #endif
  403. bool success = false;
  404. m_CanCatch = SetCanCatch(m_Bait);
  405. if (m_CanCatch)
  406. {
  407. if (m_CatchingContext.RollCatch())
  408. {
  409. success = true;
  410. #ifdef DEVELOPER
  411. if (IsCLIParam("catchingLogs"))
  412. {
  413. Print("dbgTrapz | success!!!");
  414. Print("---------------------");
  415. }
  416. #endif
  417. }
  418. }
  419. #ifdef DEVELOPER
  420. string dbgSuccessOverride;
  421. if (GetCLIParam("trapsSuccessOverride",dbgSuccessOverride))
  422. {
  423. if (dbgSuccessOverride == "true" || dbgSuccessOverride.ToInt() == 1)
  424. success = true;
  425. else if (dbgSuccessOverride == "false" || dbgSuccessOverride.ToInt() == 0)
  426. success = false;
  427. }
  428. #endif
  429. m_Timer.Stop();
  430. #ifdef DEVELOPER
  431. if (m_ElapsedTime >= m_AdjustedMaxActiveTime || (IsCLIParam("trapsQuick") && !success))
  432. #else
  433. if (m_ElapsedTime >= m_AdjustedMaxActiveTime)
  434. #endif
  435. {
  436. SetUsed();
  437. return;
  438. }
  439. if (success)
  440. {
  441. m_RollSuccessTime = m_ElapsedTime;
  442. m_CurrentlyUsedDelta = 0;
  443. TrySpawnCatch();
  444. }
  445. else
  446. {
  447. RunTrappingTimer(m_UpdateWaitTime,"EvaluateCatch");
  448. }
  449. }
  450. bool IsPlayerInVicinity()
  451. {
  452. if (!GetCEApi())
  453. {
  454. Debug.Log("CE not enabled, player avoidance not available!");
  455. return false;
  456. }
  457. return !GetCEApi().AvoidPlayer(GetPosition(), m_CurrentMinimalDistance);
  458. }
  459. void TrySpawnCatch()
  460. {
  461. IncreaseElapsedTime();
  462. AdjustDetectionRange();
  463. #ifdef DEVELOPER
  464. if (IsCLIParam("trapsQuick") || m_CurrentMinimalDistance <= 0 || !IsPlayerInVicinity())
  465. #else
  466. if (m_CurrentMinimalDistance <= 0 || !IsPlayerInVicinity())
  467. #endif
  468. {
  469. SpawnCatch();
  470. }
  471. else if (m_ElapsedTime < m_AdjustedMaxActiveTime)
  472. {
  473. RunTrappingTimer(m_SpawnUpdateWaitTime,"TrySpawnCatch");
  474. }
  475. }
  476. // Actually spawns the prey
  477. void SpawnCatch()
  478. {
  479. // Only server side, let's make sure
  480. if (GetGame().IsMultiplayer() && GetGame().IsClient())
  481. return;
  482. UpdatePreyPos();
  483. ItemBase catch;
  484. if (m_CanCatch)
  485. {
  486. catch = ItemBase.Cast(m_CatchingContext.SpawnAndSetupCatch(m_YieldItemIdx,m_PreyPos));
  487. OnCatchSpawnServer();
  488. SetCatchSuccessful(catch != null);
  489. // We change the trap state and visuals
  490. SetUsed();
  491. }
  492. SetSynchDirty();
  493. }
  494. void SetCatchSuccessful(bool successful)
  495. {
  496. m_IsCatchSuccessful = successful;
  497. }
  498. void OnCatchSpawnServer()
  499. {
  500. PlayCatchEffectsServer();
  501. }
  502. void OnCatchSpawnClient()
  503. {
  504. UpdatePreyPos(); //previously set on server only
  505. PlayCatchEffectsClient();
  506. }
  507. protected void PlayCatchEffectsServer()
  508. {
  509. if (m_YieldItemIdx == -1)
  510. return;
  511. YieldItemBase yItem = GetGame().GetMission().GetWorldData().GetCatchYieldBank().GetYieldItemByIdx(m_YieldItemIdx);
  512. PlayCatchNoise(yItem);
  513. PlayCatchParticleSynced(yItem);
  514. }
  515. protected void PlayCatchEffectsClient()
  516. {
  517. if (m_YieldItemIdx == -1)
  518. return;
  519. YieldItemBase yItem = GetGame().GetMission().GetWorldData().GetCatchYieldBank().GetYieldItemByIdx(m_YieldItemIdx);
  520. PlayCatchSound(yItem);
  521. }
  522. protected void PlayCatchSound(YieldItemBase yItem)
  523. {
  524. if (yItem.GetCatchDeathSoundset() != "")
  525. SEffectManager.PlaySoundEnviroment(yItem.GetCatchDeathSoundset(),m_PreyPos);
  526. }
  527. protected void PlayCatchNoise(YieldItemBase yItem)
  528. {
  529. string noiseType = yItem.GetCatchAINoise();
  530. if (noiseType == "")
  531. return;
  532. NoiseParams m_NoisePar = new NoiseParams();
  533. m_NoisePar.Load(noiseType);
  534. float noiseMultiplier = yItem.GetCatchAINoiseBaseStrength();
  535. noiseMultiplier *= NoiseAIEvaluate.GetNoiseReduction(GetGame().GetWeather());
  536. GetGame().GetNoiseSystem().AddNoiseTarget(m_PreyPos, 5, m_NoisePar, noiseMultiplier);
  537. }
  538. protected void PlayCatchParticleSynced(YieldItemBase yItem)
  539. {
  540. int particleId = yItem.GetCatchParticleID();
  541. if (particleId == ParticleList.INVALID)
  542. return;
  543. if (m_CatchParticleEffecterId < 0)
  544. {
  545. m_CatchParticleEffecterId = SEffectManager.CreateParticleServer(m_PreyPos, new ParticleEffecterParameters("ParticleEffecter", 5, particleId));
  546. }
  547. else
  548. {
  549. SEffectManager.ReinitParticleServer(m_CatchParticleEffecterId, new ParticleEffecterParameters("ParticleEffecter", 5, particleId)); //reinit here, since particleId might differ
  550. SEffectManager.ReactivateParticleServer(m_CatchParticleEffecterId);
  551. }
  552. }
  553. //Pre-roll validation, bait compatibility handled between YieldItems and bait type
  554. bool SetCanCatch( out EntityAI bait )
  555. {
  556. return m_CatchingContext.IsValid();
  557. }
  558. override void OnItemLocationChanged( EntityAI old_owner, EntityAI new_owner )
  559. {
  560. super.OnItemLocationChanged( old_owner, new_owner );
  561. if ( GetGame().IsServer() )
  562. {
  563. // throw trap from vicinity if the trap does not need installation ( action required )
  564. if ( new_owner == NULL && m_NeedInstalation == false )
  565. {
  566. SetActive();
  567. }
  568. else if ( old_owner == NULL && new_owner != NULL )
  569. {
  570. if ( m_IsFoldable )
  571. {
  572. Fold();
  573. }
  574. else
  575. {
  576. SetInactive();
  577. }
  578. }
  579. if (m_YieldItemIdx != -1) //resets sound effect idx
  580. {
  581. m_YieldItemIdx = -1;
  582. SetSynchDirty();
  583. }
  584. }
  585. }
  586. // Generic water check, no real distinction between pond or sea
  587. bool IsSurfaceWater(vector position)
  588. {
  589. string surfaceType;
  590. GetGame().SurfaceGetType3D(position[0], position[1], position[2], surfaceType);
  591. return Surface.AllowedWaterSurface(position[1] + 0.1, surfaceType, m_PlaceableWaterSurfaceList);
  592. }
  593. // Can only receive attachment if deployed
  594. override bool CanDisplayAttachmentSlot( int slot_id )
  595. {
  596. super.CanDisplayAttachmentSlot( slot_id );
  597. return IsDeployed();
  598. }
  599. override bool CanReceiveAttachment( EntityAI attachment, int slotId )
  600. {
  601. super.CanReceiveAttachment( attachment, slotId );
  602. return IsDeployed();
  603. }
  604. override void EEItemAttached( EntityAI item, string slot_name )
  605. {
  606. super.EEItemAttached( item, slot_name );
  607. if (IsActive() && GetGame().IsServer())
  608. {
  609. ResetActiveProgress();
  610. m_CatchingContext.UpdateDataAndMasks();
  611. m_CatchingContext.GenerateResult();
  612. ResetRunningTimerProgress();
  613. }
  614. }
  615. override void EEItemDetached(EntityAI item, string slot_name)
  616. {
  617. super.EEItemDetached( item, slot_name );
  618. if (IsActive() && GetGame().IsServer())
  619. {
  620. ResetActiveProgress();
  621. m_CatchingContext.UpdateDataAndMasks();
  622. m_CatchingContext.GenerateResult();
  623. ResetRunningTimerProgress();
  624. }
  625. }
  626. void InitCatchingComponent();
  627. void ClearCatchingComponent()
  628. {
  629. if (m_CatchingContext)
  630. delete m_CatchingContext;
  631. }
  632. void UpdateTrapEnviroMask()
  633. {
  634. m_CatchEnviroMask = m_CatchingContext.UpdateTrapEnviroMask();
  635. }
  636. void SetTrapEnviroMask(int value)
  637. {
  638. m_CatchingContext.SetTrapEnviroMask(value);
  639. }
  640. void HandleBaitLoss()
  641. {
  642. if (m_CatchingContext)
  643. {
  644. if (m_IsCatchSuccessful)
  645. m_CatchingContext.RemoveBait();
  646. else
  647. m_CatchingContext.ReduceBaitQty(m_BaitLossFraction);
  648. }
  649. }
  650. //! detaches everything on catching end (some slots may not be accessible when folded)
  651. void DetachAllAttachments()
  652. {
  653. int count = GetInventory().AttachmentCount();
  654. if (count > 0)
  655. {
  656. EntityAI att;
  657. for (int i = 0; i < count; i++)
  658. {
  659. att = GetInventory().GetAttachmentFromIndex(i);
  660. GetInventory().DropEntity(InventoryMode.SERVER,this,att);
  661. }
  662. }
  663. }
  664. //================================================================
  665. // ADVANCED PLACEMENT
  666. //================================================================
  667. override void OnPlacementComplete(Man player, vector position = "0 0 0", vector orientation = "0 0 0")
  668. {
  669. super.OnPlacementComplete(player, position, orientation);
  670. if (GetGame().IsServer())
  671. {
  672. vector rotation_matrix[3];
  673. float direction[4];
  674. Math3D.YawPitchRollMatrix(orientation, rotation_matrix);
  675. Math3D.MatrixToQuat(rotation_matrix, direction);
  676. InventoryLocation source = new InventoryLocation;
  677. InventoryLocation destination = new InventoryLocation;
  678. if (GetInventory().GetCurrentInventoryLocation(source))
  679. {
  680. destination.SetGroundEx(this, position, direction);
  681. if (GetGame().IsMultiplayer())
  682. {
  683. player.ServerTakeToDst(source, destination);
  684. SetupTrapPlayer(PlayerBase.Cast(player), false);
  685. }
  686. else // singleplayer
  687. {
  688. PlayerBase.Cast(player).GetDayZPlayerInventory().RedirectToHandEvent(InventoryMode.LOCAL, source, destination);
  689. GetGame().GetCallQueue(CALL_CATEGORY_SYSTEM).CallLater(SetupTrapPlayer, 100, false, PlayerBase.Cast(player), false);
  690. }
  691. }
  692. InitCatchingComponent();
  693. UpdateTrapEnviroMask();
  694. SetActive();
  695. }
  696. }
  697. bool IsPlaceable()
  698. {
  699. if ( GetGame().IsServer() )
  700. {
  701. InventoryLocation loc = new InventoryLocation();
  702. GetInventory().GetCurrentInventoryLocation(loc);
  703. if (loc.GetType() == InventoryLocationType.HANDS)
  704. {
  705. PlayerBase player = PlayerBase.Cast(GetHierarchyRootPlayer());
  706. vector player_pos = player.GetPosition();
  707. vector aim_pos = player.GetAimPosition();
  708. if ( vector.DistanceSq(player_pos, aim_pos) <= ( 1.5 * 1.5 ) )
  709. {
  710. return IsPlaceableAtPosition( aim_pos );
  711. }
  712. }
  713. }
  714. return false;
  715. }
  716. override bool CanBePlaced( Man player, vector position )
  717. {
  718. return IsPlaceableAtPosition(position);
  719. }
  720. // We add the action to deploy a trap laid on ground
  721. override void SetActions()
  722. {
  723. super.SetActions();
  724. AddAction(ActionActivateTrap);
  725. AddAction(ActionDeployHuntingTrap);
  726. }
  727. // ===============================================================
  728. // ===================== DEPRECATED ============================
  729. // ===============================================================
  730. const string m_PlaceableWaterType //!DEPRECATED
  731. ref Timer m_PrevTimer;//!DEPRECATED
  732. bool m_BaitNeeded;//!DEPRECATED
  733. bool m_IsUsable;//!DEPRECATED
  734. private ItemBase m_Catch;//!DEPRECATED, no reason to keep the information as member
  735. ref Timer m_AlignCatchTimer;//!DEPRECATED
  736. string m_InfoSetup;//!DEPRECATED
  737. protected bool m_IsInProgress;//!DEPRECATED
  738. protected ref EffectSound m_DeployLoopSound;//!DEPRECATED
  739. protected EntityAI m_Bait;
  740. float m_BaitCatchProb; //!DEPRECATED
  741. float m_NoBaitCatchProb; //!DEPRECATED
  742. float m_FinalCatchProb; //!DEPRECATED
  743. bool m_WaterSurfaceForSetup; //!DEPRECATED
  744. ref multiMap<string, float> m_CatchesPond; //!DEPRECATED
  745. ref multiMap<string, float> m_CatchesSea; //!DEPRECATED
  746. ref multiMap<string, float> m_CatchesGroundAnimal; //!DEPRECATED
  747. //!DEPRECATED
  748. bool CanPutInInventory(EntityAI player);
  749. //!DEPRECATED
  750. void AlignCatch(ItemBase obj, string catch_name);
  751. ///!DEPRECATED
  752. void CatchSetQuant(ItemBase catch);
  753. void PlayDeployLoopSound(); //!DEPRECATED
  754. void StopDeployLoopSound(); //!DEPRECATED
  755. // ===============================================================
  756. }