Ticket #1720: patrol_V3.4.patch

File patrol_V3.4.patch, 10.2 KB (added by sanderd17, 3 years ago)

Update to current SVN

  • binaries/data/config/default.cfg

     
    284284garrison = Ctrl              ; Modifier to garrison when clicking on building
    285285autorallypoint = Ctrl        ; Modifier to set the rally point on the building itself
    286286guard = "G"                  ; Modifier to escort/guard when clicking on unit/building
     287patrol = "Y"                 ; Modifier to patrol a unit
    287288queue = Shift                ; Modifier to queue unit orders instead of replacing
    288289batchtrain = Shift           ; Modifier to train units in batches
    289290massbarter = Shift           ; Modifier to barter bunch of resources
  • binaries/data/mods/public/gui/session/input.js

     
    1616const ACTION_GARRISON = 1;
    1717const ACTION_REPAIR = 2;
    1818const ACTION_GUARD = 3;
     19const ACTION_PATROL = 4;
    1920var preSelectedAction = ACTION_NONE;
    2021
    2122const INPUT_NORMAL = 0;
     
    207208            }
    208209            return { "possible": true, "data": data, "cursor": cursor };
    209210        }
    210 
    211         return { "possible": (action == "move" || action == "attack-move" || action == "remove-guard") };
     211       
     212        return { "possible": (action == "move" || action == "attack-move" || action == "remove-guard" || action == "patrol") };
    212213    }
    213214
    214215    // Look at the first targeted entity
     
    11601161    // of running it immediately
    11611162    var queued = Engine.HotkeyIsPressed("session.queue");
    11621163    var target = Engine.GetTerrainAtScreenPoint(ev.x, ev.y);
    1163 
     1164   
    11641165    if (unitActions[action.type] && unitActions[action.type].execute)
    11651166        return unitActions[action.type].execute(target, action, selection, queued);
    11661167    error("Invalid action.type "+action.type);
  • binaries/data/mods/public/gui/session/unit_actions.js

     
    208208        "specificness": 10,
    209209    },
    210210
     211    "patrol":
     212    {
     213        "execute": function(target, action, selection, queued)
     214        {
     215            Engine.PostNetworkCommand({
     216                "type": "patrol",
     217                "entities": selection,
     218                "x": target.x,
     219                "z": target.z,
     220                "target": action.target,
     221                "targetClasses": { "attack": ["Unit"] }, // patrol should only attack units
     222                "queued": queued,
     223                "allowCapture": false
     224            });
     225            Engine.GuiInterfaceCall("PlaySound", { "name": "order_patrol", "entity": selection[0] });
     226            return true;
     227        },
     228        "getActionInfo": function(entState, targetState)
     229        {
     230            return { "possible": true };
     231        },
     232        "hotkeyActionCheck": function(target)
     233        {
     234            if (Engine.HotkeyIsPressed("session.patrol") && getActionInfo("patrol", target).possible)
     235                return { "type": "patrol", "cursor": "action-patrol", "target": target };
     236            return false;
     237        },
     238        "preSelectedActionCheck" : function(target)
     239        {
     240            if (preSelectedAction != ACTION_PATROL)
     241                return false;
     242            if (getActionInfo("patrol", target).possible)
     243                return { "type": "patrol", "cursor": "action-patrol", "target": target };
     244            return false;
     245        },
     246        "specificness": 37,
     247
     248    },
     249
    211250    "heal":
    212251    {
    213252        "execute": function(target, action, selection, queued)
     
    12091248        },
    12101249    },
    12111250
     1251    "patrol": {
     1252        "getInfo": function(entState)
     1253        {
     1254            if (!entState.unitAI)
     1255                return false;
     1256            return {
     1257                "tooltip": translate("Patrol"),
     1258                "icon": "patrol.png"
     1259            };
     1260        },
     1261        "execute": function(entState)
     1262        {
     1263            inputState = INPUT_PRESELECTEDACTION;
     1264            preSelectedAction = ACTION_PATROL;
     1265        },
     1266    },
     1267
    12121268    "share-dropsite": {
    12131269        "getInfo": function(entState)
    12141270        {
  • binaries/data/mods/public/simulation/components/UnitAI.js

     
    514514        this.FinishOrder();
    515515    },
    516516
     517    "Order.Patrol": function(msg) {
     518        // Let players move captured domestic animals around
     519        if (this.IsAnimal() || this.IsTurret())
     520        {
     521            this.FinishOrder();
     522            return;
     523        }
     524
     525        // For packable units:
     526        // 1. If packed, we can move.
     527        // 2. If unpacked, we first need to pack, then follow case 1.
     528        if (this.CanPack())
     529        {
     530            // Case 2: pack
     531            this.PushOrderFront("Pack", { "force": true });
     532            return;
     533        }
     534
     535        this.MoveToPoint(this.order.data.x, this.order.data.z);
     536        this.SetNextState("INDIVIDUAL.PATROL");
     537    },
     538
    517539    "Order.Heal": function(msg) {
    518540        // Check the target is alive
    519541        if (!this.TargetIsAlive(this.order.data.target))
     
    829851                this.FinishOrder();
    830852        },
    831853
     854        "Order.Patrol": function(msg) {
     855            this.CallMemberFunction("SetHeldPosition", [msg.data.x, msg.data.z]);
     856
     857            this.MoveToPoint(this.order.data.x, this.order.data.z);
     858            this.SetNextState("PATROL");
     859        },
     860
    832861        "Order.Guard": function(msg) {
    833862            this.CallMemberFunction("Guard", [msg.data.target, false]);
    834863            var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation);
     
    10781107            },
    10791108        },
    10801109
     1110        "PATROL": {
     1111            "enter": function(msg) {
     1112                this.StartTimer(0, 1000);
     1113
     1114                // memorize the origin position in case that we want to go back
     1115                let cntPosition = Engine.QueryInterface(this.entity, IID_Position);
     1116                if (!cntPosition || !cntPosition.IsInWorld())
     1117                {
     1118                    this.FinishOrder();
     1119                    return;
     1120                }
     1121                this.patrolStartPos = cntPosition.GetPosition();
     1122            },
     1123
     1124            "Timer": function(msg) {
     1125                // check if there are no enemies to attack
     1126                this.FindWalkAndFightTargets();
     1127            },
     1128
     1129            "leave": function(msg) {
     1130                this.StopTimer();
     1131            },
     1132
     1133            "MoveStarted": function(msg) {
     1134                var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation);
     1135                cmpFormation.SetRearrange(true);
     1136                cmpFormation.MoveMembersIntoFormation(true, true);
     1137            },
     1138
     1139            "MoveCompleted": function() {   
     1140                // A-B-A-B-..:
     1141                // if the user only commands one patrol order, the patrol will be between
     1142                // the last position and the defined waypoint
     1143                // A-B-C-..-A-B-..:
     1144                // otherwise, the patrol is only between the given patrol commands and the
     1145                // last position is not included (last position = the position where the unit
     1146                // is located at the time of the first patrol order)
     1147                if (this.orderQueue.length == 1)
     1148                {
     1149                    this.orderQueue.push({ "type": "Patrol", "data": this.patrolStartPos });
     1150                }
     1151
     1152                this.orderQueue.push(this.order);
     1153                this.FinishOrder();
     1154            },
     1155        },
     1156
    10811157        "GARRISON":{
    10821158            "enter": function() {
    10831159                // If the garrisonholder should pickup, warn it so it can take needed action
     
    15551631            },
    15561632        },
    15571633
     1634        "PATROL": {
     1635            "enter": function () {
     1636                this.StartTimer(0, 1000);
     1637                this.SelectAnimation("move");
     1638
     1639                // memorize the origin position in case that we want to go back
     1640                let cntPosition = Engine.QueryInterface(this.entity, IID_Position);
     1641                if (!cntPosition || !cntPosition.IsInWorld())
     1642                {
     1643                    this.FinishOrder();
     1644                    return;
     1645                }
     1646                this.patrolStartPos = cntPosition.GetPosition();
     1647            },
     1648
     1649            "leave": function() {
     1650                this.StopTimer();
     1651            },
     1652
     1653            "Timer": function(msg) {
     1654                this.FindWalkAndFightTargets();
     1655            },
     1656
     1657            "MoveCompleted": function() {
     1658                if (this.orderQueue.length == 1)
     1659                {
     1660                    this.orderQueue.push({"type": "Patrol", "data": this.patrolStartPos});
     1661                }
     1662
     1663                this.orderQueue.push(this.order);
     1664                this.FinishOrder();
     1665            },
     1666        },
     1667
    15581668        "GUARD": {
    15591669            "RemoveGuard": function() {
    15601670                this.StopMoving();
     
    17991909                    }
    18001910                    // Check the target is still alive and attackable
    18011911                    if (this.TargetIsAlive(target) &&
    1802                         this.CanAttack(target, this.order.data.forceResponse || null) &&
    1803                         !this.CheckTargetAttackRange(target, this.order.data.attackType))
     1912                        this.CanAttack(target, this.order.data.forceResponse || null) &&
     1913                        !this.CheckTargetAttackRange(target, this.order.data.attackType))
    18041914                    {
    18051915                        // Can't reach it - try to chase after it
    18061916                        if (this.ShouldChaseTargetedEntity(target, this.order.data.force))
     
    20412151                    var cmpSupply = Engine.QueryInterface(this.gatheringTarget, IID_ResourceSupply);
    20422152                    var cmpMirage = Engine.QueryInterface(this.gatheringTarget, IID_Mirage);
    20432153                    if ((!cmpMirage || !cmpMirage.Mirages(IID_ResourceSupply)) &&
    2044                         (!cmpSupply || !cmpSupply.AddGatherer(cmpOwnership.GetOwner(), this.entity)))
     2154                        (!cmpSupply || !cmpSupply.AddGatherer(cmpOwnership.GetOwner(), this.entity)))
    20452155                    {
    20462156                        // Save the current order's data in case we need it later
    20472157                        var oldType = this.order.data.type;
     
    35743684        error("FinishOrder called for entity " + this.entity + " (" + template + ") when order queue is empty\n" + stack);
    35753685    }
    35763686
     3687    // next order
    35773688    this.orderQueue.shift();
    35783689    this.order = this.orderQueue[0];
    35793690
     
    47854896        case "WalkToPointRange":
    47864897        case "MoveIntoFormation":
    47874898        case "GatherNearPosition":
     4899        case "Patrol":
    47884900            targetPositions.push(new Vector2D(order.data.x, order.data.z));
    47894901            break; // and continue the loop
    47904902
     
    49975109    this.AddOrder("WalkAndFight", { "x": x, "z": z, "targetClasses": targetClasses, "force": true }, queued);
    49985110};
    49995111
     5112UnitAI.prototype.Patrol = function(x, z, targetClasses, queued)
     5113{
     5114    this.AddOrder("Patrol", { "x": x, "z": z, "targetClasses": targetClasses, "force": true }, queued);
     5115};
     5116
    50005117/**
    50015118 * Adds leave foundation order to queue, treated as forced.
    50025119 */
  • binaries/data/mods/public/simulation/helpers/Commands.js

     
    174174        });
    175175    },
    176176
     177    "patrol": function(player, cmd, data)
     178    {
     179        GetFormationUnitAIs(data.entities, player).forEach(cmpUnitAI => {
     180            cmpUnitAI.Patrol(cmd.x, cmd.z, cmd.targetClasses, cmd.queued);
     181        });
     182    },
     183
    177184    "heal": function(player, cmd, data)
    178185    {
    179186        if (g_DebugCommands && !(IsOwnedByPlayer(player, cmd.target) || IsOwnedByAllyOfPlayer(player, cmd.target)))