LCOV - code coverage report
Current view: top level - simulation/helpers - Position.js (source / functions) Hit Total Coverage
Test: lcov.info Lines: 57 67 85.1 %
Date: 2023-04-02 12:52:40 Functions: 7 7 100.0 %

          Line data    Source code
       1             : function PositionHelper() {}
       2             : 
       3             : /**
       4             :  * @param {number} firstEntity - The entityID of an entity.
       5             :  * @param {number} secondEntity - The entityID of an entity.
       6             :  *
       7             :  * @return {number} - The horizontal distance between the two given entities. Returns
       8             :  *                      infinity when the distance cannot be calculated.
       9             :  */
      10           6 : PositionHelper.prototype.DistanceBetweenEntities = function(firstEntity, secondEntity)
      11             : {
      12           5 :         let cmpFirstPosition = Engine.QueryInterface(firstEntity, IID_Position);
      13           5 :         if (!cmpFirstPosition || !cmpFirstPosition.IsInWorld())
      14           1 :                 return Infinity;
      15             : 
      16           4 :         let cmpSecondPosition = Engine.QueryInterface(secondEntity, IID_Position);
      17           4 :         if (!cmpSecondPosition || !cmpSecondPosition.IsInWorld())
      18           0 :                 return Infinity;
      19             : 
      20           4 :         return cmpFirstPosition.GetPosition2D().distanceTo(cmpSecondPosition.GetPosition2D());
      21             : };
      22             : 
      23             : /**
      24             :  * @param {Vector2D} origin - The point to check around.
      25             :  * @param {number}   radius - The radius around the point to check.
      26             :  * @param {number[]} players - The players of which we need to check entities.
      27             :  * @param {number}   iid - Interface IID that returned entities must implement. Defaults to none.
      28             :  *
      29             :  * @return {number[]} The id's of the entities in range of the given point.
      30             :  */
      31           6 : PositionHelper.prototype.EntitiesNearPoint = function(origin, radius, players, iid = 0)
      32             : {
      33          18 :         if (!origin || !radius || !players || !players.length)
      34           0 :                 return [];
      35             : 
      36          18 :         let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
      37          18 :         return cmpRangeManager.ExecuteQueryAroundPos(origin, 0, radius, players, iid, true);
      38             : };
      39             : 
      40             : /**
      41             :  * Gives the position of the given entity, taking the lateness into account.
      42             :  * Note that vertical movement is ignored.
      43             :  *
      44             :  * @param {number} ent - Entity id of the entity we are finding the location for.
      45             :  * @param {number} lateness - The time passed since the expected time to fire the function.
      46             :  *
      47             :  * @return {Vector3D} The interpolated location of the entity.
      48             :  */
      49           6 : PositionHelper.prototype.InterpolatedLocation = function(ent, lateness)
      50             : {
      51          33 :         let cmpTargetPosition = Engine.QueryInterface(ent, IID_Position);
      52          33 :         if (!cmpTargetPosition || !cmpTargetPosition.IsInWorld()) // TODO: handle dead target properly
      53           2 :                 return undefined;
      54          31 :         let curPos = cmpTargetPosition.GetPosition();
      55          31 :         let prevPos = cmpTargetPosition.GetPreviousPosition();
      56          31 :         let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
      57          31 :         let turnLength = cmpTimer.GetLatestTurnLength();
      58          31 :         return new Vector3D(
      59             :             (curPos.x * (turnLength - lateness) + prevPos.x * lateness) / turnLength,
      60             :             0,
      61             :             (curPos.z * (turnLength - lateness) + prevPos.z * lateness) / turnLength
      62             :         );
      63             : };
      64             : 
      65             : /**
      66             :  * Test if a point is inside an entity's footprint.
      67             :  * Note that edges may be not included for square entities due to rounding.
      68             :  *
      69             :  * @param {number} ent - Id of the entity we are checking with.
      70             :  * @param {Vector3D} point - The point we are checking with.
      71             :  * @param {number} lateness - The time passed since the expected time to fire the function.
      72             :  *
      73             :  * @return {boolean} True if the point is inside of the entity's footprint.
      74             :  */
      75           6 : PositionHelper.prototype.TestCollision = function(ent, point, lateness)
      76             : {
      77          46 :         let targetPosition = this.InterpolatedLocation(ent, lateness);
      78          46 :         if (!targetPosition)
      79           1 :                 return false;
      80             : 
      81          45 :         let cmpFootprint = Engine.QueryInterface(ent, IID_Footprint);
      82          45 :         if (!cmpFootprint)
      83           1 :                 return false;
      84             : 
      85          44 :         let targetShape = cmpFootprint.GetShape();
      86          44 :         if (!targetShape)
      87           1 :                 return false;
      88             : 
      89          43 :         if (targetShape.type == "circle")
      90          27 :                 return targetPosition.horizDistanceToSquared(point) < targetShape.radius * targetShape.radius;
      91             : 
      92          16 :         if (targetShape.type == "square")
      93             :         {
      94          16 :                 let angle = Engine.QueryInterface(ent, IID_Position).GetRotation().y;
      95          16 :                 let distance = Vector2D.from3D(Vector3D.sub(point, targetPosition)).rotate(-angle);
      96          16 :                 return Math.abs(distance.x) < targetShape.width / 2 && Math.abs(distance.y) < targetShape.depth / 2;
      97             :         }
      98             : 
      99           0 :         warn("TestCollision called with an invalid footprint shape: " + targetShape.type + ".");
     100           0 :         return false;
     101             : };
     102             : 
     103             : /**
     104             :  * Get the predicted time of collision between a projectile (or a chaser)
     105             :  * and its target, assuming they both move in straight line at a constant speed.
     106             :  * Vertical component of movement is ignored.
     107             :  *
     108             :  * @param {Vector3D} firstPosition - The 3D position of the projectile (or chaser).
     109             :  * @param {number} selfSpeed - The horizontal speed of the projectile (or chaser).
     110             :  * @param {Vector3D} targetPosition - The 3D position of the target.
     111             :  * @param {Vector3D} targetVelocity - The 3D velocity vector of the target.
     112             :  *
     113             :  * @return {number|boolean} - The time to collision or false if the collision will not happen.
     114             :  */
     115           6 : PositionHelper.prototype.PredictTimeToTarget = function(firstPosition, selfSpeed, targetPosition, targetVelocity)
     116             : {
     117       18254 :         let relativePosition = new Vector3D.sub(targetPosition, firstPosition);
     118       18254 :         let a = targetVelocity.x * targetVelocity.x + targetVelocity.z * targetVelocity.z - selfSpeed * selfSpeed;
     119       18254 :         let b = relativePosition.x * targetVelocity.x + relativePosition.z * targetVelocity.z;
     120       18254 :         let c = relativePosition.x * relativePosition.x + relativePosition.z * relativePosition.z;
     121             : 
     122             :         // The predicted time to reach the target is the smallest non negative solution
     123             :         // (when it exists) of the equation a t^2 + 2 b t + c = 0.
     124             :         // Using c>=0, we can straightly compute the right solution.
     125             : 
     126       18254 :         if (c == 0)
     127         756 :                 return 0;
     128             : 
     129       17498 :         let disc = b * b - a * c;
     130       17498 :         if (a < 0 || b < 0 && disc >= 0)
     131        9813 :                 return c / (Math.sqrt(disc) - b);
     132             : 
     133        7685 :         return false;
     134             : };
     135             : 
     136             : /**
     137             :  * @param {number} target - EntityID to find the spawn position for.
     138             :  * @param {number} entity - EntityID to find the spawn position for.
     139             :  * @param {boolean} forced - Optionally whether the spawning is forced.
     140             :  * @return {Vector3D} - An appropriate spawning position.
     141             :  */
     142           6 : PositionHelper.prototype.GetSpawnPosition = function(target, entity, forced)
     143             : {
     144          11 :         let cmpFootprint = Engine.QueryInterface(target, IID_Footprint);
     145          11 :         let cmpHealth = Engine.QueryInterface(target, IID_Health);
     146          11 :         let cmpIdentity = Engine.QueryInterface(target, IID_Identity);
     147             : 
     148          11 :         if (!cmpFootprint)
     149           0 :                 return null;
     150             : 
     151             :         // If the spawner is a sinking ship, restrict the location to the intersection of both passabilities.
     152             :         // TODO: should use passability classes to be more generic.
     153             :         let pos;
     154          11 :         if ((!cmpHealth || cmpHealth.GetHitpoints() == 0) && cmpIdentity && cmpIdentity.HasClass("Ship"))
     155           0 :                 pos = cmpFootprint.PickSpawnPointBothPass(entity);
     156             :         else
     157          11 :                 pos = cmpFootprint.PickSpawnPoint(entity);
     158             : 
     159          11 :         if (pos.y < 0)
     160             :         {
     161           0 :                 if (!forced)
     162           0 :                         return null;
     163             : 
     164             :                 // If ejection is forced, we need to continue, so use center of the entity.
     165           0 :                 let cmpPosition = Engine.QueryInterface(target, IID_Position);
     166           0 :                 pos = cmpPosition.GetPosition();
     167             :         }
     168          11 :         return pos;
     169             : };
     170             : 
     171           6 : Engine.RegisterGlobal("PositionHelper", new PositionHelper());

Generated by: LCOV version 1.14