Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_BaseUseSupportStationAction.c
Go to the documentation of this file.
2{
3 [Attribute("#AR-SupportStation_ActionInvalid_NotInRange", desc: "No support stations of type in range", uiwidget: UIWidgets.LocaleEditBox)]
5
6 [Attribute("#AR-SupportStation_ActionInvalid_Destroyed", desc: "Support station in range but the only one is destroyed", uiwidget: UIWidgets.LocaleEditBox)]
8
9 [Attribute("#AR-SupportStation_ActionInvalid_HostileFaction", desc: "There are support stations in range but user is an invalid faction (Generally means faction is hostile)", uiwidget: UIWidgets.LocaleEditBox)]
11
12 [Attribute("#AR-SupportStation_ActionInvalid_Supplies", desc: "There are support stations in range but non of them have enough supplies", uiwidget: UIWidgets.LocaleEditBox)]
14
15 [Attribute("#AR-SupportStation_ActionInvalid_NoSupplyStorage", desc: "There are support stations in range but it cannot execute the action as the supply storages are all full", uiwidget: UIWidgets.LocaleEditBox)]
17
18 [Attribute("#AR-SupportStation_ActionInvalid_IsMoving", desc: "There are support stations in range but all of them are moving", uiwidget: UIWidgets.LocaleEditBox)]
20
21 [Attribute("#AR-SupportStation_ActionInvalid_Disabled", desc: "There are support stations use range and are in range but all of them are disabled (by the game master)", uiwidget: UIWidgets.LocaleEditBox)]
23
24 [Attribute("1", desc: "Show supplies in action if there is a supply cost")]
26
27 [Attribute("0", desc: "If true will check if support station component can be found on children. Only enable if support station is on Vehicle part and support station does not have range")]
29
30 [Attribute("-1", desc: "What animation the player should play if using the support station with a gadget. Leave -1 to not play any animation")]
32
33 [Attribute("1", desc: "If an animation is assigned, does the animation loop?")]
35
36 [Attribute("0", desc: "If an animation is assigned, does the animation play while the character is in a vehicle?")]
38
39 protected bool m_bIsMaster;
40 protected bool m_bActionActive;
41
42 protected IEntity m_ActionUser; //~ The player that uses is currently using the action
43 protected SCR_BaseSupportStationComponent m_ActionOwnerSupportStationComponent;
44 protected SCR_BaseSupportStationComponent m_SupportStationComponent;
45
46 //~ To save performance it will only look for valid support station every x miliseconds or if no current supply station or if current is no longer valid
47 protected BaseWorld m_World;
48 protected float m_fLastCheckedCanPerform = 0;
49 protected bool m_bSupportStationWasNull = false;
50 protected const int DELAY_CAN_PERFORM = 500; //~ In milisecs if player hovers over action it will check every x miliseconds the highest priority Support station, Else it will simply check if the current is still valid
51
52 protected int m_iSuppliesOnUse;
53 protected int m_iAvailableSupplies;
54 protected bool m_bCanPerform;
56
57 protected SCR_SupportStationGadgetComponent m_SupportStationGadget;
59
60 protected const float MAXIMUM_VEHICLE_SPEED_FOR_INTERACTION_SQ = 0.04;
61
62 protected const LocalizedString INVALID_TARGET_VEHICLE_SPEED = "#AR-SupportStation_ActionInvalid_IsTargetMoving";
63 protected const LocalizedString ACTION_WITH_SUPPLYCOST_FORMATTING = "#AR-ActionFormat_SupplyCost";
64 protected const LocalizedString ACTION_WITH_SUPPLYGAIN_FORMATTING = "#AR-ActionFormat_SupplyGain";
65 protected const LocalizedString ACTION_WITH_PARAM_FORMATTING = "#AR-SupportStation_ActionFormat_WithParam";
66 protected const LocalizedString ACTION_PERCENTAGE_FORMATTING = "#AR-SupportStation_ActionFormat_Percentage";
67
68 //------------------------------------------------------------------------------------------------
70 {
71 Print("Do not use 'SCR_BaseUseSupportStationAction' as action, inherit from it and override ' SupportStationActionType' function to the correct type!", LogLevel.ERROR);
72 return ESupportStationType.NONE;
73 }
74
75 //------------------------------------------------------------------------------------------------
76 //~ Executed on perform (server only) and on CanBePerformedScript every time DELAY_CAN_PERFORM passes (Local only)
77 protected SCR_BaseSupportStationComponent GetClosestValidSupportStation(IEntity actionOwner, IEntity actionUser, out ESupportStationReasonInvalid reasonInvalid = 0)
78 {
79 SCR_BaseSupportStationComponent supportStationComponent;
80 vector actionWorldPosition = GetWorldPositionAction();
81
82 //~ Should always take held gadget over any other support station unless the user holds no Gadget
84 {
85 supportStationComponent = m_SupportStationGadget.GetSupportStation(GetSupportStationType());
86 if (supportStationComponent)
87 {
88 //~ Held Gadget is valid
89 if (supportStationComponent.IsValid(actionOwner, actionUser, this, actionWorldPosition, reasonInvalid, m_iSuppliesOnUse))
90 return supportStationComponent;
91 //~ The held gadget wasn't valid
92 else
93 {
94 m_iAvailableSupplies = supportStationComponent.GetMaxAvailableSupplies();
95 return null;
96 }
97
98 }
99 }
100
101 //~ Only execute without manager if its owner has a SCR_BaseSupportStationComponent on it that must be executed without manager
103 {
104 if (m_ActionOwnerSupportStationComponent.IsValid(actionOwner, actionUser, this, actionWorldPosition, reasonInvalid, m_iSuppliesOnUse))
106
108 return null;
109 }
110
111 //~ Get manager
113 if (supportStationManager)
114 {
115 //~ If not get First valid SCR_BaseSupportStationComponent
116 supportStationComponent = supportStationManager.GetClosestValidSupportStation(GetSupportStationType(), actionUser, actionOwner, this, actionWorldPosition, reasonInvalid, m_iSuppliesOnUse);
117 if (supportStationComponent)
118 return supportStationComponent;
119 }
120
121 //~ Only check held gadget if other support stations around at least did not fail because there were no supplies
122 if (reasonInvalid != ESupportStationReasonInvalid.NO_SUPPLIES)
123 {
124 //~ Get held Gadget support station if it did not already check it because it had priority
126 {
127 supportStationComponent = m_SupportStationGadget.GetSupportStation(GetSupportStationType());
128 if (supportStationComponent)
129 {
130 //~ Held Gadget is valid
131 if (supportStationComponent.IsValid(actionOwner, actionUser, this, actionWorldPosition, reasonInvalid, m_iSuppliesOnUse))
132 return supportStationComponent;
133 else
134 {
135 m_iAvailableSupplies = supportStationComponent.GetMaxAvailableSupplies();
136 return null;
137 }
138 }
139 }
140 }
141
142 if (supportStationComponent)
143 m_iAvailableSupplies = supportStationComponent.GetMaxAvailableSupplies();
144 else
146
147 return null;
148 }
149
150 //------------------------------------------------------------------------------------------------
151 override bool CanBeShownScript(IEntity user)
152 {
153 if (!GetOwner() || !super.CanBeShownScript(user))
154 return false;
155
156 m_SupportStationGadget = SCR_SupportStationGadgetComponent.GetHeldSupportStationGadget(GetSupportStationType(), user);
158 return false;
159
160 //~ Don't show if support station is on owner and it is disabled
161 SCR_BaseSupportStationComponent supportStationComponent = SCR_BaseSupportStationComponent.Cast(GetOwner().FindComponent(SCR_BaseSupportStationComponent));
162 if (supportStationComponent && !supportStationComponent.UsesRange() && !supportStationComponent.IsEnabled())
163 return false;
164
165 //~ Don't show if fully destroyed (vehicle parts will check parent)
166 if (!CanShowDestroyed())
167 return false;
168
169 //~ All checks passed
170 return true;
171 }
172
173 //------------------------------------------------------------------------------------------------
174 protected bool CanShowDestroyed()
175 {
176 //~ Don't show if damage manager destroyed
177 SCR_DamageManagerComponent damageComponent = SCR_DamageManagerComponent.Cast(GetOwner().FindComponent(SCR_DamageManagerComponent));
178 if (damageComponent)
179 return damageComponent.GetState() != EDamageState.DESTROYED;
180
181 //~ Don't show if default hitZone is destroyed
183 if (hitZoneContainer)
184 {
185 HitZone defaultHitZone = hitZoneContainer.GetDefaultHitZone();
186 return defaultHitZone.GetDamageState() != EDamageState.DESTROYED;
187 }
188
189 return true;
190 }
191
192 //---- REFACTOR NOTE START: CanBePerformedScript is updated each fix frame by code. The can perform check however is quite expensive to check so I add delays to only check x seconds ----
193 //------------------------------------------------------------------------------------------------
194 override bool CanBePerformedScript(IEntity user)
195 {
196 //~ Owner can be deleted so make sure the rest of CanBePerformed is not called
197 if (!GetOwner())
198 return false;
199
200 //~ To optimize only get perform if action is active
201 //if (!m_bActionActive && !m_bIsMaster)
202 // return true;
203
204 //~ Only one player can perform at the same time
206 {
208 return false;
209 }
210
211 ESupportStationReasonInvalid reasonInvalid;
212 //~ Only check every x seconds if support station is still valid (valid support station is also checked on execute action). This is for performance issue as checking for all support stations can be performance heavy
213 if (m_World.GetWorldTime() < (m_fLastCheckedCanPerform + DELAY_CAN_PERFORM))
214 {
215 //~ Support station assigned and still valid. So action can be performed
217 {
218 SetCanPerform(true, -1);
219 return true;
220 }
221 //~ No support station was valid but only recheck once DELAY_CAN_PERFORM if it is valid again. So make sure action cannot be performed
223 {
224 SetCanPerform(false, -1);
225 return false;
226 }
227 }
228
229 //~ Support station is no longer valid so check for a new one
232 m_iAvailableSupplies = m_SupportStationComponent.GetMaxAvailableSupplies();
233
234 //~ Only called when updated
236
237 //~ Save if support station was null to make sure it only checks for valid support station after the delay
239
240 SetCanPerform(m_SupportStationComponent != null, reasonInvalid);
241 return m_SupportStationComponent != null;
242 }
243 //---- REFACTOR NOTE END ----
244
245 //------------------------------------------------------------------------------------------------
246 //~ Set if action can be performed and to update displayed action name and invalid reason
247 protected void SetCanPerform(bool canPerform, ESupportStationReasonInvalid reasonInvalid)
248 {
249 m_bCanPerform = canPerform;
250
251 if (reasonInvalid >= 0)
252 {
253 m_eCannotPerformReason = reasonInvalid;
255
256 }
257 }
258
259 //------------------------------------------------------------------------------------------------
260 bool CanPerform(out ESupportStationReasonInvalid cannotPerformReason)
261 {
262 cannotPerformReason = m_eCannotPerformReason;
263 return m_bCanPerform;
264 }
265
266 //------------------------------------------------------------------------------------------------
267 //~ Executed every time can be performed delay is done
268 protected void CanBePerformedUpdate(IEntity user)
269 {
270 //~ Save last performed
271 m_fLastCheckedCanPerform = m_World.GetWorldTime();
272 }
273
274 //------------------------------------------------------------------------------------------------
275 //~ Get invalid perform reason text
277 {
278 //~ No stations of type in range
279 if (reasonInvalid == ESupportStationReasonInvalid.NOT_IN_RANGE)
281 if (reasonInvalid == ESupportStationReasonInvalid.DESTROYED_STATION)
283 //~ Disabled by Editor
284 else if (reasonInvalid == ESupportStationReasonInvalid.DISABLED)
286 //~ Faction of user is invalid compaired to faction of Support station
287 else if (reasonInvalid == ESupportStationReasonInvalid.INVALID_FACTION)
289 //~ Stations have no supplies
290 else if (reasonInvalid == ESupportStationReasonInvalid.NO_SUPPLIES)
292 //~ Stations are unable to store any more supplies
293 else if (reasonInvalid == ESupportStationReasonInvalid.NO_SUPPLY_STORAGE_SPACE)
295 //~ Stations are all moving
296 else if (reasonInvalid == ESupportStationReasonInvalid.IS_MOVING)
298
299 //~ Show default unavailible
300 return string.Empty;
301 }
302
303 //------------------------------------------------------------------------------------------------
304 protected void ResetReferencesOnServer()
305 {
309 }
310
311 //------------------------------------------------------------------------------------------------
312 //~ If continues action it will only execute everytime the duration is done
313 override void PerformContinuousAction(IEntity pOwnerEntity, IEntity pUserEntity, float timeSlice)
314 {
316 return;
317
318 if (!LoopActionUpdate(timeSlice))
319 return;
320
321 //~ Has gadget and loops animation
323 {
324 //~ Character animates in vehicle or is not in vehicle
325 if (m_bAnimateGadgetInVehicle || !IsUserInVehicle(pUserEntity))
326 {
327 //~ Not yet in loop animation
328 if (!m_SupportStationGadget.InUseAnimationLoop(pUserEntity))
329 return;
330 }
331 }
332
333 //~ Only start showing progress after first action completed
334 m_bLoopAction = true;
335
336 PerformAction(pOwnerEntity, pUserEntity);
337 }
338
339 //------------------------------------------------------------------------------------------------
340 override void PerformAction(IEntity pOwnerEntity, IEntity pUserEntity)
341 {
342 //~ Action can be performed server only
343 if (!m_bIsMaster)
344 {
345 if (!m_bLoopAction) // if we arent looping, then whatever will happen, action user is no longer valid
346 m_ActionUser = null;
347
348 return;
349 }
350
351 //~ Resets all references so server grabs them all fresh
353
354 if (!CanBeShownScript(pUserEntity))
355 {
356 if (!m_bLoopAction)
357 m_ActionUser = null;
358
359 return;
360 }
361
362 if (!CanBePerformedScript(pUserEntity))
363 {
364 if (!m_bLoopAction)
365 m_ActionUser = null;
366
367 return;
368 }
369
370 //Execute Supply station
371 m_SupportStationComponent.OnExecutedServer(pOwnerEntity, pUserEntity, this);
372
373 //~ Update supplies
374 m_iAvailableSupplies = m_SupportStationComponent.GetMaxAvailableSupplies();
375 if (!m_bLoopAction)
376 m_ActionUser = null;
377 }
378
379 //------------------------------------------------------------------------------------------------
380 override void Init(IEntity pOwnerEntity, GenericComponent pManagerComponent)
381 {
382 super.Init(pOwnerEntity, pManagerComponent);
383
385 if ((gameMode && gameMode.IsMaster()) || (!gameMode && Replication.IsServer()))
386 m_bIsMaster = true;
387
388 m_World = GetGame().GetWorld();
389
390 //~ Init check
392
394 Print("'SCR_BaseUseSupportStationAction' Support Station action type: '" + typename.EnumToString(ESupportStationType, GetSupportStationType()) + "' has PerformPerFrame true but the duraction is greater than 0. Set it to less that 0, eg: 1 sec == -1", LogLevel.ERROR);
395
396 //~ Delay init to get components correctly
397 GetGame().GetCallqueue().CallLater(DelayedInit, param1: pOwnerEntity);
398 }
399
400 //------------------------------------------------------------------------------------------------
401 protected void DelayedInit(IEntity owner)
402 {
403 if (!owner)
404 return;
405
406 m_ActionOwnerSupportStationComponent = SCR_BaseSupportStationComponent.FindSupportStation(owner, GetSupportStationType(), queryFlags: SCR_EComponentFinderQueryFlags.ENTITY);
407
408 //~ Get support station of children
410 {
411 if (Vehicle.Cast(owner))
412 m_ActionOwnerSupportStationComponent = SCR_BaseSupportStationComponent.FindSupportStation(owner, GetSupportStationType(), queryFlags: SCR_EComponentFinderQueryFlags.SLOTS);
413 else
414 m_ActionOwnerSupportStationComponent = SCR_BaseSupportStationComponent.FindSupportStation(owner, GetSupportStationType(), queryFlags: SCR_EComponentFinderQueryFlags.CHILDREN);
415 }
416 }
417
418 //------------------------------------------------------------------------------------------------
419 override bool CanBroadcastScript()
420 {
421 return true;
422 }
423
424 //------------------------------------------------------------------------------------------------
425 protected bool CanHaveMultipleUsers()
426 {
427 return false;
428 }
429
430 //------------------------------------------------------------------------------------------------
432 protected float GetActionPercentage()
433 {
434 return int.MIN;
435 }
436
437 //------------------------------------------------------------------------------------------------
438 protected int GetActionDecimalCount()
439 {
440 return 1;
441 }
442
443 //------------------------------------------------------------------------------------------------
445 protected bool RequiresGadget()
446 {
447 return false;
448 }
449
450 //------------------------------------------------------------------------------------------------
452 protected bool PrioritizeHeldGadget()
453 {
454 return false;
455 }
456
457 //------------------------------------------------------------------------------------------------
460 {
461 return true;
462 }
463
464 //------------------------------------------------------------------------------------------------
467 {
468 return m_ActionUser;
469 }
470
471 //-----------------------------------------------------------------------------------
476
477 //------------------------------------------------------------------------------------------------
478 override void OnActionStart(IEntity pUserEntity)
479 {
480 m_ActionUser = pUserEntity;
481
482 super.OnActionStart(pUserEntity);
483
484 //~ Or if AI just do it
486 return;
487
488 m_SupportStationGadget = SCR_SupportStationGadgetComponent.GetHeldSupportStationGadget(GetSupportStationType(), pUserEntity);
490 {
491 m_bLoopAction = true;
492 return;
493 }
495 {
496 m_bLoopAction = true;
497
499 m_SupportStationGadget.StartGadgetAnimation(pUserEntity, m_iGadgetAnimationCommand, this);
500
501 return;
502 }
503
504 m_bLoopAction = false;
505
507 m_SupportStationGadget.StartGadgetAnimation(pUserEntity, m_iGadgetAnimationCommand, this);
508 }
509
510 //------------------------------------------------------------------------------------------------
511 protected bool IsUserInVehicle(notnull IEntity user)
512 {
513 ChimeraCharacter chimeraCharacter = ChimeraCharacter.Cast(user);
514 return chimeraCharacter && chimeraCharacter.IsInVehicle();
515 }
516
517 //------------------------------------------------------------------------------------------------
518 override void OnActionCanceled(IEntity pOwnerEntity, IEntity pUserEntity)
519 {
520 super.OnActionCanceled(pUserEntity);
521
522 //~ Remove gadget user
523 m_ActionUser = null;
524
526 return;
527
529 m_SupportStationGadget.StopGadgetAnimation(pUserEntity, m_iGadgetAnimationCommand);
530 }
531
532 //------------------------------------------------------------------------------------------------
533 protected string GetActionStringParam()
534 {
535 return string.Empty;
536 }
537
538 //------------------------------------------------------------------------------------------------
539 protected override void OnActionSelected()
540 {
541 super.OnActionSelected();
543 m_bActionActive = true;
544
545 }
546
547 //------------------------------------------------------------------------------------------------
548 protected override void OnActionDeselected()
549 {
550 super.OnActionSelected();
551 m_bActionActive = false;
552 }
553
554 //------------------------------------------------------------------------------------------------
555 override bool GetActionNameScript(out string outName)
556 {
557 //~ Support station is overwriting the action name
558 if (outName.IsEmpty())
559 {
561 outName = m_SupportStationComponent.GetOverrideUserActionName();
562
563 if (outName.IsEmpty())
564 {
565 UIInfo uiInfo = GetUIInfo();
566 if (uiInfo)
567 outName = uiInfo.GetName();
568 }
569 }
570
571 //~ If action is active show additional params
572 if (m_bActionActive)
573 {
574 string actionParam = GetActionStringParam();
575 float actionPercentage = int.MIN;
576
577 if (actionParam.IsEmpty())
578 actionPercentage = GetActionPercentage();
579
580 //~ Get percentage string
581 if (actionPercentage != int.MIN)
582 actionParam = SCR_FormatHelper.FloatToStringNoZeroDecimalEndings(actionPercentage, GetActionDecimalCount());
583
584 //~ Show percentage
585 if (!actionParam.IsEmpty())
586 {
587 if (actionPercentage != int.MIN)
588 outName = WidgetManager.Translate(ACTION_PERCENTAGE_FORMATTING, outName, actionParam);
589 else
590 outName = WidgetManager.Translate(ACTION_WITH_PARAM_FORMATTING, outName, actionParam);
591 }
592
593 //~ Show supply cost
595 {
596 //~ If has supply cost
597 if (!m_SupportStationComponent.HasSupplyGainInsteadOfCost(this))
598 {
599 //~ Show if can perform or if not enough supplies
602 }
603 //~ If has supply gain
604 else
605 {
606 //~ Show if can perform or if not enough storage for supply gain supplies
607 if (m_bCanPerform || m_eCannotPerformReason == ESupportStationReasonInvalid.NO_SUPPLY_STORAGE_SPACE)
609 }
610
611
612 }
613 }
614
615 return !outName.IsEmpty();
616 }
617
618 //------------------------------------------------------------------------------------------------
620 {
621 //~ Safety if action owner is deleted while player is still using it
623 {
626 }
627 }
628}
629
ESupportStationType
ArmaReforgerScripted GetGame()
Definition game.c:1398
SCR_BaseGameMode GetGameMode()
SCR_EComponentFinderQueryFlags
Used for component finding to know where it can search to get the given component.
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
proto external bool ShouldPerformPerFrame()
Should this action be performed every frame the input action is triggered?
proto external float GetActionDuration()
Returns the duration of this action in seconds.
proto external IEntity GetOwner()
Returns the parent entity of this action.
proto external UIInfo GetUIInfo()
Returns the UIInfo set for this user action or null if none.
string m_sCannotPerformReason
Main replication API.
Definition Replication.c:14
sealed bool IsMaster()
override void PerformAction(IEntity pOwnerEntity, IEntity pUserEntity)
override void PerformContinuousAction(IEntity pOwnerEntity, IEntity pUserEntity, float timeSlice)
LocalizedString GetInvalidPerformReasonString(ESupportStationReasonInvalid reasonInvalid)
bool RequiresGadget()
If true will only show the action if the player is holding the correct support station gadget.
SCR_BaseSupportStationComponent m_ActionOwnerSupportStationComponent
override void OnActionCanceled(IEntity pOwnerEntity, IEntity pUserEntity)
SCR_BaseSupportStationComponent GetClosestValidSupportStation(IEntity actionOwner, IEntity actionUser, out ESupportStationReasonInvalid reasonInvalid=0)
SCR_BaseSupportStationComponent m_SupportStationComponent
SCR_SupportStationGadgetComponent m_SupportStationGadget
override void OnActionStart(IEntity pUserEntity)
override bool GetActionNameScript(out string outName)
float GetActionPercentage()
If not -1 it will show the percentage on the current action.
void SetCanPerform(bool canPerform, ESupportStationReasonInvalid reasonInvalid)
ESupportStationReasonInvalid m_eCannotPerformReason
bool PrioritizeHeldGadget()
If true will always take support station from held gadget and skip any other checks if a held support...
bool AllowGetSupportStationFromGadget()
If true it allows getting the support station from gadgets.
IEntity GetCurrentActionUser()
Get which entity is currently activly using the action.
override void Init(IEntity pOwnerEntity, GenericComponent pManagerComponent)
bool CanPerform(out ESupportStationReasonInvalid cannotPerformReason)
static IEntity GetLocalControlledEntity()
A scripted action class having optional logic to check if vehicle is valid.
bool LoopActionUpdate(float timeSlice)
SCR_BaseSupportStationComponent GetClosestValidSupportStation(ESupportStationType type, notnull IEntity actionUser, notnull IEntity actionOwner, SCR_BaseUseSupportStationAction action, vector actionPosition, out ESupportStationReasonInvalid reasonInvalid, out int supplyCost)
static SCR_SupportStationManagerComponent GetInstance()
UIInfo - allows to define UI elements.
Definition UIInfo.c:14
enum EPhysicsLayerPresets Vehicle
Definition gameLib.c:24
proto void Print(void var, LogLevel level=LogLevel.NORMAL)
Prints content of variable to console/log.
LogLevel
Enum with severity of the logging message.
Definition LogLevel.c:14
SCR_FieldOfViewSettings Attribute
EDamageState
Tuple param1
@ PerformAction