LCOV - code coverage report
Current view: top level - simulation/components - AttackDetection.js (source / functions) Hit Total Coverage
Test: lcov.info Lines: 0 71 0.0 %
Date: 2023-04-02 12:52:40 Functions: 0 10 0.0 %

          Line data    Source code
       1             : function AttackDetection() {}
       2             : 
       3           0 : AttackDetection.prototype.Schema =
       4             :         "<a:help>Detects incoming attacks.</a:help>" +
       5             :         "<a:example/>" +
       6             :         "<element name='SuppressionTransferRange' a:help='Any attacks within this range in meters will replace the previous attack suppression'>" +
       7             :                 "<ref name='positiveDecimal'/>" +
       8             :         "</element>" +
       9             :         "<element name='SuppressionRange' a:help='Other attacks within this range in meters will not be registered'>" +
      10             :                 "<ref name='positiveDecimal'/>" +
      11             :         "</element>" +
      12             :         "<element name='SuppressionTime' a:help='Other attacks within this time in milliseconds will not be registered'>" +
      13             :                 "<data type='positiveInteger'/>" +
      14             :         "</element>";
      15             : 
      16           0 : AttackDetection.prototype.Init = function()
      17             : {
      18           0 :         this.suppressionTime = +this.template.SuppressionTime;
      19             :         // Use squared distance to avoid sqrts
      20           0 :         this.suppressionTransferRangeSquared = +this.template.SuppressionTransferRange * +this.template.SuppressionTransferRange;
      21           0 :         this.suppressionRangeSquared = +this.template.SuppressionRange * +this.template.SuppressionRange;
      22           0 :         this.suppressedList = [];
      23             : };
      24             : 
      25           0 : AttackDetection.prototype.ActivateTimer = function()
      26             : {
      27           0 :         Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer).SetTimeout(this.entity, IID_AttackDetection, "HandleTimeout", this.suppressionTime);
      28             : };
      29             : 
      30           0 : AttackDetection.prototype.AddSuppression = function(event)
      31             : {
      32           0 :         this.suppressedList.push(event);
      33           0 :         this.ActivateTimer();
      34             : };
      35             : 
      36           0 : AttackDetection.prototype.UpdateSuppressionEvent = function(index, event)
      37             : {
      38           0 :         this.suppressedList[index] = event;
      39           0 :         this.ActivateTimer();
      40             : };
      41             : 
      42             : // Message handlers
      43             : 
      44           0 : AttackDetection.prototype.OnGlobalAttacked = function(msg)
      45             : {
      46           0 :         var cmpPlayer = Engine.QueryInterface(this.entity, IID_Player);
      47           0 :         var cmpOwnership = Engine.QueryInterface(msg.target, IID_Ownership);
      48           0 :         if (cmpOwnership.GetOwner() != cmpPlayer.GetPlayerID())
      49           0 :                 return;
      50             : 
      51           0 :         Engine.PostMessage(msg.target, MT_MinimapPing);
      52             : 
      53           0 :         this.AttackAlert(msg.target, msg.attacker, msg.type, msg.attackerOwner);
      54             : };
      55             : 
      56             : // External interface
      57             : 
      58           0 : AttackDetection.prototype.AttackAlert = function(target, attacker, type, attackerOwner)
      59             : {
      60           0 :         let playerID = Engine.QueryInterface(this.entity, IID_Player).GetPlayerID();
      61             : 
      62             :         // Don't register attacks dealt against other players
      63           0 :         if (Engine.QueryInterface(target, IID_Ownership).GetOwner() != playerID)
      64           0 :                 return;
      65             : 
      66           0 :         let cmpAttackerOwnership = Engine.QueryInterface(attacker, IID_Ownership);
      67           0 :         let atkOwner = cmpAttackerOwnership && cmpAttackerOwnership.GetOwner() != INVALID_PLAYER ? cmpAttackerOwnership.GetOwner() : attackerOwner;
      68             :         // Don't register attacks dealt by myself
      69           0 :         if (atkOwner == playerID)
      70           0 :                 return;
      71             : 
      72             :         // Since livestock can be attacked/gathered by other players
      73             :         // and generally are not so valuable as other units/buildings,
      74             :         // we have a lower priority notification for it, which can be
      75             :         // overriden by a regular one.
      76           0 :         var cmpTargetIdentity = Engine.QueryInterface(target, IID_Identity);
      77           0 :         var targetIsDomesticAnimal = cmpTargetIdentity && cmpTargetIdentity.HasClass("Animal") && cmpTargetIdentity.HasClass("Domestic");
      78             : 
      79           0 :         var cmpPosition = Engine.QueryInterface(target, IID_Position);
      80           0 :         if (!cmpPosition || !cmpPosition.IsInWorld())
      81           0 :                 return;
      82           0 :         var event = {
      83             :                 "target": target,
      84             :                 "position": cmpPosition.GetPosition(),
      85             :                 "time": Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer).GetTime(),
      86             :                 "targetIsDomesticAnimal": targetIsDomesticAnimal
      87             :         };
      88             : 
      89             :         // If we already have a low priority livestock event in suppressed list,
      90             :         // and now a more important target is attacked, we want to upgrade the
      91             :         // suppressed event and send the new notification
      92           0 :         var isPriorityIncreased = false;
      93           0 :         for (var i = 0; i < this.suppressedList.length; ++i)
      94             :         {
      95           0 :                 var element = this.suppressedList[i];
      96             : 
      97             :                 // If the new attack is within suppression distance of this element,
      98             :                 // then check if the element should be updated and return
      99           0 :                 var dist = event.position.horizDistanceToSquared(element.position);
     100           0 :                 if (dist >= this.suppressionRangeSquared)
     101           0 :                         continue;
     102             : 
     103           0 :                 isPriorityIncreased = element.targetIsDomesticAnimal && !targetIsDomesticAnimal;
     104           0 :                 var isPriorityDescreased = !element.targetIsDomesticAnimal && targetIsDomesticAnimal;
     105             : 
     106           0 :                 if (isPriorityIncreased ||
     107             :                     (!isPriorityDescreased && dist < this.suppressionTransferRangeSquared))
     108           0 :                         this.UpdateSuppressionEvent(i, event);
     109             : 
     110             :                 // If priority has increased, exit the loop to send the upgraded notification below
     111           0 :                 if (isPriorityIncreased)
     112           0 :                         break;
     113             : 
     114           0 :                 return;
     115             :         }
     116             : 
     117             :         // If priority has increased for an existing event, then we already have it
     118             :         // in the suppression list
     119           0 :         if (!isPriorityIncreased)
     120           0 :                 this.AddSuppression(event);
     121             : 
     122           0 :         Engine.PostMessage(this.entity, MT_AttackDetected, { "player": playerID, "event": event });
     123           0 :         Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface).PushNotification({
     124             :                 "type": "attack",
     125             :                 "target": target,
     126             :                 "players": [playerID],
     127             :                 "attacker": atkOwner,
     128             :                 "position": event.position,
     129             :                 "targetIsDomesticAnimal": targetIsDomesticAnimal
     130             :         });
     131             : 
     132           0 :         let soundGroup = "attacked";
     133           0 :         if (type == "capture")
     134           0 :                 soundGroup += "_capture";
     135             : 
     136           0 :         if (attackerOwner === 0)
     137           0 :                 soundGroup += "_gaia";
     138             : 
     139           0 :         PlaySound(soundGroup, target);
     140             : };
     141             : 
     142           0 : AttackDetection.prototype.GetSuppressionTime = function()
     143             : {
     144           0 :         return this.suppressionTime;
     145             : };
     146             : 
     147           0 : AttackDetection.prototype.HandleTimeout = function()
     148             : {
     149           0 :         var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
     150           0 :         var now = cmpTimer.GetTime();
     151           0 :         for (var i = 0; i < this.suppressedList.length; ++i)
     152             :         {
     153           0 :                 var event = this.suppressedList[i];
     154             : 
     155             :                 // Check if this event has timed out
     156           0 :                 if (now - event.time >= this.suppressionTime)
     157             :                 {
     158           0 :                         this.suppressedList.splice(i, 1);
     159           0 :                         return;
     160             :                 }
     161             :         }
     162             : };
     163             : 
     164           0 : AttackDetection.prototype.GetIncomingAttacks = function()
     165             : {
     166           0 :         return this.suppressedList;
     167             : };
     168             : 
     169           0 : Engine.RegisterComponentType(IID_AttackDetection, "AttackDetection", AttackDetection);

Generated by: LCOV version 1.14