dayzanimal.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967
  1. class DayZCreatureAnimInterface
  2. {
  3. private void DayZCreatureAnimInterface() {}
  4. private void ~DayZCreatureAnimInterface() {}
  5. //-----------------------------------------------------
  6. // Binds, returns -1 when error, otherwise if ok
  7. //! returns command index -
  8. proto native TAnimGraphCommand BindCommand(string pCommandName);
  9. //!
  10. proto native TAnimGraphVariable BindVariableFloat(string pVariable);
  11. proto native TAnimGraphVariable BindVariableInt(string pVariable);
  12. proto native TAnimGraphVariable BindVariableBool(string pVariable);
  13. //!
  14. proto native TAnimGraphTag BindTag(string pTagName);
  15. //!
  16. proto native TAnimGraphEvent BindEvent(string pEventName);
  17. }
  18. class DayZCreature extends EntityAI
  19. {
  20. #ifdef _DAYZ_CREATURE_DEBUG_SHADOW
  21. proto native void DebugSetShadow(DayZCreature creature);
  22. #endif
  23. proto native bool RegisterAnimationEvent(string event_name, string function_name);
  24. proto native void SetAnimationInstanceByName(string animation_instance_name, int instance_uuid, float duration);
  25. proto native int GetCurrentAnimationInstanceUUID();
  26. proto native DayZCreatureAnimInterface GetAnimInterface();
  27. proto native void UpdateSimulationPrecision(int simLOD);
  28. //---------------------------------------------------------
  29. // helper functions for disabling simulation upon death
  30. proto native void StartDeath();
  31. proto native void ResetDeath();
  32. proto native void ResetDeathCooldown();
  33. proto native bool IsDeathProcessed();
  34. proto native bool IsDeathConditionMet();
  35. //---------------------------------------------------------
  36. // bone transforms
  37. //! returns bone index for a name (-1 if pBoneName doesn't exist)
  38. proto native int GetBoneIndexByName(string pBoneName);
  39. override bool IsDayZCreature()
  40. {
  41. return true;
  42. }
  43. override bool CanBeSkinned()
  44. {
  45. return true;
  46. }
  47. override bool IsIgnoredByConstruction()
  48. {
  49. return IsRuined();
  50. }
  51. override bool IsManagingArrows()
  52. {
  53. return true;
  54. }
  55. override bool DisableVicinityIcon()
  56. {
  57. return true;
  58. }
  59. override void AddArrow(Object arrow, int componentIndex, vector closeBonePosWS, vector closeBoneRotWS)
  60. {
  61. CachedObjectsArrays.ARRAY_STRING.Clear();
  62. GetActionComponentNameList(componentIndex, CachedObjectsArrays.ARRAY_STRING, "fire");
  63. int pivot = -1;
  64. for (int i = 0; i < CachedObjectsArrays.ARRAY_STRING.Count() && pivot == -1; i++)
  65. {
  66. pivot = GetBoneIndexByName(CachedObjectsArrays.ARRAY_STRING.Get(i));
  67. }
  68. vector parentTransMat[4];
  69. vector arrowTransMat[4];
  70. if (pivot == -1)
  71. {
  72. GetTransform(parentTransMat);
  73. }
  74. else
  75. {
  76. vector rotMatrix[3];
  77. Math3D.YawPitchRollMatrix(closeBoneRotWS * Math.RAD2DEG,rotMatrix);
  78. parentTransMat[0] = rotMatrix[0];
  79. parentTransMat[1] = rotMatrix[1];
  80. parentTransMat[2] = rotMatrix[2];
  81. parentTransMat[3] = closeBonePosWS;
  82. }
  83. arrow.GetTransform(arrowTransMat);
  84. Math3D.MatrixInvMultiply4(parentTransMat, arrowTransMat, arrowTransMat);
  85. // orthogonalize matrix - parent might be skewed
  86. Math3D.MatrixOrthogonalize4(arrowTransMat);
  87. arrow.SetTransform(arrowTransMat);
  88. AddChild(arrow, pivot);
  89. }
  90. override bool HasFixedActionTargetCursorPosition()
  91. {
  92. return true;
  93. }
  94. //-------------------------------------------------------------
  95. //!
  96. //! ModOverrides
  97. //!
  98. // these functions are for modded overide in script command mods
  99. bool ModCommandHandlerBefore(float pDt, int pCurrentCommandID, bool pCurrentCommandFinished)
  100. {
  101. return false;
  102. }
  103. bool ModCommandHandlerInside(float pDt, int pCurrentCommandID, bool pCurrentCommandFinished)
  104. {
  105. return false;
  106. }
  107. bool ModCommandHandlerAfter(float pDt, int pCurrentCommandID, bool pCurrentCommandFinished)
  108. {
  109. return false;
  110. }
  111. }
  112. class DayZCreatureAI extends DayZCreature
  113. {
  114. proto native AIAgent GetAIAgent();
  115. proto native bool IsSoundInsideBuilding();
  116. #ifdef DIAG_DEVELOPER
  117. proto native void DebugDisableAIControl();
  118. proto native void DebugRestoreAIControl();
  119. #endif
  120. proto native void AddDamageSphere(string bone_name, string ammo_name, float radius, float duration, bool invertTeams);
  121. proto native DayZCreatureAIType GetCreatureAIType();
  122. /*!
  123. AIAgent initialization.
  124. Manual ai initialization for creatures created with CreateObject(... init_ai = false...).
  125. */
  126. proto native void InitAIAgent(AIGroup group);
  127. proto native void DestroyAIAgent();
  128. int m_EffectTriggerCount;//how many effect triggers is this AI inside of(overlapping triggers)
  129. protected DayZPlayer m_CinematicPlayer;
  130. void DayZCreatureAI()
  131. {
  132. RegisterAnimEvents();
  133. SetFlags(EntityFlags.TOUCHTRIGGERS, false);
  134. }
  135. void IncreaseEffectTriggerCount()
  136. {
  137. m_EffectTriggerCount++;
  138. }
  139. void DecreaseEffectTriggerCount()
  140. {
  141. m_EffectTriggerCount--;
  142. }
  143. void AddDamageSphere(AnimDamageParams damage_params)
  144. {
  145. AddDamageSphere(damage_params.m_sBoneName, damage_params.m_sAmmoName, damage_params.m_fRadius, damage_params.m_fDuration, damage_params.m_bInvertTeams);
  146. }
  147. override void EEKilled(Object killer)
  148. {
  149. super.EEKilled(killer);
  150. CreateComponent(COMP_TYPE_BODY_STAGING); // TO DO: This is never called on clients in multiplayer! That's why skinning doesn't work properly in MP. DAYZ-28269
  151. }
  152. AnimBootsType GetBootsType()
  153. {
  154. return AnimBootsType.None;
  155. }
  156. AbstractWave PlaySound(SoundObject so, SoundObjectBuilder sob)
  157. {
  158. if(so == NULL)
  159. {
  160. return NULL;
  161. }
  162. so.SetPosition(GetPosition());
  163. AbstractWave wave = GetGame().GetSoundScene().Play3D(so, sob);
  164. return wave;
  165. }
  166. void OnSoundEvent(int event_id, string event_user_string)
  167. {
  168. AnimSoundEvent sound_event = GetCreatureAIType().GetSoundEvent(event_id);
  169. if(sound_event != NULL)
  170. {
  171. ProcessSoundEvent(sound_event);
  172. }
  173. }
  174. void OnSoundVoiceEvent(int event_id, string event_user_string)
  175. {
  176. AnimSoundVoiceEvent voice_event = GetCreatureAIType().GetSoundVoiceEvent(event_id);
  177. if(voice_event != NULL)
  178. {
  179. ProcessSoundVoiceEvent(voice_event);
  180. }
  181. }
  182. void OnStepEvent(int event_id, string event_user_string)
  183. {
  184. AnimStepEvent step_event = GetCreatureAIType().GetStepEvent(event_id);
  185. if(step_event != NULL)
  186. {
  187. ProcessStepEvent(step_event);
  188. }
  189. }
  190. void OnDamageEvent(int event_id, string event_user_string)
  191. {
  192. AnimDamageEvent damage_event = GetCreatureAIType().GetDamageEvent(event_id);
  193. if(damage_event != NULL)
  194. {
  195. ProcessDamageEvent(damage_event);
  196. }
  197. }
  198. protected void RegisterAnimEvents()
  199. {
  200. if(!RegisterAnimationEvent("Sound", "OnSoundEvent"))
  201. {
  202. Print("Error registering anim. event (Sound)");
  203. }
  204. if(!RegisterAnimationEvent("SoundVoice", "OnSoundVoiceEvent"))
  205. {
  206. Print("Error registering anim. event (SoundVoice)");
  207. }
  208. if(!GetGame().IsDedicatedServer())
  209. {
  210. if(!RegisterAnimationEvent("Step", "OnStepEvent"))
  211. {
  212. Print("Error registering anim. event (Step)");
  213. }
  214. }
  215. if(!RegisterAnimationEvent("Damage", "OnDamageEvent"))
  216. {
  217. Print("Error registering anim. event (Damage)");
  218. }
  219. }
  220. private void ProcessSoundEvent(AnimSoundEvent sound_event)
  221. {
  222. if(!GetGame().IsDedicatedServer())
  223. {
  224. SoundObjectBuilder objectBuilder = sound_event.GetSoundBuilder();
  225. if(NULL != objectBuilder)
  226. {
  227. objectBuilder.AddEnvSoundVariables(GetPosition());
  228. SoundObject soundObject = objectBuilder.BuildSoundObject();
  229. PlaySound(soundObject, objectBuilder);
  230. }
  231. }
  232. if(GetGame().IsServer())
  233. {
  234. if(sound_event.m_NoiseParams != NULL)
  235. GetGame().GetNoiseSystem().AddNoise(this, sound_event.m_NoiseParams, GetGame().GetWeather().GetNoiseReductionByWeather());
  236. }
  237. }
  238. private void ProcessSoundVoiceEvent(AnimSoundVoiceEvent sound_event)
  239. {
  240. if(!GetGame().IsDedicatedServer())
  241. {
  242. SoundObjectBuilder objectBuilder = sound_event.GetSoundBuilder();
  243. if(NULL != objectBuilder)
  244. {
  245. objectBuilder.AddEnvSoundVariables(GetPosition());
  246. SoundObject soundObject = objectBuilder.BuildSoundObject();
  247. AttenuateSoundIfNecessary(soundObject);
  248. PlaySound(soundObject, objectBuilder);
  249. }
  250. }
  251. if(GetGame().IsServer())
  252. {
  253. if(sound_event.m_NoiseParams != NULL)
  254. GetGame().GetNoiseSystem().AddNoise(this, sound_event.m_NoiseParams, GetGame().GetWeather().GetNoiseReductionByWeather());
  255. }
  256. }
  257. private void ProcessStepEvent(AnimStepEvent step_event)
  258. {
  259. SoundObjectBuilder soundBuilder = step_event.GetSoundBuilder(GetSurfaceType().Hash());
  260. if(soundBuilder == NULL)
  261. return;
  262. soundBuilder.AddEnvSoundVariables(GetPosition());
  263. SoundObject soundObject = soundBuilder.BuildSoundObject();
  264. AttenuateSoundIfNecessary(soundObject);
  265. PlaySound(soundObject, soundBuilder);
  266. //TODO effects
  267. }
  268. private void ProcessDamageEvent(AnimDamageEvent damage_event)
  269. {
  270. AddDamageSphere(damage_event.m_DamageParams);
  271. }
  272. protected void AttenuateSoundIfNecessary(SoundObject soundObject)
  273. {
  274. if (GetGame().GetPlayer() != NULL && (IsSoundInsideBuilding() != GetGame().GetPlayer().IsSoundInsideBuilding() || GetGame().GetPlayer().IsCameraInsideVehicle()))
  275. {
  276. soundObject.SetKind(WaveKind.WAVEATTALWAYS);
  277. }
  278. else
  279. {
  280. soundObject.SetKind(WaveKind.WAVEEFFECTEX);
  281. }
  282. }
  283. bool ResistContaminatedEffect()
  284. {
  285. return false;
  286. }
  287. // ================
  288. // EASTER EGG
  289. // ================
  290. //Used for easter egg sound selection
  291. bool IsDanger()
  292. {
  293. return false;
  294. }
  295. string CaptureSound()
  296. {
  297. return "";
  298. }
  299. string ReleaseSound()
  300. {
  301. return "";
  302. }
  303. // ================
  304. // CINEMATIC CONTROLLER
  305. // ================
  306. void CinematicTakeControl(DayZPlayer player)
  307. {
  308. m_CinematicPlayer = player;
  309. }
  310. bool CinematicCanJump()
  311. {
  312. return true;
  313. }
  314. override bool ModCommandHandlerBefore(float pDt, int pCurrentCommandID, bool pCurrentCommandFinished)
  315. {
  316. if (!m_CinematicPlayer)
  317. {
  318. return super.ModCommandHandlerBefore(pDt, pCurrentCommandID, pCurrentCommandFinished);
  319. }
  320. UAInterface input = m_CinematicPlayer.GetInputInterface();
  321. DayZCreatureAIInputController controller;
  322. GetGame().GameScript.CallFunction(this, "GetInputController", controller, 0);
  323. if (!input || !controller)
  324. {
  325. return super.ModCommandHandlerBefore(pDt, pCurrentCommandID, pCurrentCommandFinished);
  326. }
  327. float movementX = input.SyncedValue_ID(UAAimRight) - input.SyncedValue_ID(UAAimLeft);
  328. float maxTurnSpeed = 100.0;
  329. movementX = Math.Clamp(movementX * maxTurnSpeed * pDt, -180, 180);
  330. if (input.SyncedValue_ID(UALookAround) > 0)
  331. {
  332. movementX = 0;
  333. }
  334. bool isJump = input.SyncedValue_ID(UAGetOver) > 0;
  335. bool isMove = input.SyncedValue_ID(UAMoveForward) > 0;
  336. bool isRest = input.SyncedValue_ID(UAMoveBack) > 0;
  337. bool isSleep = input.SyncedValue_ID(UAReloadMagazine) > 0;
  338. float heading = GetOrientation()[0] + movementX;
  339. int iAlert = 0;
  340. float fAlert = 0;
  341. int iSpeed = 0;
  342. float fSpeed = 0;
  343. if (isMove)
  344. {
  345. iAlert = 1;
  346. fAlert = 0.2;
  347. bool isSprint = input.SyncedValue_ID(UATurbo) > 0;
  348. bool isJog = input.SyncedValue_ID(UAWalkRunTemp) > 0;
  349. bool isWalk = !isSprint && !isJog;
  350. if (isSprint)
  351. {
  352. //! sprint
  353. iSpeed = 3;
  354. }
  355. else if (isJog)
  356. {
  357. //! jog
  358. iSpeed = 2;
  359. }
  360. else if (isWalk)
  361. {
  362. //! walk
  363. iSpeed = 1;
  364. }
  365. }
  366. DayZAnimalInputController animalController;
  367. if (Class.CastTo(animalController, controller))
  368. {
  369. animalController.OverrideBehaviourSlot(true, DayZAnimalBehaviourSlot.NON_SPECIFIC_THREAT);
  370. animalController.OverrideBehaviourAction(true, DayZAnimalBehaviourAction.TRAVELING_INPUT);
  371. if (!isMove)
  372. {
  373. if (isRest)
  374. {
  375. iSpeed = 0;
  376. animalController.OverrideBehaviourAction(true, DayZAnimalBehaviourAction.IDLE1_INPUT);
  377. }
  378. if (isSleep)
  379. {
  380. iSpeed = 0;
  381. animalController.OverrideBehaviourAction(true, DayZAnimalBehaviourAction.WALKING_INPUT);
  382. }
  383. }
  384. }
  385. bool lowVel = GetVelocity(this).Length() < 0.5;
  386. if (iSpeed > 0 && lowVel)
  387. {
  388. iAlert = 4;
  389. fAlert = 1.0;
  390. iSpeed = 3;
  391. }
  392. if (animalController)
  393. {
  394. switch (iSpeed)
  395. {
  396. case 0:
  397. fSpeed = 0;
  398. break;
  399. case 1:
  400. fSpeed = 2;
  401. break;
  402. case 2:
  403. fSpeed = 3;
  404. break;
  405. case 3:
  406. fSpeed = 5;
  407. break;
  408. }
  409. }
  410. controller.OverrideTurnSpeed(true, Math.PI2 / pDt);
  411. controller.OverrideMovementSpeed(true, fSpeed);
  412. controller.OverrideHeading(true, heading * Math.DEG2RAD);
  413. controller.OverrideAlertLevel(true, true, iAlert, fAlert);
  414. if (CinematicCanJump() && isJump)
  415. {
  416. controller.OverrideJump(true, 101, 2.0);
  417. }
  418. return true;
  419. }
  420. }
  421. enum DayZAnimalConstants
  422. {
  423. COMMANDID_MOVE,
  424. COMMANDID_JUMP,
  425. COMMANDID_DEATH,
  426. COMMANDID_HIT,
  427. COMMANDID_ATTACK,
  428. COMMANDID_SCRIPT,
  429. };
  430. class DayZAnimalCommandMove extends AnimCommandBase
  431. {
  432. }
  433. class DayZAnimalCommandAttack extends AnimCommandBase
  434. {
  435. }
  436. class DayZAnimalCommandJump extends AnimCommandBase
  437. {
  438. }
  439. class DayZAnimalCommandLookAt extends AnimCommandBase
  440. {
  441. }
  442. class DayZAnimalCommandBehaviourModifier extends AnimCommandBase
  443. {
  444. }
  445. class DayZAnimalCommandHit extends AnimCommandBase
  446. {
  447. }
  448. class DayZAnimalCommandDeath extends AnimCommandBase
  449. {
  450. }
  451. class DayZAnimalCommandAnimCallback extends AnimCommandBase
  452. {
  453. }
  454. /**
  455. *\brief DayZAnimalCommandScript fully scriptable command
  456. * \warning NON-MANAGED, will be managed by C++ once it is sent to the CommandHandler through DayZAnimal.StartCommand_Script
  457. * \note So ideally, it is best to set up the DayZAnimalCommandScript, not create any instances and start it through DayZAnimal.StartCommand_ScriptInst
  458. * In case an instance needs to be created, it needs manual deletion if not sent to the CommandHandler
  459. * But deleting it while it is in the CommandHandler will cause crashes
  460. */
  461. class DayZAnimalCommandScript extends AnimCommandBase
  462. {
  463. //! constructor must have 1st parameter to be DayZAnimal
  464. //void DayZAnimalCommandScript(DayZAnimal pAnimal)
  465. //---------------------------------------------------------------
  466. // usable everywhere
  467. //! this terminates command script and shows CommandHandler( ... pCurrentCommandFinished == true );
  468. proto native void SetFlagFinished(bool pFinished);
  469. //---------------------------------------------------------------
  470. // PrePhys Update
  471. //! script function usable in PrePhysUpdate
  472. proto native bool PrePhys_GetTranslation(out vector pOutTransl); // vec3 in local space !
  473. proto native bool PrePhys_GetRotation(out float pOutRot[4]); // quaternion in local space !
  474. proto native void PrePhys_SetTranslation(vector pInTransl); // vec3 in local space !
  475. proto native void PrePhys_SetRotation(float pInRot[4]); // quaternion in local space !
  476. //---------------------------------------------------------------
  477. // PostPhys Update
  478. //! override this !
  479. //! final adjustment of physics state (after physics was applied)
  480. //! returns true if command continues running / false if command should end (or you can use SetFlagFinished(true))
  481. bool PostPhysUpdate(float pDt);
  482. //! script function usable in PostPhysUpdate
  483. proto native void PostPhys_GetPosition(out vector pOutTransl); //! vec3 in world space
  484. proto native void PostPhys_GetRotation(out float pOutRot[4]); //! quaternion in world space
  485. proto native void PostPhys_SetPosition(vector pInTransl); //! vec3 in world space
  486. proto native void PostPhys_SetRotation(float pInRot[4]); //! quaternion in world space
  487. proto native void PostPhys_LockRotation(); //! do not process rotations !
  488. }
  489. class DayZAnimal extends DayZCreatureAI
  490. {
  491. //! Melee hit components (AI targeting)
  492. protected ref array<ref DayZAIHitComponent> m_HitComponentsForAI;
  493. protected string m_DefaultHitComponent;
  494. protected string m_DefaultHitPositionComponent;
  495. protected vector m_DefaultHitPosition;
  496. proto native DayZAnimalInputController GetInputController();
  497. proto native void StartCommand_Death(int pType, int pDirection);
  498. proto native void StartCommand_Move();
  499. proto native void StartCommand_Jump();
  500. proto native void StartCommand_Attack();
  501. proto native void StartCommand_Hit(int pType, int pDirection);
  502. //! scripted commands
  503. proto native DayZAnimalCommandScript StartCommand_Script(DayZAnimalCommandScript pInfectedCommand);
  504. proto native DayZAnimalCommandScript StartCommand_ScriptInst(typename pCallbackClass);
  505. proto native DayZAnimalCommandScript GetCommand_Script();
  506. proto native void SignalAIAttackStarted();
  507. proto native void SignalAIAttackEnded();
  508. void DayZAnimal()
  509. {
  510. // testing: animals have no inventory by default
  511. //GetInventory().LockInventory(LOCK_FROM_SCRIPT); // Hides animals from vicinity in inventory. Remove this if wanted otherwise.
  512. m_HitComponentsForAI = new array<ref DayZAIHitComponent>;
  513. RegisterHitComponentsForAI();
  514. //! sets default hit position and cache it here (mainly for impact particles)
  515. m_DefaultHitPosition = SetDefaultHitPosition(GetDefaultHitPositionComponent());
  516. }
  517. override bool IsHealthVisible()
  518. {
  519. return false;
  520. }
  521. override bool IsAnimal()
  522. {
  523. return true;
  524. }
  525. override bool IsInventoryVisible()
  526. {
  527. return false;
  528. }
  529. override int GetHideIconMask()
  530. {
  531. return EInventoryIconVisibility.HIDE_VICINITY;
  532. /*
  533. if (IsAlive())
  534. {
  535. return EInventoryIconVisibility.HIDE_VICINITY;
  536. }
  537. return super.GetHideIconMask();
  538. */
  539. }
  540. void CommandHandler(float dt, int currentCommandID, bool currentCommandFinished)
  541. {
  542. DayZAnimalInputController inputController = GetInputController();
  543. //! for mods
  544. if( ModCommandHandlerBefore(dt, currentCommandID, currentCommandFinished) )
  545. {
  546. return;
  547. }
  548. if (HandleDeath(currentCommandID, inputController))
  549. {
  550. return;
  551. }
  552. if (currentCommandFinished)
  553. {
  554. if (currentCommandID == DayZAnimalConstants.COMMANDID_ATTACK)
  555. {
  556. SignalAIAttackEnded();
  557. }
  558. StartCommand_Move();
  559. return;
  560. }
  561. //! for mods
  562. if( ModCommandHandlerInside(dt, currentCommandID, currentCommandFinished) )
  563. {
  564. return;
  565. }
  566. if (HandleDamageHit(currentCommandID))
  567. {
  568. if (currentCommandID == DayZAnimalConstants.COMMANDID_ATTACK)
  569. {
  570. SignalAIAttackEnded();
  571. }
  572. return;
  573. }
  574. if (currentCommandID == DayZAnimalConstants.COMMANDID_MOVE)
  575. {
  576. if (inputController.IsJump())
  577. {
  578. StartCommand_Jump();
  579. return;
  580. }
  581. if (inputController.IsAttack())
  582. {
  583. StartCommand_Attack();
  584. SignalAIAttackStarted();
  585. return;
  586. }
  587. }
  588. //!
  589. if( ModCommandHandlerAfter(dt, currentCommandID, currentCommandFinished) )
  590. {
  591. return;
  592. }
  593. }
  594. bool m_DamageHitToProcess = false;
  595. int m_DamageHitType = 0;
  596. int m_DamageHitDirection = 0;
  597. bool HandleDeath(int currentCommandID, DayZAnimalInputController inputController)
  598. {
  599. if (inputController.IsDead())
  600. {
  601. if (currentCommandID == DayZAnimalConstants.COMMANDID_DEATH)
  602. {
  603. return true;
  604. }
  605. if (m_DamageHitToProcess)
  606. {
  607. m_DamageHitToProcess = false;
  608. StartCommand_Death(m_DamageHitType, m_DamageHitDirection);
  609. }
  610. else
  611. {
  612. StartCommand_Death(0, 0);
  613. }
  614. return true;
  615. }
  616. return false;
  617. }
  618. bool HandleDamageHit(int currentCommandID)
  619. {
  620. if (m_DamageHitToProcess)
  621. {
  622. m_DamageHitToProcess = false;
  623. if (currentCommandID != DayZAnimalConstants.COMMANDID_HIT)
  624. {
  625. StartCommand_Hit(m_DamageHitType, m_DamageHitDirection);
  626. }
  627. return true;
  628. }
  629. return false;
  630. }
  631. override void EEHitBy(TotalDamageResult damageResult, int damageType, EntityAI source, int component, string dmgZone, string ammo, vector modelPos, float speedCoef)
  632. {
  633. super.EEHitBy(damageResult, damageType, source, component, dmgZone, ammo, modelPos, speedCoef);
  634. m_TransportHitRegistered = false;
  635. int transferShockToDamageCoef = g_Game.ConfigGetInt(string.Format("%1 %2 DamageApplied transferShockToDamage", CFG_AMMO, ammo));
  636. if (transferShockToDamageCoef == 1)
  637. {
  638. //Print("DayZAnimal | EEHitBy | nonlethal hit");
  639. AddHealth("", "Health", -ConvertNonlethalDamage(damageResult.GetDamage(dmgZone, "Shock"), damageType));
  640. }
  641. else
  642. {
  643. ComponentAnimalBleeding animal_bleeding = ComponentAnimalBleeding.Cast( GetComponent( COMP_TYPE_ANIMAL_BLEEDING ) );
  644. animal_bleeding.CreateWound( damageResult, dmgZone, ammo );
  645. }
  646. int type = 0;
  647. int direction = 0;
  648. if (ComputeDamageHitParams(source, dmgZone, ammo, type, direction) == true)
  649. {
  650. QueueDamageHit(type, direction);
  651. }
  652. }
  653. void QueueDamageHit(int type, int direction)
  654. {
  655. m_DamageHitToProcess = true;
  656. m_DamageHitType = type;
  657. m_DamageHitDirection = direction;
  658. }
  659. bool ComputeDamageHitParams(EntityAI source, string dmgZone, string ammo, out int type, out int direction)
  660. {
  661. type = 0; // not used right now
  662. float angleDeg = ComputeHitDirectionAngleDeg(source);
  663. direction = TranslateHitAngleDegToDirectionIndex(angleDeg);
  664. direction += FindComponentDirectionOffset(dmgZone);
  665. return true;
  666. }
  667. float ComputeHitDirectionAngleDeg(EntityAI source)
  668. {
  669. vector targetDirection = GetDirection();
  670. vector toSourceDirection = (source.GetPosition() - GetPosition());
  671. targetDirection[1] = 0;
  672. toSourceDirection[1] = 0;
  673. targetDirection.Normalize();
  674. toSourceDirection.Normalize();
  675. float cosFi = vector.Dot(targetDirection, toSourceDirection);
  676. vector cross = targetDirection * toSourceDirection;
  677. float dirAngleDeg = Math.Acos(cosFi) * Math.RAD2DEG;
  678. if ( cross[1] < 0 )
  679. dirAngleDeg = -dirAngleDeg;
  680. return dirAngleDeg;
  681. }
  682. int TranslateHitAngleDegToDirectionIndex(float angleDeg)
  683. {
  684. if (angleDeg >= -20 && angleDeg <= 20) // front
  685. {
  686. return 1;
  687. }
  688. else if (angleDeg < 0) // left
  689. {
  690. return 2;
  691. }
  692. return 3; // right
  693. }
  694. int FindComponentDirectionOffset(string component)
  695. {
  696. const int directionCount = 4;
  697. int offset = 0;
  698. if (component.Length() == 0)
  699. {
  700. offset = 0;
  701. }
  702. else if (component == "Zone_Head")
  703. {
  704. offset = directionCount;
  705. }
  706. else if (component == "Zone_Chest" || component == "Zone_Legs_Front" || component == "Zone_Spine_Front" || component == "Zone_Neck")
  707. {
  708. offset = 2 * directionCount;
  709. }
  710. else
  711. {
  712. offset = 3 * directionCount;
  713. }
  714. return offset;
  715. }
  716. //-------------------------------------------------------------
  717. //!
  718. //! Phx contact event
  719. //!
  720. override protected void EOnContact(IEntity other, Contact extra)
  721. {
  722. if( !IsAlive() )
  723. return;
  724. Transport transport = Transport.Cast(other);
  725. if( transport )
  726. {
  727. if ( GetGame().IsServer() )
  728. {
  729. RegisterTransportHit(transport);
  730. }
  731. }
  732. }
  733. //! register hit components for AI melee (used by attacking AI)
  734. void RegisterHitComponentsForAI()
  735. {
  736. //! registers default hit compoent for the entity
  737. m_DefaultHitComponent = "Zone_Chest";
  738. //! registers default hit position component for entity
  739. m_DefaultHitPositionComponent = "Pelvis";
  740. //! register hit components that are selected by probability
  741. DayZAIHitComponentHelpers.RegisterHitComponent(m_HitComponentsForAI, "Zone_Chest", 50);
  742. }
  743. override string GetHitComponentForAI()
  744. {
  745. string hitComp;
  746. if (DayZAIHitComponentHelpers.SelectMostProbableHitComponent(m_HitComponentsForAI, hitComp))
  747. {
  748. return hitComp;
  749. }
  750. return GetDefaultHitComponent();
  751. }
  752. override string GetDefaultHitComponent()
  753. {
  754. return m_DefaultHitComponent;
  755. }
  756. override string GetDefaultHitPositionComponent()
  757. {
  758. return m_DefaultHitPositionComponent;
  759. }
  760. override vector GetDefaultHitPosition()
  761. {
  762. return m_DefaultHitPosition;
  763. }
  764. protected vector SetDefaultHitPosition(string pSelection)
  765. {
  766. return GetSelectionPositionMS(pSelection);
  767. }
  768. override protected float ConvertNonlethalDamage(float damage, DamageType damageType)
  769. {
  770. switch (damageType)
  771. {
  772. case DamageType.CLOSE_COMBAT:
  773. return damage * GameConstants.NL_DAMAGE_CLOSECOMBAT_CONVERSION_ANIMALS;
  774. case DamageType.FIRE_ARM:
  775. return damage * GameConstants.NL_DAMAGE_FIREARM_CONVERSION_ANIMALS;
  776. }
  777. return super.ConvertNonlethalDamage(damage, damageType);
  778. }
  779. }