Ticket #1001: attack-move-v3.diff

File attack-move-v3.diff, 10.2 KB (added by mimo, 11 years ago)
  • binaries/data/mods/public/gui/session/input.js

     
    187187    {
    188188        if (action == "set-rallypoint" && haveRallyPoints)
    189189            return {"possible": true};
    190         else if (action == "move")
     190        else if (action == "move" || action == "attack-move")
    191191            return {"possible": true};
    192192        else
    193193            return {"possible": false};
     
    404404            break;
    405405        }
    406406    }
    407     if (action == "move")
     407    if (action == "move" || action == "attack-move")
    408408        return {"possible": true};
    409409    else
    410410        return {"possible": false};
     
    480480    {
    481481        return {"type": "attack", "cursor": "action-attack", "target": target};
    482482    }
     483    else if (Engine.HotkeyIsPressed("session.attackmove") && getActionInfo("attack-move", target).possible)
     484    {
     485            return {"type": "attack-move", "cursor": "action-attack"};
     486    }
    483487    else if (Engine.HotkeyIsPressed("session.garrison"))
    484488    {
    485489        if (getActionInfo("garrison", target).possible)
     
    13201324        Engine.GuiInterfaceCall("PlaySound", { "name": "order_walk", "entity": selection[0] });
    13211325        return true;
    13221326
     1327    case "attack-move":
     1328        var target = Engine.GetTerrainAtScreenPoint(ev.x, ev.y);
     1329        Engine.PostNetworkCommand({"type": "attack-walk", "entities": selection, "x": target.x, "z": target.z, "queued": queued});
     1330        Engine.GuiInterfaceCall("PlaySound", { "name": "order_walk", "entity": selection[0] });
     1331        return true;
     1332
    13231333    case "attack":
    13241334        Engine.PostNetworkCommand({"type": "attack", "entities": selection, "target": action.target, "queued": queued});
    13251335        Engine.GuiInterfaceCall("PlaySound", { "name": "order_attack", "entity": selection[0] });
     
    14191429            Engine.GuiInterfaceCall("PlaySound", { "name": "order_walk", "entity": selection[0] });
    14201430            return true;
    14211431
     1432        case "attack-move":
     1433            Engine.PostNetworkCommand({"type": "attack-walk", "entities": selection, "x": target.x, "z": target.z, "queued": queued});
     1434            Engine.GuiInterfaceCall("PlaySound", { "name": "order_walk", "entity": selection[0] });
     1435            return true;
     1436
    14221437        case "set-rallypoint":
    14231438            Engine.PostNetworkCommand({"type": "set-rallypoint", "entities": selection, "x": target.x, "z": target.z});
    14241439            // Display rally point at the new coordinates, to avoid display lag
  • binaries/data/mods/public/simulation/helpers/Commands.js

     
    8888        });
    8989        break;
    9090
     91    case "attack-walk":
     92        var entities = FilterEntityList(cmd.entities, player, controlAllUnits);
     93        GetFormationUnitAIs(entities, player).forEach(function(cmpUnitAI) {
     94            cmpUnitAI.WalkAndFight(cmd.x, cmd.z, cmd.queued);
     95        });
     96        break;
     97
    9198    case "attack":
    9299        if (g_DebugCommands && !(IsOwnedByEnemyOfPlayer(player, cmd.target) || IsOwnedByNeutralOfPlayer(player, cmd.target)))
    93100        {
  • binaries/data/mods/public/simulation/components/UnitAI.js

     
    270270            this.SetNextState("INDIVIDUAL.WALKING");
    271271    },
    272272
     273    "Order.WalkAndFight": function(msg) {
     274        // Let players move captured domestic animals around
     275        if (this.IsAnimal() && !this.IsDomestic())
     276        {
     277            this.FinishOrder();
     278            return;
     279        }
     280
     281        // For packable units:
     282        // 1. If packed, we can move.
     283        // 2. If unpacked, we first need to pack, then follow case 1.
     284        if (this.CanPack())
     285        {
     286            // Case 2: pack
     287            this.PushOrderFront("Pack", { "force": true });
     288            return;
     289        }
     290
     291        this.SetHeldPosition(this.order.data.x, this.order.data.z);
     292        this.MoveToPoint(this.order.data.x, this.order.data.z);
     293        if (this.IsAnimal())
     294            this.SetNextState("ANIMAL.WALKING");   // WalkAndFight not applicable for animals
     295        else
     296            this.SetNextState("INDIVIDUAL.WALKINGANDFIGHTING");
     297    },
     298
     299
    273300    "Order.WalkToTarget": function(msg) {
    274301        // Let players move captured domestic animals around
    275302        if (this.IsAnimal() && !this.IsDomestic())
     
    353380            if (this.CanUnpack())
    354381            {
    355382                // Ignore unforced attacks
     383                // this would prevent attacks from AttackVisibleEntity or AttackEntityInZone ?
     384                // so we accept attacks against targets for which we have a bonus
    356385                // TODO: use special stances instead?
    357                 if (!this.order.data.force)
     386                if (!this.order.data.force && this.GetAttackBonus(type, this.order.data.target) < 1.5)
    358387                {
    359388                    this.FinishOrder();
    360389                    return;
     
    628657            this.MoveToPoint(this.order.data.x, this.order.data.z);
    629658            this.SetNextState("WALKING");
    630659        },
     660
     661        "Order.WalkAndFight": function(msg) {
     662            var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation);
     663            cmpFormation.CallMemberFunction("SetHeldPosition", [msg.data.x, msg.data.z]);
     664
     665            this.MoveToPoint(this.order.data.x, this.order.data.z);
     666            this.SetNextState("WALKINGANDFIGHTING");
     667        },
    631668       
    632669        "Order.MoveIntoFormation": function(msg) {
    633670            var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation);
     
    885922            },
    886923        },
    887924
     925        "WALKINGANDFIGHTING": {
     926            "enter": function(msg) {
     927                this.StartTimer(0, 1000);
     928            },
     929
     930            "Timer": function(msg) {
     931                // check if there are no ennemies to attack
     932                var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation);
     933                for each (var ent in cmpFormation.members)
     934                {
     935                    var cmpUnitAI =  Engine.QueryInterface(ent, IID_UnitAI);
     936                        if (cmpUnitAI.FindNewTargets())
     937                    {
     938                        if (cmpUnitAI.orderQueue[0] && cmpUnitAI.orderQueue[0].type == "Attack")
     939                        {
     940                            var data = cmpUnitAI.orderQueue[0].data;
     941                            cmpUnitAI.FinishOrder();
     942                            this.PushOrderFront("Attack", { "target": data.target, "force": false, "forceResponse": data.forceResponse });
     943                            break;
     944                        }
     945                    }
     946                }
     947            },
     948
     949            "leave": function(msg) {
     950                this.StopTimer();
     951            },
     952
     953            "MoveStarted": function(msg) {
     954                var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation);
     955                cmpFormation.SetRearrange(true);
     956                cmpFormation.MoveMembersIntoFormation(true, true);
     957            },
     958
     959            "MoveCompleted": function(msg) {
     960                var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation);
     961
     962                if (this.FinishOrder())
     963                {
     964                    cmpFormation.CallMemberFunction("ResetFinishOrder", []);
     965                    return;
     966                }
     967
     968                // No more orders left.
     969                cmpFormation.Disband();
     970            },
     971        },
     972
    888973        "FORMING": {
    889974            "MoveStarted": function(msg) {
    890975                var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation);
     
    9381023
    9391024                // Execute the next order
    9401025                if (this.FinishOrder())
     1026                {
     1027                    // if WalkAndFight order, look for new target before moving again
     1028                    if (this.orderQueue.length > 0 && this.orderQueue[0].type == "WalkAndFight")
     1029                    {
     1030                        for each (var ent in cmpFormation.members)
     1031                        {
     1032                            var cmpUnitAI =  Engine.QueryInterface(ent, IID_UnitAI);
     1033                                if (cmpUnitAI.FindNewTargets())
     1034                            {
     1035                                if (cmpUnitAI.orderQueue[0] && cmpUnitAI.orderQueue[0].type == "Attack")
     1036                                {
     1037                                    var data = cmpUnitAI.orderQueue[0].data;
     1038                                    cmpUnitAI.FinishOrder();
     1039                                    this.PushOrderFront("Attack", { "target": data.target, "force": false, "forceResponse": data.forceResponse });
     1040                                    break;
     1041                                }
     1042                            }
     1043                        }
     1044                    }
    9411045                    return;
     1046                }
    9421047
    9431048                // No more order left.
    9441049                cmpFormation.Disband();
     
    11461251            },
    11471252        },
    11481253
     1254        "WALKINGANDFIGHTING": {
     1255            "enter": function () {
     1256                this.StartTimer(0, 1000);
     1257                this.SelectAnimation("move");
     1258            },
     1259
     1260            "Timer": function(msg) {
     1261                this.FindNewTargets();
     1262            },
     1263
     1264            "leave": function(msg) {
     1265                this.StopTimer();
     1266            },
     1267
     1268            "MoveCompleted": function() {
     1269                this.FinishOrder();
     1270            },
     1271        },
     1272
    11491273        "FLEEING": {
    11501274            "enter": function() {
    11511275                this.PlaySound("panic");
     
    13351459                    }
    13361460
    13371461                    // Can't reach it, no longer owned by enemy, or it doesn't exist any more - give up
     1462                    // Except if in WalkAndFight mode where we look for more ennemies around before moving again
    13381463                    if (this.FinishOrder())
     1464                    {
     1465                        if (this.orderQueue.length > 0 && this.orderQueue[0].type == "WalkAndFight")
     1466                                this.FindNewTargets();
    13391467                        return;
     1468                    }
    13401469
    13411470                    // See if we can switch to a new nearby enemy
    13421471                    if (this.FindNewTargets())
     
    32133342    return cmpAttack.GetBestAttackAgainst(target);
    32143343};
    32153344
     3345UnitAI.prototype.GetAttackBonus = function(type, target)
     3346{
     3347    var cmpAttack = Engine.QueryInterface(this.entity, IID_Attack);
     3348    if (!cmpAttack)
     3349        return 1;
     3350    return cmpAttack.GetAttackBonus(type, target);
     3351};
     3352
    32163353/**
    32173354 * Try to find one of the given entities which can be attacked,
    32183355 * and start attacking it.
     
    34253562        switch (order.type)
    34263563        {
    34273564        case "Walk":
     3565        case "WalkAndFight":
    34283566        case "WalkToPointRange":
    34293567        case "MoveIntoFormation":
    34303568        case "GatherNearPosition":
     
    35113649};
    35123650
    35133651/**
     3652 * Adds walk-and-fight order to queue, this only occurs in response
     3653 * to a player order, and so is forced.
     3654 */
     3655UnitAI.prototype.WalkAndFight = function(x, z, queued)
     3656{
     3657    this.AddOrder("WalkAndFight", { "x": x, "z": z, "force": true }, queued);
     3658};
     3659
     3660/**
    35143661 * Adds leave foundation order to queue, treated as forced.
    35153662 */
    35163663UnitAI.prototype.LeaveFoundation = function(target)
  • binaries/data/config/default.cfg

     
    245245hotkey.session.kill = Delete                ; Destroy selected units
    246246hotkey.session.attack = Ctrl                ; Modifier to force attack instead of another action
    247247hotkey.session.garrison = Ctrl              ; Modifier to garrison when clicking on building
     248hotkey.session.attackmove = AltGr           ; Modifier to attackmove when clicking on a point
    248249hotkey.session.queue = Shift                ; Modifier to queue unit orders instead of replacing
    249250hotkey.session.batchtrain = Shift           ; Modifier to train units in batches
    250251hotkey.session.massbarter = Shift           ; Modifier to barter bunch of resources