Ticket #1720: patrol_V3.2.patch

File patrol_V3.2.patch, 10.2 KB (added by svott, 8 years ago)
  • binaries/data/config/default.cfg

     
    280280garrison = Ctrl              ; Modifier to garrison when clicking on building
    281281autorallypoint = Ctrl        ; Modifier to set the rally point on the building itself
    282282guard = "G"                  ; Modifier to escort/guard when clicking on unit/building
     283patrol = "Y"                 ; Modifier to patrol a unit
    283284queue = Shift                ; Modifier to queue unit orders instead of replacing
    284285batchtrain = Shift           ; Modifier to train units in batches
    285286massbarter = 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;
     
    208209            return { "possible": true, "data": data, "cursor": cursor };
    209210        }
    210211
     212        if (action == "patrol")
     213        {
     214            // dirty hack
     215            return { "possible": true };
     216        }
     217
    211218        return { "possible": (action == "move" || action == "attack-move" || action == "remove-guard") };
    212219    }
    213220
     
    11601167    // of running it immediately
    11611168    var queued = Engine.HotkeyIsPressed("session.queue");
    11621169    var target = Engine.GetTerrainAtScreenPoint(ev.x, ev.y);
    1163 
     1170   
    11641171    if (unitActions[action.type] && unitActions[action.type].execute)
    11651172        return unitActions[action.type].execute(target, action, selection, queued);
    11661173    error("Invalid action.type "+action.type);
  • binaries/data/mods/public/gui/session/unit_actions.js

     
    139139        "specificness": 10,
    140140    },
    141141
     142    "patrol":
     143    {
     144        "execute": function(target, action, selection, queued)
     145        {
     146            var targetClasses = { "attack": ["Unit"] }; // patrol should only attack units - if a new strucure is build near to the patrol, the patrol will recognize the units
     147            Engine.PostNetworkCommand({ "type": "patrol", "entities": selection, "x": target.x, "z": target.z, "target": action.target, "targetClasses": targetClasses, "queued": queued, "allowCapture": false });
     148            Engine.GuiInterfaceCall("PlaySound", { "name": "order_patrol", "entity": selection[0] });
     149            return true;
     150        },
     151        "getActionInfo": function(entState, targetState)
     152        {
     153            return { "possible": true };
     154        },
     155        "hotkeyActionCheck": function(target)
     156        {
     157            if (Engine.HotkeyIsPressed("session.patrol") && getActionInfo("patrol", target).possible)
     158                return { "type": "patrol", "cursor": "action-patrol", "target": target };
     159            return false;
     160        },
     161        "preSelectedActionCheck" : function(target)
     162        {
     163            if (preSelectedAction != ACTION_PATROL)
     164                return false;
     165            if (getActionInfo("patrol", target).possible)
     166                return { "type": "patrol", "cursor": "action-patrol", "target": target };
     167            return false;
     168        },
     169        "specificness": 37,
     170
     171    },
     172
    142173    "heal":
    143174    {
    144175        "execute": function(target, action, selection, queued)
     
    894925            toggleTrade();
    895926        },
    896927    },
     928    // Patrol
     929    "patrol": {
     930        "getInfo": function(entState)
     931        {
     932            if (!entState.unitAI)
     933                return false;
     934            return {
     935                "tooltip": translate("Patrol"),
     936                "icon": "patrol.png"
     937            };
     938        },
     939        "execute": function(entState)
     940        {
     941            inputState = INPUT_PRESELECTEDACTION;
     942            preSelectedAction = ACTION_PATROL;
     943        },
     944    },
    897945    // Dropsite sharing
    898946    "share-dropsite": {
    899947        "getInfo": function(entState)
  • binaries/data/mods/public/simulation/components/UnitAI.js

     
    510510        this.FinishOrder();
    511511    },
    512512
     513    "Order.Patrol": function(msg) {
     514        // Let players move captured domestic animals around
     515        if (this.IsAnimal() || this.IsTurret())
     516        {
     517            this.FinishOrder();
     518            return;
     519        }
     520
     521        // For packable units:
     522        // 1. If packed, we can move.
     523        // 2. If unpacked, we first need to pack, then follow case 1.
     524        if (this.CanPack())
     525        {
     526            // Case 2: pack
     527            this.PushOrderFront("Pack", { "force": true });
     528            return;
     529        }
     530
     531        this.MoveToPoint(this.order.data.x, this.order.data.z);
     532        this.SetNextState("INDIVIDUAL.PATROL");
     533    },
     534
    513535    "Order.Heal": function(msg) {
    514536        // Check the target is alive
    515537        if (!this.TargetIsAlive(this.order.data.target))
     
    825847                this.FinishOrder();
    826848        },
    827849
     850        "Order.Patrol": function(msg) {
     851            this.CallMemberFunction("SetHeldPosition", [msg.data.x, msg.data.z]);
     852
     853            this.MoveToPoint(this.order.data.x, this.order.data.z);
     854            this.SetNextState("PATROL");
     855        },
     856
    828857        "Order.Guard": function(msg) {
    829858            this.CallMemberFunction("Guard", [msg.data.target, false]);
    830859            var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation);
     
    10741103            },
    10751104        },
    10761105
     1106        "PATROL": {
     1107            "enter": function(msg) {
     1108                this.StartTimer(0, 1000);
     1109
     1110                // memorize the origin position in case that we want to go back
     1111                let cntPosition = Engine.QueryInterface(this.entity, IID_Position);
     1112                if (!cntPosition || !cntPosition.IsInWorld())
     1113                {
     1114                    this.FinishOrder();
     1115                    return;
     1116                }
     1117                this.patrolStartPos = cntPosition.GetPosition();
     1118            },
     1119
     1120            "Timer": function(msg) {
     1121                // check if there are no enemies to attack
     1122                this.FindWalkAndFightTargets();
     1123            },
     1124
     1125            "leave": function(msg) {
     1126                this.StopTimer();
     1127            },
     1128
     1129            "MoveStarted": function(msg) {
     1130                var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation);
     1131                cmpFormation.SetRearrange(true);
     1132                cmpFormation.MoveMembersIntoFormation(true, true);
     1133            },
     1134
     1135            "MoveCompleted": function() {   
     1136                // A-B-A-B-..:
     1137                // if the user only commands one patrol order, the patrol will be between
     1138                // the last position and the defined waypoint
     1139                // A-B-C-..-A-B-..:
     1140                // otherwise, the patrol is only between the given patrol commands and the
     1141                // last position is not included (last position = the position where the unit
     1142                // is located at the time of the first patrol order)
     1143                if (this.orderQueue.length == 1)
     1144                {
     1145                    this.orderQueue.push({ "type": "Patrol", "data": this.patrolStartPos });
     1146                }
     1147
     1148                this.orderQueue.push(this.order);
     1149                this.FinishOrder();
     1150            },
     1151        },
     1152
    10771153        "GARRISON":{
    10781154            "enter": function() {
    10791155                // If the garrisonholder should pickup, warn it so it can take needed action
     
    15511627            },
    15521628        },
    15531629
     1630        "PATROL": {
     1631            "enter": function () {
     1632                this.StartTimer(0, 1000);
     1633                this.SelectAnimation("move");
     1634
     1635                // memorize the origin position in case that we want to go back
     1636                let cntPosition = Engine.QueryInterface(this.entity, IID_Position);
     1637                if (!cntPosition || !cntPosition.IsInWorld())
     1638                {
     1639                    this.FinishOrder();
     1640                    return;
     1641                }
     1642                this.patrolStartPos = cntPosition.GetPosition();
     1643            },
     1644
     1645            "leave": function() {
     1646                this.StopTimer();
     1647            },
     1648
     1649            "Timer": function(msg) {
     1650                this.FindWalkAndFightTargets();
     1651            },
     1652
     1653            "MoveCompleted": function() {
     1654                if (this.orderQueue.length == 1)
     1655                {
     1656                    this.orderQueue.push({"type": "Patrol", "data": this.patrolStartPos});
     1657                }
     1658
     1659                this.orderQueue.push(this.order);
     1660                this.FinishOrder();
     1661            },
     1662        },
     1663
    15541664        "GUARD": {
    15551665            "RemoveGuard": function() {
    15561666                this.StopMoving();
     
    17951905                    }
    17961906                    // Check the target is still alive and attackable
    17971907                    if (this.TargetIsAlive(target) &&
    1798                         this.CanAttack(target, this.order.data.forceResponse || null) &&
    1799                         !this.CheckTargetAttackRange(target, this.order.data.attackType))
     1908                        this.CanAttack(target, this.order.data.forceResponse || null) &&
     1909                        !this.CheckTargetAttackRange(target, this.order.data.attackType))
    18001910                    {
    18011911                        // Can't reach it - try to chase after it
    18021912                        if (this.ShouldChaseTargetedEntity(target, this.order.data.force))
     
    20372147                    var cmpSupply = Engine.QueryInterface(this.gatheringTarget, IID_ResourceSupply);
    20382148                    var cmpMirage = Engine.QueryInterface(this.gatheringTarget, IID_Mirage);
    20392149                    if ((!cmpMirage || !cmpMirage.Mirages(IID_ResourceSupply)) &&
    2040                         (!cmpSupply || !cmpSupply.AddGatherer(cmpOwnership.GetOwner(), this.entity)))
     2150                        (!cmpSupply || !cmpSupply.AddGatherer(cmpOwnership.GetOwner(), this.entity)))
    20412151                    {
    20422152                        // Save the current order's data in case we need it later
    20432153                        var oldType = this.order.data.type;
     
    35603670        error("FinishOrder called for entity " + this.entity + " (" + template + ") when order queue is empty\n" + stack);
    35613671    }
    35623672
     3673    // next order
    35633674    this.orderQueue.shift();
    35643675    this.order = this.orderQueue[0];
    35653676
     
    47714882        case "WalkToPointRange":
    47724883        case "MoveIntoFormation":
    47734884        case "GatherNearPosition":
     4885        case "Patrol":
    47744886            targetPositions.push(new Vector2D(order.data.x, order.data.z));
    47754887            break; // and continue the loop
    47764888
     
    49835095    this.AddOrder("WalkAndFight", { "x": x, "z": z, "targetClasses": targetClasses, "force": true }, queued);
    49845096};
    49855097
     5098UnitAI.prototype.Patrol = function(x, z, targetClasses, queued)
     5099{
     5100    this.AddOrder("Patrol", { "x": x, "z": z, "targetClasses": targetClasses, "force": true }, queued);
     5101};
     5102
    49865103/**
    49875104 * Adds leave foundation order to queue, treated as forced.
    49885105 */
  • 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)))