# Add hunting (animals get killed before gathering meat from them)
This was SVN commit r8296.
This commit is contained in:
parent
69b2581ff0
commit
368b07b04e
@ -42,11 +42,27 @@ var AnimalFsmSpec = {
|
||||
// ignore spurious movement messages
|
||||
},
|
||||
|
||||
"HealthChanged": function(msg) {
|
||||
// If we died (got reduced to 0 hitpoints), stop the AI and act like a corpse
|
||||
if (msg.to == 0)
|
||||
this.SetNextState("CORPSE");
|
||||
},
|
||||
|
||||
"CORPSE": {
|
||||
"enter": function() {
|
||||
this.StopMoving();
|
||||
},
|
||||
|
||||
"Attacked": function(msg) {
|
||||
// Do nothing, because we're dead already
|
||||
},
|
||||
},
|
||||
|
||||
"SKITTISH": {
|
||||
|
||||
"ResourceGather": function(msg) {
|
||||
// If someone's carving chunks of meat off us, then run away
|
||||
this.MoveAwayFrom(msg.gatherer, +this.template.FleeDistance);
|
||||
"Attacked": function(msg) {
|
||||
// If someone's attacking us, then run away
|
||||
this.MoveAwayFrom(msg.data.attacker, +this.template.FleeDistance);
|
||||
this.SetNextState("FLEEING");
|
||||
this.PlaySound("panic");
|
||||
},
|
||||
@ -114,8 +130,8 @@ var AnimalFsmSpec = {
|
||||
|
||||
"PASSIVE": {
|
||||
|
||||
"ResourceGather": function(msg) {
|
||||
// Do nothing, just let them gather meat
|
||||
"Attacked": function(msg) {
|
||||
// Do nothing, just let them kill us
|
||||
},
|
||||
|
||||
"ROAMING": {
|
||||
@ -205,9 +221,14 @@ AnimalAI.prototype.OnMotionChanged = function(msg)
|
||||
}
|
||||
};
|
||||
|
||||
AnimalAI.prototype.OnResourceGather = function(msg)
|
||||
AnimalAI.prototype.OnAttacked = function(msg)
|
||||
{
|
||||
AnimalFsm.ProcessMessage(this, {"type": "ResourceGather", "gatherer": msg.gatherer});
|
||||
AnimalFsm.ProcessMessage(this, {"type": "Attacked", "data": msg});
|
||||
};
|
||||
|
||||
AnimalAI.prototype.OnHealthChanged = function(msg)
|
||||
{
|
||||
AnimalFsm.ProcessMessage(this, {"type": "HealthChanged", "from": msg.from, "to": msg.to});
|
||||
};
|
||||
|
||||
AnimalAI.prototype.TimerHandler = function(data, lateness)
|
||||
|
@ -18,10 +18,11 @@ Health.prototype.Schema =
|
||||
"<element name='RegenRate' a:help='Hitpoint regeneration rate per second. Not yet implemented'>" +
|
||||
"<ref name='nonNegativeDecimal'/>" +
|
||||
"</element>" +
|
||||
"<element name='DeathType' a:help='Graphical behaviour when the unit dies'>" +
|
||||
"<element name='DeathType' a:help='Behaviour when the unit dies'>" +
|
||||
"<choice>" +
|
||||
"<value a:help='Disappear instantly'>vanish</value>" +
|
||||
"<value a:help='Turn into a corpse'>corpse</value>" +
|
||||
"<value a:help='Remain in the world with 0 health'>remain</value>" +
|
||||
"</choice>" +
|
||||
"</element>" +
|
||||
"<element name='Healable' a:help='Indicates that the entity can be healed by healer units'>" +
|
||||
@ -40,6 +41,10 @@ Health.prototype.Init = function()
|
||||
|
||||
//// Interface functions ////
|
||||
|
||||
/**
|
||||
* Returns the current hitpoint value.
|
||||
* This is 0 if (and only if) the unit is dead.
|
||||
*/
|
||||
Health.prototype.GetHitpoints = function()
|
||||
{
|
||||
return this.hitpoints;
|
||||
@ -84,9 +89,23 @@ Health.prototype.Reduce = function(amount)
|
||||
PlaySound("death", this.entity);
|
||||
|
||||
if (this.template.DeathType == "corpse")
|
||||
{
|
||||
this.CreateCorpse();
|
||||
Engine.DestroyEntity(this.entity);
|
||||
}
|
||||
else if (this.template.DeathType == "vanish")
|
||||
{
|
||||
Engine.DestroyEntity(this.entity);
|
||||
}
|
||||
else if (this.template.DeathType == "remain")
|
||||
{
|
||||
// Don't destroy the entity
|
||||
|
||||
Engine.DestroyEntity(this.entity);
|
||||
// Make it fall over
|
||||
var cmpVisual = Engine.QueryInterface(this.entity, IID_Visual);
|
||||
if (cmpVisual)
|
||||
cmpVisual.SelectAnimation("death", true, 1.0, "");
|
||||
}
|
||||
|
||||
var old = this.hitpoints;
|
||||
this.hitpoints = 0;
|
||||
|
@ -83,6 +83,13 @@ var UnitFsmSpec = {
|
||||
},
|
||||
|
||||
"Order.Attack": function(msg) {
|
||||
// Check the target is alive
|
||||
if (!this.TargetIsAlive(this.order.data.target))
|
||||
{
|
||||
this.FinishOrder();
|
||||
return;
|
||||
}
|
||||
|
||||
// Work out how to attack the given target
|
||||
var type = this.GetBestAttack();
|
||||
if (!type)
|
||||
@ -109,6 +116,22 @@ var UnitFsmSpec = {
|
||||
},
|
||||
|
||||
"Order.Gather": function(msg) {
|
||||
// If the target is still alive, we need to kill it first
|
||||
if (this.TargetIsAlive(this.order.data.target))
|
||||
{
|
||||
// Make sure we can attack the target, else we'll get very stuck
|
||||
if (!this.GetBestAttack())
|
||||
{
|
||||
// Oops, we can't attack at all - give up
|
||||
// TODO: should do something so the player knows why this failed
|
||||
this.FinishOrder();
|
||||
return;
|
||||
}
|
||||
|
||||
this.PushOrderFront("Attack", { "target": this.order.data.target });
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to move within range
|
||||
if (this.MoveToTargetRange(this.order.data.target, IID_ResourceGatherer))
|
||||
{
|
||||
@ -308,27 +331,29 @@ var UnitFsmSpec = {
|
||||
},
|
||||
|
||||
"Timer": function(msg) {
|
||||
// Check we can still reach the target
|
||||
if (this.CheckTargetRange(this.order.data.target, IID_Attack, this.attackType))
|
||||
// Check the target is still alive
|
||||
if (this.TargetIsAlive(this.order.data.target))
|
||||
{
|
||||
var cmpAttack = Engine.QueryInterface(this.entity, IID_Attack);
|
||||
cmpAttack.PerformAttack(this.attackType, this.order.data.target);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Try to chase after it
|
||||
// Check we can still reach the target
|
||||
if (this.CheckTargetRange(this.order.data.target, IID_Attack, this.attackType))
|
||||
{
|
||||
var cmpAttack = Engine.QueryInterface(this.entity, IID_Attack);
|
||||
cmpAttack.PerformAttack(this.attackType, this.order.data.target);
|
||||
return;
|
||||
}
|
||||
|
||||
// Can't reach it - try to chase after it
|
||||
if (this.MoveToTargetRange(this.order.data.target, IID_Attack, this.attackType))
|
||||
{
|
||||
this.SetNextState("COMBAT.CHASING");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Can't reach it, or it doesn't exist any more - give up
|
||||
this.FinishOrder();
|
||||
|
||||
// TODO: see if we can switch to a new nearby enemy
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Can't reach it, or it doesn't exist any more - give up
|
||||
this.FinishOrder();
|
||||
|
||||
// TODO: see if we can switch to a new nearby enemy
|
||||
},
|
||||
|
||||
// TODO: respond to target deaths immediately, rather than waiting
|
||||
@ -702,6 +727,15 @@ UnitAI.prototype.GetRunSpeed = function()
|
||||
return cmpMotion.GetRunSpeed();
|
||||
};
|
||||
|
||||
UnitAI.prototype.TargetIsAlive = function(ent)
|
||||
{
|
||||
var cmpHealth = Engine.QueryInterface(ent, IID_Health);
|
||||
if (!cmpHealth)
|
||||
return false;
|
||||
|
||||
return (cmpHealth.GetHitpoints() != 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* Play a sound appropriate to the current entity.
|
||||
*/
|
||||
|
@ -1,7 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Entity parent="template_unit_fauna">
|
||||
<Identity>
|
||||
</Identity>
|
||||
<Health>
|
||||
<DeathType>remain</DeathType>
|
||||
</Health>
|
||||
<ResourceSupply>
|
||||
<Amount>100</Amount>
|
||||
<Type>food.meat</Type>
|
||||
|
@ -1,7 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Entity parent="template_unit_fauna">
|
||||
<Identity>
|
||||
</Identity>
|
||||
<Health>
|
||||
<DeathType>remain</DeathType>
|
||||
</Health>
|
||||
<ResourceSupply>
|
||||
<Amount>100</Amount>
|
||||
<Type>food.meat</Type>
|
||||
|
Loading…
Reference in New Issue
Block a user