1
0
forked from 0ad/0ad

Improve neutral and ally combat handling. Refs #7.

This was SVN commit r12780.
This commit is contained in:
leper 2012-10-23 23:13:39 +00:00
parent c98a97924d
commit ca4dedbc3e
6 changed files with 43 additions and 22 deletions

View File

@ -286,6 +286,7 @@ function getActionInfo(action, target)
var playerState = simState.players[entState.player]; var playerState = simState.players[entState.player];
var playerOwned = (targetState.player == entState.player); var playerOwned = (targetState.player == entState.player);
var allyOwned = playerState.isAlly[targetState.player]; var allyOwned = playerState.isAlly[targetState.player];
var neutralOwned = playerState.isNeutral[targetState.player];
var enemyOwned = playerState.isEnemy[targetState.player]; var enemyOwned = playerState.isEnemy[targetState.player];
var gaiaOwned = (targetState.player == 0); var gaiaOwned = (targetState.player == 0);
@ -388,7 +389,7 @@ function getActionInfo(action, target)
return {"possible": true}; return {"possible": true};
break; break;
case "attack": case "attack":
if (entState.attack && targetState.hitpoints && enemyOwned) if (entState.attack && targetState.hitpoints && (enemyOwned || neutralOwned))
return {"possible": Engine.GuiInterfaceCall("CanAttack", {"entity": entState.id, "target": target})}; return {"possible": Engine.GuiInterfaceCall("CanAttack", {"entity": entState.id, "target": target})};
break; break;
} }

View File

@ -287,16 +287,15 @@ function addChatMessage(msg, playerAssignments)
break; break;
case "diplomacy": case "diplomacy":
username= escapeText(g_Players[msg.player1].name); username= escapeText(g_Players[msg.player1].name);
playerColor = g_Players[msg.player1].color.r + " " + g_Players[msg.player1].color.g + " " + g_Players[msg.player1].color.b;
// TODO: Proper wording for all cases // TODO: Proper wording for all cases
if (msg.player == Engine.GetPlayerID()) if (msg.player == Engine.GetPlayerID())
{ {
playerColor = g_Players[msg.player1].color.r + " " + g_Players[msg.player1].color.g + " " + g_Players[msg.player1].color.b;
formatted = "You are now "+msg.status+" with [color=\"" + playerColor + "\"]"+username + "[/color]."; formatted = "You are now "+msg.status+" with [color=\"" + playerColor + "\"]"+username + "[/color].";
} }
else if (msg.player1 == Engine.GetPlayerID()) else if (msg.player1 == Engine.GetPlayerID())
{ {
playerColor = g_Players[msg.player].color.r + " " + g_Players[msg.player].color.g + " " + g_Players[msg.player].color.b;
formatted = "[color=\"" + playerColor + "\"]" + username + "[/color] is now " + msg.status + " with you." formatted = "[color=\"" + playerColor + "\"]" + username + "[/color] is now " + msg.status + " with you."
} }
else // No need for other players to know of this. else // No need for other players to know of this.

View File

