Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_AIGetArtilleryAimDistanceCompensation.c
Go to the documentation of this file.
2{
3 // Inputs
4 protected static const string PORT_ARTILLERY_ENTITY = "ArtilleryEntity";
5 protected static const string PORT_AMMO_PREFAB = "AmmoPrefab";
6 protected static const string PORT_TARGET_POS = "TargetPos";
7
8 // Outputs
9 protected static const string PORT_AIM_POS = "AimPos";
10 protected static const string PORT_INIT_SPEED_ID = "InitSpeedId";
11
12 //---------------------------------------------------------------------------------
13 override ENodeResult EOnTaskSimulate(AIAgent owner, float dt)
14 {
15 // Read inputs
16 IEntity artilleryEntity;
17 ResourceName ammoPrefab;
18 vector targetPos;
19 GetVariableIn(PORT_ARTILLERY_ENTITY, artilleryEntity);
22
23 if (!artilleryEntity || ammoPrefab.IsEmpty() || targetPos == vector.Zero)
24 return ENodeResult.FAIL;
25
26 // Get aim limits of artillery
27 float aimAngleMinRad, aimAngleMaxRad;
28 GetVerticalAimLimits(artilleryEntity, aimAngleMinRad, aimAngleMaxRad);
29
30 // Get initial speed coefficients of ammo
31 array<float> initSpeedCoefficients = {};
32 bool ammoSupportsSpeedConfigurations = GetAmmoInitialSpeedCoefficients(ammoPrefab, initSpeedCoefficients);
33
34 // If different ammo configurations aren't supported, ensure the array is not empty. Use 1.0 initial speed.
35 if (initSpeedCoefficients.IsEmpty())
36 initSpeedCoefficients.Insert(1.0);
37
38 // Load Entity Source
39 Resource ammoResource = Resource.Load(ammoPrefab);
40 if (!ammoResource.IsValid())
41 return ENodeResult.FAIL;
42
43 BaseResourceObject ammoResourceObj = ammoResource.GetResource();
44 if (!ammoResourceObj)
45 return ENodeResult.FAIL;
46
47 IEntitySource ammoEntitySrc = ammoResourceObj.ToEntitySource();
48 if (!ammoEntitySrc)
49 return ENodeResult.FAIL;
50
51 // Calculate compensation
52
53 vector artilleryPos = artilleryEntity.GetOrigin();
54 float distToTgtHoriz = vector.DistanceXZ(artilleryPos, targetPos);
55 float distToTgtVert = targetPos[1] - artilleryPos[1];
56
57 float aimOffsetVert;
58 int initSpeedId;
59 bool canHitTarget = CalculateDistanceCompensation(distToTgtHoriz, distToTgtVert, ammoEntitySrc, initSpeedCoefficients, aimAngleMinRad, aimAngleMaxRad, aimOffsetVert, initSpeedId);
60
61 // If ammo doesn't support speed configurations, initSpeedId is meaningless, set it to -1 so that the BT knows to not try to configure it
62 if (!ammoSupportsSpeedConfigurations)
63 initSpeedId = -1;
64
65 if (!canHitTarget)
66 return ENodeResult.FAIL;
67
68 vector aimPos = targetPos;
69 aimPos[1] = aimPos[1] + aimOffsetVert;
71
73
74 return ENodeResult.SUCCESS;
75 }
76
77 //---------------------------------------------------------------------------------
78 bool CalculateDistanceCompensation(float distToTgtHoriz, float distToTgtVert, notnull IEntitySource entitySrc, notnull array<float> initSpeedCoeffs, float aimAngleMinRad, float aimAngleMaxRad, out float outAimOffsetVert, out int outInitSpeedId)
79 {
80 // Bail if distance is 0, this makes no sense, and might cause exception
81 if (distToTgtHoriz <= 0)
82 {
83 outAimOffsetVert = 0;
84 outInitSpeedId = -1;
85 return false;
86 }
87
88 // If angle is bigger then tangent is bigger. Tangents are easier to compute than angles in the loop below.
89 float aimAngleTanMin = Math.Tan(aimAngleMinRad);
90 float aimAngleTanMax = Math.Tan(aimAngleMaxRad);
91
92 // Try all variants of initial speed coefficients, until we find the one which can both hit target and is within turret's aiming limits
93 bool canHitTarget = false;
94 float aimOffsetVert = 0;
95 int initSpeedId = -1;
96
97 // First try all variants with the proper ballistics algorithm, with vertical interval compensation
98 for (int i = 0; i < initSpeedCoeffs.Count(); i++)
99 {
100 float initialSpeedCoefficient = initSpeedCoeffs[i];
101
102 float flightTime;
103 bool ballisticsGood = BallisticTable.GetAimHeightOfProjectileAltitudeFromSource(distToTgtHoriz, aimOffsetVert, flightTime, entitySrc, distToTgtVert, initialSpeedCoefficient);
104
105 // Can't hit it - try next one
106 if (!ballisticsGood)
107 continue;
108
109 // Can hit it, but is aim angle within the aim limits?
110 float aimAngleTan = (aimOffsetVert + distToTgtVert) / distToTgtHoriz;
111 if (aimAngleTan > aimAngleTanMax || aimAngleTan < aimAngleTanMin)
112 continue;
113
114 canHitTarget = true;
115 initSpeedId = i;
116 break;
117 }
118
119 // If we still can't hit target with proper ballistics calculation, try the basic ballistic algorithm, without vertical interval compensation
120 if (!canHitTarget)
121 {
122 for (int i = 0; i < initSpeedCoeffs.Count(); i++)
123 {
124 float initialSpeedCoefficient = initSpeedCoeffs[i];
125
126 float flightTime;
127 aimOffsetVert = BallisticTable.GetHeightFromProjectileSource(distToTgtHoriz, flightTime, entitySrc, initSpeedCoef: initialSpeedCoefficient, bDirectFire: false);
128 bool ballisticsGood = flightTime > 0;
129
130 // Can't hit it - try next one
131 if (!ballisticsGood)
132 continue;
133
134 // Can hit it, but is aim angle within the aim limits?
135 float aimAngleTan = (aimOffsetVert + distToTgtVert) / distToTgtHoriz;
136 if (aimAngleTan > aimAngleTanMax || aimAngleTan < aimAngleTanMin)
137 continue;
138
139 canHitTarget = true;
140 initSpeedId = i;
141 break;
142 }
143 }
144
145 outAimOffsetVert = aimOffsetVert;
146 outInitSpeedId = initSpeedId;
147
148 return canHitTarget;
149 }
150
151 //---------------------------------------------------------------------------------
152 void GetVerticalAimLimits(notnull IEntity artilleryEntity, out float outAngleMinRad, out float outAngleMaxRad)
153 {
154 float angleMinRad = 0;
155 float angleMaxRad = Math.PI_HALF;
156
157 AimingComponent aimingComp = AimingComponent.Cast(artilleryEntity.FindComponent(AimingComponent));
158
159 if (aimingComp)
160 {
161 vector limitsHoriz, limitsVert;
162 aimingComp.GetAimingLimits(limitsHoriz, limitsVert);
163
164 angleMinRad = Math.DEG2RAD * limitsVert[0];
165 angleMaxRad = Math.DEG2RAD * limitsVert[1];
166 }
167
168 outAngleMinRad = angleMinRad;
169 outAngleMaxRad = angleMaxRad;
170 }
171
172 //---------------------------------------------------------------------------------
173 // Returns true if ammo supports initial speed configurations
174 bool GetAmmoInitialSpeedCoefficients(ResourceName ammoResourceName, notnull array<float> outCoefficients)
175 {
176 // This can be potentially interfaced with other types of ammo which support different configurations
177 outCoefficients.Clear();
178
179 int defaultConfigId;
180 array<float> initSpeedCoefficients = SCR_MortarShellGadgetComponent.GetPrefabInitSpeedCoef(ammoResourceName, defaultConfigId);
181
182 if (initSpeedCoefficients && !initSpeedCoefficients.IsEmpty())
183 {
184 outCoefficients.Copy(initSpeedCoefficients);
185 return true;
186 }
187
188 return false;
189 }
190
191 //---------------------------------------------------------------------------------
193 protected override TStringArray GetVariablesOut() { return s_aVarsOut; }
194
196 protected override TStringArray GetVariablesIn() { return s_aVarsIn; }
197
198 override static bool VisibleInPalette() { return true; }
199
200 override static string GetOnHoverDescription() { return "Performs ballistic calculations for artillery. It resolves where to aim and which initial speed to use."; }
201}
proto external vector GetOrigin()
Definition Math.c:13
proto void SetVariableOut(string name, void val)
proto bool GetVariableIn(string name, out void val)
Object holding reference to resource. In destructor release the resource.
Definition Resource.c:25
bool GetAmmoInitialSpeedCoefficients(ResourceName ammoResourceName, notnull array< float > outCoefficients)
bool CalculateDistanceCompensation(float distToTgtHoriz, float distToTgtVert, notnull IEntitySource entitySrc, notnull array< float > initSpeedCoeffs, float aimAngleMinRad, float aimAngleMaxRad, out float outAimOffsetVert, out int outInitSpeedId)
void GetVerticalAimLimits(notnull IEntity artilleryEntity, out float outAngleMinRad, out float outAngleMaxRad)
override ENodeResult EOnTaskSimulate(AIAgent owner, float dt)
ENodeResult
Definition ENodeResult.c:13
array< string > TStringArray
Definition Types.c:385