Changeset View
Changeset View
Standalone View
Standalone View
binaries/data/mods/public/simulation/components/UnitAI.js
Show First 20 Lines • Show All 476 Lines • ▼ Show 20 Lines | "Order.Heal": function(msg) { | ||||
return ACCEPT_ORDER; | return ACCEPT_ORDER; | ||||
}, | }, | ||||
"Order.Gather": function(msg) { | "Order.Gather": function(msg) { | ||||
if (!this.CanGather(msg.data.target)) | if (!this.CanGather(msg.data.target)) | ||||
{ | { | ||||
this.SetNextState("INDIVIDUAL.GATHER.FINDINGNEWTARGET"); | this.SetNextState("INDIVIDUAL.GATHER.FINDINGNEWTARGET"); | ||||
return ACCEPT_ORDER; | return ACCEPT_ORDER; | ||||
} | } | ||||
// If the unit is full go to the nearest dropsite instead of trying to gather. | // If the unit is full go to the nearest dropsite instead of trying to gather. | ||||
let cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer); | let cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer); | ||||
if (cmpResourceGatherer && !cmpResourceGatherer.CanCarryMore(msg.data.type.generic)) | if (cmpResourceGatherer && !cmpResourceGatherer.CanCarryMore(msg.data.type.generic)) | ||||
{ | { | ||||
let nearestDropsite = this.FindNearestDropsite(msg.data.type.generic); | this.SetNextState("INDIVIDUAL.GATHER.RETURNINGRESOURCE"); | ||||
wraitii: Mh, why's this necessary? | |||||
Done Inline ActionsBecause we don't go out and in the GATHER state when gathering and tasked to gather another resource. Freagarach: Because we don't go out and in the GATHER state when gathering and tasked to gather another… | |||||
Done Inline ActionsRight. I think the comment should state this. wraitii: Right. I think the comment should state this. | |||||
if (nearestDropsite) | |||||
this.PushOrderFront("ReturnResource", { | |||||
"target": nearestDropsite, | |||||
"force": false, | |||||
"type": msg.data.type | |||||
}); | |||||
// Players expect the unit to move, so walk to the target instead of trying to gather. | |||||
else if (!this.FinishOrder()) | |||||
this.WalkToTarget(msg.data.target, false); | |||||
return ACCEPT_ORDER; | return ACCEPT_ORDER; | ||||
} | } | ||||
if (this.MustKillGatherTarget(msg.data.target)) | if (this.MustKillGatherTarget(msg.data.target)) | ||||
{ | { | ||||
// Make sure we can attack the target, else we'll get very stuck | // Make sure we can attack the target, else we'll get very stuck | ||||
if (!this.GetBestAttackAgainst(msg.data.target, false)) | if (!this.GetBestAttackAgainst(msg.data.target, false)) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 1,824 Lines • ▼ Show 20 Lines | "COMBAT": { | ||||
!msg.obstructed && this.CheckRange(this.order.data)) | !msg.obstructed && this.CheckRange(this.order.data)) | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
}, | }, | ||||
}, | }, | ||||
}, | }, | ||||
}, | }, | ||||
"GATHER": { | "GATHER": { | ||||
"enter": function() { | |||||
let cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer); | |||||
if (cmpResourceGatherer) | |||||
cmpResourceGatherer.AddToPlayerCounter(this.order.data.type.generic); | |||||
return false; | |||||
}, | |||||
"leave": function() { | "leave": function() { | ||||
let cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer); | |||||
if (cmpResourceGatherer) | |||||
cmpResourceGatherer.RemoveFromPlayerCounter(); | |||||
// Show the carried resource, if we've gathered anything. | // Show the carried resource, if we've gathered anything. | ||||
this.SetDefaultAnimationVariant(); | this.SetDefaultAnimationVariant(); | ||||
}, | }, | ||||
"APPROACHING": { | "APPROACHING": { | ||||
"enter": function() { | "enter": function() { | ||||
this.gatheringTarget = this.order.data.target; // temporary, deleted in "leave". | this.gatheringTarget = this.order.data.target; // temporary, deleted in "leave". | ||||
Show All 22 Lines | "GATHER": { | ||||
"force": this.order.data.force | "force": this.order.data.force | ||||
}); | }); | ||||
return true; | return true; | ||||
} | } | ||||
this.SetNextState("FINDINGNEWTARGET"); | this.SetNextState("FINDINGNEWTARGET"); | ||||
return true; | return true; | ||||
} | } | ||||
this.SetAnimationVariant("approach_" + this.order.data.type.specific); | this.SetAnimationVariant("approach_" + this.order.data.type.specific); | ||||
let cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer); | |||||
if (cmpResourceGatherer) | |||||
cmpResourceGatherer.AddToPlayerCounter(this.order.data.type.generic); | |||||
return false; | return false; | ||||
}, | }, | ||||
"MovementUpdate": function(msg) { | "MovementUpdate": function(msg) { | ||||
// The GATHERING timer will handle finding a valid resource. | // The GATHERING timer will handle finding a valid resource. | ||||
if (msg.likelyFailure) | if (msg.likelyFailure) | ||||
this.SetNextState("FINDINGNEWTARGET"); | this.SetNextState("FINDINGNEWTARGET"); | ||||
else if (this.CheckRange(this.order.data, IID_ResourceGatherer)) | else if (this.CheckRange(this.order.data, IID_ResourceGatherer)) | ||||
this.SetNextState("GATHERING"); | this.SetNextState("GATHERING"); | ||||
}, | }, | ||||
"leave": function() { | "leave": function() { | ||||
this.StopMoving(); | this.StopMoving(); | ||||
if (!this.gatheringTarget) | if (!this.gatheringTarget) | ||||
return; | return; | ||||
// don't use ownership because this is called after a conversion/resignation | |||||
// and the ownership would be invalid then. | |||||
let cmpSupply = Engine.QueryInterface(this.gatheringTarget, IID_ResourceSupply); | let cmpSupply = Engine.QueryInterface(this.gatheringTarget, IID_ResourceSupply); | ||||
if (cmpSupply) | if (cmpSupply) | ||||
cmpSupply.RemoveGatherer(this.entity); | cmpSupply.RemoveGatherer(this.entity); | ||||
let cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer); | |||||
if (cmpResourceGatherer) | |||||
cmpResourceGatherer.RemoveFromPlayerCounter(); | |||||
delete this.gatheringTarget; | delete this.gatheringTarget; | ||||
}, | }, | ||||
}, | }, | ||||
// Walking to a good place to gather resources near, used by GatherNearPosition | // Walking to a good place to gather resources near, used by GatherNearPosition | ||||
"WALKING": { | "WALKING": { | ||||
"enter": function() { | "enter": function() { | ||||
if (!this.MoveTo(this.order.data)) | if (!this.MoveTo(this.order.data)) | ||||
▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | "GATHER": { | ||||
"leave": function() { | "leave": function() { | ||||
let cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer); | let cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer); | ||||
if (cmpResourceGatherer) | if (cmpResourceGatherer) | ||||
cmpResourceGatherer.StopGathering(); | cmpResourceGatherer.StopGathering(); | ||||
}, | }, | ||||
"InventoryFilled": function(msg) { | "InventoryFilled": function(msg) { | ||||
let nearestDropsite = this.FindNearestDropsite(this.order.data.type.generic); | this.SetNextState("RETURNINGRESOURCE"); | ||||
if (nearestDropsite) | |||||
this.PushOrderFront("ReturnResource", { "target": nearestDropsite, "force": false }); | |||||
else | |||||
this.FinishOrder(); | |||||
}, | }, | ||||
"OutOfRange": function(msg) { | "OutOfRange": function(msg) { | ||||
if (this.MoveToTargetRange(this.order.data.target, IID_ResourceGatherer)) | if (this.MoveToTargetRange(this.order.data.target, IID_ResourceGatherer)) | ||||
this.SetNextState("APPROACHING"); | this.SetNextState("APPROACHING"); | ||||
// Our target is no longer visible - go to its last known position first | // Our target is no longer visible - go to its last known position first | ||||
// and then hopefully it will become visible. | // and then hopefully it will become visible. | ||||
▲ Show 20 Lines • Show All 86 Lines • ▼ Show 20 Lines | "GATHER": { | ||||
{ | { | ||||
this.PushOrderFront("ReturnResource", { "target": nearestDropsite, "force": false }); | this.PushOrderFront("ReturnResource", { "target": nearestDropsite, "force": false }); | ||||
return true; | return true; | ||||
} | } | ||||
// No dropsites - just give up. | // No dropsites - just give up. | ||||
return true; | return true; | ||||
}, | }, | ||||
}, | }, | ||||
"RETURNINGRESOURCE": { | |||||
"enter": function() { | |||||
let nearestDropsite = this.FindNearestDropsite(this.order.data.type.generic); | |||||
if (!nearestDropsite) | |||||
{ | |||||
// The player expects the unit to move upon failure. | |||||
let formerTarget = this.order.data.target; | |||||
if (!this.FinishOrder()) | |||||
this.WalkToTarget(formerTarget); | |||||
return true; | |||||
} | |||||
this.order.data.formerTarget = this.order.data.target; | |||||
this.order.data.target = nearestDropsite; | |||||
this.SetDefaultAnimationVariant(); | |||||
this.SetNextState("APPROACHING"); | |||||
return true; | |||||
}, | |||||
"leave": function() { | |||||
}, | |||||
"APPROACHING": "INDIVIDUAL.RETURNRESOURCE.APPROACHING", | |||||
"DROPPINGRESOURCES": { | |||||
"enter": function() { | |||||
let cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer); | |||||
if (this.CanReturnResource(this.order.data.target, true, cmpResourceGatherer)) | |||||
{ | |||||
cmpResourceGatherer.CommitResources(this.order.data.target); | |||||
this.order.data.target = this.order.data.formerTarget; | |||||
// Stop showing the carried resource animation. | |||||
this.SetDefaultAnimationVariant(); | |||||
this.SetNextState("GATHER.APPROACHING"); | |||||
} | |||||
else | |||||
this.SetNextState("RETURNINGRESOURCE"); | |||||
return true; | |||||
}, | |||||
"leave": function() { | |||||
}, | |||||
}, | |||||
}, | |||||
}, | }, | ||||
"HEAL": { | "HEAL": { | ||||
"Attacked": function(msg) { | "Attacked": function(msg) { | ||||
if (!this.GetStance().respondStandGround && !this.order.data.force) | if (!this.GetStance().respondStandGround && !this.order.data.force) | ||||
this.Flee(msg.data.attacker, false); | this.Flee(msg.data.attacker, false); | ||||
}, | }, | ||||
▲ Show 20 Lines • Show All 2,908 Lines • ▼ Show 20 Lines | UnitAI.prototype.PerformGather = function(target, queued, force, pushFront = false) | ||||
this.RememberTargetPosition(order); | this.RememberTargetPosition(order); | ||||
order.initPos = order.lastPos; | order.initPos = order.lastPos; | ||||
if (this.order && | if (this.order && | ||||
(this.order.type == "Gather" || this.order.type == "Attack") && | (this.order.type == "Gather" || this.order.type == "Attack") && | ||||
this.order.data && | this.order.data && | ||||
this.order.data.target === order.target) | this.order.data.target === order.target) | ||||
{ | { | ||||
Done Inline ActionsThis may be done nicer. Freagarach: This may be done nicer. | |||||
Done Inline ActionsThis is a workaround the fact that we don't pass GATHER.enter, right? I generally tend to prefer duplication but simple code over weird abstractions like this in UnitAI, it is at least explicit. If you want, you can add a function that wraps the logic up (see MoveTo). My solution would be to either:
wraitii: This is a workaround the fact that we don't pass GATHER.enter, right?
I generally tend to… | |||||
Done Inline ActionsI guess I can move some stuff from the order to the entering of the gather state? Freagarach: I guess I can move some stuff from the order to the entering of the gather state? | |||||
this.order.data.lastPos = order.lastPos; | this.order.data.lastPos = order.lastPos; | ||||
this.order.data.force = order.force; | this.order.data.force = order.force; | ||||
if (order.force) | if (order.force) | ||||
this.orderQueue = [this.order]; | this.orderQueue = [this.order]; | ||||
return; | return; | ||||
} | } | ||||
this.AddOrder("Gather", order, queued, pushFront); | this.AddOrder("Gather", order, queued, pushFront); | ||||
▲ Show 20 Lines • Show All 875 Lines • Show Last 20 Lines |
Wildfire Games · Phabricator
Mh, why's this necessary?