1
0
forked from 0ad/0ad

# Add hunting (animals get killed before gathering meat from them)

This was SVN commit r8296.
This commit is contained in:
Ykkrosh 2010-10-06 21:37:55 +00:00
parent 69b2581ff0
commit 368b07b04e
5 changed files with 104 additions and 28 deletions

View File

@ -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)

View File

@ -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;

View File

@ -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.
*/

View File

@ -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>

View File

@ -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>