dayzanimal.c 24 KB

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