emotemanager.c 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275
  1. class EmoteCB : HumanCommandActionCallback
  2. {
  3. bool m_IsFullbody;
  4. int m_callbackID; //Animation cmd ID
  5. PlayerBase m_player;
  6. EmoteManager m_Manager;
  7. void ~EmoteCB()
  8. {
  9. if (m_Manager)
  10. {
  11. m_Manager.OnCallbackEnd();
  12. }
  13. if (GetGame() && m_player)
  14. m_player.RequestHandAnimationStateRefresh();
  15. }
  16. bool CancelCondition()
  17. {
  18. return false;
  19. }
  20. bool IsEmoteCallback()
  21. {
  22. return IsGestureCallback();
  23. }
  24. override void OnAnimationEvent(int pEventID)
  25. {
  26. switch (pEventID)
  27. {
  28. case EmoteConstants.EMOTE_SUICIDE_DEATH :
  29. if (GetGame().IsServer())
  30. m_Manager.KillPlayer();
  31. m_Manager.LogSuicide();
  32. break;
  33. case UA_ANIM_EVENT :
  34. if (m_callbackID == DayZPlayerConstants.CMD_GESTUREFB_SURRENDERIN)
  35. m_Manager.m_ItemToBeCreated = true;
  36. break;
  37. case EmoteConstants.EMOTE_SUICIDE_BLEED :
  38. if (GetGame().IsServer())
  39. m_Manager.CreateBleedingEffect(m_callbackID);
  40. break;
  41. case EmoteConstants.EMOTE_SUICIDE_SIMULATION_END :
  42. if (GetGame().IsServer())
  43. {
  44. EntityAI itemInHands = m_player.GetHumanInventory().GetEntityInHands();
  45. if (itemInHands)
  46. {
  47. vector m4[4];
  48. itemInHands.GetTransform(m4);
  49. m_player.GetInventory().DropEntityWithTransform(InventoryMode.SERVER, m_player, itemInHands, m4);
  50. }
  51. }
  52. m_player.StartDeath();
  53. break;
  54. }
  55. }
  56. override bool IsGestureCallback()
  57. {
  58. return true;
  59. }
  60. };
  61. class EmoteLauncher
  62. {
  63. static const int FORCE_NONE = 0;
  64. static const int FORCE_DIFFERENT = 1;
  65. static const int FORCE_ALL = 2;
  66. protected bool m_InterruptsSameIDEmote;
  67. protected int m_ForcePlayEmote;
  68. protected int m_ID;
  69. void EmoteLauncher(int emoteID, bool interrupts_same)
  70. {
  71. m_ID = emoteID;
  72. m_InterruptsSameIDEmote = interrupts_same;
  73. m_ForcePlayEmote = FORCE_NONE;
  74. }
  75. void SetForced(int mode)
  76. {
  77. m_ForcePlayEmote = mode;
  78. }
  79. int GetForced()
  80. {
  81. return m_ForcePlayEmote;
  82. }
  83. int GetID()
  84. {
  85. return m_ID;
  86. }
  87. }
  88. class EmoteManager
  89. {
  90. PlayerBase m_Player;
  91. ItemBase m_item;
  92. EmoteCB m_Callback;
  93. HumanInputController m_HIC;
  94. ref array<string> m_InterruptInputs;
  95. ref array<UAIDWrapper> m_InterruptInputDirect;
  96. ref InventoryLocation m_HandInventoryLocation;
  97. ref EmoteLauncher m_MenuEmote;
  98. bool m_bEmoteIsRequestPending;
  99. bool m_bEmoteIsPlaying;
  100. bool m_IsSurrendered;
  101. bool m_ItemToBeCreated;
  102. bool m_CancelEmote;
  103. bool m_InstantCancelEmote;
  104. bool m_GestureInterruptInput;
  105. protected bool m_ItemToHands; //deprecated
  106. protected bool m_ItemIsOn;
  107. protected bool m_MouseButtonPressed;
  108. protected bool m_PlayerDies;
  109. protected bool m_controllsLocked;
  110. protected bool m_InventoryAccessLocked;
  111. protected bool m_EmoteLockState;
  112. protected int m_DeferredEmoteExecution;
  113. protected int m_GestureID;
  114. protected int m_PreviousGestureID;
  115. protected int m_CurrentGestureID;
  116. protected int m_LastMask;
  117. protected int m_RPSOutcome;
  118. protected int m_InterruptInputsCount;
  119. protected const int CALLBACK_CMD_INVALID = -1;
  120. protected const int CALLBACK_CMD_END = -2;
  121. protected const int CALLBACK_CMD_GESTURE_INTERRUPT = -3;
  122. protected const int CALLBACK_CMD_INSTACANCEL = -4;
  123. PluginAdminLog m_AdminLog;
  124. protected ref Timer m_ReservationTimer;
  125. protected ref map<int, ref EmoteBase> m_NameEmoteMap; //<emote_ID,EmoteBase>
  126. protected ref array<ref EmoteBase> m_EmoteClassArray; //registered 'EmoteBase' object refs
  127. protected ref array<int> m_EmoteIDs; //IDs of registered emotes (found in 'EmoteConstants'). For quick access.
  128. protected ref array<int> m_EmoteInputIDs; //input IDs for the registered 'EmoteBase' objects
  129. protected SHumanCommandSwimSettings m_HumanSwimSettings;
  130. void EmoteManager(PlayerBase player)
  131. {
  132. m_Player = player;
  133. m_HIC = m_Player.GetInputController();
  134. m_ItemIsOn = false;
  135. m_controllsLocked = false;
  136. m_InventoryAccessLocked = false;
  137. m_RPSOutcome = -1;
  138. m_DeferredEmoteExecution = CALLBACK_CMD_INVALID;
  139. m_InterruptInputs = new array<string>;
  140. m_InterruptInputs.Insert("UAMoveForward");
  141. m_InterruptInputs.Insert("UAMoveBack");
  142. m_InterruptInputs.Insert("UATurnLeft");
  143. m_InterruptInputs.Insert("UATurnRight");
  144. m_InterruptInputs.Insert("UAMoveLeft");
  145. m_InterruptInputs.Insert("UAMoveRight");
  146. m_InterruptInputs.Insert("UAStand");
  147. m_InterruptInputs.Insert("UACrouch");
  148. m_InterruptInputs.Insert("UAProne");
  149. m_InterruptInputs.Insert("UAGetOver");
  150. m_HandInventoryLocation = new InventoryLocation();
  151. m_HandInventoryLocation.SetHands(m_Player, null);
  152. if (GetGame().IsServer())
  153. {
  154. m_AdminLog = PluginAdminLog.Cast(GetPlugin(PluginAdminLog));
  155. }
  156. m_ReservationTimer = new Timer();
  157. m_ReservationTimer.Run(8, this, "CheckEmoteLockedState", null, true);
  158. m_HumanSwimSettings = m_Player.GetDayZPlayerType().CommandSwimSettingsW();
  159. ConstructData();
  160. }
  161. void ~EmoteManager()
  162. {
  163. if (m_ReservationTimer && m_ReservationTimer.IsRunning())
  164. m_ReservationTimer.Stop();
  165. }
  166. void ConstructData()
  167. {
  168. EmoteConstructor ec = new EmoteConstructor;
  169. if (!m_NameEmoteMap)
  170. {
  171. ec.ConstructEmotes(m_Player,m_NameEmoteMap);
  172. m_EmoteClassArray = new array<ref EmoteBase>;
  173. m_EmoteIDs = new array<int>;
  174. m_EmoteInputIDs = new array<int>;
  175. int inputID;
  176. int count = m_NameEmoteMap.Count();
  177. UAInput inp;
  178. for (int i = 0; i < count; i++)
  179. {
  180. m_EmoteClassArray.Insert(m_NameEmoteMap.GetElement(i));
  181. m_EmoteIDs.Insert(m_NameEmoteMap.GetElement(i).GetID());
  182. inp = GetUApi().GetInputByName(m_NameEmoteMap.GetElement(i).GetInputActionName());
  183. inputID = inp.ID();
  184. m_EmoteInputIDs.Insert(inputID);
  185. }
  186. if (m_EmoteInputIDs.Count() != m_EmoteClassArray.Count())
  187. {
  188. ErrorEx("Faulty emote data detected in 'ConstructData' method!",ErrorExSeverity.WARNING);
  189. }
  190. }
  191. }
  192. void SetGesture(int id)
  193. {
  194. m_GestureID = id;
  195. }
  196. int GetGesture()
  197. {
  198. return m_GestureID;
  199. }
  200. int DetermineGestureIndex()
  201. {
  202. int count = m_EmoteInputIDs.Count();
  203. for (int i = 0; i < count; ++i)
  204. {
  205. if (GetUApi().GetInputByID(m_EmoteInputIDs[i]).LocalPress())
  206. {
  207. return m_EmoteIDs[i];
  208. }
  209. }
  210. return 0;
  211. }
  212. //! Also includes a stance check for FB callbacks
  213. bool DetermineEmoteData(EmoteBase emote, out int callback_ID, out int stancemask, out bool is_fullbody)
  214. {
  215. if (emote.DetermineOverride(callback_ID, stancemask, is_fullbody))
  216. {
  217. return emote.EmoteFBStanceCheck(stancemask);
  218. }
  219. else if (emote.GetAdditiveCallbackUID() != 0 && m_Player.IsPlayerInStance(emote.GetStanceMaskAdditive()))
  220. {
  221. callback_ID = emote.GetAdditiveCallbackUID();
  222. stancemask = emote.GetStanceMaskAdditive();
  223. is_fullbody = false;
  224. return true;
  225. }
  226. else if (emote.GetFullbodyCallbackUID() != 0 && emote.EmoteFBStanceCheck(emote.GetStanceMaskFullbody()))
  227. {
  228. callback_ID = emote.GetFullbodyCallbackUID();
  229. stancemask = emote.GetStanceMaskFullbody();
  230. is_fullbody = true;
  231. return true;
  232. }
  233. return false;
  234. }
  235. //Called from players commandhandler each frame, checks input
  236. void Update(float deltaT)
  237. {
  238. // no updates on restrained characters
  239. if (m_Player.IsRestrained())
  240. return;
  241. if (m_ItemToBeCreated)
  242. {
  243. if (GetGame().IsServer() && m_Callback && !m_Player.GetItemInHands())
  244. {
  245. m_Player.GetHumanInventory().CreateInHands("SurrenderDummyItem");
  246. }
  247. m_ItemToBeCreated = false;
  248. }
  249. int gestureSlot = 0;
  250. #ifndef SERVER
  251. gestureSlot = DetermineGestureIndex();
  252. #endif
  253. //deferred emote cancel
  254. if (m_InstantCancelEmote) //'hard' cancel
  255. {
  256. if (m_Callback)
  257. {
  258. m_Callback.Cancel();
  259. }
  260. if (m_MenuEmote)
  261. {
  262. m_MenuEmote = null;
  263. }
  264. m_DeferredEmoteExecution = CALLBACK_CMD_INVALID;
  265. m_InstantCancelEmote = false;
  266. m_bEmoteIsRequestPending = false;
  267. if (m_IsSurrendered)
  268. ClearSurrenderState();
  269. else
  270. SetEmoteLockState(false);
  271. }
  272. else if (m_CancelEmote) //'soft' cancel
  273. {
  274. if (m_IsSurrendered)
  275. {
  276. ClearSurrenderState();
  277. }
  278. else if (m_Callback)
  279. {
  280. m_Callback.InternalCommand(DayZPlayerConstants.CMD_ACTIONINT_INTERRUPT);
  281. }
  282. m_bEmoteIsRequestPending = false;
  283. m_CancelEmote = false;
  284. }
  285. if (m_MenuEmote && m_MenuEmote.GetForced() > EmoteLauncher.FORCE_NONE && !GetGame().IsDedicatedServer()) //forced emote playing
  286. {
  287. SendEmoteRequestSync(m_MenuEmote.GetID());
  288. }
  289. else if (m_Callback)
  290. {
  291. bool uiGesture = false;
  292. if (!GetGame().IsDedicatedServer())
  293. {
  294. uiGesture = GetGame().GetUIManager().IsMenuOpen(MENU_GESTURES);
  295. if (InterruptGestureCheck())
  296. {
  297. SendEmoteRequestSync(CALLBACK_CMD_END);
  298. }
  299. if (InterruptWaterCheck())
  300. {
  301. SendEmoteRequestSync(CALLBACK_CMD_INSTACANCEL);
  302. }
  303. }
  304. if (gestureSlot > 0 || m_GestureInterruptInput || (m_HIC.IsSingleUse() && !uiGesture) || (m_HIC.IsContinuousUseStart() && !uiGesture) || (m_Callback.m_IsFullbody && !uiGesture && m_HIC.IsWeaponRaised()))
  305. {
  306. if (m_CurrentGestureID == EmoteConstants.ID_EMOTE_SUICIDE && m_HIC.IsSingleUse())
  307. {
  308. if (m_Callback.GetState() == m_Callback.STATE_LOOP_LOOP)
  309. {
  310. CommitSuicide();
  311. }
  312. else
  313. {
  314. return;
  315. }
  316. }
  317. else if ((m_CurrentGestureID == EmoteConstants.ID_EMOTE_THUMB || m_CurrentGestureID == EmoteConstants.ID_EMOTE_THUMBDOWN) && m_HIC.IsSingleUse())
  318. {
  319. m_Callback.InternalCommand(DayZPlayerConstants.CMD_ACTIONINT_ACTION);
  320. }
  321. else if (m_HIC.IsSingleUse() && (m_CurrentGestureID == EmoteConstants.ID_EMOTE_RPS || m_CurrentGestureID == EmoteConstants.ID_EMOTE_RPS_R || m_CurrentGestureID == EmoteConstants.ID_EMOTE_RPS_P || m_CurrentGestureID == EmoteConstants.ID_EMOTE_RPS_S))
  322. {
  323. if (m_RPSOutcome != -1)
  324. {
  325. if (m_RPSOutcome == 0)
  326. {
  327. m_Callback.InternalCommand(DayZPlayerConstants.CMD_ACTIONINT_RPS_ROCK);
  328. }
  329. else if (m_RPSOutcome == 1)
  330. {
  331. m_Callback.InternalCommand(DayZPlayerConstants.CMD_ACTIONINT_RPS_PAPER);
  332. }
  333. else if (m_RPSOutcome == 2)
  334. {
  335. m_Callback.InternalCommand(DayZPlayerConstants.CMD_ACTIONINT_RPS_SCISSORS);
  336. }
  337. m_RPSOutcome = -1;
  338. }
  339. else
  340. {
  341. m_Callback.InternalCommand(DayZPlayerConstants.CMD_ACTIONINT_END);
  342. }
  343. }
  344. else if (m_CurrentGestureID != EmoteConstants.ID_EMOTE_SUICIDE || (m_CurrentGestureID == EmoteConstants.ID_EMOTE_SUICIDE && m_Callback.GetState() < 3))
  345. {
  346. SendEmoteRequestSync(CALLBACK_CMD_END);
  347. }
  348. else if (m_CurrentGestureID == EmoteConstants.ID_EMOTE_SUICIDE)
  349. {
  350. SendEmoteRequestSync(CALLBACK_CMD_END);
  351. }
  352. }
  353. if (m_LastMask != -1 && m_Player.IsPlayerInStance(DayZPlayerConstants.STANCEMASK_PRONE))
  354. {
  355. m_Callback.Cancel();
  356. }
  357. if (m_MenuEmote && m_bEmoteIsPlaying)
  358. {
  359. SendEmoteRequestSync(CALLBACK_CMD_END);
  360. }
  361. if (m_DeferredEmoteExecution == CALLBACK_CMD_END)
  362. {
  363. EndCallbackCommand();
  364. }
  365. if (m_DeferredEmoteExecution == CALLBACK_CMD_GESTURE_INTERRUPT)
  366. {
  367. InterruptCallbackCommand();
  368. }
  369. }
  370. //no m_Callback exists
  371. else
  372. {
  373. if (m_bEmoteIsRequestPending && (m_Player.IsUnconscious() || !m_Player.IsAlive()))
  374. {
  375. m_bEmoteIsRequestPending = false;
  376. }
  377. if (m_bEmoteIsPlaying)
  378. {
  379. OnEmoteEnd();
  380. }
  381. else if (!m_Player.GetItemInHands() && m_IsSurrendered && !m_ItemToBeCreated && (!m_MenuEmote || m_MenuEmote.GetForced() != EmoteLauncher.FORCE_NONE)) //play only when there is time to do so
  382. {
  383. PlaySurrenderInOut(false);
  384. return;
  385. }
  386. // getting out of surrender state
  387. else if (m_IsSurrendered && m_Player.GetItemInHands() && (m_HIC.IsSingleUse() || m_HIC.IsContinuousUseStart() || m_HIC.IsWeaponRaised()))
  388. {
  389. if (m_Player.GetItemInHands())
  390. m_Player.GetItemInHands().DeleteSafe();//Note, this keeps item 'alive' until it is released by all the systems (inventory swapping etc.)
  391. return;
  392. }
  393. // fallback in case lock does not end properly
  394. else if (m_IsSurrendered && (!m_Player.GetItemInHands() || (m_Player.GetItemInHands() && m_Player.GetItemInHands().GetType() != "SurrenderDummyItem" && m_EmoteLockState)))
  395. {
  396. ClearSurrenderState();
  397. return;
  398. }
  399. //actual emote launch
  400. else if (m_DeferredEmoteExecution > CALLBACK_CMD_INVALID)
  401. {
  402. PlayEmote(m_DeferredEmoteExecution);
  403. }
  404. //client-side emote launcher
  405. else if (!m_bEmoteIsPlaying && m_MenuEmote && !GetGame().IsDedicatedServer())
  406. {
  407. SendEmoteRequestSync(m_MenuEmote.GetID());
  408. }
  409. else if (!m_MenuEmote && gestureSlot > 0)
  410. {
  411. CreateEmoteCBFromMenu(gestureSlot,true); //translation no longer needed
  412. }
  413. }
  414. }
  415. void OnEmoteEnd()
  416. {
  417. ShowItemInHands();
  418. if (m_PlayerDies)
  419. {
  420. m_Player.SetHealth(0.0);
  421. return;
  422. }
  423. //surrender "state" OFF switch only
  424. if (m_CurrentGestureID == EmoteConstants.ID_EMOTE_SURRENDER)
  425. {
  426. if (m_IsSurrendered && !m_Player.GetItemInHands())
  427. {
  428. m_IsSurrendered = false;
  429. }
  430. }
  431. m_CurrentGestureID = 0;
  432. m_bEmoteIsPlaying = false;
  433. m_bEmoteIsRequestPending = false;
  434. if (m_IsSurrendered)
  435. return;
  436. m_GestureInterruptInput = false;
  437. SetEmoteLockState(false);
  438. // back to the default - shoot from camera - if not set already
  439. if (!m_Player.IsShootingFromCamera())
  440. m_Player.OverrideShootFromCamera(true);
  441. }
  442. //server-side
  443. bool OnInputUserDataProcess(int userDataType, ParamsReadContext ctx)
  444. {
  445. if (userDataType == INPUT_UDT_GESTURE)
  446. {
  447. int forced = EmoteLauncher.FORCE_NONE;
  448. int gestureID = -1;
  449. int random = -1;
  450. if (ctx.Read(gestureID))
  451. {
  452. ctx.Read(forced);
  453. if (ctx.Read(random))
  454. {
  455. m_RPSOutcome = random;
  456. }
  457. //server-side check, sends CALLBACK_CMD_INSTACANCEL as a fail
  458. if (forced == EmoteLauncher.FORCE_NONE && !CanPlayEmote(gestureID))
  459. gestureID = CALLBACK_CMD_INSTACANCEL;
  460. ScriptJunctureData pCtx = new ScriptJunctureData;
  461. pCtx.Write(gestureID);
  462. pCtx.Write(forced);
  463. m_Player.SendSyncJuncture(DayZPlayerSyncJunctures.SJ_GESTURE_REQUEST, pCtx);
  464. m_bEmoteIsRequestPending = true;
  465. }
  466. return true;
  467. }
  468. return false;
  469. }
  470. //server and client
  471. void OnSyncJuncture(int pJunctureID, ParamsReadContext pCtx)
  472. {
  473. int forced;
  474. int gesture_id;
  475. if (!m_CancelEmote)
  476. {
  477. pCtx.Read(gesture_id);
  478. pCtx.Read(forced);
  479. EmoteBase emoteData;
  480. if ((m_Callback || m_IsSurrendered) && (forced == EmoteLauncher.FORCE_ALL || (forced == EmoteLauncher.FORCE_DIFFERENT && m_CurrentGestureID != gesture_id)))
  481. {
  482. if (m_Callback)
  483. {
  484. if (m_NameEmoteMap.Find(m_CurrentGestureID,emoteData) && emoteData.CanBeCanceledNormally(m_Callback))
  485. m_CancelEmote = true;
  486. else
  487. return;
  488. }
  489. m_CancelEmote = true;
  490. }
  491. if (gesture_id == CALLBACK_CMD_INSTACANCEL)
  492. {
  493. if (m_Callback)
  494. {
  495. if (m_NameEmoteMap.Find(m_CurrentGestureID,emoteData) && !emoteData.CanBeCanceledNormally(m_Callback))
  496. {
  497. m_InstantCancelEmote = false;
  498. return;
  499. }
  500. }
  501. m_InstantCancelEmote = true;
  502. }
  503. m_DeferredEmoteExecution = gesture_id;
  504. }
  505. else
  506. m_CancelEmote = false;
  507. }
  508. void OnCallbackEnd()
  509. {
  510. EmoteBase emoteData;
  511. if (m_NameEmoteMap.Find(m_CurrentGestureID,emoteData))
  512. emoteData.OnCallbackEnd();
  513. }
  514. void AfterStoreLoad()
  515. {
  516. if (m_Player.GetItemInHands() && SurrenderDummyItem.Cast(m_Player.GetItemInHands()))
  517. m_Player.GetItemInHands().Delete();
  518. }
  519. bool PlayEmote(int id)
  520. {
  521. m_DeferredEmoteExecution = CALLBACK_CMD_INVALID;
  522. m_bEmoteIsRequestPending = false;
  523. if (CanPlayEmote(id))
  524. {
  525. EmoteBase emote;
  526. m_NameEmoteMap.Find(id,emote);
  527. if (m_AdminLog)
  528. m_AdminLog.OnEmote(m_Player, emote);
  529. m_PreviousGestureID = m_CurrentGestureID;
  530. m_CurrentGestureID = id;
  531. if (id > 0)
  532. {
  533. if (emote)
  534. {
  535. int callback_ID;
  536. int stancemask;
  537. bool is_fullbody;
  538. if (DetermineEmoteData(emote,callback_ID,stancemask,is_fullbody))
  539. {
  540. if (!emote.EmoteStartOverride(EmoteCB,callback_ID,stancemask,is_fullbody))
  541. {
  542. emote.OnBeforeStandardCallbackCreated(callback_ID,stancemask,is_fullbody);
  543. CreateEmoteCallback(EmoteCB,callback_ID,stancemask,is_fullbody);
  544. }
  545. if (emote.GetHideItemInHands())
  546. {
  547. HideItemInHands();
  548. }
  549. }
  550. else
  551. {
  552. ErrorEx("EmoteManager | DetermineEmoteData failed!");
  553. }
  554. }
  555. }
  556. }
  557. SetEmoteLockState(m_bEmoteIsPlaying);
  558. return m_bEmoteIsPlaying;
  559. }
  560. //creates Emote callback
  561. protected void CreateEmoteCallback(typename callbacktype, int id, int mask, bool fullbody)
  562. {
  563. if (m_Player)
  564. {
  565. m_LastMask = -1;
  566. if (fullbody)
  567. {
  568. Class.CastTo(m_Callback, m_Player.StartCommand_Action(id,callbacktype,mask));
  569. m_Callback.m_IsFullbody = true;
  570. m_Callback.EnableCancelCondition(true);
  571. }
  572. else if (m_Player.IsPlayerInStance(mask))
  573. {
  574. m_LastMask = mask; //character is probably not prone now
  575. Class.CastTo(m_Callback, m_Player.AddCommandModifier_Action(id,callbacktype));
  576. }
  577. if (m_Callback)
  578. {
  579. m_bEmoteIsPlaying = true;
  580. m_Callback.m_callbackID = id;
  581. m_Callback.m_player = m_Player;
  582. m_Callback.m_Manager = this;
  583. }
  584. }
  585. }
  586. protected void HideItemInHands()
  587. {
  588. m_item = m_Player.GetItemInHands();
  589. if (m_Callback && m_item)
  590. {
  591. m_Player.TryHideItemInHands(true);
  592. }
  593. }
  594. protected void ShowItemInHands()
  595. {
  596. if (m_item)
  597. {
  598. m_Player.TryHideItemInHands(false);
  599. }
  600. }
  601. void RequestCommitSuicide()
  602. {
  603. if (!GetGame().IsClient())
  604. CommitSuicide();
  605. }
  606. protected void CommitSuicide()
  607. {
  608. Weapon_Base weapon;
  609. WeaponEventBase weapon_event = new WeaponEventTrigger;
  610. if (Weapon_Base.CastTo(weapon,m_Player.GetItemInHands()))
  611. {
  612. if (weapon.CanFire())
  613. {
  614. m_Callback.RegisterAnimationEvent("Simulation_End",EmoteConstants.EMOTE_SUICIDE_SIMULATION_END);
  615. m_Player.SetSuicide(true);
  616. weapon.ProcessWeaponEvent(weapon_event);
  617. m_Callback.InternalCommand(DayZPlayerConstants.CMD_ACTIONINT_FINISH);
  618. if (m_Player.IsAlive())
  619. {
  620. EntityAI helm = m_Player.FindAttachmentBySlotName("Headgear");
  621. if (helm && GetGame().IsServer())
  622. {
  623. float damage = helm.GetMaxHealth("","");
  624. helm.AddHealth("","", -damage/2);
  625. }
  626. GetGame().GetCallQueue(CALL_CATEGORY_GAMEPLAY).Call(this.KillPlayer);
  627. if (m_AdminLog)
  628. {
  629. m_AdminLog.Suicide(m_Player);
  630. }
  631. }
  632. }
  633. else
  634. {
  635. if (!weapon.IsDamageDestroyed())
  636. {
  637. weapon.ProcessWeaponEvent(weapon_event);
  638. }
  639. m_Callback.InternalCommand(DayZPlayerConstants.CMD_ACTIONINT_END);
  640. }
  641. }
  642. else if (m_Player.GetItemInHands() && m_Player.GetItemInHands().ConfigIsExisting("suicideAnim"))
  643. {
  644. m_Callback.RegisterAnimationEvent("Death",EmoteConstants.EMOTE_SUICIDE_DEATH);
  645. m_Callback.RegisterAnimationEvent("Bleed",EmoteConstants.EMOTE_SUICIDE_BLEED);
  646. m_Callback.RegisterAnimationEvent("Simulation_End",EmoteConstants.EMOTE_SUICIDE_SIMULATION_END);
  647. m_Callback.InternalCommand(DayZPlayerConstants.CMD_ACTIONINT_FINISH);
  648. m_Player.SetSuicide(true);
  649. }
  650. else
  651. {
  652. m_Callback.InternalCommand(DayZPlayerConstants.CMD_ACTIONINT_FINISH);
  653. }
  654. }
  655. void KillPlayer()
  656. {
  657. if (GetGame().IsServer())
  658. {
  659. m_Player.SetHealth(0);
  660. }
  661. }
  662. void LogSuicide()
  663. {
  664. if (GetGame().IsServer())
  665. {
  666. PlayerIdentity identity = m_Player.GetIdentity();
  667. if (identity)
  668. {
  669. if (m_AdminLog)
  670. m_AdminLog.Suicide(m_Player);
  671. }
  672. }
  673. }
  674. void CreateEmoteCBFromMenu(int id, bool interrupts_same = false)
  675. {
  676. m_MenuEmote = new EmoteLauncher(id,interrupts_same);
  677. }
  678. EmoteLauncher GetEmoteLauncher()
  679. {
  680. return m_MenuEmote;
  681. }
  682. void InterruptCallbackCommand()
  683. {
  684. m_Callback.InternalCommand(DayZPlayerConstants.CMD_ACTIONINT_INTERRUPT);
  685. if (m_MenuEmote)
  686. m_MenuEmote = null;
  687. m_DeferredEmoteExecution = CALLBACK_CMD_INVALID;
  688. }
  689. void EndCallbackCommand()
  690. {
  691. if (m_CurrentGestureID == EmoteConstants.ID_EMOTE_DANCE)
  692. {
  693. m_Callback.InternalCommand(DayZPlayerConstants.CMD_ACTIONINT_INTERRUPT);
  694. }
  695. else
  696. {
  697. m_Callback.InternalCommand(DayZPlayerConstants.CMD_ACTIONINT_END);
  698. }
  699. if (m_MenuEmote)
  700. m_MenuEmote = null;
  701. m_DeferredEmoteExecution = CALLBACK_CMD_INVALID;
  702. }
  703. //sends request (client)
  704. void SendEmoteRequestSync(int id)
  705. {
  706. int forced = EmoteLauncher.FORCE_NONE;
  707. if (m_MenuEmote)
  708. {
  709. forced = m_MenuEmote.GetForced();
  710. }
  711. m_RPSOutcome = -1;
  712. switch (id)
  713. {
  714. case EmoteConstants.ID_EMOTE_RPS :
  715. m_RPSOutcome = Math.RandomInt(0,3);
  716. break;
  717. case EmoteConstants.ID_EMOTE_RPS_R :
  718. m_RPSOutcome = 0;
  719. break;
  720. case EmoteConstants.ID_EMOTE_RPS_P :
  721. m_RPSOutcome = 1;
  722. break;
  723. case EmoteConstants.ID_EMOTE_RPS_S :
  724. m_RPSOutcome = 2;
  725. break;
  726. }
  727. ScriptInputUserData ctx = new ScriptInputUserData;
  728. if (GetGame().IsMultiplayer() && GetGame().IsClient())
  729. {
  730. bool canProceed = true; //running callbacks in certain state can block additional actions
  731. EmoteBase emoteData = m_NameEmoteMap.Get(m_CurrentGestureID);
  732. if (m_Callback && emoteData)
  733. {
  734. canProceed = emoteData.CanBeCanceledNormally(m_Callback);
  735. }
  736. if (ctx.CanStoreInputUserData() && ((CanPlayEmote(id) && CanPlayEmoteClientCheck(id)) || forced) && canProceed)
  737. {
  738. ctx.Write(INPUT_UDT_GESTURE);
  739. ctx.Write(id);
  740. ctx.Write(forced);
  741. if (m_RPSOutcome != -1)
  742. {
  743. ctx.Write(m_RPSOutcome);
  744. }
  745. ctx.Send();
  746. m_bEmoteIsRequestPending = true;
  747. }
  748. else
  749. {
  750. m_bEmoteIsRequestPending = false;
  751. }
  752. m_MenuEmote = NULL;
  753. SetEmoteLockState(IsEmotePlaying());
  754. }
  755. else if (!GetGame().IsMultiplayer())
  756. {
  757. if (id == CALLBACK_CMD_END)
  758. {
  759. EndCallbackCommand();
  760. }
  761. else if (id == CALLBACK_CMD_GESTURE_INTERRUPT)
  762. {
  763. m_DeferredEmoteExecution = CALLBACK_CMD_GESTURE_INTERRUPT;
  764. }
  765. else if (CanPlayEmote(id) && CanPlayEmoteClientCheck(id))
  766. {
  767. PlayEmote(id);
  768. }
  769. else
  770. {
  771. SetEmoteLockState(IsEmotePlaying());
  772. }
  773. m_MenuEmote = NULL;
  774. }
  775. }
  776. bool IsControllsLocked()
  777. {
  778. return m_controllsLocked;
  779. }
  780. bool CanPlayEmote(int id)
  781. {
  782. //special cases
  783. if (id == CALLBACK_CMD_END || id == CALLBACK_CMD_GESTURE_INTERRUPT || id == CALLBACK_CMD_INSTACANCEL)
  784. {
  785. return true;
  786. }
  787. if (!m_Player || !m_Player.IsAlive() || (!IsEmotePlaying() && (m_Player.GetCommand_Action() || m_Player.GetCommandModifier_Action())) || m_Player.GetThrowing().IsThrowingModeEnabled())
  788. {
  789. //Debug.Log("!CanPlayEmote | reason: 1");
  790. return false;
  791. }
  792. ItemBase item = m_Player.GetItemInHands();
  793. if (item)
  794. {
  795. if (item.IsHeavyBehaviour() && id != EmoteConstants.ID_EMOTE_SURRENDER)
  796. {
  797. //Debug.Log("!CanPlayEmote | reason: 2");
  798. return false;
  799. }
  800. SurrenderDummyItem sda;
  801. if (m_Player.IsItemsToDelete() && Class.CastTo(sda,item) && !sda.IsSetForDeletion())
  802. {
  803. //Debug.Log("!CanPlayEmote | reason: 3");
  804. return false;
  805. }
  806. }
  807. if ((m_Player.GetWeaponManager() && m_Player.GetWeaponManager().IsRunning()) || (m_Player.GetActionManager() && m_Player.GetActionManager().GetRunningAction()))
  808. {
  809. //Debug.Log("!CanPlayEmote | reason: 4");
  810. return false;
  811. }
  812. if (m_HIC.IsWeaponRaised() || m_Player.IsRolling() || m_Player.IsClimbing() || m_Player.IsRestrainStarted() || m_Player.IsFighting() || m_Player.IsSwimming() || m_Player.IsClimbingLadder() || m_Player.IsFalling() || m_Player.IsUnconscious() || m_Player.IsJumpInProgress() || m_Player.IsRestrained()) // rework conditions into something better?
  813. {
  814. //Debug.Log("!CanPlayEmote | reason: 5");
  815. return false;
  816. }
  817. if (m_Player.GetCommand_Vehicle())
  818. {
  819. //Debug.Log("!CanPlayEmote | reason: 6");
  820. return false;
  821. }
  822. HumanCommandMove cm = m_Player.GetCommand_Move();
  823. if (cm)
  824. {
  825. if (cm.IsOnBack() && id != EmoteConstants.ID_EMOTE_SURRENDER)
  826. return false;
  827. if (cm.IsChangingStance())
  828. return false;
  829. }
  830. //"locks" player in surrender state
  831. if (m_IsSurrendered && (id != EmoteConstants.ID_EMOTE_SURRENDER))
  832. {
  833. //Debug.Log("!CanPlayEmote | reason: 8");
  834. return false;
  835. }
  836. if (m_Player.GetDayZPlayerInventory().IsProcessing())
  837. {
  838. //Debug.Log("!CanPlayEmote | reason: 9");
  839. return false;
  840. }
  841. EmoteBase emote;
  842. if (m_NameEmoteMap.Find(id,emote))
  843. {
  844. int callback_ID;
  845. int stancemask;
  846. bool is_fullbody;
  847. if (DetermineEmoteData(emote,callback_ID,stancemask,is_fullbody) && emote.EmoteCondition(stancemask))
  848. {
  849. return true;
  850. }
  851. //Debug.Log("!CanPlayEmote | reason: 10");
  852. }
  853. return false;
  854. }
  855. bool CanPlayEmoteClientCheck(int id)
  856. {
  857. if (!GetGame().IsClient())
  858. return true;
  859. if (GetGame().GetUIManager().FindMenu(MENU_INVENTORY))
  860. {
  861. //Debug.Log("!CanPlayEmoteClientCheck | reason: 1");
  862. return false;
  863. }
  864. return true;
  865. }
  866. void PlaySurrenderInOut(bool state)
  867. {
  868. m_PreviousGestureID = m_CurrentGestureID;
  869. m_CurrentGestureID = EmoteConstants.ID_EMOTE_SURRENDER;
  870. if (state)
  871. {
  872. ItemBase item = m_Player.GetItemInHands();
  873. if (item)
  874. {
  875. if (!m_Player.CanDropEntity(item))
  876. return;
  877. if (m_Player.GetInventory().HasInventoryReservation(null, m_HandInventoryLocation))
  878. m_Player.GetInventory().ClearInventoryReservationEx(null, m_HandInventoryLocation);
  879. if (GetGame().IsMultiplayer())
  880. {
  881. if (GetGame().IsServer())
  882. m_Player.ServerDropEntity(item);
  883. }
  884. else
  885. {
  886. m_Player.PhysicalPredictiveDropItem(item); //SP only
  887. }
  888. }
  889. CreateEmoteCallback(EmoteCB,DayZPlayerConstants.CMD_GESTUREFB_SURRENDERIN,DayZPlayerConstants.STANCEMASK_ALL,true);
  890. if (m_Callback)
  891. {
  892. m_Callback.RegisterAnimationEvent("ActionExec", UA_ANIM_EVENT);
  893. m_IsSurrendered = true; //sets state immediately on anim start
  894. }
  895. }
  896. else
  897. {
  898. if (m_Player.IsAlive() && !m_Player.IsUnconscious())
  899. {
  900. CreateEmoteCallback(EmoteCB,DayZPlayerConstants.CMD_GESTUREFB_SURRENDEROUT,DayZPlayerConstants.STANCEMASK_ALL,true);
  901. }
  902. else
  903. {
  904. OnEmoteEnd();
  905. }
  906. }
  907. }
  908. //!
  909. void SetEmoteLockState(bool state)
  910. {
  911. //separate inventory access locking
  912. if (state != m_InventoryAccessLocked)
  913. {
  914. m_Player.SetInventorySoftLock(state);
  915. m_InventoryAccessLocked = state;
  916. }
  917. if (GetGame().IsClient() && m_InventoryAccessLocked && GetGame().GetUIManager().FindMenu(MENU_INVENTORY))
  918. m_Player.CloseInventoryMenu();
  919. //Movement lock in fullbody anims
  920. if (state && m_Callback && m_Callback.m_IsFullbody)
  921. m_controllsLocked = true;
  922. else
  923. m_controllsLocked = false;
  924. if (state == m_EmoteLockState)
  925. return;
  926. if (!m_HandInventoryLocation)
  927. {
  928. m_HandInventoryLocation = new InventoryLocation;
  929. m_HandInventoryLocation.SetHands(m_Player,null);
  930. }
  931. if (!state)
  932. {
  933. if (m_Player.GetInventory().HasInventoryReservation(null, m_HandInventoryLocation))
  934. m_Player.GetInventory().ClearInventoryReservationEx(null, m_HandInventoryLocation);
  935. if (m_Player.GetActionManager())
  936. m_Player.GetActionManager().EnableActions(true);
  937. }
  938. else
  939. {
  940. if (!m_Player.GetInventory().HasInventoryReservation(null, m_HandInventoryLocation))
  941. m_Player.GetInventory().AddInventoryReservationEx(null, m_HandInventoryLocation, GameInventory.c_InventoryReservationTimeoutMS);
  942. if (m_Player.GetActionManager())
  943. m_Player.GetActionManager().EnableActions(false);
  944. }
  945. m_EmoteLockState = state;
  946. }
  947. void CheckEmoteLockedState()
  948. {
  949. if (!m_Player.GetItemInHands() || (m_Player.GetItemInHands() && !SurrenderDummyItem.Cast(m_Player.GetItemInHands())))
  950. return;
  951. //refreshes reservation in case of unwanted timeout
  952. if (m_EmoteLockState && m_HandInventoryLocation)
  953. {
  954. m_Player.GetInventory().ExtendInventoryReservationEx(null, m_HandInventoryLocation, 10000);
  955. }
  956. }
  957. //! directly force-ends surrender state AND requests hard cancel
  958. void EndSurrenderRequest(SurrenderData data = null)
  959. {
  960. if (m_IsSurrendered && data)
  961. {
  962. PostSurrenderRequestServer();
  963. data.End();
  964. }
  965. }
  966. //! clears surrender state only
  967. protected void ClearSurrenderState()
  968. {
  969. if (m_IsSurrendered)
  970. {
  971. SurrenderDummyItem dummyItem = SurrenderDummyItem.Cast(m_Player.GetItemInHands());
  972. if (dummyItem)
  973. dummyItem.DeleteSafe();
  974. m_IsSurrendered = false;
  975. SetEmoteLockState(IsEmotePlaying());
  976. }
  977. }
  978. void ForceSurrenderState(bool state)
  979. {
  980. m_IsSurrendered = state;
  981. SetEmoteLockState(IsEmotePlaying());
  982. }
  983. //! server only
  984. protected void PostSurrenderRequestServer()
  985. {
  986. if ((GetGame().IsMultiplayer() && GetGame().IsServer()) || !GetGame().IsMultiplayer())
  987. {
  988. ScriptJunctureData pCtx = new ScriptJunctureData;
  989. pCtx.Write(CALLBACK_CMD_INSTACANCEL);
  990. pCtx.Write(EmoteLauncher.FORCE_ALL);
  991. m_Player.SendSyncJuncture(DayZPlayerSyncJunctures.SJ_GESTURE_REQUEST, pCtx);
  992. }
  993. }
  994. //sent from server to cancel generic emote callback
  995. void ServerRequestEmoteCancel()
  996. {
  997. ScriptJunctureData pCtx = new ScriptJunctureData;
  998. pCtx.Write(CALLBACK_CMD_GESTURE_INTERRUPT);
  999. m_Player.SendSyncJuncture(DayZPlayerSyncJunctures.SJ_GESTURE_REQUEST, pCtx);
  1000. }
  1001. bool InterruptGestureCheck()
  1002. {
  1003. //init pass
  1004. if (!m_InterruptInputDirect)
  1005. {
  1006. m_InterruptInputDirect = new array<UAIDWrapper>;
  1007. m_InterruptInputsCount = m_InterruptInputs.Count();
  1008. for (int i = 0; i < m_InterruptInputsCount; i++)
  1009. {
  1010. m_InterruptInputDirect.Insert(GetUApi().GetInputByName(m_InterruptInputs[i]).GetPersistentWrapper());
  1011. }
  1012. }
  1013. //interrupts any callback if restrain action is in progress, takes priority
  1014. if (!m_Callback.m_IsFullbody)
  1015. return false;
  1016. for (int idx = 0; idx < m_InterruptInputsCount; idx++)
  1017. {
  1018. if (m_InterruptInputDirect[idx].InputP().LocalPress())
  1019. {
  1020. return true;
  1021. }
  1022. }
  1023. return false;
  1024. }
  1025. bool InterruptWaterCheck()
  1026. {
  1027. float waterLevel = m_Player.GetCurrentWaterLevel();
  1028. if (m_Player.IsPlayerInStance(DayZPlayerConstants.STANCEMASK_PRONE | DayZPlayerConstants.STANCEMASK_PRONE) && waterLevel >= m_HumanSwimSettings.m_fToCrouchLevel)
  1029. {
  1030. return true;
  1031. }
  1032. else if (m_Player.IsPlayerInStance(DayZPlayerConstants.STANCEMASK_CROUCH | DayZPlayerConstants.STANCEIDX_RAISEDCROUCH) && waterLevel >= m_HumanSwimSettings.m_fToErectLevel)
  1033. {
  1034. return true;
  1035. }
  1036. return m_Player.GetModifiersManager() && m_Player.GetModifiersManager().IsModifierActive(eModifiers.MDF_DROWNING);
  1037. }
  1038. bool IsEmotePlaying()
  1039. {
  1040. return m_bEmoteIsPlaying || m_IsSurrendered || m_bEmoteIsRequestPending;
  1041. }
  1042. map<int,ref EmoteBase> GetNameEmoteMap()
  1043. {
  1044. return m_NameEmoteMap;
  1045. }
  1046. void CreateBleedingEffect(int Callback_ID)
  1047. {
  1048. if (GetGame().IsServer() && m_Player.IsAlive())
  1049. {
  1050. switch (Callback_ID)
  1051. {
  1052. case DayZPlayerConstants.CMD_SUICIDEFB_1HD :
  1053. m_Player.GetBleedingManagerServer().AttemptAddBleedingSourceBySelection("Neck");
  1054. break;
  1055. case DayZPlayerConstants.CMD_SUICIDEFB_FIREAXE :
  1056. m_Player.GetBleedingManagerServer().AttemptAddBleedingSourceBySelection("LeftForeArmRoll");
  1057. break;
  1058. case DayZPlayerConstants.CMD_SUICIDEFB_PITCHFORK :
  1059. m_Player.GetBleedingManagerServer().AttemptAddBleedingSourceBySelection("Spine2");
  1060. break;
  1061. case DayZPlayerConstants.CMD_SUICIDEFB_SWORD :
  1062. m_Player.GetBleedingManagerServer().AttemptAddBleedingSourceBySelection("Spine2");
  1063. break;
  1064. case DayZPlayerConstants.CMD_SUICIDEFB_SPEAR :
  1065. m_Player.GetBleedingManagerServer().AttemptAddBleedingSourceBySelection("Head");
  1066. break;
  1067. case DayZPlayerConstants.CMD_SUICIDEFB_WOODAXE :
  1068. m_Player.GetBleedingManagerServer().AttemptAddBleedingSourceBySelection("LeftForeArmRoll");
  1069. break;
  1070. default :
  1071. ErrorEx("EmoteManager.c | CreateBleedingEffect | WRONG ID",ErrorExSeverity.INFO);
  1072. break;
  1073. }
  1074. }
  1075. }
  1076. /////////////////////////////////////////////////////////
  1077. //! Deprecated
  1078. protected void PickEmote(int gestureslot)
  1079. {
  1080. }
  1081. };
  1082. class SurrenderData
  1083. {
  1084. //!called on surrender end request end
  1085. void End();
  1086. }
  1087. /**@class ChainedDropAndKillPlayerLambda
  1088. * @brief drops weapon in hands to ground and then calls kill
  1089. **/
  1090. class ChainedDropAndKillPlayerLambda : ReplaceItemWithNewLambdaBase
  1091. {
  1092. PlayerBase m_Player;
  1093. void ChainedDropAndKillPlayerLambda (EntityAI old_item, string new_item_type, PlayerBase player)
  1094. {
  1095. m_Player = player;
  1096. InventoryLocation gnd = new InventoryLocation;
  1097. vector mtx[4];
  1098. old_item.GetTransform(mtx);
  1099. gnd.SetGround(old_item, mtx);
  1100. OverrideNewLocation(gnd);
  1101. }
  1102. override void Execute (HumanInventoryWithFSM fsm_to_notify = null)
  1103. {
  1104. if (PrepareLocations())
  1105. {
  1106. vector transform[4];
  1107. m_Player.GetInventory().TakeToDst(InventoryMode.SERVER, m_OldLocation, m_NewLocation);
  1108. m_Player.OnItemInHandsChanged();
  1109. }
  1110. m_Player.SetHealth(0);
  1111. if (LogManager.IsInventoryHFSMLogEnable()) hndDebugPrint("[syncinv] player=" + Object.GetDebugName(m_Player) + " STS = " + m_Player.GetSimulationTimeStamp() + " ChainedDropAndKillPlayerLambda");
  1112. }
  1113. }