@ -96,7 +96,9 @@ EndGameManager.prototype.UpdatePlayerStates = function()
{ //Active player { //Active player
for (var j = 0; j < numPlayers && onlyAlliesLeft; j++) for (var j = 0; j < numPlayers && onlyAlliesLeft; j++)
{ {
if (cmpPlayers[j].GetState() == "active" && (cmpPlayers[i].IsEnemy(j+1) || cmpPlayers[j].IsEnemy(i+1))) if (cmpPlayers[j].GetState() == "active"
&& (cmpPlayers[i].IsEnemy(j+1) || cmpPlayers[j].IsEnemy(i+1)
|| cmpPlayers[i].IsNeutral(j+1) || cmpPlayers[j].IsNeutral(i+1)))
{ // Only need to find an active non-allied player { // Only need to find an active non-allied player
onlyAlliesLeft = false; onlyAlliesLeft = false;
} }

View File

@ -923,7 +923,7 @@ var UnitFsmSpec = {
"Timer": function(msg) { "Timer": function(msg) {
var target = this.order.data.target; var target = this.order.data.target;
// Check the target is still alive and attackable // Check the target is still alive and attackable
if (this.TargetIsAlive(target) && this.CanAttack(target)) if (this.TargetIsAlive(target) && this.CanAttack(target, this.order.data.forceResponse || null))
{ {
// Check we can still reach the target // Check we can still reach the target
if (this.CheckTargetRange(target, IID_Attack, this.attackType)) if (this.CheckTargetRange(target, IID_Attack, this.attackType))
@ -2725,13 +2725,13 @@ UnitAI.prototype.GetBestAttackAgainst = function(target)
* and start attacking it. * and start attacking it.
* Returns true if it found something to attack. * Returns true if it found something to attack.
*/ */
UnitAI.prototype.AttackVisibleEntity = function(ents) UnitAI.prototype.AttackVisibleEntity = function(ents, forceResponse)
{ {
for each (var target in ents) for each (var target in ents)
{ {
if (this.CanAttack(target)) if (this.CanAttack(target, forceResponse))
{ {
this.PushOrderFront("Attack", { "target": target, "force": false }); this.PushOrderFront("Attack", { "target": target, "force": false, "forceResponse": forceResponse });
return true; return true;
} }
} }
@ -2743,14 +2743,14 @@ UnitAI.prototype.AttackVisibleEntity = function(ents)
* and which is close to the hold position, and start attacking it. * and which is close to the hold position, and start attacking it.
* Returns true if it found something to attack. * Returns true if it found something to attack.
*/ */
UnitAI.prototype.AttackEntityInZone = function(ents) UnitAI.prototype.AttackEntityInZone = function(ents, forceResponse)
{ {
for each (var target in ents) for each (var target in ents)
{ {
var type = this.GetBestAttackAgainst(target); var type = this.GetBestAttackAgainst(target);
if (this.CanAttack(target) && this.CheckTargetDistanceFromHeldPosition(target, IID_Attack, type)) if (this.CanAttack(target, forceResponse) && this.CheckTargetDistanceFromHeldPosition(target, IID_Attack, type))
{ {
this.PushOrderFront("Attack", { "target": target, "force": false }); this.PushOrderFront("Attack", { "target": target, "force": false, "forceResponse": forceResponse });
return true; return true;
} }
} }
@ -2768,13 +2768,13 @@ UnitAI.prototype.RespondToTargetedEntities = function(ents)
return false; return false;
if (this.GetStance().respondChase) if (this.GetStance().respondChase)
return this.AttackVisibleEntity(ents); return this.AttackVisibleEntity(ents, true);
if (this.GetStance().respondStandGround) if (this.GetStance().respondStandGround)
return this.AttackVisibleEntity(ents); return this.AttackVisibleEntity(ents, true);
if (this.GetStance().respondHoldGround) if (this.GetStance().respondHoldGround)
return this.AttackEntityInZone(ents); return this.AttackEntityInZone(ents, true);
if (this.GetStance().respondFlee) if (this.GetStance().respondFlee)
{ {
@ -3402,7 +3402,7 @@ UnitAI.prototype.WalkToHeldPosition = function()
//// Helper functions //// //// Helper functions ////
UnitAI.prototype.CanAttack = function(target) UnitAI.prototype.CanAttack = function(target, forceResponse)
{ {
// Formation controllers should always respond to commands // Formation controllers should always respond to commands
// (then the individual units can make up their own minds) // (then the individual units can make up their own minds)
@ -3424,7 +3424,7 @@ UnitAI.prototype.CanAttack = function(target)
// Verify that the target is owned by an enemy of this entity's player, // Verify that the target is owned by an enemy of this entity's player,
// or that it's an attackable resource supply like a domestic animal // or that it's an attackable resource supply like a domestic animal
var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
if (!cmpOwnership || (!this.MustKillGatherTarget(target) && !IsOwnedByEnemyOfPlayer(cmpOwnership.GetOwner(), target))) if (!cmpOwnership || (!this.MustKillGatherTarget(target) && !(IsOwnedByEnemyOfPlayer(cmpOwnership.GetOwner(), target) || IsOwnedByNeutralOfPlayer(cmpOwnership.GetOwner(), target) || forceResponse)))
return false; return false;
return true; return true;

View File

@ -89,7 +89,7 @@ function ProcessCommand(player, cmd)
break; break;
case "attack": case "attack":
if (g_DebugCommands && !IsOwnedByEnemyOfPlayer(player, cmd.target)) if (g_DebugCommands && !(IsOwnedByEnemyOfPlayer(player, cmd.target) || IsOwnedByNeutralOfPlayer(player, cmd.target)))
{ {
// This check is for debugging only! // This check is for debugging only!
warn("Invalid command: attack target is not owned by enemy of player "+player+": "+uneval(cmd)); warn("Invalid command: attack target is not owned by enemy of player "+player+": "+uneval(cmd));

View File

@ -246,7 +246,6 @@ function IsOwnedByGaia(target)
*/ */
function IsOwnedByAllyOfPlayer(player, target) function IsOwnedByAllyOfPlayer(player, target)
{ {
// Figure out which player controls the foundation being built
var targetOwner = 0; var targetOwner = 0;
var cmpOwnershipTarget = Engine.QueryInterface(target, IID_Ownership); var cmpOwnershipTarget = Engine.QueryInterface(target, IID_Ownership);
if (cmpOwnershipTarget) if (cmpOwnershipTarget)
@ -263,11 +262,10 @@ function IsOwnedByAllyOfPlayer(player, target)
} }
/** /**
* Returns true if the entity 'target' is owned by an enemy of player * Returns true if the entity 'target' is owned by someone neutral to player
*/ */
function IsOwnedByEnemyOfPlayer(player, target) function IsOwnedByNeutralOfPlayer(player,target)
{ {
// Figure out which player controls the foundation being built
var targetOwner = 0; var targetOwner = 0;
var cmpOwnershipTarget = Engine.QueryInterface(target, IID_Ownership); var cmpOwnershipTarget = Engine.QueryInterface(target, IID_Ownership);
if (cmpOwnershipTarget) if (cmpOwnershipTarget)
@ -276,7 +274,27 @@ function IsOwnedByEnemyOfPlayer(player, target)
var cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager); var cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
var cmpPlayer = Engine.QueryInterface(cmpPlayerManager.GetPlayerByID(player), IID_Player); var cmpPlayer = Engine.QueryInterface(cmpPlayerManager.GetPlayerByID(player), IID_Player);
// Check for allied diplomacy status // Check for neutral diplomacy status
if (cmpPlayer.IsNeutral(targetOwner))
return true;
return false;
}
/**
* Returns true if the entity 'target' is owned by an enemy of player
*/
function IsOwnedByEnemyOfPlayer(player, target)
{
var targetOwner = 0;
var cmpOwnershipTarget = Engine.QueryInterface(target, IID_Ownership);
if (cmpOwnershipTarget)
targetOwner = cmpOwnershipTarget.GetOwner();
var cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
var cmpPlayer = Engine.QueryInterface(cmpPlayerManager.GetPlayerByID(player), IID_Player);
// Check for enemy diplomacy status
if (cmpPlayer.IsEnemy(targetOwner)) if (cmpPlayer.IsEnemy(targetOwner))
return true; return true;
@ -290,4 +308,5 @@ Engine.RegisterGlobal("IsOwnedByAllyOfEntity", IsOwnedByAllyOfEntity);
Engine.RegisterGlobal("IsOwnedByPlayer", IsOwnedByPlayer); Engine.RegisterGlobal("IsOwnedByPlayer", IsOwnedByPlayer);
Engine.RegisterGlobal("IsOwnedByGaia", IsOwnedByGaia); Engine.RegisterGlobal("IsOwnedByGaia", IsOwnedByGaia);
Engine.RegisterGlobal("IsOwnedByAllyOfPlayer", IsOwnedByAllyOfPlayer); Engine.RegisterGlobal("IsOwnedByAllyOfPlayer", IsOwnedByAllyOfPlayer);
Engine.RegisterGlobal("IsOwnedByNeutralOfPlayer", IsOwnedByNeutralOfPlayer);
Engine.RegisterGlobal("IsOwnedByEnemyOfPlayer", IsOwnedByEnemyOfPlayer); Engine.RegisterGlobal("IsOwnedByEnemyOfPlayer", IsOwnedByEnemyOfPlayer);