trapspawnbase.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877
  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. m_CurrentlyUsedDelta = duration;
  268. m_Timer.Run(duration, this, fnName);
  269. }
  270. // Set animation phases according to state
  271. void SetActive()
  272. {
  273. UpdatePreyPos();
  274. if ( GetGame().IsServer() && !IsActive() )
  275. {
  276. SetCatchSuccessful(false);
  277. m_IsActive = true;
  278. m_IsPastWaitingTime = false;
  279. m_YieldItemIdx = -1;
  280. if (m_CatchParticleEffecterId >= 0)
  281. SEffectManager.DestroyEffecterParticleServer(m_CatchParticleEffecterId);
  282. m_CatchParticleEffecterId = -1;
  283. SetSynchDirty();
  284. if ( m_AnimationPhaseSet != "" && m_AnimationPhaseTriggered != "" )
  285. {
  286. SetAnimationPhase( m_AnimationPhaseSet, 1 );
  287. SetAnimationPhase( m_AnimationPhaseTriggered, 0 );
  288. SetAnimationPhase( m_AnimationPhaseUsed, 1 );
  289. }
  290. ResetActiveProgress();
  291. m_InitWaitTime = Math.RandomFloatInclusive(m_InitWaitTimeMin,m_InitWaitTimeMax);
  292. if (!m_IsStoreLoad) //presumably activated by the player, store load initializes component separately
  293. {
  294. InitCatchingComponent();
  295. UpdateTrapEnviroMask();
  296. RunTrappingTimer(m_InitWaitTime + m_UpdateWaitTime,"EvaluateCatch");
  297. m_AdjustedMaxActiveTime = m_MaxActiveTime + m_InitWaitTime;
  298. }
  299. else //presumed store load
  300. {
  301. SetTrapEnviroMask(m_CatchEnviroMask);
  302. RunTrappingTimer(m_UpdateWaitTime,"EvaluateCatch");
  303. m_AdjustedMaxActiveTime = m_MaxActiveTime;
  304. }
  305. }
  306. }
  307. void SetInactive()
  308. {
  309. if ( GetGame().IsServer() )
  310. {
  311. // We stop timers as the trap is no longer active, then update visuals
  312. m_IsActive = false;
  313. ClearCatchingComponent();
  314. if ( m_Timer )
  315. {
  316. m_Timer.Stop();
  317. }
  318. m_IsPastWaitingTime = false;
  319. SetDeployed( false );
  320. SetSynchDirty();
  321. }
  322. }
  323. void SetUsed()
  324. {
  325. if ( GetGame().IsServer() )
  326. {
  327. // We updated state, visuals and stop timers
  328. m_IsActive = false;
  329. m_IsDeployed = false;
  330. // Deal damage to trap
  331. AddDefect();
  332. HandleBaitLoss();
  333. DetachAllAttachments();
  334. ClearCatchingComponent();
  335. if ( m_Timer )
  336. {
  337. m_Timer.Stop();
  338. }
  339. m_IsPastWaitingTime = false;
  340. if ( m_AnimationPhaseSet != "" && m_AnimationPhaseTriggered != "" )
  341. {
  342. SetAnimationPhase( m_AnimationPhaseSet, 1 );
  343. SetAnimationPhase( m_AnimationPhaseTriggered, 1 );
  344. SetAnimationPhase( m_AnimationPhaseUsed, 0 );
  345. }
  346. m_CatchingContext = null;
  347. SetSynchDirty();
  348. }
  349. }
  350. void IncreaseElapsedTime()
  351. {
  352. m_ElapsedTime += m_CurrentlyUsedDelta;
  353. #ifdef DEVELOPER
  354. if (IsCLIParam("catchingLogs"))
  355. {
  356. Print("dbgTrapz | delta: " + m_CurrentlyUsedDelta);
  357. Print("dbgTrapz | m_ElapsedTime: " + m_ElapsedTime);
  358. Print("dbgTrapz | m_AdjustedMaxActiveTime: " + m_AdjustedMaxActiveTime);
  359. }
  360. #endif
  361. }
  362. void AdjustDetectionRange()
  363. {
  364. if (m_CurrentMinimalDistance > 0)
  365. {
  366. float time = m_ElapsedTime - m_RollSuccessTime;
  367. float timeLimit = m_AdjustedMaxActiveTime - m_RollSuccessTime;
  368. time = Math.InverseLerp(0,timeLimit,time);
  369. time = Easing.EaseInQuad(time);
  370. m_CurrentMinimalDistance = Math.Lerp(m_MinimalDistanceFromPlayersToCatch,0,time);
  371. m_CurrentMinimalDistance = Math.Clamp(m_CurrentMinimalDistance,0,m_MinimalDistanceFromPlayersToCatch);
  372. #ifdef DEVELOPER
  373. if (IsCLIParam("catchingLogs"))
  374. {
  375. Print("dbgTrapz | adjusted distance: " + m_CurrentMinimalDistance + "/" + m_MinimalDistanceFromPlayersToCatch + " | LERP progress: " + time);
  376. }
  377. #endif
  378. }
  379. }
  380. void EvaluateCatch()
  381. {
  382. #ifdef DEVELOPER
  383. m_dbgAttemptCount++;
  384. #endif
  385. m_IsPastWaitingTime = true;
  386. IncreaseElapsedTime();
  387. #ifdef DEVELOPER
  388. if (IsCLIParam("catchingLogs"))
  389. {
  390. Print("dbgTrapz | m_dbgAttemptCount: " + m_dbgAttemptCount + "/" + (m_MaxActiveTime/m_UpdateWaitTime));
  391. }
  392. #endif
  393. bool success = false;
  394. m_CanCatch = SetCanCatch(m_Bait);
  395. if (m_CanCatch)
  396. {
  397. if (m_CatchingContext.RollCatch())
  398. {
  399. success = true;
  400. #ifdef DEVELOPER
  401. if (IsCLIParam("catchingLogs"))
  402. {
  403. Print("dbgTrapz | success!!!");
  404. Print("---------------------");
  405. }
  406. #endif
  407. }
  408. }
  409. m_Timer.Stop();
  410. if (m_ElapsedTime >= m_AdjustedMaxActiveTime)
  411. {
  412. SetUsed();
  413. return;
  414. }
  415. if (success)
  416. {
  417. m_RollSuccessTime = m_ElapsedTime;
  418. m_CurrentlyUsedDelta = 0;
  419. TrySpawnCatch();
  420. }
  421. else
  422. {
  423. RunTrappingTimer(m_UpdateWaitTime,"EvaluateCatch");
  424. }
  425. }
  426. bool IsPlayerInVicinity()
  427. {
  428. if (!GetCEApi())
  429. {
  430. Debug.Log("CE not enabled, player avoidance not available!");
  431. return false;
  432. }
  433. return !GetCEApi().AvoidPlayer(GetPosition(), m_CurrentMinimalDistance);
  434. }
  435. void TrySpawnCatch()
  436. {
  437. IncreaseElapsedTime();
  438. AdjustDetectionRange();
  439. if (m_CurrentMinimalDistance <= 0 || !IsPlayerInVicinity())
  440. {
  441. SpawnCatch();
  442. }
  443. else if (m_ElapsedTime < m_AdjustedMaxActiveTime)
  444. {
  445. RunTrappingTimer(m_SpawnUpdateWaitTime,"TrySpawnCatch");
  446. }
  447. }
  448. // Actually spawns the prey
  449. void SpawnCatch()
  450. {
  451. // Only server side, let's make sure
  452. if (GetGame().IsMultiplayer() && GetGame().IsClient())
  453. return;
  454. UpdatePreyPos();
  455. ItemBase catch;
  456. if (m_CanCatch)
  457. {
  458. catch = ItemBase.Cast(m_CatchingContext.SpawnAndSetupCatch(m_YieldItemIdx,m_PreyPos));
  459. OnCatchSpawnServer();
  460. SetCatchSuccessful(catch != null);
  461. // We change the trap state and visuals
  462. SetUsed();
  463. }
  464. SetSynchDirty();
  465. }
  466. void SetCatchSuccessful(bool successful)
  467. {
  468. m_IsCatchSuccessful = successful;
  469. }
  470. void OnCatchSpawnServer()
  471. {
  472. PlayCatchEffectsServer();
  473. }
  474. void OnCatchSpawnClient()
  475. {
  476. UpdatePreyPos(); //previously set on server only
  477. PlayCatchEffectsClient();
  478. }
  479. protected void PlayCatchEffectsServer()
  480. {
  481. if (m_YieldItemIdx == -1)
  482. return
  483. YieldItemBase yItem = GetGame().GetMission().GetWorldData().GetCatchYieldBank().GetYieldItemByIdx(m_YieldItemIdx);
  484. PlayCatchNoise(yItem);
  485. PlayCatchParticleSynced(yItem);
  486. }
  487. protected void PlayCatchEffectsClient()
  488. {
  489. if (m_YieldItemIdx == -1)
  490. return
  491. YieldItemBase yItem = GetGame().GetMission().GetWorldData().GetCatchYieldBank().GetYieldItemByIdx(m_YieldItemIdx);
  492. PlayCatchSound(yItem);
  493. }
  494. protected void PlayCatchSound(YieldItemBase yItem)
  495. {
  496. if (yItem.GetCatchDeathSoundset() != "")
  497. SEffectManager.PlaySoundEnviroment(yItem.GetCatchDeathSoundset(),m_PreyPos);
  498. }
  499. protected void PlayCatchNoise(YieldItemBase yItem)
  500. {
  501. NoiseParams m_NoisePar = new NoiseParams();
  502. string noiseType = yItem.GetCatchAINoise();
  503. if (noiseType == "")
  504. return;
  505. m_NoisePar.Load(noiseType);
  506. float noiseMultiplier = yItem.GetCatchAINoiseBaseStrength();
  507. noiseMultiplier *= NoiseAIEvaluate.GetNoiseReduction(GetGame().GetWeather());
  508. GetGame().GetNoiseSystem().AddNoiseTarget(m_PreyPos, 5, m_NoisePar, noiseMultiplier);
  509. }
  510. protected void PlayCatchParticleSynced(YieldItemBase yItem)
  511. {
  512. int particleId = yItem.GetCatchParticleID();
  513. if (particleId == ParticleList.INVALID)
  514. return;
  515. if (m_CatchParticleEffecterId < 0)
  516. {
  517. m_CatchParticleEffecterId = SEffectManager.CreateParticleServer(m_PreyPos, new ParticleEffecterParameters("ParticleEffecter", 5, particleId));
  518. }
  519. else
  520. {
  521. SEffectManager.ReinitParticleServer(m_CatchParticleEffecterId, new ParticleEffecterParameters("ParticleEffecter", 5, particleId)); //reinit here, since particleId might differ
  522. SEffectManager.ReactivateParticleServer(m_CatchParticleEffecterId);
  523. }
  524. }
  525. //Pre-roll validation, bait compatibility handled between YieldItems and bait type
  526. bool SetCanCatch( out EntityAI bait )
  527. {
  528. return m_CatchingContext.IsValid();
  529. }
  530. override void OnItemLocationChanged( EntityAI old_owner, EntityAI new_owner )
  531. {
  532. super.OnItemLocationChanged( old_owner, new_owner );
  533. if ( GetGame().IsServer() )
  534. {
  535. // throw trap from vicinity if the trap does not need installation ( action required )
  536. if ( new_owner == NULL && m_NeedInstalation == false )
  537. {
  538. SetActive();
  539. }
  540. else if ( old_owner == NULL && new_owner != NULL )
  541. {
  542. if ( m_IsFoldable )
  543. {
  544. Fold();
  545. }
  546. else
  547. {
  548. SetInactive();
  549. }
  550. }
  551. if (m_YieldItemIdx != -1) //resets sound effect idx
  552. {
  553. m_YieldItemIdx = -1;
  554. SetSynchDirty();
  555. }
  556. }
  557. }
  558. // Generic water check, no real distinction between pond or sea
  559. bool IsSurfaceWater(vector position)
  560. {
  561. string surfaceType;
  562. GetGame().SurfaceGetType3D(position[0], position[1], position[2], surfaceType);
  563. return Surface.AllowedWaterSurface(position[1] + 0.1, surfaceType, m_PlaceableWaterSurfaceList);
  564. }
  565. // Can only receive attachment if deployed
  566. override bool CanDisplayAttachmentSlot( int slot_id )
  567. {
  568. super.CanDisplayAttachmentSlot( slot_id );
  569. return IsDeployed();
  570. }
  571. override bool CanReceiveAttachment( EntityAI attachment, int slotId )
  572. {
  573. super.CanReceiveAttachment( attachment, slotId );
  574. return IsDeployed();
  575. }
  576. override void EEItemAttached( EntityAI item, string slot_name )
  577. {
  578. super.EEItemAttached( item, slot_name );
  579. if (IsActive() && GetGame().IsServer())
  580. {
  581. ResetActiveProgress();
  582. m_CatchingContext.UpdateDataAndMasks();
  583. m_CatchingContext.GenerateResult();
  584. ResetRunningTimerProgress();
  585. }
  586. }
  587. override void EEItemDetached(EntityAI item, string slot_name)
  588. {
  589. super.EEItemDetached( item, slot_name );
  590. if (IsActive() && GetGame().IsServer())
  591. {
  592. ResetActiveProgress();
  593. m_CatchingContext.UpdateDataAndMasks();
  594. m_CatchingContext.GenerateResult();
  595. ResetRunningTimerProgress();
  596. }
  597. }
  598. void InitCatchingComponent();
  599. void ClearCatchingComponent()
  600. {
  601. if (m_CatchingContext)
  602. delete m_CatchingContext;
  603. }
  604. void UpdateTrapEnviroMask()
  605. {
  606. m_CatchEnviroMask = m_CatchingContext.UpdateTrapEnviroMask();
  607. }
  608. void SetTrapEnviroMask(int value)
  609. {
  610. m_CatchingContext.SetTrapEnviroMask(value);
  611. }
  612. void HandleBaitLoss()
  613. {
  614. if (m_CatchingContext)
  615. {
  616. if (m_IsCatchSuccessful)
  617. m_CatchingContext.RemoveBait();
  618. else
  619. m_CatchingContext.ReduceBaitQty(m_BaitLossFraction);
  620. }
  621. }
  622. //! detaches everything on catching end (some slots may not be accessible when folded)
  623. void DetachAllAttachments()
  624. {
  625. int count = GetInventory().AttachmentCount();
  626. if (count > 0)
  627. {
  628. EntityAI att;
  629. for (int i = 0; i < count; i++)
  630. {
  631. att = GetInventory().GetAttachmentFromIndex(i);
  632. GetInventory().DropEntity(InventoryMode.SERVER,this,att);
  633. }
  634. }
  635. }
  636. //================================================================
  637. // ADVANCED PLACEMENT
  638. //================================================================
  639. override void OnPlacementComplete(Man player, vector position = "0 0 0", vector orientation = "0 0 0")
  640. {
  641. super.OnPlacementComplete(player, position, orientation);
  642. if (GetGame().IsServer())
  643. {
  644. vector rotation_matrix[3];
  645. float direction[4];
  646. Math3D.YawPitchRollMatrix(orientation, rotation_matrix);
  647. Math3D.MatrixToQuat(rotation_matrix, direction);
  648. InventoryLocation source = new InventoryLocation;
  649. InventoryLocation destination = new InventoryLocation;
  650. if (GetInventory().GetCurrentInventoryLocation(source))
  651. {
  652. destination.SetGroundEx(this, position, direction);
  653. if (GetGame().IsMultiplayer())
  654. {
  655. player.ServerTakeToDst(source, destination);
  656. SetupTrapPlayer(PlayerBase.Cast(player), false);
  657. }
  658. else // singleplayer
  659. {
  660. PlayerBase.Cast(player).GetDayZPlayerInventory().RedirectToHandEvent(InventoryMode.LOCAL, source, destination);
  661. GetGame().GetCallQueue(CALL_CATEGORY_SYSTEM).CallLater(SetupTrapPlayer, 100, false, PlayerBase.Cast(player), false);
  662. }
  663. }
  664. InitCatchingComponent();
  665. UpdateTrapEnviroMask();
  666. SetActive();
  667. }
  668. }
  669. bool IsPlaceable()
  670. {
  671. if ( GetGame().IsServer() )
  672. {
  673. InventoryLocation loc = new InventoryLocation();
  674. GetInventory().GetCurrentInventoryLocation(loc);
  675. if (loc.GetType() == InventoryLocationType.HANDS)
  676. {
  677. PlayerBase player = PlayerBase.Cast(GetHierarchyRootPlayer());
  678. vector player_pos = player.GetPosition();
  679. vector aim_pos = player.GetAimPosition();
  680. if ( vector.DistanceSq(player_pos, aim_pos) <= ( 1.5 * 1.5 ) )
  681. {
  682. return IsPlaceableAtPosition( aim_pos );
  683. }
  684. }
  685. }
  686. return false;
  687. }
  688. override bool CanBePlaced( Man player, vector position )
  689. {
  690. return IsPlaceableAtPosition(position);
  691. }
  692. // We add the action to deploy a trap laid on ground
  693. override void SetActions()
  694. {
  695. super.SetActions();
  696. AddAction(ActionActivateTrap);
  697. AddAction(ActionDeployHuntingTrap);
  698. }
  699. // ===============================================================
  700. // ===================== DEPRECATED ============================
  701. // ===============================================================
  702. const string m_PlaceableWaterType //!DEPRECATED
  703. ref Timer m_PrevTimer;//!DEPRECATED
  704. bool m_BaitNeeded;//!DEPRECATED
  705. bool m_IsUsable;//!DEPRECATED
  706. private ItemBase m_Catch;//!DEPRECATED, no reason to keep the information as member
  707. ref Timer m_AlignCatchTimer;//!DEPRECATED
  708. string m_InfoSetup;//!DEPRECATED
  709. protected bool m_IsInProgress;//!DEPRECATED
  710. protected ref EffectSound m_DeployLoopSound;//!DEPRECATED
  711. protected EntityAI m_Bait;
  712. float m_BaitCatchProb; //!DEPRECATED
  713. float m_NoBaitCatchProb; //!DEPRECATED
  714. float m_FinalCatchProb; //!DEPRECATED
  715. bool m_WaterSurfaceForSetup; //!DEPRECATED
  716. ref multiMap<string, float> m_CatchesPond; //!DEPRECATED
  717. ref multiMap<string, float> m_CatchesSea; //!DEPRECATED
  718. ref multiMap<string, float> m_CatchesGroundAnimal; //!DEPRECATED
  719. //!DEPRECATED
  720. bool CanPutInInventory(EntityAI player);
  721. //!DEPRECATED
  722. void AlignCatch(ItemBase obj, string catch_name);
  723. ///!DEPRECATED
  724. void CatchSetQuant(ItemBase catch);
  725. void PlayDeployLoopSound(); //!DEPRECATED
  726. void StopDeployLoopSound(); //!DEPRECATED
  727. // ===============================================================
  728. }