mirror of
https://gitea.wildfiregames.com/0ad/0ad.git
synced 2026-06-26 20:05:21 +00:00
Switch default behavior from capture to attack.
Discussed countless times on the forum. We try this out this release. Patch by: @marder Differential revision: https://code.wildfiregames.com/D4697 Idea accepted by: @asterix, @wowgetoffyourcellphone, @chrstgtr Comments by: ^ + @Stan This was SVN commit r27399.
This commit is contained in:
@@ -332,7 +332,8 @@ unload = "U" ; Unload garrisoned units when a building/mechanica
|
|||||||
unloadturrets = "U" ; Unload turreted units.
|
unloadturrets = "U" ; Unload turreted units.
|
||||||
leaveturret = "U" ; Leave turret point.
|
leaveturret = "U" ; Leave turret point.
|
||||||
move = "" ; Modifier to move to a point instead of another action (e.g. gather)
|
move = "" ; Modifier to move to a point instead of another action (e.g. gather)
|
||||||
attack = Ctrl ; Modifier to attack instead of another action (e.g. capture)
|
capture = Ctrl ; Modifier to capture instead of another action (e.g. attack)
|
||||||
|
attack = "" ; Modifier to attack instead of another action (e.g. capture)
|
||||||
attackmove = Ctrl ; Modifier to attackmove when clicking on a point
|
attackmove = Ctrl ; Modifier to attackmove when clicking on a point
|
||||||
attackmoveUnit = "Ctrl+Q" ; Modifier to attackmove targeting only units when clicking on a point
|
attackmoveUnit = "Ctrl+Q" ; Modifier to attackmove targeting only units when clicking on a point
|
||||||
garrison = Ctrl ; Modifier to garrison when clicking on building
|
garrison = Ctrl ; Modifier to garrison when clicking on building
|
||||||
|
|||||||
@@ -43,6 +43,10 @@
|
|||||||
"name": "Force move",
|
"name": "Force move",
|
||||||
"desc": "Modifier to move to a point instead of another action (e.g. gather)."
|
"desc": "Modifier to move to a point instead of another action (e.g. gather)."
|
||||||
},
|
},
|
||||||
|
"session.capture": {
|
||||||
|
"name": "Force capture",
|
||||||
|
"desc": "Modifier to capture instead of another action (e.g. attack)."
|
||||||
|
},
|
||||||
"session.attack": {
|
"session.attack": {
|
||||||
"name": "Force attack",
|
"name": "Force attack",
|
||||||
"desc": "Modifier to attack instead of another action (e.g. capture)."
|
"desc": "Modifier to attack instead of another action (e.g. capture)."
|
||||||
|
|||||||
@@ -113,9 +113,10 @@ You may change hotkeys in [font="sans-bold-14"]Options > Hotkeys[font="sans-14"]
|
|||||||
hotkey.selection.singleselection – Modifier to select units individually, opposed to per formation.
|
hotkey.selection.singleselection – Modifier to select units individually, opposed to per formation.
|
||||||
Right Click with a structure(s) selected – Set a rally point for units created/ungarrisoned from that structure
|
Right Click with a structure(s) selected – Set a rally point for units created/ungarrisoned from that structure
|
||||||
hotkey.session.garrison + Right Click with unit(s) selected – Garrison (If the cursor is over an own or allied structure)
|
hotkey.session.garrison + Right Click with unit(s) selected – Garrison (If the cursor is over an own or allied structure)
|
||||||
hotkey.session.attack + Right Click with unit(s) selected – Attack (instead of capture or gather)
|
hotkey.session.attack + Right Click with unit(s) selected – Attack (instead of another action)
|
||||||
hotkey.session.attackmove + Right Click with unit(s) selected – Attack move (by default all enemy units and structures along the way are targeted)
|
hotkey.session.attackmove + Right Click with unit(s) selected – Attack move (by default all enemy units and structures along the way are targeted)
|
||||||
hotkey.session.attackmoveUnit + Right Click with unit(s) selected – Attack move, only units along the way are targeted
|
hotkey.session.attackmoveUnit + Right Click with unit(s) selected – Attack move, only units along the way are targeted
|
||||||
|
hotkey.session.capture + Right Click with unit(s) selected – Capture (instead of another action)
|
||||||
hotkey.session.snaptoedges + Mouse Move near structures – Align the new structure with an existing nearby structure
|
hotkey.session.snaptoedges + Mouse Move near structures – Align the new structure with an existing nearby structure
|
||||||
hotkey.session.flare + Right Click – Send a flare to your allies
|
hotkey.session.flare + Right Click – Send a flare to your allies
|
||||||
|
|
||||||
|
|||||||
@@ -181,6 +181,11 @@ var g_UnitActions =
|
|||||||
})
|
})
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
"hotkeyActionCheck": function(target, selection)
|
||||||
|
{
|
||||||
|
return Engine.HotkeyIsPressed("session.capture") &&
|
||||||
|
this.actionCheck(target, selection);
|
||||||
|
},
|
||||||
"actionCheck": function(target, selection)
|
"actionCheck": function(target, selection)
|
||||||
{
|
{
|
||||||
let actionInfo = getActionInfo("capture", target, selection);
|
let actionInfo = getActionInfo("capture", target, selection);
|
||||||
@@ -191,7 +196,7 @@ var g_UnitActions =
|
|||||||
"firstAbleEntity": actionInfo.entity
|
"firstAbleEntity": actionInfo.entity
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
"specificness": 9,
|
"specificness": 10,
|
||||||
},
|
},
|
||||||
|
|
||||||
"attack":
|
"attack":
|
||||||
@@ -243,7 +248,7 @@ var g_UnitActions =
|
|||||||
"firstAbleEntity": actionInfo.entity
|
"firstAbleEntity": actionInfo.entity
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
"specificness": 10,
|
"specificness": 9,
|
||||||
},
|
},
|
||||||
|
|
||||||
"call-to-arms": {
|
"call-to-arms": {
|
||||||
@@ -261,7 +266,7 @@ var g_UnitActions =
|
|||||||
"targetClasses": targetClasses,
|
"targetClasses": targetClasses,
|
||||||
"queued": queued,
|
"queued": queued,
|
||||||
"pushFront": pushFront,
|
"pushFront": pushFront,
|
||||||
"allowCapture": true,
|
"allowCapture": Engine.HotkeyIsPressed("session.capture"),
|
||||||
"formation": g_AutoFormation.getNull()
|
"formation": g_AutoFormation.getNull()
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
@@ -305,7 +310,7 @@ var g_UnitActions =
|
|||||||
"target": action.target,
|
"target": action.target,
|
||||||
"targetClasses": { "attack": g_PatrolTargets },
|
"targetClasses": { "attack": g_PatrolTargets },
|
||||||
"queued": queued,
|
"queued": queued,
|
||||||
"allowCapture": false,
|
"allowCapture": Engine.HotkeyIsPressed("session.capture"),
|
||||||
"formation": g_AutoFormation.getDefault()
|
"formation": g_AutoFormation.getDefault()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -185,6 +185,8 @@ var g_LeaveFoundationRange = 4;
|
|||||||
|
|
||||||
UnitAI.prototype.notifyToCheerInRange = 30;
|
UnitAI.prototype.notifyToCheerInRange = 30;
|
||||||
|
|
||||||
|
UnitAI.prototype.DEFAULT_CAPTURE = false;
|
||||||
|
|
||||||
// To reject an order, use 'return this.FinishOrder();'
|
// To reject an order, use 'return this.FinishOrder();'
|
||||||
const ACCEPT_ORDER = true;
|
const ACCEPT_ORDER = true;
|
||||||
|
|
||||||
@@ -535,7 +537,7 @@ UnitAI.prototype.UnitFsmSpec = {
|
|||||||
if (!this.AbleToMove() && !this.CheckTargetRange(msg.data.target, IID_Attack, bestAttack))
|
if (!this.AbleToMove() && !this.CheckTargetRange(msg.data.target, IID_Attack, bestAttack))
|
||||||
return this.FinishOrder();
|
return this.FinishOrder();
|
||||||
|
|
||||||
this.PushOrderFront("Attack", { "target": msg.data.target, "force": !!msg.data.force, "hunting": true, "allowCapture": false });
|
this.PushOrderFront("Attack", { "target": msg.data.target, "force": !!msg.data.force, "hunting": true });
|
||||||
return ACCEPT_ORDER;
|
return ACCEPT_ORDER;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -767,7 +769,6 @@ UnitAI.prototype.UnitFsmSpec = {
|
|||||||
|
|
||||||
"Order.Attack": function(msg) {
|
"Order.Attack": function(msg) {
|
||||||
let target = msg.data.target;
|
let target = msg.data.target;
|
||||||
let allowCapture = msg.data.allowCapture;
|
|
||||||
let cmpTargetUnitAI = Engine.QueryInterface(target, IID_UnitAI);
|
let cmpTargetUnitAI = Engine.QueryInterface(target, IID_UnitAI);
|
||||||
if (cmpTargetUnitAI && cmpTargetUnitAI.IsFormationMember())
|
if (cmpTargetUnitAI && cmpTargetUnitAI.IsFormationMember())
|
||||||
target = cmpTargetUnitAI.GetFormationController();
|
target = cmpTargetUnitAI.GetFormationController();
|
||||||
@@ -781,7 +782,7 @@ UnitAI.prototype.UnitFsmSpec = {
|
|||||||
}
|
}
|
||||||
return this.FinishOrder();
|
return this.FinishOrder();
|
||||||
}
|
}
|
||||||
this.CallMemberFunction("Attack", [target, allowCapture, false]);
|
this.CallMemberFunction("Attack", [target, msg.data.allowCapture, false]);
|
||||||
let cmpAttack = Engine.QueryInterface(this.entity, IID_Attack);
|
let cmpAttack = Engine.QueryInterface(this.entity, IID_Attack);
|
||||||
if (cmpAttack && cmpAttack.CanAttackAsFormation())
|
if (cmpAttack && cmpAttack.CanAttackAsFormation())
|
||||||
this.SetNextState("COMBAT.ATTACKING");
|
this.SetNextState("COMBAT.ATTACKING");
|
||||||
@@ -832,7 +833,7 @@ UnitAI.prototype.UnitFsmSpec = {
|
|||||||
}
|
}
|
||||||
return ACCEPT_ORDER;
|
return ACCEPT_ORDER;
|
||||||
}
|
}
|
||||||
this.PushOrderFront("Attack", { "target": msg.data.target, "force": !!msg.data.force, "hunting": true, "allowCapture": false, "min": 0, "max": 10 });
|
this.PushOrderFront("Attack", { "target": msg.data.target, "force": !!msg.data.force, "hunting": true, "min": 0, "max": 10 });
|
||||||
return ACCEPT_ORDER;
|
return ACCEPT_ORDER;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1300,8 +1301,7 @@ UnitAI.prototype.UnitFsmSpec = {
|
|||||||
"ATTACKING": {
|
"ATTACKING": {
|
||||||
// Wait for individual members to finish
|
// Wait for individual members to finish
|
||||||
"enter": function(msg) {
|
"enter": function(msg) {
|
||||||
let target = this.order.data.target;
|
const target = this.order.data.target;
|
||||||
let allowCapture = this.order.data.allowCapture;
|
|
||||||
if (!this.CheckFormationTargetAttackRange(target))
|
if (!this.CheckFormationTargetAttackRange(target))
|
||||||
{
|
{
|
||||||
if (this.CanAttack(target) && this.CheckTargetVisible(target))
|
if (this.CanAttack(target) && this.CheckTargetVisible(target))
|
||||||
@@ -1322,8 +1322,7 @@ UnitAI.prototype.UnitFsmSpec = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
"Timer": function(msg) {
|
"Timer": function(msg) {
|
||||||
let target = this.order.data.target;
|
const target = this.order.data.target;
|
||||||
let allowCapture = this.order.data.allowCapture;
|
|
||||||
if (!this.CheckFormationTargetAttackRange(target))
|
if (!this.CheckFormationTargetAttackRange(target))
|
||||||
{
|
{
|
||||||
if (this.CanAttack(target) && this.CheckTargetVisible(target))
|
if (this.CanAttack(target) && this.CheckTargetVisible(target))
|
||||||
@@ -1568,7 +1567,7 @@ UnitAI.prototype.UnitFsmSpec = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.CheckTargetVisible(msg.data.attacker))
|
if (this.CheckTargetVisible(msg.data.attacker))
|
||||||
this.PushOrderFront("Attack", { "target": msg.data.attacker, "force": false, "allowCapture": true });
|
this.PushOrderFront("Attack", { "target": msg.data.attacker, "force": false });
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var cmpPosition = Engine.QueryInterface(msg.data.attacker, IID_Position);
|
var cmpPosition = Engine.QueryInterface(msg.data.attacker, IID_Position);
|
||||||
@@ -2112,9 +2111,6 @@ UnitAI.prototype.UnitFsmSpec = {
|
|||||||
this.PushOrder("WalkAndFight", {
|
this.PushOrder("WalkAndFight", {
|
||||||
"x": lastPos.x, "z": lastPos.z,
|
"x": lastPos.x, "z": lastPos.z,
|
||||||
"force": false,
|
"force": false,
|
||||||
// Force to true - otherwise structures might be attacked instead of captured,
|
|
||||||
// which is generally not expected (attacking units usually has allowCapture false).
|
|
||||||
"allowCapture": true
|
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -4992,12 +4988,9 @@ UnitAI.prototype.CheckTargetIsInVisionRange = function(target)
|
|||||||
return distance < range;
|
return distance < range;
|
||||||
};
|
};
|
||||||
|
|
||||||
UnitAI.prototype.GetBestAttackAgainst = function(target, allowCapture)
|
UnitAI.prototype.GetBestAttackAgainst = function(target, allowCapture = this.DEFAULT_CAPTURE)
|
||||||
{
|
{
|
||||||
var cmpAttack = Engine.QueryInterface(this.entity, IID_Attack);
|
return Engine.QueryInterface(this.entity, IID_Attack)?.GetBestAttackAgainst(target, allowCapture);
|
||||||
if (!cmpAttack)
|
|
||||||
return undefined;
|
|
||||||
return cmpAttack.GetBestAttackAgainst(target, allowCapture);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -5011,7 +5004,7 @@ UnitAI.prototype.AttackVisibleEntity = function(ents)
|
|||||||
if (!target)
|
if (!target)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
this.PushOrderFront("Attack", { "target": target, "force": false, "allowCapture": true });
|
this.PushOrderFront("Attack", { "target": target, "force": false });
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -5030,7 +5023,7 @@ UnitAI.prototype.AttackEntityInZone = function(ents)
|
|||||||
if (!target)
|
if (!target)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
this.PushOrderFront("Attack", { "target": target, "force": false, "allowCapture": true });
|
this.PushOrderFront("Attack", { "target": target, "force": false });
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -5454,12 +5447,12 @@ UnitAI.prototype.WalkToTarget = function(target, queued, pushFront)
|
|||||||
* to a player order, and so is forced.
|
* to a player order, and so is forced.
|
||||||
* If targetClasses is given, only entities matching the targetClasses can be attacked.
|
* If targetClasses is given, only entities matching the targetClasses can be attacked.
|
||||||
*/
|
*/
|
||||||
UnitAI.prototype.WalkAndFight = function(x, z, targetClasses, allowCapture = true, queued = false, pushFront = false)
|
UnitAI.prototype.WalkAndFight = function(x, z, targetClasses, allowCapture = this.DEFAULT_CAPTURE, queued = false, pushFront = false)
|
||||||
{
|
{
|
||||||
this.AddOrder("WalkAndFight", { "x": x, "z": z, "targetClasses": targetClasses, "allowCapture": allowCapture, "force": true }, queued, pushFront);
|
this.AddOrder("WalkAndFight", { "x": x, "z": z, "targetClasses": targetClasses, "allowCapture": allowCapture, "force": true }, queued, pushFront);
|
||||||
};
|
};
|
||||||
|
|
||||||
UnitAI.prototype.Patrol = function(x, z, targetClasses, allowCapture = true, queued = false, pushFront = false)
|
UnitAI.prototype.Patrol = function(x, z, targetClasses, allowCapture = this.DEFAULT_CAPTURE, queued = false, pushFront = false)
|
||||||
{
|
{
|
||||||
if (!this.CanPatrol())
|
if (!this.CanPatrol())
|
||||||
{
|
{
|
||||||
@@ -5497,7 +5490,7 @@ UnitAI.prototype.LeaveFoundation = function(target)
|
|||||||
/**
|
/**
|
||||||
* Adds attack order to the queue, forced by the player.
|
* Adds attack order to the queue, forced by the player.
|
||||||
*/
|
*/
|
||||||
UnitAI.prototype.Attack = function(target, allowCapture = true, queued = false, pushFront = false)
|
UnitAI.prototype.Attack = function(target, allowCapture = this.DEFAULT_CAPTURE, queued = false, pushFront = false)
|
||||||
{
|
{
|
||||||
if (!this.CanAttack(target))
|
if (!this.CanAttack(target))
|
||||||
{
|
{
|
||||||
@@ -6033,7 +6026,7 @@ UnitAI.prototype.FindWalkAndFightTargets = function()
|
|||||||
const order = {
|
const order = {
|
||||||
"target": target,
|
"target": target,
|
||||||
"force": false,
|
"force": false,
|
||||||
"allowCapture": this.order?.data?.allowCapture
|
"allowCapture": this.order?.data?.allowCapture || this.DEFAULT_CAPTURE
|
||||||
};
|
};
|
||||||
if (this.IsFormationMember())
|
if (this.IsFormationMember())
|
||||||
this.ReplaceOrder("Attack", order);
|
this.ReplaceOrder("Attack", order);
|
||||||
|
|||||||
@@ -183,41 +183,30 @@ var g_Commands = {
|
|||||||
|
|
||||||
"attack-walk": function(player, cmd, data)
|
"attack-walk": function(player, cmd, data)
|
||||||
{
|
{
|
||||||
let allowCapture = cmd.allowCapture || cmd.allowCapture == null;
|
|
||||||
|
|
||||||
GetFormationUnitAIs(data.entities, player, cmd, data.formation).forEach(cmpUnitAI => {
|
GetFormationUnitAIs(data.entities, player, cmd, data.formation).forEach(cmpUnitAI => {
|
||||||
cmpUnitAI.WalkAndFight(cmd.x, cmd.z, cmd.targetClasses, allowCapture, cmd.queued, cmd.pushFront);
|
cmpUnitAI.WalkAndFight(cmd.x, cmd.z, cmd.targetClasses, cmd.allowCapture, cmd.queued, cmd.pushFront);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
"attack-walk-custom": function(player, cmd, data)
|
"attack-walk-custom": function(player, cmd, data)
|
||||||
{
|
{
|
||||||
let allowCapture = cmd.allowCapture || cmd.allowCapture == null;
|
|
||||||
for (let ent in data.entities)
|
for (let ent in data.entities)
|
||||||
GetFormationUnitAIs([data.entities[ent]], player, cmd, data.formation).forEach(cmpUnitAI => {
|
GetFormationUnitAIs([data.entities[ent]], player, cmd, data.formation).forEach(cmpUnitAI => {
|
||||||
cmpUnitAI.WalkAndFight(cmd.targetPositions[ent].x, cmd.targetPositions[ent].y, cmd.targetClasses, allowCapture, cmd.queued, cmd.pushFront);
|
cmpUnitAI.WalkAndFight(cmd.targetPositions[ent].x, cmd.targetPositions[ent].y, cmd.targetClasses, cmd.allowCapture, cmd.queued, cmd.pushFront);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
"attack": function(player, cmd, data)
|
"attack": function(player, cmd, data)
|
||||||
{
|
{
|
||||||
let allowCapture = cmd.allowCapture || cmd.allowCapture == null;
|
|
||||||
|
|
||||||
if (g_DebugCommands && !allowCapture &&
|
|
||||||
!(IsOwnedByEnemyOfPlayer(player, cmd.target) || IsOwnedByNeutralOfPlayer(player, cmd.target)))
|
|
||||||
warn("Invalid command: attack target is not owned by enemy of player "+player+": "+uneval(cmd));
|
|
||||||
|
|
||||||
GetFormationUnitAIs(data.entities, player, cmd, data.formation).forEach(cmpUnitAI => {
|
GetFormationUnitAIs(data.entities, player, cmd, data.formation).forEach(cmpUnitAI => {
|
||||||
cmpUnitAI.Attack(cmd.target, allowCapture, cmd.queued, cmd.pushFront);
|
cmpUnitAI.Attack(cmd.target, cmd.allowCapture, cmd.queued, cmd.pushFront);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
"patrol": function(player, cmd, data)
|
"patrol": function(player, cmd, data)
|
||||||
{
|
{
|
||||||
let allowCapture = cmd.allowCapture || cmd.allowCapture == null;
|
|
||||||
|
|
||||||
GetFormationUnitAIs(data.entities, player, cmd, data.formation).forEach(cmpUnitAI =>
|
GetFormationUnitAIs(data.entities, player, cmd, data.formation).forEach(cmpUnitAI =>
|
||||||
cmpUnitAI.Patrol(cmd.x, cmd.z, cmd.targetClasses, allowCapture, cmd.queued)
|
cmpUnitAI.Patrol(cmd.x, cmd.z, cmd.targetClasses, cmd.allowCapture, cmd.queued)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user