Dayz Explorer  1.24.157551 (v105080)
Dayz Code Explorer by Zeroy
meleetargeting.c
Go to the documentation of this file.
2 {
3  Object Obj;
4  vector HitPos;
5  int HitComponent;
6 
7  void MeleeTargetData(Object o, vector p, int c)
8  {
9  Obj = o;
10  HitPos = p;
11  HitComponent = c;
12  }
13 }
14 
16 {
18  float ConeLength;
23 
26 
31  float MaxDist;
32 
34  ref array<typename> TargetableObjects
35 
36  void MeleeTargetSettings(vector coneOrigin, float coneLength, float coneHalfAngle, float coneMinHeight, float coneMaxHeight, vector rayStart, vector dir, float maxDist, EntityAI pToIgnore, array<typename> targetableObjects)
37  {
38  ConeOrigin = coneOrigin;
39  ConeLength = coneLength;
40  ConeHalfAngle = coneHalfAngle;
41  ConeHalfAngleRad = Math.DEG2RAD * coneHalfAngle;
42  ConeMinHeight = coneMinHeight;
43  ConeMaxHeight = coneMaxHeight;
44 
45  RayStart = rayStart;
46  RayEnd = rayStart + Math.SqrFloat(coneLength) * dir;
47 
48  Dir = dir;
49 
50  XZDir = dir;
51  XZDir[1] = 0;
52  XZDir.Normalize();
53 
54  MaxDist = maxDist;
55 
56  Attacker = pToIgnore;
57  TargetableObjects = targetableObjects;
58 
59  // Calculate cone points
61  }
62 }
63 
65 {
66  vector ComponentPos;
67  float ComponentAngle;
68  float ComponentDistance2;
69  int ComponentIdx;
70 }
71 
72 class MeleeTargeting
73 {
75 
76  MeleeTargetData GetMeleeTargetEx(MeleeTargetSettings settings, out array<Object> allTargets = null, array<string> blacklistedDamageZones = null)
77  {
78  MeleeTargetData ret;
79 
80  // Easier access to MeleeTargetSettings variables
81  vector coneOrigin = settings.ConeOrigin;
82  float coneLength = settings.ConeLength;
83  float coneHalfAngle = settings.ConeHalfAngle;
84  float radAngle = settings.ConeHalfAngleRad;
85  float coneMinHeight = settings.ConeMinHeight;
86  float coneMaxHeight = settings.ConeMaxHeight;
87 
88  vector coneLeft = settings.ConeLeftPoint;
89  vector coneRight = settings.ConeRightPoint;
90 
91  vector rayStart = settings.RayStart;
92  vector rayEnd = settings.RayEnd;
93  vector dir = settings.Dir;
94  vector xzDir = settings.XZDir;
95  float maxDist = settings.MaxDist;
96 
97  EntityAI pToIgnore = settings.Attacker;
98  array<typename> targetableObjects = settings.TargetableObjects;
99 
100  // Calculate box size
101  float boxWidth = vector.Distance(coneLeft, coneRight);
102  float boxHeight = coneMaxHeight - coneMinHeight;
103 
104  vector boxSize = Vector(boxWidth, boxHeight, coneLength);
105 
106  // Calculate box center
107  vector centerHeight = Vector(0, Math.Lerp(coneMinHeight, coneMaxHeight, 0.5), 0);
108  vector offset = xzDir * coneLength * 0.5;
109  vector boxCenter = coneOrigin + offset + centerHeight;
110 
111  // Gather all targets
112  BoxCollidingParams params = new BoxCollidingParams();
113  params.SetParams(boxCenter, xzDir.VectorToAngles(), boxSize, ObjIntersect.Fire, ObjIntersect.Fire, true);
115  array<Object> toIgnore = { pToIgnore };
116  if (GetGame().IsBoxCollidingGeometryProxy(params, toIgnore, results))
117  {
118  //
119  float retVal = float.MAX;
120  float tgAngle = Math.Tan(radAngle);
121 
122  #ifdef DIAG_DEVELOPER
123  if (DiagMenu.GetBool(DiagMenuIDs.MELEE_DRAW_RANGE) && DiagMenu.GetBool(DiagMenuIDs.MELEE_DEBUG))
124  Debug.DrawLine(rayStart, rayEnd, COLOR_GREEN, ShapeFlags.ONCE);
125  #endif
126 
127  // Find the most suitable target
128  foreach (BoxCollidingResult bResult : results)
129  {
130  Object obj = bResult.obj;
131 
132  // Check for targetable objects
133  if (!obj.IsAnyInherited(targetableObjects) || !obj.IsAlive())
134  {
135  continue;
136  }
137 
138  // Ready the defaults for the object
139  vector targetPos = obj.GetPosition();
140  float targetAngle = Math.RAD2DEG * Math.AbsFloat(Math3D.AngleFromPosition(coneOrigin, dir, targetPos));
141  float targetDistance2 = vector.DistanceSq(targetPos, Math3D.NearestPoint(rayStart, rayEnd, targetPos));
142  int hitComponent = -1;
143 
144  float csSum = float.MAX;
145 
146  // Find the most suitable component
147  ComponentResult result;
148  if (FindMostSuitableComponentEx(obj, bResult, settings, csSum, result, blacklistedDamageZones))
149  {
150  targetPos = result.ComponentPos;
151  targetAngle = result.ComponentAngle;
152  targetDistance2 = result.ComponentDistance2;
153  hitComponent = result.ComponentIdx;
154  }
155 
156  // ProxyInfo
157  if (bResult.proxyInfo)
158  {
159  foreach (BoxCollidingResult pInfo : bResult.proxyInfo)
160  {
161  if (FindMostSuitableComponentEx(obj, pInfo, settings, csSum, result, blacklistedDamageZones))
162  {
163  targetPos = result.ComponentPos;
164  targetAngle = result.ComponentAngle;
165  targetDistance2 = result.ComponentDistance2;
166  hitComponent = result.ComponentIdx;
167  }
168  }
169  }
170 
171  // No suitable component found
172  if (hitComponent == -1 || csSum == float.MAX)
173  {
174  continue;
175  }
176 
177  // Check if it is a better fit than what has been found previously
178  float sum = targetDistance2;
179  if (sum < retVal)
180  {
181  ret = new MeleeTargetData(obj, targetPos, hitComponent);
182  retVal = sum;
183  }
184 
185  allTargets.Insert(obj);
186  }
187  }
188 
189  return ret;
190  }
191 
193  {
194  return GetMeleeTargetEx(settings, allTargets);
195  }
196 
197 
198  bool FindMostSuitableComponentEx(Object obj, BoxCollidingResult bResult, MeleeTargetSettings settings, out float sum, out ref ComponentResult result, array<string> blacklistedDamageZones)
199  {
200  foreach (ComponentInfo cInfo : bResult.componentInfo)
201  {
202  ComponentResult cResult = new ComponentResult;
203 
204  if (!EvaluateComponentEx(obj, cInfo, settings, cResult, blacklistedDamageZones))
205  {
206  continue;
207  }
208 
209  // Smallest number is a winner
210  float cSum = cResult.ComponentDistance2;
211  if (cSum < sum)
212  {
213  sum = cSum;
214  result = cResult;
215  }
216  }
217 
218  return result != null;
219  }
220 
221  bool FindMostSuitableComponent(Object obj, BoxCollidingResult bResult, MeleeTargetSettings settings, out float sum, out ref ComponentResult result)
222  {
223  return FindMostSuitableComponentEx(obj, bResult, settings, sum, result, null);
224  }
225 
226  bool EvaluateComponentEx(Object obj, ComponentInfo cInfo, MeleeTargetSettings settings, out ref ComponentResult result, array<string> blacklistedDamageZones)
227  {
229  foreach (string zoneName: blacklistedDamageZones)
230  {
231  if (obj.GetDamageZoneNameByComponentIndex(cInfo.component) == zoneName)
232  {
233  return false;
234  }
235  }
236 
237  vector componentPos = cInfo.componentCenter;
238 
239  // Too far away! (fast reject)
240  float componentMaxDist2 = Math.SqrFloat(settings.MaxDist + cInfo.componentRadius * obj.GetScale());
241  vector nearestPoint = Math3D.NearestPoint(settings.RayStart, settings.RayEnd, componentPos);
242  float componentDistance2 = vector.DistanceSq(componentPos, nearestPoint);
243  if (componentDistance2 > componentMaxDist2)
244  {
245  return false;
246  }
247 
248  // Here some more accurate check could be placed that would adjust the componentPos
249 
250  // Outside of the cone angle!
251  float componentAngle = Math.RAD2DEG * Math.AbsFloat(Math3D.AngleFromPosition(settings.ConeOrigin, settings.XZDir, componentPos));
252  if (componentAngle > settings.ConeHalfAngle)
253  {
254  return false;
255  }
256 
257  // Obstructed!
258  if (IsMeleeTargetObstructed(settings.RayStart, componentPos))
259  {
260  return false;
261  }
262 
263  // We found something, fill it in!
264  result.ComponentPos = componentPos;
265  result.ComponentAngle = componentAngle;
266  result.ComponentDistance2 = componentDistance2;
267  result.ComponentIdx = cInfo.component;
268 
269  return true;
270  }
271 
272  bool EvaluateComponent(Object obj, ComponentInfo cInfo, MeleeTargetSettings settings, out ref ComponentResult result)
273  {
274  return EvaluateComponentEx(obj, cInfo, settings, result, {});
275  }
276 
277  bool IsMeleeTargetObstructed(vector rayStart, vector rayEnd)
278  {
279  if (rayStart == rayEnd)
280  {
281  return true; // Not possible to trace when this happens (zero length raycast)
282  }
283 
284  Object hitObject;
285  vector hitPos, hitNormal;
286  float hitFraction;
287 
288  return DayZPhysics.RayCastBullet( rayStart, rayEnd, MELEE_TARGET_OBSTRUCTION_LAYERS, null, hitObject, hitPos, hitNormal, hitFraction);
289  }
290 }
GetGame
proto native CGame GetGame()
ComponentResult
Definition: meleetargeting.c:64
RayStart
vector RayStart
Definition: meleetargeting.c:27
FindMostSuitableComponentEx
bool FindMostSuitableComponentEx(Object obj, BoxCollidingResult bResult, MeleeTargetSettings settings, out float sum, out ref ComponentResult result, array< string > blacklistedDamageZones)
Definition: meleetargeting.c:198
GetMeleeTarget
MeleeTargetData GetMeleeTarget(MeleeTargetSettings settings, out array< Object > allTargets=null)
Definition: meleetargeting.c:192
MaxDist
float MaxDist
Definition: meleetargeting.c:31
MeleeTargetSettings
ref array< typename > TargetableObjects void MeleeTargetSettings(vector coneOrigin, float coneLength, float coneHalfAngle, float coneMinHeight, float coneMaxHeight, vector rayStart, vector dir, float maxDist, EntityAI pToIgnore, array< typename > targetableObjects)
Definition: meleetargeting.c:36
XZDir
vector XZDir
Definition: meleetargeting.c:30
GetMeleeTargetEx
MeleeTargetData GetMeleeTargetEx(MeleeTargetSettings settings, out array< Object > allTargets=null, array< string > blacklistedDamageZones=null)
Definition: meleetargeting.c:76
DiagMenu
Definition: endebug.c:232
ConeMaxHeight
float ConeMaxHeight
Definition: meleetargeting.c:22
ConeLeftPoint
vector ConeLeftPoint
Definition: meleetargeting.c:24
IsMeleeTargetObstructed
bool IsMeleeTargetObstructed(vector rayStart, vector rayEnd)
Definition: meleetargeting.c:277
ConeHalfAngle
float ConeHalfAngle
Definition: meleetargeting.c:19
EvaluateComponent
bool EvaluateComponent(Object obj, ComponentInfo cInfo, MeleeTargetSettings settings, out ref ComponentResult result)
Definition: meleetargeting.c:272
MELEE_TARGET_OBSTRUCTION_LAYERS
class ComponentResult MELEE_TARGET_OBSTRUCTION_LAYERS
DiagMenuIDs
DiagMenuIDs
Definition: ediagmenuids.c:1
ConeHalfAngleRad
float ConeHalfAngleRad
Definition: meleetargeting.c:20
Attacker
EntityAI Attacker
Definition: meleetargeting.c:33
vector
Definition: enconvert.c:105
RayEnd
vector RayEnd
Definition: meleetargeting.c:28
ShapeFlags
ShapeFlags
Definition: endebug.c:125
Object
Definition: objecttyped.c:1
ConeOrigin
class MeleeTargetData ConeOrigin
COLOR_GREEN
const int COLOR_GREEN
Definition: constants.c:65
MeleeTargetData
Definition: meleetargeting.c:1
array< typename >
ConeLength
float ConeLength
Definition: meleetargeting.c:18
BoxCollidingParams
Class that holds parameters to feed into CGame.IsBoxCollidingGeometryProxy.
Definition: isboxcollidinggeometryproxyclasses.c:2
Debug
Definition: debug.c:13
DayZPhysics
Definition: dayzphysics.c:123
ConeRightPoint
vector ConeRightPoint
Definition: meleetargeting.c:25
ConeMinHeight
float ConeMinHeight
Definition: meleetargeting.c:21
Dir
vector Dir
Definition: meleetargeting.c:29
Math
Definition: enmath.c:6
EvaluateComponentEx
bool EvaluateComponentEx(Object obj, ComponentInfo cInfo, MeleeTargetSettings settings, out ref ComponentResult result, array< string > blacklistedDamageZones)
Definition: meleetargeting.c:226
FindMostSuitableComponent
bool FindMostSuitableComponent(Object obj, BoxCollidingResult bResult, MeleeTargetSettings settings, out float sum, out ref ComponentResult result)
Definition: meleetargeting.c:221
Vector
proto native vector Vector(float x, float y, float z)
Vector constructor from components.
MAX
const int MAX
Definition: enconvert.c:27
EntityAI
Definition: building.c:5
PhxInteractionLayers
PhxInteractionLayers
Definition: dayzphysics.c:1
Math3D
Definition: enmath3d.c:27