forked from 0ad/0ad
Destroy dying 'remain' entities and replace them with visually-identical resources. Fixes #1600.
This was SVN commit r12486.
This commit is contained in:
parent
034212a554
commit
66012e2e2c
@ -82,7 +82,7 @@ BuildingAI.prototype.SetupRangeQuery = function(owner)
|
||||
if (cmpAttack)
|
||||
{
|
||||
var range = cmpAttack.GetRange("Ranged");
|
||||
this.enemyUnitsQuery = cmpRangeManager.CreateActiveQuery(this.entity, range.min, range.max, players, 0, cmpRangeManager.GetEntityFlagMask("normal"));
|
||||
this.enemyUnitsQuery = cmpRangeManager.CreateActiveQuery(this.entity, range.min, range.max, players, IID_DamageReceiver, cmpRangeManager.GetEntityFlagMask("normal"));
|
||||
cmpRangeManager.EnableActiveQuery(this.enemyUnitsQuery);
|
||||
}
|
||||
};
|
||||
@ -135,8 +135,11 @@ BuildingAI.prototype.OnRangeUpdate = function(msg)
|
||||
|
||||
if (msg.added.length)
|
||||
msg.added = msg.added.filter(filter);
|
||||
if (msg.removed.length)
|
||||
msg.removed = msg.removed.filter(filter);
|
||||
|
||||
// Removed entities may not have cmpUnitAI.
|
||||
for (var i = 0; i < msg.removed.length; ++i)
|
||||
if (this.targetUnits.indexOf(msg.removed[i]) == -1)
|
||||
msg.removed.splice(i--, 1);
|
||||
}
|
||||
else if (msg.tag != this.enemyUnitsQuery)
|
||||
return;
|
||||
|
@ -124,18 +124,10 @@ Health.prototype.Reduce = function(amount)
|
||||
}
|
||||
else if (this.template.DeathType == "remain")
|
||||
{
|
||||
// Don't destroy the entity
|
||||
|
||||
// TODO: This is a workaround so players don't retain LOS when
|
||||
// their livestock animals die. See ticket #1600.
|
||||
var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
|
||||
if (cmpOwnership)
|
||||
cmpOwnership.SetOwner(0);
|
||||
|
||||
// Make it fall over
|
||||
var cmpVisual = Engine.QueryInterface(this.entity, IID_Visual);
|
||||
if (cmpVisual)
|
||||
cmpVisual.SelectAnimation("death", true, 1.0, "");
|
||||
var resource = this.CreateCorpse(true);
|
||||
if (resource != INVALID_ENTITY)
|
||||
Engine.BroadcastMessage(MT_EntityRenamed, { entity: this.entity, newentity: resource });
|
||||
Engine.DestroyEntity(this.entity);
|
||||
}
|
||||
|
||||
var old = this.hitpoints;
|
||||
@ -178,18 +170,23 @@ Health.prototype.Increase = function(amount)
|
||||
|
||||
//// Private functions ////
|
||||
|
||||
Health.prototype.CreateCorpse = function()
|
||||
Health.prototype.CreateCorpse = function(leaveResources)
|
||||
{
|
||||
// If the unit died while not in the world, don't create any corpse for it
|
||||
// since there's nowhere for the corpse to be placed
|
||||
var cmpPosition = Engine.QueryInterface(this.entity, IID_Position);
|
||||
if (!cmpPosition.IsInWorld())
|
||||
return;
|
||||
return INVALID_ENTITY;
|
||||
|
||||
// Create a static local version of the current entity
|
||||
// Either creates a static local version of the current entity, or a
|
||||
// persistent corpse retaining the ResourceSupply element of the parent.
|
||||
var cmpTempMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager);
|
||||
var templateName = cmpTempMan.GetCurrentTemplateName(this.entity);
|
||||
var corpse = Engine.AddLocalEntity("corpse|" + templateName);
|
||||
var corpse;
|
||||
if (leaveResources)
|
||||
corpse = Engine.AddEntity("resource|" + templateName);
|
||||
else
|
||||
corpse = Engine.AddLocalEntity("corpse|" + templateName);
|
||||
|
||||
// Copy various parameters so it looks just like us
|
||||
|
||||
@ -207,6 +204,8 @@ Health.prototype.CreateCorpse = function()
|
||||
// Make it fall over
|
||||
var cmpCorpseVisual = Engine.QueryInterface(corpse, IID_Visual);
|
||||
cmpCorpseVisual.SelectAnimation("death", true, 1.0, "");
|
||||
|
||||
return corpse;
|
||||
};
|
||||
|
||||
Health.prototype.Repair = function(builderEnt, work)
|
||||
|
@ -815,6 +815,12 @@ var UnitFsmSpec = {
|
||||
"EntityRenamed": function(msg) {
|
||||
if (this.order.data.target == msg.entity)
|
||||
this.order.data.target = msg.newentity;
|
||||
|
||||
// If we're hunting, that means we have a queued gather
|
||||
// order whose target also needs to be updated.
|
||||
if (this.order.data.hunting && this.orderQueue[1] &&
|
||||
this.orderQueue[1].type == "Gather")
|
||||
this.orderQueue[1].data.target = msg.newentity;
|
||||
},
|
||||
|
||||
"Attacked": function(msg) {
|
||||
@ -2319,6 +2325,11 @@ UnitAI.prototype.FindNearbyResource = function(filter)
|
||||
var type = cmpResourceSupply.GetType();
|
||||
var amount = cmpResourceSupply.GetCurrentAmount();
|
||||
var template = cmpTemplateManager.GetCurrentTemplateName(ent);
|
||||
|
||||
// Remove "resource|" prefix from template names, if present.
|
||||
if (template.indexOf("resource|") != -1)
|
||||
template = template.slice(9);
|
||||
|
||||
if (amount > 0 && filter(ent, type, template))
|
||||
return ent;
|
||||
}
|
||||
@ -2968,6 +2979,10 @@ UnitAI.prototype.PerformGather = function(target, queued, force)
|
||||
var cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager);
|
||||
var template = cmpTemplateManager.GetCurrentTemplateName(target);
|
||||
|
||||
// Remove "resource|" prefix from template name, if present.
|
||||
if (template.indexOf("resource|") != -1)
|
||||
template = template.slice(9);
|
||||
|
||||
// Remember the position of our target, if any, in case it disappears
|
||||
// later and we want to head to its last known position
|
||||
// (TODO: if the target moves a lot (e.g. it's an animal), maybe we
|
||||
|
@ -174,6 +174,10 @@ private:
|
||||
// Copy the components of an entity necessary for a construction foundation
|
||||
// (position, actor, armour, health, etc) into a new entity template
|
||||
void CopyFoundationSubset(CParamNode& out, const CParamNode& in);
|
||||
|
||||
// Copy the components of an entity necessary for a gatherable resource
|
||||
// into a new entity template
|
||||
void CopyResourceSubset(CParamNode& out, const CParamNode& in);
|
||||
};
|
||||
|
||||
REGISTER_COMPONENT_TYPE(TemplateManager)
|
||||
@ -324,6 +328,21 @@ bool CCmpTemplateManager::LoadTemplateFile(const std::string& templateName, int
|
||||
return true;
|
||||
}
|
||||
|
||||
// Handle special case "resource|foo"
|
||||
if (templateName.find("resource|") == 0)
|
||||
{
|
||||
// Load the base entity template, if it wasn't already loaded
|
||||
std::string baseName = templateName.substr(9);
|
||||
if (!LoadTemplateFile(baseName, depth+1))
|
||||
{
|
||||
LOGERROR(L"Failed to load entity template '%hs'", baseName.c_str());
|
||||
return false;
|
||||
}
|
||||
// Copy a subset to the requested template
|
||||
CopyResourceSubset(m_TemplateFileData[templateName], m_TemplateFileData[baseName]);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Normal case: templateName is an XML file:
|
||||
|
||||
VfsPath path = VfsPath(TEMPLATE_ROOT) / wstring_from_utf8(templateName + ".xml");
|
||||
@ -553,3 +572,26 @@ void CCmpTemplateManager::CopyFoundationSubset(CParamNode& out, const CParamNode
|
||||
if (out.GetChild("Entity").GetChild("Vision").IsOk())
|
||||
CParamNode::LoadXMLString(out, "<Entity><Vision><Range>0</Range></Vision></Entity>");
|
||||
}
|
||||
|
||||
void CCmpTemplateManager::CopyResourceSubset(CParamNode& out, const CParamNode& in)
|
||||
{
|
||||
// Currently used for animals which die and leave a gatherable corpse.
|
||||
// Mostly serves to filter out components like Vision, UnitAI, etc.
|
||||
std::set<std::string> permittedComponentTypes;
|
||||
permittedComponentTypes.insert("Ownership");
|
||||
permittedComponentTypes.insert("Position");
|
||||
permittedComponentTypes.insert("VisualActor");
|
||||
permittedComponentTypes.insert("Identity");
|
||||
permittedComponentTypes.insert("Obstruction");
|
||||
permittedComponentTypes.insert("Minimap");
|
||||
permittedComponentTypes.insert("ResourceSupply");
|
||||
permittedComponentTypes.insert("Selectable");
|
||||
permittedComponentTypes.insert("Footprint");
|
||||
permittedComponentTypes.insert("StatusBars");
|
||||
permittedComponentTypes.insert("OverlayRenderer");
|
||||
permittedComponentTypes.insert("Sound");
|
||||
permittedComponentTypes.insert("AIProxy");
|
||||
|
||||
CParamNode::LoadXMLString(out, "<Entity/>");
|
||||
out.CopyFilteredChildrenOfChild(in, "Entity", permittedComponentTypes);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user