actionbase.c 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330
  1. enum ActionConditionMask
  2. {
  3. ACM_NO_EXEPTION = 0,
  4. ACM_IN_VEHICLE = 1,
  5. ACM_ON_LADDER = 2,
  6. ACM_SWIMMING = 4,
  7. ACM_RESTRAIN = 8,
  8. ACM_RAISED = 16,
  9. ACM_ON_BACK = 32,
  10. ACM_THROWING = 64,
  11. ACM_LEANING = 128,
  12. ACM_BROKEN_LEGS = 256,
  13. ACM_IN_FREELOOK = 512,
  14. }
  15. class ActionReciveData
  16. {
  17. ItemBase m_MainItem;
  18. ref ActionTarget m_Target;
  19. }
  20. class ActionOverrideData : Managed
  21. {
  22. int m_CommandUID = -1;
  23. int m_CommandUIDProne = -1;
  24. int m_StanceMask = -1;
  25. }
  26. class ActionData
  27. {
  28. void ActionData()
  29. {
  30. m_State = UA_NONE;
  31. }
  32. ref ActionBase m_Action;
  33. ItemBase m_MainItem;
  34. ActionBaseCB m_Callback;
  35. ref CABase m_ActionComponent;
  36. int m_State;
  37. ref ActionTarget m_Target;
  38. PlayerBase m_Player;
  39. int m_PossibleStanceMask;
  40. ref array<ref InventoryLocation> m_ReservedInventoryLocations; //used also for juncture
  41. int m_RefreshReservationTimer;
  42. int m_RefreshJunctureTimer;
  43. int m_DelayedAnimationEventID;
  44. bool m_WasExecuted;
  45. bool m_WasActionStarted;
  46. bool m_ReciveEndInput;
  47. }
  48. class ActionBase : ActionBase_Basic
  49. {
  50. //STATIC DATA
  51. protected int m_RefreshReservationTimerValue = 140;
  52. // Configurable action parameters
  53. protected string m_Sound; //sound played at the beggining of action
  54. protected string m_Text;
  55. protected bool m_LockTargetOnUse; //this parameter sets wheter player can perform actions on target while other player is already performing action on it. defaulted as true
  56. protected bool m_FullBody; //tells whether action is full body or additive
  57. protected int m_StanceMask;
  58. protected ref TStringArray m_Sounds; //User action sound is picked from this array randomly
  59. ref CCIBase m_ConditionItem; //Condition Component
  60. ref CCTBase m_ConditionTarget; //Condition Component
  61. protected ActionInput m_Input;
  62. protected int m_ActionID;
  63. protected int m_VariantID;
  64. int m_ConditionMask;
  65. protected ref ActionVariantManager m_VariantManager;
  66. //RUNTIME DATA
  67. protected ref Param1<string> m_MessageParam; //used for passing messages from server to client
  68. //protected ref Param2<int,int> m_MessagesParam;
  69. //SOFT SKILLS
  70. protected float m_SpecialtyWeight;
  71. //-----------------------------------------------------
  72. // Action events and methods
  73. //-----------------------------------------------------
  74. void ActionBase()
  75. {
  76. // definable
  77. m_StanceMask = DayZPlayerConstants.STANCEMASK_ERECT | DayZPlayerConstants.STANCEMASK_CROUCH | DayZPlayerConstants.STANCEMASK_PRONE;
  78. m_FullBody = false;
  79. m_Sound = "";
  80. m_Text = "default action text";
  81. m_LockTargetOnUse = HasTarget();
  82. // dont override
  83. m_MessageParam = new Param1<string>("");
  84. //m_MessagesParam = new Param2<int,int>(0,0);
  85. m_Sounds = new TStringArray;
  86. m_Input = null;
  87. m_ActionID = 0;
  88. InitConditionMask();
  89. }
  90. bool IsLockTargetOnUse()
  91. {
  92. return m_LockTargetOnUse;
  93. }
  94. void InitConditionMask()
  95. {
  96. m_ConditionMask = ActionConditionMask.ACM_NO_EXEPTION;
  97. if (CanBeUsedInVehicle())
  98. {
  99. m_ConditionMask |= ActionConditionMask.ACM_IN_VEHICLE;
  100. }
  101. if (CanBeUsedOnLadder())
  102. {
  103. m_ConditionMask |= ActionConditionMask.ACM_ON_LADDER;
  104. }
  105. if (CanBeUsedSwimming())
  106. {
  107. m_ConditionMask |= ActionConditionMask.ACM_SWIMMING;
  108. }
  109. if (CanBeUsedInRestrain())
  110. {
  111. m_ConditionMask |= ActionConditionMask.ACM_RESTRAIN;
  112. }
  113. if (CanBeUsedRaised())
  114. {
  115. m_ConditionMask |= ActionConditionMask.ACM_RAISED;
  116. }
  117. if (CanBeUsedOnBack())
  118. {
  119. m_ConditionMask |= ActionConditionMask.ACM_ON_BACK;
  120. }
  121. if (CanBeUsedThrowing())
  122. {
  123. m_ConditionMask |= ActionConditionMask.ACM_THROWING;
  124. }
  125. if (CanBeUsedLeaning())
  126. {
  127. m_ConditionMask |= ActionConditionMask.ACM_LEANING;
  128. }
  129. if (CanBeUsedWithBrokenLegs())
  130. {
  131. m_ConditionMask |= ActionConditionMask.ACM_BROKEN_LEGS;
  132. }
  133. if (CanBeUsedInFreelook())
  134. m_ConditionMask |= ActionConditionMask.ACM_IN_FREELOOK;
  135. }
  136. bool SetupAction(PlayerBase player, ActionTarget target, ItemBase item, out ActionData action_data, Param extra_data = NULL )
  137. {
  138. action_data = CreateActionData();
  139. action_data.m_Action = this;
  140. action_data.m_Player = player;
  141. action_data.m_Target = target;
  142. action_data.m_MainItem = item;
  143. action_data.m_PossibleStanceMask = GetStanceMask(player);
  144. action_data.m_ReservedInventoryLocations = new array<ref InventoryLocation>;
  145. action_data.m_RefreshReservationTimer = m_RefreshReservationTimerValue;
  146. action_data.m_WasExecuted = false;
  147. action_data.m_WasActionStarted = false;
  148. action_data.m_ReciveEndInput = false;
  149. ActionReciveData action_recive_data = player.GetActionManager().GetReciveData();
  150. if ( action_recive_data )
  151. {
  152. HandleReciveData(action_recive_data,action_data);
  153. if ( UseMainItem() && MainItemAlwaysInHands() )
  154. {
  155. if ( player.GetItemInHands() != action_data.m_MainItem )
  156. {
  157. return false;
  158. }
  159. }
  160. }
  161. if ( !Post_SetupAction( action_data ) )
  162. return false;
  163. if ( (!GetGame().IsDedicatedServer()) && !IsInstant() )
  164. {
  165. if (!InventoryReservation(action_data))
  166. {
  167. ClearInventoryReservationEx(action_data);
  168. return false;
  169. }
  170. if ( LogManager.IsActionLogEnable() )
  171. {
  172. for ( int i = 0; i < action_data.m_ReservedInventoryLocations.Count(); i++)
  173. {
  174. Debug.ActionLog( InventoryLocation.DumpToStringNullSafe( action_data.m_ReservedInventoryLocations[i] ), action_data.m_Action.ToString() , "n/a", "LockInventoryList", action_data.m_Player.ToString() );
  175. }
  176. }
  177. }
  178. return true;
  179. }
  180. bool Post_SetupAction( ActionData action_data )
  181. {
  182. return true;
  183. }
  184. void ActionCleanup( ActionData action_data )
  185. {}
  186. typename GetInputType()
  187. {
  188. return DefaultActionInput;
  189. }
  190. void SetInput( ActionInput ai)
  191. {
  192. m_Input = ai;
  193. }
  194. ActionData CreateActionData()
  195. {
  196. return new ActionData;
  197. }
  198. void CreateConditionComponents() //Instantiates components, called once from ActionManager on actions construction
  199. {
  200. m_ConditionItem = new CCIDummy;
  201. m_ConditionTarget = new CCTDummy;
  202. }
  203. Object GetDisplayInteractObject(PlayerBase player, ActionTarget target)
  204. {
  205. return null;
  206. }
  207. //! Action is performed on target, not with item itself, when set to true.
  208. //! * target will be synced to server
  209. //! * UI: floating widget will be displayed at target pos
  210. bool HasTarget()
  211. {
  212. return true;
  213. }
  214. //! For UI: hiding of progress bar
  215. bool HasProgress()
  216. {
  217. return true;
  218. }
  219. //Action isn't synchronize to server
  220. bool IsLocal()
  221. {
  222. return false;
  223. }
  224. //Action not using animation/callback action are executed instantly (OnStart)
  225. bool IsInstant()
  226. {
  227. return false;
  228. }
  229. //! not using plane object - it's using multiple proxies
  230. bool IsUsingProxies()
  231. {
  232. return false;
  233. }
  234. bool RemoveForceTargetAfterUse()
  235. {
  236. return true;
  237. }
  238. int GetActionCategory()
  239. {
  240. return AC_UNCATEGORIZED;
  241. }
  242. bool IsEat()
  243. {
  244. return false;
  245. }
  246. bool IsDrink()
  247. {
  248. return false;
  249. }
  250. bool IsShaveSelf()
  251. {
  252. return false;
  253. }
  254. string GetText() //text game displays in HUD hint
  255. {
  256. return m_Text;
  257. }
  258. bool CanBePerformedFromQuickbar()
  259. {
  260. return false;
  261. }
  262. bool CanBePerformedFromInventory()
  263. {
  264. return false;
  265. }
  266. bool CanBeSetFromInventory()
  267. {
  268. return !CanBePerformedFromInventory();
  269. }
  270. bool CanBeUsedInRestrain()
  271. {
  272. return false;
  273. }
  274. bool CanBeUsedInVehicle()
  275. {
  276. return false;
  277. }
  278. bool CanTargetBeInVehicle()
  279. {
  280. return false;
  281. }
  282. bool CanBeUsedOnBack()
  283. {
  284. return false;
  285. }
  286. bool CanBeUsedSwimming()
  287. {
  288. return false;
  289. }
  290. bool CanBeUsedOnLadder()
  291. {
  292. return false;
  293. }
  294. bool CanBeUsedRaised()
  295. {
  296. return false;
  297. }
  298. bool CanBeUsedThrowing()
  299. {
  300. return false;
  301. }
  302. bool CanBeUsedLeaning()
  303. {
  304. return true;
  305. }
  306. bool CanBeUsedWithBrokenLegs()
  307. {
  308. return true;
  309. }
  310. bool CanBeUsedInFreelook()
  311. {
  312. return true;
  313. }
  314. //! Is an action directly related to deployment/advanced placing
  315. bool IsDeploymentAction()
  316. {
  317. return false;
  318. }
  319. bool UseMainItem()
  320. {
  321. return true;
  322. }
  323. bool MainItemAlwaysInHands()
  324. {
  325. return true;
  326. }
  327. /**
  328. Action will display the content of ActionBase::GetTargetName next to action action name (ActionTargetsCursor::GetActionDesc).
  329. \returns true if allowed; otherwise false
  330. */
  331. bool DisplayTargetInActionText()
  332. {
  333. return false;
  334. }
  335. protected bool ActionConditionContinue(ActionData action_data) //condition for action
  336. {
  337. return ActionCondition(action_data.m_Player,action_data.m_Target,action_data.m_MainItem);
  338. }
  339. protected bool ActionCondition(PlayerBase player, ActionTarget target, ItemBase item) //condition for action
  340. {
  341. return true;
  342. }
  343. /**
  344. Used to set the name of action target displayed in UI in case ActionBase::DisplayTargetInActionText is true.
  345. \param player reference to player running action
  346. \param target actual target reference
  347. \returns name of the target
  348. */
  349. string GetTargetName(PlayerBase player, ActionTarget target)
  350. {
  351. return string.Empty;
  352. }
  353. void ApplyModifiers(ActionData action_data);
  354. int GetRefreshReservationTimerValue()
  355. {
  356. return m_RefreshReservationTimerValue;
  357. }
  358. void WriteToContext(ParamsWriteContext ctx, ActionData action_data)
  359. {
  360. int componentIndex = -1;
  361. int proxyBoneIdx = -1;
  362. vector cursorHitPos = vector.Zero;
  363. array<string> selectionNames = new array<string>();
  364. Object targetObject = null;
  365. Object targetParent = null;
  366. if (UseMainItem())
  367. {
  368. ctx.Write(action_data.m_MainItem);
  369. }
  370. if (HasTarget() && !IsUsingProxies())
  371. {
  372. // callback data
  373. targetObject = action_data.m_Target.GetObject();
  374. ctx.Write(targetObject);
  375. targetParent = action_data.m_Target.GetParent();
  376. ctx.Write(targetParent);
  377. componentIndex = action_data.m_Target.GetComponentIndex();
  378. ctx.Write(componentIndex);
  379. cursorHitPos = action_data.m_Target.GetCursorHitPos();
  380. ctx.Write(cursorHitPos);
  381. }
  382. else if( HasTarget() && IsUsingProxies() )
  383. {
  384. //! get proxy bone idx from parent and selection we are looking at
  385. //! ID is used for synchronisation to server where it's translated back to object
  386. Entity entParent = Entity.Cast(action_data.m_Target.GetParent());
  387. if (entParent)
  388. {
  389. action_data.m_Target.GetObject().GetActionComponentNameList(action_data.m_Target.GetComponentIndex(), selectionNames);
  390. for (int s = 0; s < selectionNames.Count(); s++)
  391. {
  392. proxyBoneIdx = entParent.GetBoneIndex(selectionNames[s]);
  393. if( proxyBoneIdx > -1 )
  394. {
  395. break;
  396. }
  397. }
  398. }
  399. ctx.Write(proxyBoneIdx);
  400. targetParent = action_data.m_Target.GetParent();
  401. ctx.Write(targetParent);
  402. componentIndex = action_data.m_Target.GetComponentIndex();
  403. ctx.Write(componentIndex);
  404. cursorHitPos = action_data.m_Target.GetCursorHitPos();
  405. ctx.Write(cursorHitPos);
  406. }
  407. }
  408. bool ReadFromContext(ParamsReadContext ctx, out ActionReciveData action_recive_data )
  409. {
  410. if ( !action_recive_data )
  411. {
  412. action_recive_data = new ActionReciveData;
  413. }
  414. Object actionTargetObject = null;
  415. Object actionTargetParent = null;
  416. int componentIndex = -1;
  417. int proxyBoneIdx = -1;
  418. vector cursorHitPos = vector.Zero;
  419. ItemBase mainItem = null;
  420. ref ActionTarget target;
  421. if ( UseMainItem() )
  422. {
  423. if ( !ctx.Read(mainItem) )
  424. return false;
  425. }
  426. if ( HasTarget() && !IsUsingProxies() )
  427. {
  428. if ( !ctx.Read(actionTargetObject) )
  429. return false;
  430. if ( !ctx.Read(actionTargetParent))
  431. return false;
  432. if ( !ctx.Read(componentIndex) )
  433. return false;
  434. if ( !ctx.Read(cursorHitPos) )
  435. return false;
  436. target = new ActionTarget(actionTargetObject, actionTargetParent, componentIndex, cursorHitPos, 0);
  437. action_recive_data.m_Target = target;
  438. }
  439. else if( HasTarget() && IsUsingProxies() )
  440. {
  441. if ( !ctx.Read(proxyBoneIdx) )
  442. return false;
  443. if ( !ctx.Read(actionTargetParent))
  444. return false;
  445. if ( !ctx.Read(componentIndex) )
  446. return false;
  447. if ( !ctx.Read(cursorHitPos) )
  448. return false;
  449. //! create target object from proxyBoneIdx synced from client
  450. if ( proxyBoneIdx > -1 )
  451. {
  452. Entity entParent = Entity.Cast(actionTargetParent);
  453. if (entParent)
  454. {
  455. actionTargetObject = entParent.GetBoneObject(proxyBoneIdx);
  456. }
  457. }
  458. else
  459. {
  460. return false;
  461. }
  462. target = new ActionTarget(actionTargetObject, actionTargetParent, componentIndex, cursorHitPos, 0);
  463. action_recive_data.m_Target = target;
  464. }
  465. action_recive_data.m_MainItem = mainItem;
  466. return true;
  467. }
  468. void HandleReciveData(ActionReciveData action_recive_data, ActionData action_data)
  469. {
  470. action_data.m_MainItem = action_recive_data.m_MainItem;
  471. if(HasTarget())
  472. {
  473. if (action_recive_data.m_Target)
  474. {
  475. action_data.m_Target = action_recive_data.m_Target;
  476. }
  477. else
  478. {
  479. Error("Action target not created.");
  480. action_data.m_Target = new ActionTarget(NULL, NULL, -1, vector.Zero, 0);
  481. }
  482. }
  483. }
  484. //----------------------------------------------------------------------------------------------
  485. // Core methods don't override unless you know what you are doing
  486. //----------------------------------------------------------------------------------------------
  487. // COMMANDS -----------------------------------------------------------------------
  488. protected int GetStanceMaskEx(PlayerBase player, ActionTarget target, ItemBase item)
  489. {
  490. return GetStanceMask(player);
  491. }
  492. protected int GetStanceMask(PlayerBase player)
  493. {
  494. if ( HasProneException() )
  495. {
  496. if ( player.IsPlayerInStance(DayZPlayerConstants.STANCEMASK_RAISEDERECT | DayZPlayerConstants.STANCEMASK_RAISEDCROUCH | DayZPlayerConstants.STANCEMASK_RAISEDPRONE))
  497. return -1;
  498. else if ( player.IsPlayerInStance(DayZPlayerConstants.STANCEMASK_CROUCH | DayZPlayerConstants.STANCEMASK_ERECT))
  499. return DayZPlayerConstants.STANCEMASK_CROUCH | DayZPlayerConstants.STANCEMASK_ERECT;
  500. else
  501. return DayZPlayerConstants.STANCEMASK_PRONE;
  502. }
  503. return m_StanceMask;
  504. }
  505. protected int GetClosestPossibleStance(PlayerBase player, ActionTarget target, ItemBase item)
  506. {
  507. int stanceMask = GetStanceMaskEx(player, target, item);
  508. if (player.IsPlayerInStance(DayZPlayerConstants.STANCEMASK_ERECT))
  509. {
  510. if (stanceMask & DayZPlayerConstants.STANCEMASK_ERECT)
  511. return DayZPlayerConstants.STANCEMASK_ERECT;
  512. else if (stanceMask & DayZPlayerConstants.STANCEMASK_RAISEDERECT)
  513. return DayZPlayerConstants.STANCEMASK_RAISEDERECT;
  514. else if (stanceMask & DayZPlayerConstants.STANCEMASK_CROUCH)
  515. return DayZPlayerConstants.STANCEMASK_CROUCH;
  516. else if (stanceMask & DayZPlayerConstants.STANCEMASK_RAISEDCROUCH)
  517. return DayZPlayerConstants.STANCEMASK_RAISEDCROUCH;
  518. else if (stanceMask & DayZPlayerConstants.STANCEMASK_PRONE)
  519. return DayZPlayerConstants.STANCEMASK_PRONE;
  520. else if (stanceMask & DayZPlayerConstants.STANCEMASK_RAISEDPRONE)
  521. return DayZPlayerConstants.STANCEMASK_RAISEDPRONE;
  522. }
  523. if (player.IsPlayerInStance(DayZPlayerConstants.STANCEMASK_RAISEDERECT))
  524. {
  525. if (stanceMask & DayZPlayerConstants.STANCEMASK_RAISEDERECT)
  526. return DayZPlayerConstants.STANCEMASK_RAISEDERECT;
  527. else if (stanceMask & DayZPlayerConstants.STANCEMASK_ERECT)
  528. return DayZPlayerConstants.STANCEMASK_ERECT;
  529. else if (stanceMask & DayZPlayerConstants.STANCEMASK_CROUCH)
  530. return DayZPlayerConstants.STANCEMASK_CROUCH;
  531. else if (stanceMask & DayZPlayerConstants.STANCEMASK_RAISEDCROUCH)
  532. return DayZPlayerConstants.STANCEMASK_RAISEDCROUCH;
  533. else if (stanceMask & DayZPlayerConstants.STANCEMASK_PRONE)
  534. return DayZPlayerConstants.STANCEMASK_PRONE;
  535. else if (stanceMask & DayZPlayerConstants.STANCEMASK_RAISEDPRONE)
  536. return DayZPlayerConstants.STANCEMASK_RAISEDPRONE;
  537. }
  538. if (player.IsPlayerInStance(DayZPlayerConstants.STANCEMASK_CROUCH))
  539. {
  540. if (stanceMask & DayZPlayerConstants.STANCEMASK_CROUCH)
  541. return DayZPlayerConstants.STANCEMASK_CROUCH;
  542. else if (stanceMask & DayZPlayerConstants.STANCEMASK_RAISEDCROUCH)
  543. return DayZPlayerConstants.STANCEMASK_RAISEDCROUCH;
  544. else if (stanceMask & DayZPlayerConstants.STANCEMASK_ERECT)
  545. return DayZPlayerConstants.STANCEMASK_ERECT;
  546. else if (stanceMask & DayZPlayerConstants.STANCEMASK_RAISEDERECT)
  547. return DayZPlayerConstants.STANCEMASK_RAISEDERECT;
  548. else if (stanceMask & DayZPlayerConstants.STANCEMASK_PRONE)
  549. return DayZPlayerConstants.STANCEMASK_PRONE;
  550. else if (stanceMask & DayZPlayerConstants.STANCEMASK_RAISEDPRONE)
  551. return DayZPlayerConstants.STANCEMASK_RAISEDPRONE;
  552. }
  553. if (player.IsPlayerInStance(DayZPlayerConstants.STANCEMASK_RAISEDCROUCH))
  554. {
  555. if (stanceMask & DayZPlayerConstants.STANCEMASK_RAISEDCROUCH)
  556. return DayZPlayerConstants.STANCEMASK_RAISEDCROUCH;
  557. else if (stanceMask & DayZPlayerConstants.STANCEMASK_CROUCH)
  558. return DayZPlayerConstants.STANCEMASK_CROUCH;
  559. else if (stanceMask & DayZPlayerConstants.STANCEMASK_ERECT)
  560. return DayZPlayerConstants.STANCEMASK_ERECT;
  561. else if (stanceMask & DayZPlayerConstants.STANCEMASK_RAISEDERECT)
  562. return DayZPlayerConstants.STANCEMASK_RAISEDERECT;
  563. else if (stanceMask & DayZPlayerConstants.STANCEMASK_PRONE)
  564. return DayZPlayerConstants.STANCEMASK_PRONE;
  565. else if (stanceMask & DayZPlayerConstants.STANCEMASK_RAISEDPRONE)
  566. return DayZPlayerConstants.STANCEMASK_RAISEDPRONE;
  567. }
  568. if (player.IsPlayerInStance(DayZPlayerConstants.STANCEMASK_PRONE))
  569. {
  570. if (stanceMask & DayZPlayerConstants.STANCEMASK_PRONE)
  571. return DayZPlayerConstants.STANCEMASK_PRONE;
  572. else if (stanceMask & DayZPlayerConstants.STANCEMASK_RAISEDPRONE)
  573. return DayZPlayerConstants.STANCEMASK_RAISEDPRONE;
  574. else if (stanceMask & DayZPlayerConstants.STANCEMASK_RAISEDCROUCH)
  575. return DayZPlayerConstants.STANCEMASK_RAISEDCROUCH;
  576. else if (stanceMask & DayZPlayerConstants.STANCEMASK_CROUCH)
  577. return DayZPlayerConstants.STANCEMASK_CROUCH;
  578. else if (stanceMask & DayZPlayerConstants.STANCEMASK_ERECT)
  579. return DayZPlayerConstants.STANCEMASK_ERECT;
  580. else if (stanceMask & DayZPlayerConstants.STANCEMASK_RAISEDERECT)
  581. return DayZPlayerConstants.STANCEMASK_RAISEDERECT;
  582. }
  583. if (player.IsPlayerInStance(DayZPlayerConstants.STANCEMASK_RAISEDPRONE))
  584. {
  585. if (stanceMask & DayZPlayerConstants.STANCEMASK_RAISEDPRONE)
  586. return DayZPlayerConstants.STANCEMASK_RAISEDPRONE;
  587. else if (stanceMask & DayZPlayerConstants.STANCEMASK_PRONE)
  588. return DayZPlayerConstants.STANCEMASK_PRONE;
  589. else if (stanceMask & DayZPlayerConstants.STANCEMASK_RAISEDCROUCH)
  590. return DayZPlayerConstants.STANCEMASK_RAISEDCROUCH;
  591. else if (stanceMask & DayZPlayerConstants.STANCEMASK_CROUCH)
  592. return DayZPlayerConstants.STANCEMASK_CROUCH;
  593. else if (stanceMask & DayZPlayerConstants.STANCEMASK_ERECT)
  594. return DayZPlayerConstants.STANCEMASK_ERECT;
  595. else if (stanceMask & DayZPlayerConstants.STANCEMASK_RAISEDERECT)
  596. return DayZPlayerConstants.STANCEMASK_RAISEDERECT;
  597. }
  598. return -1;
  599. }
  600. protected bool IsFullBodyEx(PlayerBase player, ActionTarget target, ItemBase item)
  601. {
  602. return IsFullBody(player);
  603. }
  604. bool IsFullBody(PlayerBase player)
  605. {
  606. if ( HasProneException() )
  607. {
  608. return !( player.IsPlayerInStance(DayZPlayerConstants.STANCEMASK_CROUCH | DayZPlayerConstants.STANCEMASK_ERECT) );
  609. }
  610. return m_FullBody;
  611. }
  612. // if it is set to true if action have special fullbody animation for prone and additive for crouch and erect
  613. protected bool HasProneException()
  614. {
  615. return false;
  616. }
  617. // ACTION LOGIC -------------------------------------------------------------------
  618. // called from actionmanager.c
  619. void Start( ActionData action_data ) //Setup on start of action
  620. {
  621. action_data.m_State = UA_START;
  622. if ( LogManager.IsActionLogEnable() )
  623. {
  624. Debug.ActionLog("Time stamp: " + action_data.m_Player.GetSimulationTimeStamp(), this.ToString() , "n/a", "OnStart", action_data.m_Player.ToString() );
  625. }
  626. OnStart(action_data);
  627. if ( GetGame().IsServer() )
  628. {
  629. OnStartServer(action_data);
  630. string soundCat = GetSoundCategory(action_data);
  631. if (soundCat)
  632. action_data.m_Player.SetSoundCategoryHash(soundCat.Hash());
  633. }
  634. else
  635. {
  636. OnStartClient(action_data);
  637. }
  638. InformPlayers(action_data.m_Player,action_data.m_Target,UA_START);
  639. }
  640. void End( ActionData action_data )
  641. {
  642. if ( action_data.m_Player )
  643. {
  644. OnEnd(action_data);
  645. if ( GetGame().IsServer() )
  646. {
  647. OnEndServer(action_data);
  648. }
  649. else
  650. {
  651. OnEndClient(action_data);
  652. }
  653. action_data.m_Player.GetActionManager().OnActionEnd();
  654. }
  655. }
  656. void Interrupt(ActionData action_data)
  657. {
  658. End(action_data);
  659. }
  660. void OnEndInput(ActionData action_data)
  661. {}
  662. void EndInput(ActionData action_data)
  663. {
  664. action_data.m_ReciveEndInput = true;
  665. OnEndInput(action_data);
  666. }
  667. void OnEndRequest(ActionData action_data)
  668. {}
  669. void EndRequest(ActionData action_data)
  670. {
  671. OnEndRequest(action_data);
  672. }
  673. bool CanReceiveAction(ActionTarget target)
  674. {
  675. bool result = true;
  676. PlayerBase target_player = PlayerBase.Cast(target.GetObject());
  677. if (target_player)
  678. {
  679. result = !target_player.IsJumpInProgress();
  680. result = result && !(target_player.GetCommand_Ladder() || (target_player.GetCommand_Vehicle() && !CanTargetBeInVehicle()) || target_player.GetCommand_Swim());
  681. }
  682. return result;
  683. }
  684. static int ComputeConditionMask( PlayerBase player, ActionTarget target, ItemBase item )
  685. {
  686. int mask = 0;
  687. if ( player.GetCommand_Vehicle() )
  688. {
  689. mask |= ActionConditionMask.ACM_IN_VEHICLE;
  690. }
  691. if ( player.GetCommand_Ladder() )
  692. {
  693. mask |= ActionConditionMask.ACM_ON_LADDER;
  694. }
  695. if ( player.IsRestrained() )
  696. {
  697. mask |= ActionConditionMask.ACM_RESTRAIN;
  698. }
  699. if ( player.GetCommand_Swim() )
  700. {
  701. mask |= ActionConditionMask.ACM_SWIMMING;
  702. }
  703. if ( player.IsRaised() )
  704. {
  705. mask |= ActionConditionMask.ACM_RAISED;
  706. }
  707. if ( player.GetCommand_Move() && player.GetCommand_Move().IsOnBack() )
  708. {
  709. mask |= ActionConditionMask.ACM_ON_BACK;
  710. }
  711. if ( player.GetThrowing().IsThrowingModeEnabled())
  712. {
  713. mask |= ActionConditionMask.ACM_THROWING;
  714. }
  715. if (player.IsLeaning())
  716. {
  717. mask |= ActionConditionMask.ACM_LEANING;
  718. }
  719. if (player.GetBrokenLegs() == eBrokenLegs.BROKEN_LEGS)
  720. {
  721. mask |= ActionConditionMask.ACM_BROKEN_LEGS;
  722. }
  723. if (player.GetInputController() && player.GetInputController().CameraIsFreeLook())
  724. mask |= ActionConditionMask.ACM_IN_FREELOOK;
  725. return mask;
  726. }
  727. bool Can( PlayerBase player, ActionTarget target, ItemBase item, int condition_mask )
  728. {
  729. if (( (condition_mask & m_ConditionMask) != condition_mask ) || ( !IsFullBodyEx(player, target, item) && !player.IsPlayerInStance(GetStanceMaskEx(player, target, item)) ) || player.IsRolling())
  730. return false;
  731. if (HasTarget())
  732. {
  733. if (!FirearmActionBase.Cast(this))
  734. {
  735. EntityAI entity = EntityAI.Cast(target.GetObject());
  736. if (entity && !target.GetObject().IsMan())
  737. {
  738. Man man = entity.GetHierarchyRootPlayer();
  739. if (man && man != player)
  740. return false;
  741. }
  742. }
  743. if (m_ConditionTarget && !m_ConditionTarget.Can(player, target))
  744. return false;
  745. }
  746. if (m_ConditionItem && !m_ConditionItem.Can(player, item))
  747. return false;
  748. if (!ActionCondition(player, target, item))
  749. return false;
  750. if (IsFullBodyEx(player, target, item))
  751. {
  752. int nextStance = GetClosestPossibleStance(player, target, item);
  753. int stanceIdx = DayZPlayerUtils.ConvertStanceMaskToStanceIdx(nextStance);
  754. if (stanceIdx != -1 && !DayZPlayerUtils.PlayerCanChangeStance(player, stanceIdx ))
  755. return false;
  756. }
  757. return true;
  758. }
  759. bool Can(PlayerBase player, ActionTarget target, ItemBase item)
  760. {
  761. int condition_mask = ComputeConditionMask(player, target, item);
  762. return Can( player, target, item, condition_mask);
  763. }
  764. protected bool CanContinue( ActionData action_data )
  765. {
  766. if (!action_data.m_Player.IsPlayerInStance(action_data.m_PossibleStanceMask) || !m_ConditionItem || !m_ConditionItem.CanContinue(action_data.m_Player,action_data.m_MainItem) || !m_ConditionTarget || !m_ConditionTarget.CanContinue(action_data.m_Player,action_data.m_Target))
  767. return false;
  768. return ActionConditionContinue(action_data);
  769. }
  770. bool HasVariants()
  771. {
  772. return m_VariantManager != null;
  773. }
  774. int GetVariantsCount()
  775. {
  776. if (m_VariantManager)
  777. return m_VariantManager.GetActionsCount();
  778. return 0;
  779. }
  780. int GetVariants(out array<ref ActionBase> variants)
  781. {
  782. if (m_VariantManager)
  783. return m_VariantManager.GetActions(variants);
  784. return 0;
  785. }
  786. void SetVariantID(int ID)
  787. {
  788. m_VariantID = ID;
  789. }
  790. int GetVariantID()
  791. {
  792. return m_VariantID;
  793. }
  794. void UpdateVariants(Object item, Object target, int componet_index)
  795. {
  796. if ( m_VariantManager )
  797. {
  798. m_VariantManager.UpdateVariants(item, target, componet_index);
  799. }
  800. }
  801. ActionVariantManager GetVariantManager()
  802. {
  803. if ( !m_VariantManager )
  804. m_VariantManager = new ActionVariantManager(this.Type());
  805. return m_VariantManager;
  806. }
  807. // Called when item changes location during performed action
  808. void OnItemLocationChanged(ItemBase item)
  809. {}
  810. // call only on client side for lock inventory before action
  811. // return if has successfuly reserved inventory
  812. bool InventoryReservation(ActionData action_data)
  813. {
  814. if ((IsLocal() || !UseAcknowledgment()) && IsInstant())
  815. return true;
  816. //action_data.m_ReservedInventoryLocations = new array<ref InventoryLocation>;
  817. bool success = true;
  818. InventoryLocation targetInventoryLocation = NULL;
  819. InventoryLocation handInventoryLocation = NULL;
  820. // lock target if it has target
  821. if (HasTarget())
  822. {
  823. ItemBase targetItem;
  824. if ( ItemBase.CastTo(targetItem,action_data.m_Target.GetObject()) )
  825. {
  826. targetInventoryLocation = new InventoryLocation;
  827. targetItem.GetInventory().GetCurrentInventoryLocation(targetInventoryLocation);
  828. if ( action_data.m_Player.GetInventory().HasInventoryReservation( targetItem, targetInventoryLocation) )
  829. {
  830. success = false;
  831. }
  832. else
  833. {
  834. action_data.m_Player.GetInventory().AddInventoryReservationEx( targetItem, targetInventoryLocation, GameInventory.c_InventoryReservationTimeoutMS);
  835. }
  836. }
  837. }
  838. handInventoryLocation = new InventoryLocation;
  839. handInventoryLocation.SetHands(action_data.m_Player,action_data.m_Player.GetItemInHands());
  840. if (action_data.m_Player.GetInventory().HasInventoryReservation( action_data.m_Player.GetItemInHands(), handInventoryLocation))
  841. {
  842. if (HasTarget())
  843. {
  844. action_data.m_Player.GetInventory().ClearInventoryReservation(targetItem, targetInventoryLocation);
  845. }
  846. success = false;
  847. }
  848. else
  849. {
  850. action_data.m_Player.GetInventory().AddInventoryReservationEx( action_data.m_Player.GetItemInHands(), handInventoryLocation, GameInventory.c_InventoryReservationTimeoutMS);
  851. }
  852. if (success)
  853. {
  854. if (targetInventoryLocation)
  855. action_data.m_ReservedInventoryLocations.Insert(targetInventoryLocation);
  856. if (handInventoryLocation)
  857. action_data.m_ReservedInventoryLocations.Insert(handInventoryLocation);
  858. }
  859. return success;
  860. }
  861. void ClearInventoryReservationEx(ActionData action_data)
  862. {
  863. if (action_data.m_ReservedInventoryLocations)
  864. {
  865. InventoryLocation il;
  866. for ( int i = 0; i < action_data.m_ReservedInventoryLocations.Count(); i++)
  867. {
  868. il = action_data.m_ReservedInventoryLocations.Get(i);
  869. action_data.m_Player.GetInventory().ClearInventoryReservationEx( il.GetItem() , il );
  870. }
  871. action_data.m_ReservedInventoryLocations.Clear();
  872. }
  873. }
  874. void RefreshReservations(ActionData action_data)
  875. {
  876. if (action_data.m_ReservedInventoryLocations)
  877. {
  878. InventoryLocation il;
  879. for (int i = 0; i < action_data.m_ReservedInventoryLocations.Count(); i++)
  880. {
  881. il = action_data.m_ReservedInventoryLocations.Get(i);
  882. EntityAI entity = il.GetItem();
  883. action_data.m_Player.GetInventory().ExtendInventoryReservationEx(il.GetItem() , il, 10000);
  884. }
  885. }
  886. }
  887. bool AddActionJuncture(ActionData action_data)
  888. {
  889. bool accepted = true;
  890. if (HasTarget())
  891. {
  892. EntityAI targetEntity;
  893. if (EntityAI.CastTo(targetEntity,action_data.m_Target.GetObject()))
  894. {
  895. if (IsLockTargetOnUse())
  896. {
  897. InventoryLocation targetIl = new InventoryLocation();
  898. targetEntity.GetInventory().GetCurrentInventoryLocation(targetIl);
  899. //Lock target
  900. if (!GetGame().AddInventoryJunctureEx(action_data.m_Player, targetEntity, targetIl, true, 10000))
  901. {
  902. accepted = false;
  903. }
  904. else
  905. {
  906. action_data.m_ReservedInventoryLocations.Insert(targetIl);
  907. }
  908. }
  909. }
  910. }
  911. return accepted;
  912. }
  913. void ClearActionJuncture(ActionData action_data)
  914. {
  915. if (action_data.m_Player.GetInstanceType() == DayZPlayerInstanceType.INSTANCETYPE_SERVER)
  916. {
  917. if (action_data.m_ReservedInventoryLocations)
  918. {
  919. InventoryLocation il;
  920. for ( int i = 0; i < action_data.m_ReservedInventoryLocations.Count(); i++)
  921. {
  922. il = action_data.m_ReservedInventoryLocations.Get(i);
  923. EntityAI entity = il.GetItem();
  924. if (entity)
  925. {
  926. GetGame().ClearJunctureEx(action_data.m_Player, entity);
  927. }
  928. }
  929. action_data.m_ReservedInventoryLocations.Clear();
  930. }
  931. }
  932. }
  933. void RefreshActionJuncture(ActionData action_data)
  934. {
  935. if (action_data.m_ReservedInventoryLocations)
  936. {
  937. InventoryLocation il;
  938. for (int i = 0; i < action_data.m_ReservedInventoryLocations.Count(); i++)
  939. {
  940. il = action_data.m_ReservedInventoryLocations.Get(i);
  941. EntityAI entity = il.GetItem();
  942. if (entity)
  943. {
  944. GetGame().ExtendActionJuncture(action_data.m_Player, entity, 10000);
  945. }
  946. }
  947. }
  948. }
  949. // action need first have permission from server before can start
  950. bool UseAcknowledgment()
  951. {
  952. return true;
  953. }
  954. //! DEPRECATED delivers message ids to clients based on given context
  955. protected void InformPlayers( PlayerBase player, ActionTarget target, int state );
  956. void SendMessageToClient( Object reciever, string message ) //sends given string to client, don't use if not nescessary
  957. {
  958. PlayerBase man;
  959. if (GetGame().IsServer() && Class.CastTo(man, reciever) && m_MessageParam && reciever.IsAlive() && message != "")
  960. {
  961. m_MessageParam.param1 = message;
  962. GetGame().RPCSingleParam(man, ERPCs.RPC_USER_ACTION_MESSAGE, m_MessageParam, true, man.GetIdentity());
  963. }
  964. }
  965. // ActionCondition Rules
  966. // ------------------------------------------------------
  967. protected bool IsDamageDestroyed(ActionTarget target)
  968. {
  969. return target.GetObject() && target.GetObject().IsDamageDestroyed();
  970. }
  971. protected bool IsBuilding(ActionTarget target)
  972. {
  973. return target.GetObject() && target.GetObject().IsBuilding();
  974. }
  975. protected bool IsTransport(ActionTarget target)
  976. {
  977. return target.GetObject() && target.GetObject().IsTransport();
  978. }
  979. protected bool IsInReach(PlayerBase player, ActionTarget target, float maxDistance = 1.0)
  980. {
  981. Object obj = target.GetObject();
  982. if (!obj)
  983. return false;
  984. float distanceRoot, distanceHead;
  985. vector modelPos, worldPos, playerHeadPos;
  986. // we're using sq distance in comparison
  987. maxDistance = maxDistance * maxDistance;
  988. // get position of Head bone
  989. MiscGameplayFunctions.GetHeadBonePos(player, playerHeadPos);
  990. array<string> componentNames = new array<string>();
  991. obj.GetActionComponentNameList(target.GetComponentIndex(), componentNames);
  992. foreach (string componentName : componentNames)
  993. {
  994. if (componentName.Contains("doorstwin"))
  995. continue;
  996. modelPos = obj.GetSelectionPositionMS(componentName);
  997. worldPos = obj.ModelToWorld(modelPos);
  998. break;
  999. }
  1000. distanceRoot = vector.DistanceSq(worldPos, player.GetPosition());
  1001. distanceHead = vector.DistanceSq(worldPos, playerHeadPos);
  1002. return distanceRoot <= maxDistance || distanceHead <= maxDistance;
  1003. }
  1004. // ------------------------------------------------------
  1005. // SOUNDS ------------------------------------------------------
  1006. SoundOnVehicle PlayActionSound( PlayerBase player )
  1007. {
  1008. if ( GetGame().IsServer() && player )
  1009. {
  1010. if ( m_Sound != "" )
  1011. {
  1012. return GetGame().CreateSoundOnObject(player, m_Sound, 6, false);
  1013. }
  1014. else if ( m_Sounds && m_Sounds.Count() > 0 )
  1015. {
  1016. int rand_num = Math.RandomInt(0, m_Sounds.Count());
  1017. return GetGame().CreateSoundOnObject(player, m_Sounds.Get(rand_num), 6, false);
  1018. }
  1019. }
  1020. return NULL;
  1021. }
  1022. void OnActionInfoUpdate( PlayerBase player, ActionTarget target, ItemBase item )
  1023. {
  1024. }
  1025. //sound category matches with a soundtable category in config, selects correct soundset
  1026. string GetSoundCategory(ActionData action_data)
  1027. {
  1028. return "";
  1029. }
  1030. // EVENTS ------------------------------------------------
  1031. void OnUpdate(ActionData action_data)
  1032. {}
  1033. void OnUpdateClient(ActionData action_data)
  1034. {
  1035. if ( !GetGame().IsDedicatedServer() )
  1036. {
  1037. if (action_data.m_RefreshReservationTimer > 0)
  1038. {
  1039. action_data.m_RefreshReservationTimer--;
  1040. }
  1041. else
  1042. {
  1043. action_data.m_RefreshReservationTimer = m_RefreshReservationTimerValue;
  1044. RefreshReservations(action_data);
  1045. }
  1046. }
  1047. }
  1048. void OnUpdateServer(ActionData action_data)
  1049. {
  1050. if (action_data.m_RefreshJunctureTimer > 0)
  1051. {
  1052. action_data.m_RefreshJunctureTimer--;
  1053. }
  1054. else
  1055. {
  1056. action_data.m_RefreshJunctureTimer = m_RefreshReservationTimerValue;
  1057. RefreshActionJuncture(action_data);
  1058. }
  1059. }
  1060. void OnStart(ActionData action_data)
  1061. {
  1062. if (action_data.m_Player != NULL && action_data.m_Player.IsPlacingLocal() && !IsDeploymentAction())
  1063. action_data.m_Player.PlacingCancelLocal();
  1064. }
  1065. void OnStartClient(ActionData action_data)
  1066. {}
  1067. void OnStartServer(ActionData action_data)
  1068. {
  1069. }
  1070. void OnEnd(ActionData action_data)
  1071. {
  1072. }
  1073. void OnEndClient(ActionData action_data)
  1074. {}
  1075. void OnEndServer(ActionData action_data)
  1076. {
  1077. }
  1078. // SOFT SKILLS ------------------------------------------------
  1079. float GetSpecialtyWeight()
  1080. {
  1081. if(m_SpecialtyWeight == 0)
  1082. {
  1083. #ifdef DEVELOPER
  1084. //Print("UserAction does not use SoftSkills");
  1085. #endif
  1086. }
  1087. return m_SpecialtyWeight;
  1088. }
  1089. int GetState( ActionData action_data )
  1090. {
  1091. return action_data.m_State;
  1092. }
  1093. float GetProgress( ActionData action_data )
  1094. {
  1095. return -1;
  1096. }
  1097. float GetProgressWidgetMultiplier( ActionData action_data ) // override when action length is not supposed to be the same length as progress widget
  1098. {
  1099. return 1;
  1100. }
  1101. ActionInput GetInput()
  1102. {
  1103. return m_Input;
  1104. }
  1105. void SetID(int actionId)
  1106. {
  1107. m_ActionID = actionId;
  1108. }
  1109. int GetID()
  1110. {
  1111. return m_ActionID;
  1112. }
  1113. string GetAdminLogMessage(ActionData action_data)
  1114. {
  1115. return "";
  1116. }
  1117. };