trapspawnbase.c 21 KB

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