actionbase.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221
  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 bool IsFullBodyEx(PlayerBase player, ActionTarget target, ItemBase item)
  506. {
  507. return IsFullBody(player);
  508. }
  509. bool IsFullBody(PlayerBase player)
  510. {
  511. if ( HasProneException() )
  512. {
  513. return !( player.IsPlayerInStance(DayZPlayerConstants.STANCEMASK_CROUCH | DayZPlayerConstants.STANCEMASK_ERECT) );
  514. }
  515. return m_FullBody;
  516. }
  517. // if it is set to true if action have special fullbody animation for prone and additive for crouch and erect
  518. protected bool HasProneException()
  519. {
  520. return false;
  521. }
  522. // ACTION LOGIC -------------------------------------------------------------------
  523. // called from actionmanager.c
  524. void Start( ActionData action_data ) //Setup on start of action
  525. {
  526. action_data.m_State = UA_START;
  527. if ( LogManager.IsActionLogEnable() )
  528. {
  529. Debug.ActionLog("Time stamp: " + action_data.m_Player.GetSimulationTimeStamp(), this.ToString() , "n/a", "OnStart", action_data.m_Player.ToString() );
  530. }
  531. OnStart(action_data);
  532. if ( GetGame().IsServer() )
  533. {
  534. OnStartServer(action_data);
  535. string soundCat = GetSoundCategory(action_data);
  536. if (soundCat)
  537. action_data.m_Player.SetSoundCategoryHash(soundCat.Hash());
  538. }
  539. else
  540. {
  541. OnStartClient(action_data);
  542. }
  543. InformPlayers(action_data.m_Player,action_data.m_Target,UA_START);
  544. }
  545. void End( ActionData action_data )
  546. {
  547. if ( action_data.m_Player )
  548. {
  549. OnEnd(action_data);
  550. if ( GetGame().IsServer() )
  551. {
  552. OnEndServer(action_data);
  553. }
  554. else
  555. {
  556. OnEndClient(action_data);
  557. }
  558. action_data.m_Player.GetActionManager().OnActionEnd();
  559. }
  560. }
  561. void Interrupt(ActionData action_data)
  562. {
  563. End(action_data);
  564. }
  565. void OnEndInput(ActionData action_data)
  566. {}
  567. void EndInput(ActionData action_data)
  568. {
  569. action_data.m_ReciveEndInput = true;
  570. OnEndInput(action_data);
  571. }
  572. void OnEndRequest(ActionData action_data)
  573. {}
  574. void EndRequest(ActionData action_data)
  575. {
  576. OnEndRequest(action_data);
  577. }
  578. bool CanReceiveAction(ActionTarget target)
  579. {
  580. bool result = true;
  581. PlayerBase target_player = PlayerBase.Cast(target.GetObject());
  582. if (target_player)
  583. {
  584. result = !target_player.IsJumpInProgress();
  585. result = result && !(target_player.GetCommand_Ladder() || (target_player.GetCommand_Vehicle() && !CanTargetBeInVehicle()) || target_player.GetCommand_Swim());
  586. }
  587. return result;
  588. }
  589. static int ComputeConditionMask( PlayerBase player, ActionTarget target, ItemBase item )
  590. {
  591. int mask = 0;
  592. if ( player.GetCommand_Vehicle() )
  593. {
  594. mask |= ActionConditionMask.ACM_IN_VEHICLE;
  595. }
  596. if ( player.GetCommand_Ladder() )
  597. {
  598. mask |= ActionConditionMask.ACM_ON_LADDER;
  599. }
  600. if ( player.IsRestrained() )
  601. {
  602. mask |= ActionConditionMask.ACM_RESTRAIN;
  603. }
  604. if ( player.GetCommand_Swim() )
  605. {
  606. mask |= ActionConditionMask.ACM_SWIMMING;
  607. }
  608. if ( player.IsRaised() )
  609. {
  610. mask |= ActionConditionMask.ACM_RAISED;
  611. }
  612. if ( player.GetCommand_Move() && player.GetCommand_Move().IsOnBack() )
  613. {
  614. mask |= ActionConditionMask.ACM_ON_BACK;
  615. }
  616. if ( player.GetThrowing().IsThrowingModeEnabled())
  617. {
  618. mask |= ActionConditionMask.ACM_THROWING;
  619. }
  620. if (player.IsLeaning())
  621. {
  622. mask |= ActionConditionMask.ACM_LEANING;
  623. }
  624. if (player.GetBrokenLegs() == eBrokenLegs.BROKEN_LEGS)
  625. {
  626. mask |= ActionConditionMask.ACM_BROKEN_LEGS;
  627. }
  628. if (player.GetInputController() && player.GetInputController().CameraIsFreeLook())
  629. mask |= ActionConditionMask.ACM_IN_FREELOOK;
  630. return mask;
  631. }
  632. bool Can( PlayerBase player, ActionTarget target, ItemBase item, int condition_mask )
  633. {
  634. if (( (condition_mask & m_ConditionMask) != condition_mask ) || ( !IsFullBodyEx(player, target, item) && !player.IsPlayerInStance(GetStanceMaskEx(player, target, item)) ) || player.IsRolling())
  635. return false;
  636. if (HasTarget())
  637. {
  638. if (!FirearmActionBase.Cast(this))
  639. {
  640. EntityAI entity = EntityAI.Cast(target.GetObject());
  641. if (entity && !target.GetObject().IsMan())
  642. {
  643. Man man = entity.GetHierarchyRootPlayer();
  644. if (man && man != player)
  645. return false;
  646. }
  647. }
  648. if (m_ConditionTarget && !m_ConditionTarget.Can(player, target))
  649. return false;
  650. }
  651. if (m_ConditionItem && !m_ConditionItem.Can(player, item))
  652. return false;
  653. if (!ActionCondition(player, target, item))
  654. return false;
  655. if (IsFullBodyEx(player, target, item))
  656. {
  657. int stanceIdx = DayZPlayerUtils.ConvertStanceMaskToStanceIdx(GetStanceMaskEx(player, target, item));
  658. if (stanceIdx != -1 && !DayZPlayerUtils.PlayerCanChangeStance(player, stanceIdx ))
  659. return false;
  660. }
  661. return true;
  662. }
  663. bool Can(PlayerBase player, ActionTarget target, ItemBase item)
  664. {
  665. int condition_mask = ComputeConditionMask(player, target, item);
  666. return Can( player, target, item, condition_mask);
  667. }
  668. protected bool CanContinue( ActionData action_data )
  669. {
  670. 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))
  671. return false;
  672. return ActionConditionContinue(action_data);
  673. }
  674. bool HasVariants()
  675. {
  676. return m_VariantManager != null;
  677. }
  678. int GetVariantsCount()
  679. {
  680. if (m_VariantManager)
  681. return m_VariantManager.GetActionsCount();
  682. return 0;
  683. }
  684. int GetVariants(out array<ref ActionBase> variants)
  685. {
  686. if (m_VariantManager)
  687. return m_VariantManager.GetActions(variants);
  688. return 0;
  689. }
  690. void SetVariantID(int ID)
  691. {
  692. m_VariantID = ID;
  693. }
  694. int GetVariantID()
  695. {
  696. return m_VariantID;
  697. }
  698. void UpdateVariants(Object item, Object target, int componet_index)
  699. {
  700. if ( m_VariantManager )
  701. {
  702. m_VariantManager.UpdateVariants(item, target, componet_index);
  703. }
  704. }
  705. ActionVariantManager GetVariantManager()
  706. {
  707. if ( !m_VariantManager )
  708. m_VariantManager = new ActionVariantManager(this.Type());
  709. return m_VariantManager;
  710. }
  711. // Called when item changes location during performed action
  712. void OnItemLocationChanged(ItemBase item)
  713. {}
  714. // call only on client side for lock inventory before action
  715. // return if has successfuly reserved inventory
  716. bool InventoryReservation(ActionData action_data)
  717. {
  718. if ((IsLocal() || !UseAcknowledgment()) && IsInstant())
  719. return true;
  720. //action_data.m_ReservedInventoryLocations = new array<ref InventoryLocation>;
  721. bool success = true;
  722. InventoryLocation targetInventoryLocation = NULL;
  723. InventoryLocation handInventoryLocation = NULL;
  724. // lock target if it has target
  725. if (HasTarget())
  726. {
  727. ItemBase targetItem;
  728. if ( ItemBase.CastTo(targetItem,action_data.m_Target.GetObject()) )
  729. {
  730. targetInventoryLocation = new InventoryLocation;
  731. targetItem.GetInventory().GetCurrentInventoryLocation(targetInventoryLocation);
  732. if ( action_data.m_Player.GetInventory().HasInventoryReservation( targetItem, targetInventoryLocation) )
  733. {
  734. success = false;
  735. }
  736. else
  737. {
  738. action_data.m_Player.GetInventory().AddInventoryReservationEx( targetItem, targetInventoryLocation, GameInventory.c_InventoryReservationTimeoutMS);
  739. }
  740. }
  741. }
  742. handInventoryLocation = new InventoryLocation;
  743. handInventoryLocation.SetHands(action_data.m_Player,action_data.m_Player.GetItemInHands());
  744. if (action_data.m_Player.GetInventory().HasInventoryReservation( action_data.m_Player.GetItemInHands(), handInventoryLocation))
  745. {
  746. if (HasTarget())
  747. {
  748. action_data.m_Player.GetInventory().ClearInventoryReservation(targetItem, targetInventoryLocation);
  749. }
  750. success = false;
  751. }
  752. else
  753. {
  754. action_data.m_Player.GetInventory().AddInventoryReservationEx( action_data.m_Player.GetItemInHands(), handInventoryLocation, GameInventory.c_InventoryReservationTimeoutMS);
  755. }
  756. if (success)
  757. {
  758. if (targetInventoryLocation)
  759. action_data.m_ReservedInventoryLocations.Insert(targetInventoryLocation);
  760. if (handInventoryLocation)
  761. action_data.m_ReservedInventoryLocations.Insert(handInventoryLocation);
  762. }
  763. return success;
  764. }
  765. void ClearInventoryReservationEx(ActionData action_data)
  766. {
  767. if (action_data.m_ReservedInventoryLocations)
  768. {
  769. InventoryLocation il;
  770. for ( int i = 0; i < action_data.m_ReservedInventoryLocations.Count(); i++)
  771. {
  772. il = action_data.m_ReservedInventoryLocations.Get(i);
  773. action_data.m_Player.GetInventory().ClearInventoryReservationEx( il.GetItem() , il );
  774. }
  775. action_data.m_ReservedInventoryLocations.Clear();
  776. }
  777. }
  778. void RefreshReservations(ActionData action_data)
  779. {
  780. if (action_data.m_ReservedInventoryLocations)
  781. {
  782. InventoryLocation il;
  783. for (int i = 0; i < action_data.m_ReservedInventoryLocations.Count(); i++)
  784. {
  785. il = action_data.m_ReservedInventoryLocations.Get(i);
  786. EntityAI entity = il.GetItem();
  787. action_data.m_Player.GetInventory().ExtendInventoryReservationEx(il.GetItem() , il, 10000);
  788. }
  789. }
  790. }
  791. bool AddActionJuncture(ActionData action_data)
  792. {
  793. bool accepted = true;
  794. if (HasTarget())
  795. {
  796. EntityAI targetEntity;
  797. if (EntityAI.CastTo(targetEntity,action_data.m_Target.GetObject()))
  798. {
  799. if (IsLockTargetOnUse())
  800. {
  801. InventoryLocation targetIl = new InventoryLocation();
  802. targetEntity.GetInventory().GetCurrentInventoryLocation(targetIl);
  803. //Lock target
  804. if (!GetGame().AddInventoryJunctureEx(action_data.m_Player, targetEntity, targetIl, true, 10000))
  805. {
  806. accepted = false;
  807. }
  808. else
  809. {
  810. action_data.m_ReservedInventoryLocations.Insert(targetIl);
  811. }
  812. }
  813. }
  814. }
  815. return accepted;
  816. }
  817. void ClearActionJuncture(ActionData action_data)
  818. {
  819. if (action_data.m_Player.GetInstanceType() == DayZPlayerInstanceType.INSTANCETYPE_SERVER)
  820. {
  821. if (action_data.m_ReservedInventoryLocations)
  822. {
  823. InventoryLocation il;
  824. for ( int i = 0; i < action_data.m_ReservedInventoryLocations.Count(); i++)
  825. {
  826. il = action_data.m_ReservedInventoryLocations.Get(i);
  827. EntityAI entity = il.GetItem();
  828. if (entity)
  829. {
  830. GetGame().ClearJunctureEx(action_data.m_Player, entity);
  831. }
  832. }
  833. action_data.m_ReservedInventoryLocations.Clear();
  834. }
  835. }
  836. }
  837. void RefreshActionJuncture(ActionData action_data)
  838. {
  839. if (action_data.m_ReservedInventoryLocations)
  840. {
  841. InventoryLocation il;
  842. for (int i = 0; i < action_data.m_ReservedInventoryLocations.Count(); i++)
  843. {
  844. il = action_data.m_ReservedInventoryLocations.Get(i);
  845. EntityAI entity = il.GetItem();
  846. if (entity)
  847. {
  848. GetGame().ExtendActionJuncture(action_data.m_Player, entity, 10000);
  849. }
  850. }
  851. }
  852. }
  853. // action need first have permission from server before can start
  854. bool UseAcknowledgment()
  855. {
  856. return true;
  857. }
  858. //! DEPRECATED delivers message ids to clients based on given context
  859. protected void InformPlayers( PlayerBase player, ActionTarget target, int state );
  860. void SendMessageToClient( Object reciever, string message ) //sends given string to client, don't use if not nescessary
  861. {
  862. PlayerBase man;
  863. if (GetGame().IsServer() && Class.CastTo(man, reciever) && m_MessageParam && reciever.IsAlive() && message != "")
  864. {
  865. m_MessageParam.param1 = message;
  866. GetGame().RPCSingleParam(man, ERPCs.RPC_USER_ACTION_MESSAGE, m_MessageParam, true, man.GetIdentity());
  867. }
  868. }
  869. // ActionCondition Rules
  870. // ------------------------------------------------------
  871. protected bool IsDamageDestroyed(ActionTarget target)
  872. {
  873. return target.GetObject() && target.GetObject().IsDamageDestroyed();
  874. }
  875. protected bool IsBuilding(ActionTarget target)
  876. {
  877. return target.GetObject() && target.GetObject().IsBuilding();
  878. }
  879. protected bool IsTransport(ActionTarget target)
  880. {
  881. return target.GetObject() && target.GetObject().IsTransport();
  882. }
  883. protected bool IsInReach(PlayerBase player, ActionTarget target, float maxDistance = 1.0)
  884. {
  885. Object obj = target.GetObject();
  886. if (!obj)
  887. return false;
  888. float distanceRoot, distanceHead;
  889. vector modelPos, worldPos, playerHeadPos;
  890. // we're using sq distance in comparison
  891. maxDistance = maxDistance * maxDistance;
  892. // get position of Head bone
  893. MiscGameplayFunctions.GetHeadBonePos(player, playerHeadPos);
  894. array<string> componentNames = new array<string>();
  895. obj.GetActionComponentNameList(target.GetComponentIndex(), componentNames);
  896. foreach (string componentName : componentNames)
  897. {
  898. if (componentName.Contains("doorstwin"))
  899. continue;
  900. modelPos = obj.GetSelectionPositionMS(componentName);
  901. worldPos = obj.ModelToWorld(modelPos);
  902. break;
  903. }
  904. distanceRoot = vector.DistanceSq(worldPos, player.GetPosition());
  905. distanceHead = vector.DistanceSq(worldPos, playerHeadPos);
  906. return distanceRoot <= maxDistance || distanceHead <= maxDistance;
  907. }
  908. // ------------------------------------------------------
  909. // SOUNDS ------------------------------------------------------
  910. SoundOnVehicle PlayActionSound( PlayerBase player )
  911. {
  912. if ( GetGame().IsServer() && player )
  913. {
  914. if ( m_Sound != "" )
  915. {
  916. return GetGame().CreateSoundOnObject(player, m_Sound, 6, false);
  917. }
  918. else if ( m_Sounds && m_Sounds.Count() > 0 )
  919. {
  920. int rand_num = Math.RandomInt(0, m_Sounds.Count());
  921. return GetGame().CreateSoundOnObject(player, m_Sounds.Get(rand_num), 6, false);
  922. }
  923. }
  924. return NULL;
  925. }
  926. void OnActionInfoUpdate( PlayerBase player, ActionTarget target, ItemBase item )
  927. {
  928. }
  929. //sound category matches with a soundtable category in config, selects correct soundset
  930. string GetSoundCategory(ActionData action_data)
  931. {
  932. return "";
  933. }
  934. // EVENTS ------------------------------------------------
  935. void OnUpdate(ActionData action_data)
  936. {}
  937. void OnUpdateClient(ActionData action_data)
  938. {
  939. if ( !GetGame().IsDedicatedServer() )
  940. {
  941. if (action_data.m_RefreshReservationTimer > 0)
  942. {
  943. action_data.m_RefreshReservationTimer--;
  944. }
  945. else
  946. {
  947. action_data.m_RefreshReservationTimer = m_RefreshReservationTimerValue;
  948. RefreshReservations(action_data);
  949. }
  950. }
  951. }
  952. void OnUpdateServer(ActionData action_data)
  953. {
  954. if (action_data.m_RefreshJunctureTimer > 0)
  955. {
  956. action_data.m_RefreshJunctureTimer--;
  957. }
  958. else
  959. {
  960. action_data.m_RefreshJunctureTimer = m_RefreshReservationTimerValue;
  961. RefreshActionJuncture(action_data);
  962. }
  963. }
  964. void OnStart(ActionData action_data)
  965. {
  966. if (action_data.m_Player != NULL && action_data.m_Player.IsPlacingLocal() && !IsDeploymentAction())
  967. action_data.m_Player.PlacingCancelLocal();
  968. }
  969. void OnStartClient(ActionData action_data)
  970. {}
  971. void OnStartServer(ActionData action_data)
  972. {
  973. }
  974. void OnEnd(ActionData action_data)
  975. {
  976. }
  977. void OnEndClient(ActionData action_data)
  978. {}
  979. void OnEndServer(ActionData action_data)
  980. {
  981. }
  982. // SOFT SKILLS ------------------------------------------------
  983. float GetSpecialtyWeight()
  984. {
  985. if(m_SpecialtyWeight == 0)
  986. {
  987. #ifdef DEVELOPER
  988. //Print("UserAction does not use SoftSkills");
  989. #endif
  990. }
  991. return m_SpecialtyWeight;
  992. }
  993. int GetState( ActionData action_data )
  994. {
  995. return action_data.m_State;
  996. }
  997. float GetProgress( ActionData action_data )
  998. {
  999. return -1;
  1000. }
  1001. ActionInput GetInput()
  1002. {
  1003. return m_Input;
  1004. }
  1005. void SetID(int actionId)
  1006. {
  1007. m_ActionID = actionId;
  1008. }
  1009. int GetID()
  1010. {
  1011. return m_ActionID;
  1012. }
  1013. string GetAdminLogMessage(ActionData action_data)
  1014. {
  1015. return "";
  1016. }
  1017. };