Ticket #2034: escort.diff

File escort.diff, 23.8 KB (added by mimo, 11 years ago)

oups, i forgot the svn add ! here it is

  • binaries/data/config/default.cfg

     
    278278hotkey.session.deselectgroup = Ctrl         ; Modifier to deselect units when clicking group icon, instead of selecting
    279279hotkey.session.rotate.cw = RightBracket     ; Rotate building placement preview clockwise
    280280hotkey.session.rotate.ccw = LeftBracket     ; Rotate building placement preview anticlockwise
     281hotkey.selection.includeorder = F1          ; Include in selection the units with special orders (i.e. escort)
     282hotkey.session.escort = AltGr               ; Modifier to escort/guard when clicking on unit/building
    281283hotkey.timewarp.fastforward = Space         ; If timewarp mode enabled, speed up the game
    282284hotkey.timewarp.rewind = Backspace          ; If timewarp mode enabled, go back to earlier point in the game
    283285
  • binaries/data/mods/public/gui/session/input.js

     
    416416            if (entState.attack && targetState.hitpoints && (enemyOwned || neutralOwned))
    417417                return {"possible": Engine.GuiInterfaceCall("CanAttack", {"entity": entState.id, "target": target})};
    418418            break;
     419        case "escort":
     420            if (targetState.escort && playerOwned)
     421            {
     422                var allowedClasses = targetState.escort.allowedClasses;
     423                for each (var unitClass in entState.identity.classes)
     424                {
     425                    if (allowedClasses.indexOf(unitClass) != -1)
     426                    {
     427                        return {"possible": true};
     428                    }
     429                }
     430            }
     431            break;
    419432        }
    420433    }
    421434    if (action == "move" || action == "attack-move")
     
    503516    {
    504517            return {"type": "attack-move", "cursor": "action-attack-move"};
    505518    }
     519    else if (Engine.HotkeyIsPressed("session.escort") && getActionInfo("escort", target).possible)
     520    {
     521        return {"type": "escort", "cursor": "action-guard", "target": target};
     522    }
    506523    else
    507524    {
    508525        if ((actionInfo = getActionInfo("setup-trade-route", target)).possible)
     
    653670    return preferredEnts;
    654671}
    655672
     673// Removes any units with special orders (i.e. escort)
     674function getNoOrderEntities(ents)
     675{
     676    var noOrderEnts = [];
     677    for each (var ent in ents)
     678    {
     679        var keep = true;
     680        var entState = GetEntityState(ent);
     681        if (entState.unitAI)
     682        {
     683            for each (var order in entState.unitAI.orders)
     684            {
     685                if (order.type == "Escort")
     686                {
     687                    keep = false;
     688                    break;
     689                }
     690            }
     691        }
     692        if (keep)
     693            noOrderEnts.push(ent);
     694    }
     695    return noOrderEnts;
     696}
     697
    656698// Removes any support units from the passed list of entities
    657699function getMilitaryEntities(ents)
    658700{
     
    750792                    }
    751793                }
    752794
     795                // By default, we do not want to select units with special orders
     796                if (!Engine.HotkeyIsPressed("selection.includeorder"))
     797                    ents = getNoOrderEntities(ents);
     798
    753799                // Remove the bandbox hover highlighting
    754800                g_Selection.setHighlightList([]);
    755801
     
    12061252
    12071253                    // TODO: Should we handle "control all units" here as well?
    12081254                    ents = Engine.PickSimilarFriendlyEntities(templateToMatch, showOffscreen, matchRank, false);
     1255
     1256                    // By default, we do not want to select units with special orders
     1257                    if (!Engine.HotkeyIsPressed("selection.includeorder"))
     1258                        ents = getNoOrderEntities(ents);
    12091259                }
    12101260                else
    12111261                {
     
    13811431        Engine.GuiInterfaceCall("PlaySound", { "name": "order_garrison", "entity": selection[0] });
    13821432        return true;
    13831433
     1434    case "escort":
     1435        Engine.PostNetworkCommand({"type": "escort", "entities": selection, "target": action.target, "queued": queued});
     1436        //Engine.GuiInterfaceCall("PlaySound", { "name": "order_attack", "entity": selection[0] });
     1437        return true;
     1438
    13841439    case "set-rallypoint":
    13851440        var pos = undefined;
    13861441        // if there is a position set in the action then use this so that when setting a
  • binaries/data/mods/public/simulation/templates/template_unit_support.xml

     
    1515    <GenericName>Support</GenericName>
    1616    <Classes datatype="tokens">Support Organic</Classes>
    1717  </Identity>
     18  <Escort>
     19    <List datatype="tokens">Support Infantry Cavalry</List>
     20    <LandEscortRange>8</LandEscortRange>
     21  </Escort>
    1822  <Loot>
    1923    <xp>10</xp>
    2024    <food>1</food>
  • binaries/data/mods/public/simulation/templates/template_unit_infantry.xml

     
    5151    <Classes datatype="tokens">Infantry CitizenSoldier Worker Organic</Classes>
    5252    <Rank>Basic</Rank>
    5353  </Identity>
     54  <Escort>
     55    <List datatype="tokens">Support Infantry Cavalry</List>
     56    <LandEscortRange>8</LandEscortRange>
     57  </Escort>
    5458  <Loot>
    5559    <xp>100</xp>
    5660    <food>5</food>
  • binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship.xml

     
    3333    <GenericName>Ship</GenericName>
    3434    <Classes datatype="tokens">Ship</Classes>
    3535  </Identity>
     36  <Escort>
     37    <List datatype="tokens">Ship</List>
     38    <NavalEscortRange>20</NavalEscortRange>
     39  </Escort>
    3640  <Obstruction>
    3741    <Unit radius="8.0"/>
    3842  </Obstruction>
  • binaries/data/mods/public/simulation/templates/template_unit_cavalry.xml

     
    3333    <GenericName>Cavalry</GenericName>
    3434    <Rank>Basic</Rank>
    3535  </Identity>
     36  <Escort>
     37    <List datatype="tokens">Cavalry</List>
     38    <LandEscortRange>8</LandEscortRange>
     39  </Escort>
    3640  <Loot>
    3741    <xp>130</xp>
    3842    <food>10</food>
  • binaries/data/mods/public/simulation/templates/template_structure.xml

     
    1414    <DefaultArrowCount>0</DefaultArrowCount>
    1515    <GarrisonArrowMultiplier>0</GarrisonArrowMultiplier>
    1616  </BuildingAI>
     17  <Escort>
     18    <List datatype="tokens">Infantry</List>
     19    <LandEscortRange>12</LandEscortRange>
     20  </Escort>
    1721  <BuildRestrictions>
    1822    <PlacementType>land</PlacementType>
    1923    <Territory>own</Territory>
  • binaries/data/mods/public/simulation/templates/template_unit_mechanical.xml

     
    1414    <GenericName>Mechanical</GenericName>
    1515    <Classes datatype="tokens">Mechanical</Classes>
    1616  </Identity>
     17  <Escort>
     18    <List datatype="tokens">Infantry Cavalry</List>
     19    <LandEscortRange>8</LandEscortRange>
     20  </Escort>
    1721  <Loot>
    1822    <xp>60</xp>
    1923    <food>0</food>
  • binaries/data/mods/public/simulation/templates/template_unit_champion.xml

     
    88    <Classes datatype="tokens">Champion Organic</Classes>
    99    <RequiredTechnology>phase_city</RequiredTechnology>
    1010  </Identity>
     11  <Escort>
     12    <List datatype="tokens">Support Infantry Cavalry</List>
     13    <LandEscortRange>8</LandEscortRange>
     14  </Escort>
    1115  <Loot>
    1216    <xp>150</xp>
    1317    <food>10</food>
  • binaries/data/mods/public/simulation/templates/template_unit_hero.xml

     
    3838    <Classes datatype="tokens">Hero Organic</Classes>
    3939    <RequiredTechnology>phase_city</RequiredTechnology>
    4040  </Identity>
     41  <Escort>
     42    <List datatype="tokens">Support Infantry Cavalry</List>
     43    <LandEscortRange>8</LandEscortRange>
     44  </Escort>
    4145  <Loot>
    4246    <xp>400</xp>
    4347    <food>10</food>
  • binaries/data/mods/public/simulation/templates/template_structure_military_dock.xml

     
    2626    <Classes datatype="tokens">Village Naval Market NavalMarket Dock</Classes>
    2727    <Icon>structures/dock.png</Icon>
    2828  </Identity>
     29  <Escort>
     30    <List datatype="tokens">Infantry Ship</List>
     31    <LandEscortRange>12</LandEscortRange>
     32    <NavalEscortRange>20</NavalEscortRange>
     33  </Escort>
    2934  <Loot>
    3035    <xp>100</xp>
    3136    <food>0</food>
  • binaries/data/mods/public/simulation/helpers/Commands.js

     
    319319        }
    320320        break;
    321321
     322    case "escort":
     323        // Verify that the building can be controlled by the player
     324        if (CanControlUnit(cmd.target, player, controlAllUnits))
     325        {
     326            GetFormationUnitAIs(entities, player).forEach(function(cmpUnitAI) {
     327                cmpUnitAI.Escort(cmd.target, cmd.queued);
     328            });
     329        }
     330        else if (g_DebugCommands)
     331        {
     332            warn("Invalid command: escort target cannot be controlled by player "+player+": "+uneval(cmd));
     333        }
     334        break;
     335
    322336    case "stop":
    323337        GetFormationUnitAIs(entities, player).forEach(function(cmpUnitAI) {
    324338            cmpUnitAI.Stop(cmd.queued);
  • binaries/data/mods/public/simulation/components/UnitAI.js

     
    160160        // ignore
    161161    },
    162162
     163    "EscortedAttacked": function(msg) {
     164        // ignore
     165    },
     166
    163167    // Formation handlers:
    164168
    165169    "FormationLeave": function(msg) {
     
    328332        }
    329333    },
    330334
     335    "Order.Escort": function(msg) {
     336        var cmpEscort = Engine.QueryInterface(this.order.data.target, IID_Escort);
     337        if (!cmpEscort || !cmpEscort.AllowedToEscort(this.entity))
     338        {
     339            this.FinishOrder();
     340            return;
     341        }
     342        this.escortRange = cmpEscort.GetRange(this.entity);
     343
     344        var ok = this.MoveToTargetRangeExplicit(this.order.data.target, 0, this.escortRange);
     345        if (ok)
     346            this.SetNextState("INDIVIDUAL.ESCORT.ESCORTING");
     347        else
     348            this.SetNextState("INDIVIDUAL.ESCORT.GUARDING");
     349    },
     350
    331351    "Order.Flee": function(msg) {
    332352        // We use the distance between the enities to account for ranged attacks
    333353        var distance = DistanceBetweenEntities(this.entity, this.order.data.target) + (+this.template.FleeDistance);
     
    685705                this.FinishOrder();
    686706        },
    687707
     708        "Order.Escort": function(msg) {
     709            var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation);
     710            cmpFormation.CallMemberFunction("Escort", [msg.data.target, false]);
     711            cmpFormation.Disband();
     712        },
     713
    688714        "Order.Stop": function(msg) {
    689715            var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation);
    690716            cmpFormation.CallMemberFunction("Stop", [false]);
     
    11481174            }
    11491175        },
    11501176
     1177        "EscortedAttacked": function(msg) {
     1178            this.RespondToTargetedEntities([msg.data.attacker]);
     1179        },
     1180
    11511181        "IDLE": {
    11521182            "enter": function() {
    11531183                // Switch back to idle animation to guarantee we won't
     
    12521282            },
    12531283        },
    12541284
     1285        "ESCORT": {
     1286            "enter": function () {
     1287                if (this.escort && this.escort != this.order.data.target)
     1288                {
     1289                    Engine.PostMessage(this.escort, MT_EscortChanged, { "escort": this.entity });
     1290                    this.escort = undefined;
     1291                }
     1292
     1293                if (!this.escort)
     1294                {
     1295                    this.escort = this.order.data.target;
     1296                    Engine.PostMessage(this.escort, MT_EscortChanged, { "escort": this.entity });
     1297                }
     1298
     1299                this.order.data.status = "running";
     1300            },
     1301
     1302            "leave": function () {
     1303                // if not dead, check if it's just a temporary leave (i.e. to attack or repair)
     1304                if (this.TargetIsAlive(this.entity))
     1305                {
     1306                    for each (var order in this.orderQueue)
     1307                    {
     1308                        if (order.type == "Escort"  && order.data.target == this.escort && order.data.status == "running")
     1309                            return;
     1310                    }
     1311                }
     1312                Engine.PostMessage(this.escort, MT_EscortChanged, { "escort": this.entity });
     1313                delete this.escortRange;
     1314                delete this.escort;
     1315            },
     1316
     1317            "ESCORTING": {
     1318                "enter": function () {
     1319                    this.StartTimer(0, 1000);
     1320                    this.SelectAnimation("move");
     1321                    var cmpPosition = Engine.QueryInterface(this.escort, IID_Position);
     1322                    if (cmpPosition && cmpPosition.IsInWorld())
     1323                    {
     1324                        var pos = cmpPosition.GetPosition();
     1325                        this.SetHeldPosition(pos.x, pos.z);
     1326                    }
     1327                    // adapt the speed to the one of the target
     1328                    var cmpUnitAI = Engine.QueryInterface(this.escort, IID_UnitAI);
     1329                    if (cmpUnitAI)
     1330                    {
     1331                        var speed = cmpUnitAI.GetWalkSpeed();
     1332                        if (speed < this.GetWalkSpeed())
     1333                            this.SetMoveSpeed(speed);
     1334                    }
     1335                },
     1336
     1337                "Timer": function(msg) {
     1338                    // Check the target is alive
     1339                    if (!this.TargetIsAlive(this.escort))
     1340                    {
     1341                        this.FinishOrder();
     1342                        return;
     1343                    }
     1344                    var cmpPosition = Engine.QueryInterface(this.escort, IID_Position);
     1345                    if (cmpPosition && cmpPosition.IsInWorld())
     1346                    {
     1347                        var pos = cmpPosition.GetPosition();
     1348                        this.SetHeldPosition(pos.x, pos.z);
     1349                    }
     1350                    this.FindNewTargets();
     1351                },
     1352
     1353                "leave": function(msg) {
     1354                    this.SetMoveSpeed(this.GetWalkSpeed());
     1355                    this.StopTimer();
     1356                },
     1357
     1358                "MoveCompleted": function() {
     1359                    var ok = this.MoveToTargetRangeExplicit(this.escort, 0, this.escortRange);
     1360                    if (!ok)
     1361                        this.SetNextState("GUARDING");
     1362                },
     1363            },
     1364
     1365            "GUARDING": {
     1366                "enter": function () {
     1367                    this.StartTimer(1000, 1000);
     1368                    var cmpPosition = Engine.QueryInterface(this.entity, IID_Position);
     1369                    if (cmpPosition && cmpPosition.IsInWorld())
     1370                    {
     1371                        var pos = cmpPosition.GetPosition();
     1372                        this.SetHeldPosition(pos.x, pos.z);
     1373                    }
     1374                    this.SelectAnimation("idle");
     1375                    if (this.FindNewTargets())
     1376                        return true;
     1377                    return false;
     1378                },
     1379
     1380                "LosRangeUpdate": function(msg) {
     1381                    // Start attacking one of the newly-seen enemy (if any)
     1382                    if (this.GetStance().targetVisibleEnemies)
     1383                        this.AttackEntitiesByPreference(msg.data.added);
     1384                },
     1385
     1386                "LosGaiaRangeUpdate": function(msg) {
     1387                    // Start attacking one of the newly-seen enemy (if any)
     1388                    if (this.GetStance().targetVisibleEnemies)
     1389                        this.AttackGaiaEntitiesByPreference(msg.data.added);
     1390                },
     1391
     1392                "Timer": function(msg) {
     1393                    // Check the target is alive
     1394                    if (!this.TargetIsAlive(this.escort))
     1395                    {
     1396                        this.FinishOrder();
     1397                        return;
     1398                    }
     1399                    // then check is the target has moved
     1400                    var ok = this.MoveToTargetRangeExplicit(this.escort, 0, this.escortRange);
     1401                    if (ok)
     1402                        this.SetNextState("ESCORTING");
     1403                    else
     1404                    {
     1405                        // if nothing else to do, check if the escorted needs to be healed or repaired
     1406                        var cmpHealth = Engine.QueryInterface(this.escort, IID_Health);
     1407                        if (cmpHealth && (cmpHealth.GetHitpoints() < cmpHealth.GetMaxHitpoints()))
     1408                        {
     1409                            if (this.CanHeal(this.escort))
     1410                                this.PushOrderFront("Heal", { "target": this.escort, "force": false });
     1411                            else if (this.CanRepair(this.escort) && cmpHealth.IsRepairable())
     1412                                this.PushOrderFront("Repair", { "target": this.escort, "autocontinue": false, "force": false });
     1413                        }
     1414                    }
     1415                },
     1416
     1417                "leave": function(msg) {
     1418                    this.StopTimer();
     1419                },
     1420            },
     1421        },
     1422
    12551423        "FLEEING": {
    12561424            "enter": function() {
    12571425                this.PlaySound("panic");
     
    20992267                    return false;
    21002268                },
    21012269
     2270                "LosRangeUpdate": function(msg) {
     2271                    // if we are escorting, stop repairing to be able to fight this ennemy
     2272                    if (this.escort && this.GetStance().targetVisibleEnemies)
     2273                        this.FinishOrder();
     2274                },
     2275
     2276                "LosGaiaRangeUpdate": function(msg) {
     2277                    // if we are escorting, stop repairing to be able to fight this ennemy
     2278                    if (this.escort && this.GetStance().targetVisibleEnemies)
     2279                        this.FinishOrder();
     2280                },
     2281
    21022282                "leave": function() {
    21032283                    var cmpFoundation = Engine.QueryInterface(this.repairTarget, IID_Foundation);
    21042284                    if (cmpFoundation)
     
    29783158    UnitFsm.ProcessMessage(this, {"type": "Attacked", "data": msg});
    29793159};
    29803160
     3161UnitAI.prototype.OnEscortedAttacked = function(msg)
     3162{
     3163    UnitFsm.ProcessMessage(this, {"type": "EscortedAttacked", "data": msg.data});
     3164};
     3165
    29813166UnitAI.prototype.OnHealthChanged = function(msg)
    29823167{
    29833168    UnitFsm.ProcessMessage(this, {"type": "HealthChanged", "from": msg.from, "to": msg.to});
     
    35193704    if (force)
    35203705        return false;
    35213706
     3707    // If we are escorting, don't stop as long as the attacker is within attack range of the escorted
     3708    if (this.escort)
     3709    {
     3710        var cmpUnitAI =  Engine.QueryInterface(target, IID_UnitAI);
     3711        var cmpAttack = Engine.QueryInterface(target, IID_Attack);
     3712        for each (var type in cmpAttack.GetAttackTypes())
     3713            if (cmpUnitAI.CheckTargetRange(this.escort, IID_Attack, type))
     3714                return false;
     3715    }
     3716
    35223717    // Stop if we're in hold-ground mode and it's too far from the holding point
    35233718    if (this.GetStance().respondHoldGround)
    35243719    {
     
    35533748    if (this.GetStance().respondChase)
    35543749        return true;
    35553750
     3751    if (this.escort)
     3752    {
     3753        var cmpUnitAI =  Engine.QueryInterface(target, IID_UnitAI);
     3754        var cmpAttack = Engine.QueryInterface(target, IID_Attack);
     3755        for each (var type in cmpAttack.GetAttackTypes())
     3756            if (cmpUnitAI.CheckTargetRange(this.escort, IID_Attack, type))
     3757                return true;
     3758    }
     3759
    35563760    if (force)
    35573761        return true;
    35583762
     
    36533857
    36543858        case "WalkToTarget":
    36553859        case "WalkToTargetRange": // This doesn't move to the target (just into range), but a later order will.
     3860        case "Escort":
    36563861        case "Flee":
    36573862        case "LeaveFoundation":
    36583863        case "Attack":
     
    36983903};
    36993904
    37003905/**
     3906 * Adds escort order to the queue, forced by the player.
     3907 */
     3908UnitAI.prototype.Escort = function(target, queued)
     3909{
     3910    this.AddOrder("Escort", { "target": target, "status": "waiting", "force": false }, queued);
     3911};
     3912
     3913/**
    37013914 * Adds walk order to queue, forced by the player.
    37023915 */
    37033916UnitAI.prototype.Walk = function(x, z, queued)
     
    41614374{
    41624375    if (this.heldPosition)
    41634376    {
    4164         this.AddOrder("Walk", { "x": this.heldPosition.x, "z": this.heldPosition.z, "force": false }, false);
     4377        this.PushOrderFront("Walk", { "x": this.heldPosition.x, "z": this.heldPosition.z, "force": false });
    41654378        return true;
    41664379    }
    41674380    return false;
  • binaries/data/mods/public/simulation/components/Escort.js

     
     1function Escort() {}
     2
     3Escort.prototype.Schema =
     4    "<element name='List' a:help='Classes of entities which are allowed to escort this escorted (from Identity)'>" +
     5        "<attribute name='datatype'>" +
     6            "<value>tokens</value>" +
     7        "</attribute>" +
     8        "<text/>" +
     9    "</element>" +
     10    "<optional><element name='LandEscortRange' a:help='Distance between the escort and this escorted'>" +
     11        "<ref name='nonNegativeDecimal'/>" +
     12    "</element></optional>" +
     13    "<optional><element name='NavalEscortRange' a:help='Distance between the escort ship and this escorted'>" +
     14            "<ref name='nonNegativeDecimal'/>" +
     15    "</element></optional>";
     16
     17Escort.prototype.Init = function()
     18{
     19    this.escortList = [];
     20};
     21
     22Escort.prototype.GetRange = function(entity)
     23{
     24    var entityClasses = (Engine.QueryInterface(entity, IID_Identity)).GetClassesList();
     25    if (entityClasses.indexOf("Ship") == -1)
     26        return (+this.template.LandEscortRange || 8);
     27    else
     28        return (+this.template.NavalEscortRange || 20);
     29};
     30
     31/**
     32 * Returns an array of unit classes which can escort this entity.
     33 * Obtained from the entity's template
     34 */
     35Escort.prototype.GetAllowedClassesList = function()
     36{
     37    var string = this.template.List._string || "";
     38    return string.split(/\s+/);
     39};
     40
     41/**
     42 * Checks if an entity can be allowed to escort this escorted
     43 * based on its class
     44 */
     45Escort.prototype.AllowedToEscort = function(entity)
     46{
     47    var allowedClasses = this.GetAllowedClassesList();
     48    var entityClasses = (Engine.QueryInterface(entity, IID_Identity)).GetClassesList();
     49    for each (var allowedClass in allowedClasses)
     50    {
     51        if (entityClasses.indexOf(allowedClass) != -1)
     52            return true;
     53    }
     54    return false;
     55};
     56
     57Escort.prototype.OnAttacked = function(msg)
     58{
     59    for each (var escort in this.escortList)
     60        Engine.PostMessage(escort, MT_EscortedAttacked, { "escorted": this.entity, "data": msg });
     61};
     62
     63Escort.prototype.OnEscortChanged = function(msg)
     64{
     65    if (this.escortList.indexOf(msg.escort) == -1)
     66        this.escortList.push(msg.escort);
     67    else
     68        this.escortList.splice(this.escortList.indexOf(msg.escort), 1);
     69};
     70
     71Escort.prototype.OnGlobalEntityRenamed = function(msg)
     72{
     73    if (this.escortList.length == 0)
     74        return;
     75    var entityIndex = this.escortList.indexOf(msg.entity);
     76    if (entityIndex != -1)
     77        this.escortList[entityIndex] = msg.newentity;
     78};
     79
     80Engine.RegisterComponentType(IID_Escort, "Escort", Escort);
  • binaries/data/mods/public/simulation/components/GuiInterface.js

     
    323323        if (cmpUnitAI.isGarrisoned && ret.player)
    324324            ret.template = "p" + ret.player + "&" + ret.template;
    325325    }
     326
     327    var cmpEscort = Engine.QueryInterface(ent, IID_Escort);
     328    if (cmpEscort)
     329    {
     330        ret.escort = {
     331            "allowedClasses": cmpEscort.GetAllowedClassesList()
     332        }
     333    }
    326334   
    327335    var cmpGate = Engine.QueryInterface(ent, IID_Gate);
    328336    if (cmpGate)
  • binaries/data/mods/public/simulation/components/interfaces/UnitAI.js

     
    1111// Message of the form { "to": orderData }.
    1212// sent whenever the unit changes state
    1313Engine.RegisterMessageType("UnitAIOrderDataChanged");
     14
     15// Message of the form { "escort": escort }.
     16// sent whenever an escort is added or removed
     17Engine.RegisterMessageType("EscortChanged");
  • binaries/data/mods/public/simulation/components/interfaces/Escort.js

     
     1Engine.RegisterInterface("Escort");
     2
     3// Message of the form { "escorted": entity, "data": msg },
     4// sent whenever an escorted unit is attacked
     5Engine.RegisterMessageType("EscortedAttacked");