Add the Engine code for turrets + use them to get units on walls. The scripted TurretHolder isn't included due to lack of usability for now. Refs #2577
This was SVN commit r15246.
This commit is contained in:
parent
d05bd656e7
commit
cfec28e553
@ -227,6 +227,16 @@ Attack.prototype.CanAttack = function(target)
|
|||||||
if (cmpFormation)
|
if (cmpFormation)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
var cmpThisPosition = Engine.QueryInterface(this.entity, IID_Position);
|
||||||
|
var cmpTargetPosition = Engine.QueryInterface(target, IID_Position);
|
||||||
|
if (!cmpThisPosition || !cmpTargetPosition || !cmpThisPosition.IsInWorld() || !cmpTargetPosition.IsInWorld())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Check if the relative height difference is larger than the attack range
|
||||||
|
// If the relative height is bigger, it means they will never be able to
|
||||||
|
// reach each other, no matter how close they come.
|
||||||
|
var heightDiff = Math.abs(cmpThisPosition.GetHeightOffset() - cmpTargetPosition.GetHeightOffset());
|
||||||
|
|
||||||
const cmpIdentity = Engine.QueryInterface(target, IID_Identity);
|
const cmpIdentity = Engine.QueryInterface(target, IID_Identity);
|
||||||
if (!cmpIdentity)
|
if (!cmpIdentity)
|
||||||
return undefined;
|
return undefined;
|
||||||
@ -235,6 +245,9 @@ Attack.prototype.CanAttack = function(target)
|
|||||||
|
|
||||||
for each (var type in this.GetAttackTypes())
|
for each (var type in this.GetAttackTypes())
|
||||||
{
|
{
|
||||||
|
if (heightDiff > this.GetRange(type).max)
|
||||||
|
continue;
|
||||||
|
|
||||||
var canAttack = true;
|
var canAttack = true;
|
||||||
var restrictedClasses = this.GetRestrictedClasses(type);
|
var restrictedClasses = this.GetRestrictedClasses(type);
|
||||||
|
|
||||||
|
@ -29,6 +29,26 @@ GarrisonHolder.prototype.Schema =
|
|||||||
"<element name='Pickup' a:help='This garrisonHolder will move to pick up units to be garrisoned'>" +
|
"<element name='Pickup' a:help='This garrisonHolder will move to pick up units to be garrisoned'>" +
|
||||||
"<data type='boolean'/>" +
|
"<data type='boolean'/>" +
|
||||||
"</element>" +
|
"</element>" +
|
||||||
|
"</optional>" +
|
||||||
|
"<optional>" +
|
||||||
|
"<element name='VisibleGarrisonPoints' a:help='Points that will be used to visibly garrison a unit'>" +
|
||||||
|
"<zeroOrMore>" +
|
||||||
|
"<element a:help='Element containing the offset coordinates'>" +
|
||||||
|
"<anyName/>" +
|
||||||
|
"<interleave>" +
|
||||||
|
"<element name='X'>" +
|
||||||
|
"<data type='decimal'/>" +
|
||||||
|
"</element>" +
|
||||||
|
"<element name='Y'>" +
|
||||||
|
"<data type='decimal'/>" +
|
||||||
|
"</element>" +
|
||||||
|
"<element name='Z'>" +
|
||||||
|
"<data type='decimal'/>" +
|
||||||
|
"</element>" +
|
||||||
|
"</interleave>" +
|
||||||
|
"</element>" +
|
||||||
|
"</zeroOrMore>" +
|
||||||
|
"</element>" +
|
||||||
"</optional>";
|
"</optional>";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -40,6 +60,18 @@ GarrisonHolder.prototype.Init = function()
|
|||||||
this.entities = [];
|
this.entities = [];
|
||||||
this.timer = undefined;
|
this.timer = undefined;
|
||||||
this.allowGarrisoning = {};
|
this.allowGarrisoning = {};
|
||||||
|
this.visibleGarrisonPoints = [];
|
||||||
|
if (this.template.VisibleGarrisonPoints)
|
||||||
|
{
|
||||||
|
for each (var offset in this.template.VisibleGarrisonPoints)
|
||||||
|
{
|
||||||
|
var o = {};
|
||||||
|
o.x = +offset.X;
|
||||||
|
o.y = +offset.Y;
|
||||||
|
o.z = +offset.Z;
|
||||||
|
this.visibleGarrisonPoints.push({"offset":o, "entity": null});
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -206,7 +238,21 @@ GarrisonHolder.prototype.Garrison = function(entity)
|
|||||||
if (!this.PerformGarrison(entity))
|
if (!this.PerformGarrison(entity))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
cmpPosition.MoveOutOfWorld();
|
var visiblyGarrisoned = false;
|
||||||
|
for (var vgp of this.visibleGarrisonPoints)
|
||||||
|
{
|
||||||
|
if (vgp.entity)
|
||||||
|
continue;
|
||||||
|
vgp.entity = entity;
|
||||||
|
cmpPosition.SetTurretParent(this.entity, vgp.offset);
|
||||||
|
var cmpUnitAI = Engine.QueryInterface(entity, IID_UnitAI)
|
||||||
|
if (cmpUnitAI)
|
||||||
|
cmpUnitAI.SetTurret(true);
|
||||||
|
visiblyGarrisoned = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!visiblyGarrisoned)
|
||||||
|
cmpPosition.MoveOutOfWorld();
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -291,8 +337,21 @@ GarrisonHolder.prototype.Eject = function(entity, forced)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var cmpNewPosition = Engine.QueryInterface(entity, IID_Position);
|
||||||
this.entities.splice(entityIndex, 1);
|
this.entities.splice(entityIndex, 1);
|
||||||
|
|
||||||
|
for (var vgp of this.visibleGarrisonPoints)
|
||||||
|
{
|
||||||
|
if (vgp.entity != entity)
|
||||||
|
continue;
|
||||||
|
cmpNewPosition.SetTurretParent(INVALID_ENTITY, new Vector3D());
|
||||||
|
vgp.entity = null;
|
||||||
|
var cmpUnitAI = Engine.QueryInterface(entity, IID_UnitAI)
|
||||||
|
if (cmpUnitAI)
|
||||||
|
cmpUnitAI.SetTurret(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
var cmpUnitAI = Engine.QueryInterface(entity, IID_UnitAI);
|
var cmpUnitAI = Engine.QueryInterface(entity, IID_UnitAI);
|
||||||
if (cmpUnitAI)
|
if (cmpUnitAI)
|
||||||
cmpUnitAI.Ungarrison();
|
cmpUnitAI.Ungarrison();
|
||||||
@ -306,8 +365,8 @@ GarrisonHolder.prototype.Eject = function(entity, forced)
|
|||||||
cmpAura.RemoveGarrisonBonus(this.entity);
|
cmpAura.RemoveGarrisonBonus(this.entity);
|
||||||
|
|
||||||
|
|
||||||
var cmpNewPosition = Engine.QueryInterface(entity, IID_Position);
|
|
||||||
cmpNewPosition.JumpTo(pos.x, pos.z);
|
cmpNewPosition.JumpTo(pos.x, pos.z);
|
||||||
|
cmpNewPosition.SetHeightOffset(0);
|
||||||
// TODO: what direction should they face in?
|
// TODO: what direction should they face in?
|
||||||
|
|
||||||
Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added" : [], "removed": [entity] });
|
Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added" : [], "removed": [entity] });
|
||||||
@ -579,8 +638,8 @@ GarrisonHolder.prototype.OnGlobalEntityRenamed = function(msg)
|
|||||||
var entityIndex = this.entities.indexOf(msg.entity);
|
var entityIndex = this.entities.indexOf(msg.entity);
|
||||||
if (entityIndex != -1)
|
if (entityIndex != -1)
|
||||||
{
|
{
|
||||||
this.entities[entityIndex] = msg.newentity;
|
this.Eject(msg.entity);
|
||||||
Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added" : [msg.newentity], "removed": [msg.entity] });
|
this.Garrison(msg.newentity);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -179,7 +179,7 @@ UnitAI.prototype.UnitFsmSpec = {
|
|||||||
// Called when being told to walk as part of a formation
|
// Called when being told to walk as part of a formation
|
||||||
"Order.FormationWalk": function(msg) {
|
"Order.FormationWalk": function(msg) {
|
||||||
// Let players move captured domestic animals around
|
// Let players move captured domestic animals around
|
||||||
if (this.IsAnimal() && !this.IsDomestic())
|
if (this.IsAnimal() && !this.IsDomestic() || this.IsTurret())
|
||||||
{
|
{
|
||||||
this.FinishOrder();
|
this.FinishOrder();
|
||||||
return;
|
return;
|
||||||
@ -207,7 +207,7 @@ UnitAI.prototype.UnitFsmSpec = {
|
|||||||
"Order.LeaveFoundation": function(msg) {
|
"Order.LeaveFoundation": function(msg) {
|
||||||
// If foundation is not ally of entity, or if entity is unpacked siege,
|
// If foundation is not ally of entity, or if entity is unpacked siege,
|
||||||
// ignore the order
|
// ignore the order
|
||||||
if (!IsOwnedByAllyOfEntity(this.entity, msg.data.target) || this.IsPacking() || this.CanPack())
|
if (!IsOwnedByAllyOfEntity(this.entity, msg.data.target) || this.IsPacking() || this.CanPack() || this.IsTurret())
|
||||||
{
|
{
|
||||||
this.FinishOrder();
|
this.FinishOrder();
|
||||||
return;
|
return;
|
||||||
@ -252,7 +252,7 @@ UnitAI.prototype.UnitFsmSpec = {
|
|||||||
|
|
||||||
"Order.Walk": function(msg) {
|
"Order.Walk": function(msg) {
|
||||||
// Let players move captured domestic animals around
|
// Let players move captured domestic animals around
|
||||||
if (this.IsAnimal() && !this.IsDomestic())
|
if (this.IsAnimal() && !this.IsDomestic() || this.IsTurret())
|
||||||
{
|
{
|
||||||
this.FinishOrder();
|
this.FinishOrder();
|
||||||
return;
|
return;
|
||||||
@ -281,7 +281,7 @@ UnitAI.prototype.UnitFsmSpec = {
|
|||||||
|
|
||||||
"Order.WalkAndFight": function(msg) {
|
"Order.WalkAndFight": function(msg) {
|
||||||
// Let players move captured domestic animals around
|
// Let players move captured domestic animals around
|
||||||
if (this.IsAnimal() && !this.IsDomestic())
|
if (this.IsAnimal() && !this.IsDomestic() || this.IsTurret())
|
||||||
{
|
{
|
||||||
this.FinishOrder();
|
this.FinishOrder();
|
||||||
return;
|
return;
|
||||||
@ -308,7 +308,7 @@ UnitAI.prototype.UnitFsmSpec = {
|
|||||||
|
|
||||||
"Order.WalkToTarget": function(msg) {
|
"Order.WalkToTarget": function(msg) {
|
||||||
// Let players move captured domestic animals around
|
// Let players move captured domestic animals around
|
||||||
if (this.IsAnimal() && !this.IsDomestic())
|
if (this.IsAnimal() && !this.IsDomestic() || this.IsTurret())
|
||||||
{
|
{
|
||||||
this.FinishOrder();
|
this.FinishOrder();
|
||||||
return;
|
return;
|
||||||
@ -489,7 +489,7 @@ UnitAI.prototype.UnitFsmSpec = {
|
|||||||
|
|
||||||
// If we can't reach the target, but are standing ground, then abandon this attack order.
|
// If we can't reach the target, but are standing ground, then abandon this attack order.
|
||||||
// Unless we're hunting, that's a special case where we should continue attacking our target.
|
// Unless we're hunting, that's a special case where we should continue attacking our target.
|
||||||
if (this.GetStance().respondStandGround && !this.order.data.force && !this.order.data.hunting)
|
if (this.GetStance().respondStandGround && !this.order.data.force && !this.order.data.hunting || this.IsTurret())
|
||||||
{
|
{
|
||||||
this.FinishOrder();
|
this.FinishOrder();
|
||||||
return;
|
return;
|
||||||
@ -688,6 +688,11 @@ UnitAI.prototype.UnitFsmSpec = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
"Order.Garrison": function(msg) {
|
"Order.Garrison": function(msg) {
|
||||||
|
if (this.IsTurret())
|
||||||
|
{
|
||||||
|
this.FinishOrder();
|
||||||
|
return;
|
||||||
|
}
|
||||||
// For packable units:
|
// For packable units:
|
||||||
// 1. If packed, we can move to the garrison target.
|
// 1. If packed, we can move to the garrison target.
|
||||||
// 2. If unpacked, we first need to pack, then follow case 1.
|
// 2. If unpacked, we first need to pack, then follow case 1.
|
||||||
@ -1245,7 +1250,7 @@ UnitAI.prototype.UnitFsmSpec = {
|
|||||||
"Order.LeaveFoundation": function(msg) {
|
"Order.LeaveFoundation": function(msg) {
|
||||||
// If foundation is not ally of entity, or if entity is unpacked siege,
|
// If foundation is not ally of entity, or if entity is unpacked siege,
|
||||||
// ignore the order
|
// ignore the order
|
||||||
if (!IsOwnedByAllyOfEntity(this.entity, msg.data.target) || this.IsPacking() || this.CanPack())
|
if (!IsOwnedByAllyOfEntity(this.entity, msg.data.target) || this.IsPacking() || this.CanPack() || this.IsTurret())
|
||||||
{
|
{
|
||||||
this.FinishOrder();
|
this.FinishOrder();
|
||||||
return;
|
return;
|
||||||
@ -2836,6 +2841,9 @@ UnitAI.prototype.UnitFsmSpec = {
|
|||||||
delete this.pickup;
|
delete this.pickup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.IsTurret())
|
||||||
|
this.SetNextState("IDLE");
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3135,6 +3143,28 @@ UnitAI.prototype.Init = function()
|
|||||||
this.lastHealed = undefined;
|
this.lastHealed = undefined;
|
||||||
|
|
||||||
this.SetStance(this.template.DefaultStance);
|
this.SetStance(this.template.DefaultStance);
|
||||||
|
this.SetTurret(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the flag to true to use this unit as a turret
|
||||||
|
* This means no moving is allowed, only turning
|
||||||
|
*/
|
||||||
|
UnitAI.prototype.SetTurret = function(flag)
|
||||||
|
{
|
||||||
|
this.isTurret = flag;
|
||||||
|
if (flag == false && this.oldStance)
|
||||||
|
this.SetStance(this.oldStance);
|
||||||
|
else if (flag == true)
|
||||||
|
{
|
||||||
|
this.OldStance = this.GetStance();
|
||||||
|
this.SetStance("standground");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
UnitAI.prototype.IsTurret = function()
|
||||||
|
{
|
||||||
|
return this.isTurret;
|
||||||
};
|
};
|
||||||
|
|
||||||
UnitAI.prototype.ReactsToAlert = function(level)
|
UnitAI.prototype.ReactsToAlert = function(level)
|
||||||
@ -4168,7 +4198,7 @@ UnitAI.prototype.MoveToTarget = function(target)
|
|||||||
|
|
||||||
UnitAI.prototype.MoveToTargetRange = function(target, iid, type)
|
UnitAI.prototype.MoveToTargetRange = function(target, iid, type)
|
||||||
{
|
{
|
||||||
if (!this.CheckTargetVisible(target))
|
if (!this.CheckTargetVisible(target) || this.IsTurret())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var cmpRanged = Engine.QueryInterface(this.entity, iid);
|
var cmpRanged = Engine.QueryInterface(this.entity, iid);
|
||||||
@ -4599,6 +4629,9 @@ UnitAI.prototype.ShouldAbandonChase = function(target, force, iid, type)
|
|||||||
*/
|
*/
|
||||||
UnitAI.prototype.ShouldChaseTargetedEntity = function(target, force)
|
UnitAI.prototype.ShouldChaseTargetedEntity = function(target, force)
|
||||||
{
|
{
|
||||||
|
if (this.IsTurret())
|
||||||
|
return false;
|
||||||
|
|
||||||
// TODO: use special stances instead?
|
// TODO: use special stances instead?
|
||||||
var cmpPack = Engine.QueryInterface(this.entity, IID_Pack);
|
var cmpPack = Engine.QueryInterface(this.entity, IID_Pack);
|
||||||
if (cmpPack)
|
if (cmpPack)
|
||||||
@ -5530,6 +5563,8 @@ UnitAI.prototype.CanGarrison = function(target)
|
|||||||
|
|
||||||
UnitAI.prototype.CanGather = function(target)
|
UnitAI.prototype.CanGather = function(target)
|
||||||
{
|
{
|
||||||
|
if (this.IsTurret())
|
||||||
|
return false;
|
||||||
// The target must be a valid resource supply.
|
// The target must be a valid resource supply.
|
||||||
var cmpResourceSupply = Engine.QueryInterface(target, IID_ResourceSupply);
|
var cmpResourceSupply = Engine.QueryInterface(target, IID_ResourceSupply);
|
||||||
if (!cmpResourceSupply)
|
if (!cmpResourceSupply)
|
||||||
@ -5602,6 +5637,8 @@ UnitAI.prototype.CanHeal = function(target)
|
|||||||
|
|
||||||
UnitAI.prototype.CanReturnResource = function(target, checkCarriedResource)
|
UnitAI.prototype.CanReturnResource = function(target, checkCarriedResource)
|
||||||
{
|
{
|
||||||
|
if (this.IsTurret())
|
||||||
|
return false;
|
||||||
// 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)
|
||||||
if (this.IsFormationController())
|
if (this.IsFormationController())
|
||||||
@ -5636,6 +5673,8 @@ UnitAI.prototype.CanReturnResource = function(target, checkCarriedResource)
|
|||||||
|
|
||||||
UnitAI.prototype.CanTrade = function(target)
|
UnitAI.prototype.CanTrade = function(target)
|
||||||
{
|
{
|
||||||
|
if (this.IsTurret())
|
||||||
|
return false;
|
||||||
// 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)
|
||||||
if (this.IsFormationController())
|
if (this.IsFormationController())
|
||||||
@ -5651,6 +5690,8 @@ UnitAI.prototype.CanTrade = function(target)
|
|||||||
|
|
||||||
UnitAI.prototype.CanRepair = function(target)
|
UnitAI.prototype.CanRepair = function(target)
|
||||||
{
|
{
|
||||||
|
if (this.IsTurret())
|
||||||
|
return false;
|
||||||
// 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)
|
||||||
if (this.IsFormationController())
|
if (this.IsFormationController())
|
||||||
|
@ -4,6 +4,25 @@
|
|||||||
<Square width="38.5" depth="8.5"/>
|
<Square width="38.5" depth="8.5"/>
|
||||||
<Height>9.0</Height>
|
<Height>9.0</Height>
|
||||||
</Footprint>
|
</Footprint>
|
||||||
|
<GarrisonHolder>
|
||||||
|
<VisibleGarrisonPoints>
|
||||||
|
<Archer1>
|
||||||
|
<X>0</X><Y>9.3</Y><Z>0</Z>
|
||||||
|
</Archer1>
|
||||||
|
<Archer2>
|
||||||
|
<X>8</X><Y>9.3</Y><Z>0</Z>
|
||||||
|
</Archer2>
|
||||||
|
<Archer3>
|
||||||
|
<X>-8</X><Y>9.3</Y><Z>0</Z>
|
||||||
|
</Archer3>
|
||||||
|
<Archer4>
|
||||||
|
<X>4</X><Y>9.3</Y><Z>0</Z>
|
||||||
|
</Archer4>
|
||||||
|
<Archer5>
|
||||||
|
<X>-4</X><Y>9.3</Y><Z>0</Z>
|
||||||
|
</Archer5>
|
||||||
|
</VisibleGarrisonPoints>
|
||||||
|
</GarrisonHolder>
|
||||||
<Identity>
|
<Identity>
|
||||||
<Civ>brit</Civ>
|
<Civ>brit</Civ>
|
||||||
<SelectionGroupName>structures/celt_wallset_stone</SelectionGroupName>
|
<SelectionGroupName>structures/celt_wallset_stone</SelectionGroupName>
|
||||||
|
@ -4,6 +4,19 @@
|
|||||||
<Square width="26.5" depth="8.5"/>
|
<Square width="26.5" depth="8.5"/>
|
||||||
<Height>9.0</Height>
|
<Height>9.0</Height>
|
||||||
</Footprint>
|
</Footprint>
|
||||||
|
<GarrisonHolder>
|
||||||
|
<VisibleGarrisonPoints>
|
||||||
|
<Archer1>
|
||||||
|
<X>0</X><Y>9.3</Y><Z>0</Z>
|
||||||
|
</Archer1>
|
||||||
|
<Archer2>
|
||||||
|
<X>4</X><Y>9.3</Y><Z>0</Z>
|
||||||
|
</Archer2>
|
||||||
|
<Archer3>
|
||||||
|
<X>-4</X><Y>9.3</Y><Z>0</Z>
|
||||||
|
</Archer3>
|
||||||
|
</VisibleGarrisonPoints>
|
||||||
|
</GarrisonHolder>
|
||||||
<Health>
|
<Health>
|
||||||
<Max>3000</Max>
|
<Max>3000</Max>
|
||||||
</Health>
|
</Health>
|
||||||
|
@ -4,6 +4,25 @@
|
|||||||
<Square width="45.0" depth="11.0"/>
|
<Square width="45.0" depth="11.0"/>
|
||||||
<Height>9.0</Height>
|
<Height>9.0</Height>
|
||||||
</Footprint>
|
</Footprint>
|
||||||
|
<GarrisonHolder>
|
||||||
|
<VisibleGarrisonPoints>
|
||||||
|
<Archer1>
|
||||||
|
<X>0</X><Y>12.5</Y><Z>0</Z>
|
||||||
|
</Archer1>
|
||||||
|
<Archer2>
|
||||||
|
<X>8</X><Y>12.5</Y><Z>0</Z>
|
||||||
|
</Archer2>
|
||||||
|
<Archer3>
|
||||||
|
<X>-8</X><Y>12.5</Y><Z>0</Z>
|
||||||
|
</Archer3>
|
||||||
|
<Archer4>
|
||||||
|
<X>4</X><Y>12.5</Y><Z>0</Z>
|
||||||
|
</Archer4>
|
||||||
|
<Archer5>
|
||||||
|
<X>-4</X><Y>12.5</Y><Z>0</Z>
|
||||||
|
</Archer5>
|
||||||
|
</VisibleGarrisonPoints>
|
||||||
|
</GarrisonHolder>
|
||||||
<Identity>
|
<Identity>
|
||||||
<Civ>cart</Civ>
|
<Civ>cart</Civ>
|
||||||
<SelectionGroupName>structures/cart_wallset_stone</SelectionGroupName>
|
<SelectionGroupName>structures/cart_wallset_stone</SelectionGroupName>
|
||||||
|
@ -4,6 +4,19 @@
|
|||||||
<Square width="31.0" depth="11.0"/>
|
<Square width="31.0" depth="11.0"/>
|
||||||
<Height>9.0</Height>
|
<Height>9.0</Height>
|
||||||
</Footprint>
|
</Footprint>
|
||||||
|
<GarrisonHolder>
|
||||||
|
<VisibleGarrisonPoints>
|
||||||
|
<Archer1>
|
||||||
|
<X>0</X><Y>12.5</Y><Z>0</Z>
|
||||||
|
</Archer1>
|
||||||
|
<Archer2>
|
||||||
|
<X>4</X><Y>12.5</Y><Z>0</Z>
|
||||||
|
</Archer2>
|
||||||
|
<Archer3>
|
||||||
|
<X>-4</X><Y>12.5</Y><Z>0</Z>
|
||||||
|
</Archer3>
|
||||||
|
</VisibleGarrisonPoints>
|
||||||
|
</GarrisonHolder>
|
||||||
<Identity>
|
<Identity>
|
||||||
<Civ>cart</Civ>
|
<Civ>cart</Civ>
|
||||||
<SelectionGroupName>structures/cart_wallset_stone</SelectionGroupName>
|
<SelectionGroupName>structures/cart_wallset_stone</SelectionGroupName>
|
||||||
|
@ -4,6 +4,25 @@
|
|||||||
<Square width="38.5" depth="8.5"/>
|
<Square width="38.5" depth="8.5"/>
|
||||||
<Height>9.0</Height>
|
<Height>9.0</Height>
|
||||||
</Footprint>
|
</Footprint>
|
||||||
|
<GarrisonHolder>
|
||||||
|
<VisibleGarrisonPoints>
|
||||||
|
<Archer1>
|
||||||
|
<X>0</X><Y>9.3</Y><Z>0</Z>
|
||||||
|
</Archer1>
|
||||||
|
<Archer2>
|
||||||
|
<X>8</X><Y>9.3</Y><Z>0</Z>
|
||||||
|
</Archer2>
|
||||||
|
<Archer3>
|
||||||
|
<X>-8</X><Y>9.3</Y><Z>0</Z>
|
||||||
|
</Archer3>
|
||||||
|
<Archer4>
|
||||||
|
<X>4</X><Y>9.3</Y><Z>0</Z>
|
||||||
|
</Archer4>
|
||||||
|
<Archer5>
|
||||||
|
<X>-4</X><Y>9.3</Y><Z>0</Z>
|
||||||
|
</Archer5>
|
||||||
|
</VisibleGarrisonPoints>
|
||||||
|
</GarrisonHolder>
|
||||||
<Identity>
|
<Identity>
|
||||||
<Civ>celt</Civ>
|
<Civ>celt</Civ>
|
||||||
<SelectionGroupName>structures/celt_wallset_stone</SelectionGroupName>
|
<SelectionGroupName>structures/celt_wallset_stone</SelectionGroupName>
|
||||||
|
@ -7,6 +7,19 @@
|
|||||||
<Health>
|
<Health>
|
||||||
<Max>3000</Max>
|
<Max>3000</Max>
|
||||||
</Health>
|
</Health>
|
||||||
|
<GarrisonHolder>
|
||||||
|
<VisibleGarrisonPoints>
|
||||||
|
<Archer1>
|
||||||
|
<X>0</X><Y>9.3</Y><Z>0</Z>
|
||||||
|
</Archer1>
|
||||||
|
<Archer2>
|
||||||
|
<X>4</X><Y>9.3</Y><Z>0</Z>
|
||||||
|
</Archer2>
|
||||||
|
<Archer3>
|
||||||
|
<X>-4</X><Y>9.3</Y><Z>0</Z>
|
||||||
|
</Archer3>
|
||||||
|
</VisibleGarrisonPoints>
|
||||||
|
</GarrisonHolder>
|
||||||
<Identity>
|
<Identity>
|
||||||
<Civ>celt</Civ>
|
<Civ>celt</Civ>
|
||||||
<SelectionGroupName>structures/celt_wallset_stone</SelectionGroupName>
|
<SelectionGroupName>structures/celt_wallset_stone</SelectionGroupName>
|
||||||
|
@ -4,6 +4,25 @@
|
|||||||
<Square width="38.5" depth="8.5"/>
|
<Square width="38.5" depth="8.5"/>
|
||||||
<Height>9.0</Height>
|
<Height>9.0</Height>
|
||||||
</Footprint>
|
</Footprint>
|
||||||
|
<GarrisonHolder>
|
||||||
|
<VisibleGarrisonPoints>
|
||||||
|
<Archer1>
|
||||||
|
<X>0</X><Y>9.3</Y><Z>0</Z>
|
||||||
|
</Archer1>
|
||||||
|
<Archer2>
|
||||||
|
<X>8</X><Y>9.3</Y><Z>0</Z>
|
||||||
|
</Archer2>
|
||||||
|
<Archer3>
|
||||||
|
<X>-8</X><Y>9.3</Y><Z>0</Z>
|
||||||
|
</Archer3>
|
||||||
|
<Archer4>
|
||||||
|
<X>4</X><Y>9.3</Y><Z>0</Z>
|
||||||
|
</Archer4>
|
||||||
|
<Archer5>
|
||||||
|
<X>-4</X><Y>9.3</Y><Z>0</Z>
|
||||||
|
</Archer5>
|
||||||
|
</VisibleGarrisonPoints>
|
||||||
|
</GarrisonHolder>
|
||||||
<Identity>
|
<Identity>
|
||||||
<Civ>gaul</Civ>
|
<Civ>gaul</Civ>
|
||||||
<SelectionGroupName>structures/celt_wallset_stone</SelectionGroupName>
|
<SelectionGroupName>structures/celt_wallset_stone</SelectionGroupName>
|
||||||
|
@ -7,6 +7,19 @@
|
|||||||
<Health>
|
<Health>
|
||||||
<Max>3000</Max>
|
<Max>3000</Max>
|
||||||
</Health>
|
</Health>
|
||||||
|
<GarrisonHolder>
|
||||||
|
<VisibleGarrisonPoints>
|
||||||
|
<Archer1>
|
||||||
|
<X>0</X><Y>9.3</Y><Z>0</Z>
|
||||||
|
</Archer1>
|
||||||
|
<Archer2>
|
||||||
|
<X>4</X><Y>9.3</Y><Z>0</Z>
|
||||||
|
</Archer2>
|
||||||
|
<Archer3>
|
||||||
|
<X>-4</X><Y>9.3</Y><Z>0</Z>
|
||||||
|
</Archer3>
|
||||||
|
</VisibleGarrisonPoints>
|
||||||
|
</GarrisonHolder>
|
||||||
<Identity>
|
<Identity>
|
||||||
<Civ>gaul</Civ>
|
<Civ>gaul</Civ>
|
||||||
<SelectionGroupName>structures/celt_wallset_stone</SelectionGroupName>
|
<SelectionGroupName>structures/celt_wallset_stone</SelectionGroupName>
|
||||||
|
@ -4,6 +4,25 @@
|
|||||||
<Square width="37" depth="9"/>
|
<Square width="37" depth="9"/>
|
||||||
<Height>9.0</Height>
|
<Height>9.0</Height>
|
||||||
</Footprint>
|
</Footprint>
|
||||||
|
<GarrisonHolder>
|
||||||
|
<VisibleGarrisonPoints>
|
||||||
|
<Archer1>
|
||||||
|
<X>0</X><Y>9.0</Y><Z>0</Z>
|
||||||
|
</Archer1>
|
||||||
|
<Archer2>
|
||||||
|
<X>8</X><Y>9.0</Y><Z>0</Z>
|
||||||
|
</Archer2>
|
||||||
|
<Archer3>
|
||||||
|
<X>-8</X><Y>9.0</Y><Z>0</Z>
|
||||||
|
</Archer3>
|
||||||
|
<Archer4>
|
||||||
|
<X>4</X><Y>9.0</Y><Z>0</Z>
|
||||||
|
</Archer4>
|
||||||
|
<Archer5>
|
||||||
|
<X>-4</X><Y>9.0</Y><Z>0</Z>
|
||||||
|
</Archer5>
|
||||||
|
</VisibleGarrisonPoints>
|
||||||
|
</GarrisonHolder>
|
||||||
<Identity>
|
<Identity>
|
||||||
<Civ>iber</Civ>
|
<Civ>iber</Civ>
|
||||||
<SelectionGroupName>structures/iber_wallset_stone</SelectionGroupName>
|
<SelectionGroupName>structures/iber_wallset_stone</SelectionGroupName>
|
||||||
|
@ -4,6 +4,19 @@
|
|||||||
<Square width="25" depth="9"/>
|
<Square width="25" depth="9"/>
|
||||||
<Height>9.0</Height>
|
<Height>9.0</Height>
|
||||||
</Footprint>
|
</Footprint>
|
||||||
|
<GarrisonHolder>
|
||||||
|
<VisibleGarrisonPoints>
|
||||||
|
<Archer1>
|
||||||
|
<X>0</X><Y>9.0</Y><Z>0</Z>
|
||||||
|
</Archer1>
|
||||||
|
<Archer2>
|
||||||
|
<X>4</X><Y>9.0</Y><Z>0</Z>
|
||||||
|
</Archer2>
|
||||||
|
<Archer3>
|
||||||
|
<X>-4</X><Y>9.0</Y><Z>0</Z>
|
||||||
|
</Archer3>
|
||||||
|
</VisibleGarrisonPoints>
|
||||||
|
</GarrisonHolder>
|
||||||
<Health>
|
<Health>
|
||||||
<Max>3000</Max>
|
<Max>3000</Max>
|
||||||
</Health>
|
</Health>
|
||||||
|
@ -10,6 +10,25 @@
|
|||||||
<Square width="36.5" depth="9.0"/>
|
<Square width="36.5" depth="9.0"/>
|
||||||
<Height>9.0</Height>
|
<Height>9.0</Height>
|
||||||
</Footprint>
|
</Footprint>
|
||||||
|
<GarrisonHolder>
|
||||||
|
<VisibleGarrisonPoints>
|
||||||
|
<Archer1>
|
||||||
|
<X>0</X><Y>9.5</Y><Z>0</Z>
|
||||||
|
</Archer1>
|
||||||
|
<Archer2>
|
||||||
|
<X>8</X><Y>9.5</Y><Z>0</Z>
|
||||||
|
</Archer2>
|
||||||
|
<Archer3>
|
||||||
|
<X>-8</X><Y>9.5</Y><Z>0</Z>
|
||||||
|
</Archer3>
|
||||||
|
<Archer4>
|
||||||
|
<X>4</X><Y>9.5</Y><Z>0</Z>
|
||||||
|
</Archer4>
|
||||||
|
<Archer5>
|
||||||
|
<X>-4</X><Y>9.5</Y><Z>0</Z>
|
||||||
|
</Archer5>
|
||||||
|
</VisibleGarrisonPoints>
|
||||||
|
</GarrisonHolder>
|
||||||
<Identity>
|
<Identity>
|
||||||
<Civ>maur</Civ>
|
<Civ>maur</Civ>
|
||||||
<SelectionGroupName>structures/maur_wallset_stone</SelectionGroupName>
|
<SelectionGroupName>structures/maur_wallset_stone</SelectionGroupName>
|
||||||
|
@ -10,6 +10,19 @@
|
|||||||
<Square width="26.5" depth="9.0"/>
|
<Square width="26.5" depth="9.0"/>
|
||||||
<Height>9.0</Height>
|
<Height>9.0</Height>
|
||||||
</Footprint>
|
</Footprint>
|
||||||
|
<GarrisonHolder>
|
||||||
|
<VisibleGarrisonPoints>
|
||||||
|
<Archer1>
|
||||||
|
<X>0</X><Y>9.5</Y><Z>0</Z>
|
||||||
|
</Archer1>
|
||||||
|
<Archer2>
|
||||||
|
<X>4</X><Y>9.5</Y><Z>0</Z>
|
||||||
|
</Archer2>
|
||||||
|
<Archer3>
|
||||||
|
<X>-4</X><Y>9.5</Y><Z>0</Z>
|
||||||
|
</Archer3>
|
||||||
|
</VisibleGarrisonPoints>
|
||||||
|
</GarrisonHolder>
|
||||||
<Identity>
|
<Identity>
|
||||||
<Civ>maur</Civ>
|
<Civ>maur</Civ>
|
||||||
<SelectionGroupName>structures/maur_wallset_stone</SelectionGroupName>
|
<SelectionGroupName>structures/maur_wallset_stone</SelectionGroupName>
|
||||||
|
@ -4,6 +4,25 @@
|
|||||||
<Square width="38.5" depth="9.0"/>
|
<Square width="38.5" depth="9.0"/>
|
||||||
<Height>9.0</Height>
|
<Height>9.0</Height>
|
||||||
</Footprint>
|
</Footprint>
|
||||||
|
<GarrisonHolder>
|
||||||
|
<VisibleGarrisonPoints>
|
||||||
|
<Archer1>
|
||||||
|
<X>0</X><Y>10.6</Y><Z>0</Z>
|
||||||
|
</Archer1>
|
||||||
|
<Archer2>
|
||||||
|
<X>8</X><Y>10.6</Y><Z>0</Z>
|
||||||
|
</Archer2>
|
||||||
|
<Archer3>
|
||||||
|
<X>-8</X><Y>10.6</Y><Z>0</Z>
|
||||||
|
</Archer3>
|
||||||
|
<Archer4>
|
||||||
|
<X>4</X><Y>10.6</Y><Z>0</Z>
|
||||||
|
</Archer4>
|
||||||
|
<Archer5>
|
||||||
|
<X>-4</X><Y>10.6</Y><Z>0</Z>
|
||||||
|
</Archer5>
|
||||||
|
</VisibleGarrisonPoints>
|
||||||
|
</GarrisonHolder>
|
||||||
<Identity>
|
<Identity>
|
||||||
<Civ>pers</Civ>
|
<Civ>pers</Civ>
|
||||||
<SelectionGroupName>structures/pers_wallset_stone</SelectionGroupName>
|
<SelectionGroupName>structures/pers_wallset_stone</SelectionGroupName>
|
||||||
@ -19,4 +38,4 @@
|
|||||||
<WallPiece>
|
<WallPiece>
|
||||||
<Length>37.0</Length>
|
<Length>37.0</Length>
|
||||||
</WallPiece>
|
</WallPiece>
|
||||||
</Entity>
|
</Entity>
|
||||||
|
@ -4,6 +4,19 @@
|
|||||||
<Square width="26.0" depth="9.0"/>
|
<Square width="26.0" depth="9.0"/>
|
||||||
<Height>9.0</Height>
|
<Height>9.0</Height>
|
||||||
</Footprint>
|
</Footprint>
|
||||||
|
<GarrisonHolder>
|
||||||
|
<VisibleGarrisonPoints>
|
||||||
|
<Archer1>
|
||||||
|
<X>0</X><Y>10.6</Y><Z>0</Z>
|
||||||
|
</Archer1>
|
||||||
|
<Archer2>
|
||||||
|
<X>4</X><Y>10.6</Y><Z>0</Z>
|
||||||
|
</Archer2>
|
||||||
|
<Archer3>
|
||||||
|
<X>-4</X><Y>10.6</Y><Z>0</Z>
|
||||||
|
</Archer3>
|
||||||
|
</VisibleGarrisonPoints>
|
||||||
|
</GarrisonHolder>
|
||||||
<Identity>
|
<Identity>
|
||||||
<Civ>pers</Civ>
|
<Civ>pers</Civ>
|
||||||
<SelectionGroupName>structures/pers_wallset_stone</SelectionGroupName>
|
<SelectionGroupName>structures/pers_wallset_stone</SelectionGroupName>
|
||||||
|
@ -4,6 +4,25 @@
|
|||||||
<Square width="40" depth="10.0"/>
|
<Square width="40" depth="10.0"/>
|
||||||
<Height>9.0</Height>
|
<Height>9.0</Height>
|
||||||
</Footprint>
|
</Footprint>
|
||||||
|
<GarrisonHolder>
|
||||||
|
<VisibleGarrisonPoints>
|
||||||
|
<Archer1>
|
||||||
|
<X>0</X><Y>9.7</Y><Z>0</Z>
|
||||||
|
</Archer1>
|
||||||
|
<Archer2>
|
||||||
|
<X>8</X><Y>9.7</Y><Z>0</Z>
|
||||||
|
</Archer2>
|
||||||
|
<Archer3>
|
||||||
|
<X>-8</X><Y>9.7</Y><Z>0</Z>
|
||||||
|
</Archer3>
|
||||||
|
<Archer4>
|
||||||
|
<X>4</X><Y>9.7</Y><Z>0</Z>
|
||||||
|
</Archer4>
|
||||||
|
<Archer5>
|
||||||
|
<X>-4</X><Y>9.7</Y><Z>0</Z>
|
||||||
|
</Archer5>
|
||||||
|
</VisibleGarrisonPoints>
|
||||||
|
</GarrisonHolder>
|
||||||
<Identity>
|
<Identity>
|
||||||
<Civ>ptol</Civ>
|
<Civ>ptol</Civ>
|
||||||
<SelectionGroupName>structures/ptol_wallset_stone</SelectionGroupName>
|
<SelectionGroupName>structures/ptol_wallset_stone</SelectionGroupName>
|
||||||
@ -19,4 +38,4 @@
|
|||||||
<WallPiece>
|
<WallPiece>
|
||||||
<Length>38.0</Length>
|
<Length>38.0</Length>
|
||||||
</WallPiece>
|
</WallPiece>
|
||||||
</Entity>
|
</Entity>
|
||||||
|
@ -4,6 +4,19 @@
|
|||||||
<Square width="28.0" depth="10.0"/>
|
<Square width="28.0" depth="10.0"/>
|
||||||
<Height>9.0</Height>
|
<Height>9.0</Height>
|
||||||
</Footprint>
|
</Footprint>
|
||||||
|
<GarrisonHolder>
|
||||||
|
<VisibleGarrisonPoints>
|
||||||
|
<Archer1>
|
||||||
|
<X>0</X><Y>9.7</Y><Z>0</Z>
|
||||||
|
</Archer1>
|
||||||
|
<Archer2>
|
||||||
|
<X>4</X><Y>9.7</Y><Z>0</Z>
|
||||||
|
</Archer2>
|
||||||
|
<Archer3>
|
||||||
|
<X>-4</X><Y>9.7</Y><Z>0</Z>
|
||||||
|
</Archer3>
|
||||||
|
</VisibleGarrisonPoints>
|
||||||
|
</GarrisonHolder>
|
||||||
<Identity>
|
<Identity>
|
||||||
<Civ>ptol</Civ>
|
<Civ>ptol</Civ>
|
||||||
<SelectionGroupName>structures/mace_wallset_stone</SelectionGroupName>
|
<SelectionGroupName>structures/mace_wallset_stone</SelectionGroupName>
|
||||||
|
@ -23,6 +23,25 @@
|
|||||||
<Square width="40.0" depth="8.0"/>
|
<Square width="40.0" depth="8.0"/>
|
||||||
<Height>7.0</Height>
|
<Height>7.0</Height>
|
||||||
</Footprint>
|
</Footprint>
|
||||||
|
<GarrisonHolder>
|
||||||
|
<VisibleGarrisonPoints>
|
||||||
|
<Archer1>
|
||||||
|
<X>0</X><Y>5.7</Y><Z>0</Z>
|
||||||
|
</Archer1>
|
||||||
|
<Archer2>
|
||||||
|
<X>8</X><Y>5.7</Y><Z>0</Z>
|
||||||
|
</Archer2>
|
||||||
|
<Archer3>
|
||||||
|
<X>-8</X><Y>5.7</Y><Z>0</Z>
|
||||||
|
</Archer3>
|
||||||
|
<Archer4>
|
||||||
|
<X>4</X><Y>5.7</Y><Z>0</Z>
|
||||||
|
</Archer4>
|
||||||
|
<Archer5>
|
||||||
|
<X>-4</X><Y>5.7</Y><Z>0</Z>
|
||||||
|
</Archer5>
|
||||||
|
</VisibleGarrisonPoints>
|
||||||
|
</GarrisonHolder>
|
||||||
<Health>
|
<Health>
|
||||||
<Max>2000</Max>
|
<Max>2000</Max>
|
||||||
</Health>
|
</Health>
|
||||||
|
@ -26,6 +26,19 @@
|
|||||||
<Health>
|
<Health>
|
||||||
<Max>1500</Max>
|
<Max>1500</Max>
|
||||||
</Health>
|
</Health>
|
||||||
|
<GarrisonHolder>
|
||||||
|
<VisibleGarrisonPoints>
|
||||||
|
<Archer1>
|
||||||
|
<X>0</X><Y>5.7</Y><Z>0</Z>
|
||||||
|
</Archer1>
|
||||||
|
<Archer2>
|
||||||
|
<X>4</X><Y>5.7</Y><Z>0</Z>
|
||||||
|
</Archer2>
|
||||||
|
<Archer3>
|
||||||
|
<X>-4</X><Y>5.7</Y><Z>0</Z>
|
||||||
|
</Archer3>
|
||||||
|
</VisibleGarrisonPoints>
|
||||||
|
</GarrisonHolder>
|
||||||
<Identity>
|
<Identity>
|
||||||
<Civ>rome</Civ>
|
<Civ>rome</Civ>
|
||||||
<SelectionGroupName>structures/rome_wallset_siege</SelectionGroupName>
|
<SelectionGroupName>structures/rome_wallset_siege</SelectionGroupName>
|
||||||
|
@ -4,6 +4,25 @@
|
|||||||
<Square width="38.5" depth="9.0"/>
|
<Square width="38.5" depth="9.0"/>
|
||||||
<Height>9.0</Height>
|
<Height>9.0</Height>
|
||||||
</Footprint>
|
</Footprint>
|
||||||
|
<GarrisonHolder>
|
||||||
|
<VisibleGarrisonPoints>
|
||||||
|
<Archer1>
|
||||||
|
<X>0</X><Y>8.9</Y><Z>0</Z>
|
||||||
|
</Archer1>
|
||||||
|
<Archer2>
|
||||||
|
<X>8</X><Y>8.9</Y><Z>0</Z>
|
||||||
|
</Archer2>
|
||||||
|
<Archer3>
|
||||||
|
<X>-8</X><Y>8.9</Y><Z>0</Z>
|
||||||
|
</Archer3>
|
||||||
|
<Archer4>
|
||||||
|
<X>4</X><Y>8.9</Y><Z>0</Z>
|
||||||
|
</Archer4>
|
||||||
|
<Archer5>
|
||||||
|
<X>-4</X><Y>8.9</Y><Z>0</Z>
|
||||||
|
</Archer5>
|
||||||
|
</VisibleGarrisonPoints>
|
||||||
|
</GarrisonHolder>
|
||||||
<Identity>
|
<Identity>
|
||||||
<Civ>rome</Civ>
|
<Civ>rome</Civ>
|
||||||
<SelectionGroupName>structures/rome_wallset_stone</SelectionGroupName>
|
<SelectionGroupName>structures/rome_wallset_stone</SelectionGroupName>
|
||||||
|
@ -4,6 +4,19 @@
|
|||||||
<Square width="26.5" depth="9.0"/>
|
<Square width="26.5" depth="9.0"/>
|
||||||
<Height>9.0</Height>
|
<Height>9.0</Height>
|
||||||
</Footprint>
|
</Footprint>
|
||||||
|
<GarrisonHolder>
|
||||||
|
<VisibleGarrisonPoints>
|
||||||
|
<Archer1>
|
||||||
|
<X>0</X><Y>8.9</Y><Z>0</Z>
|
||||||
|
</Archer1>
|
||||||
|
<Archer2>
|
||||||
|
<X>4</X><Y>8.9</Y><Z>0</Z>
|
||||||
|
</Archer2>
|
||||||
|
<Archer3>
|
||||||
|
<X>-4</X><Y>8.9</Y><Z>0</Z>
|
||||||
|
</Archer3>
|
||||||
|
</VisibleGarrisonPoints>
|
||||||
|
</GarrisonHolder>
|
||||||
<Health>
|
<Health>
|
||||||
<Max>3000</Max>
|
<Max>3000</Max>
|
||||||
</Health>
|
</Health>
|
||||||
|
@ -9,6 +9,31 @@
|
|||||||
<Health>
|
<Health>
|
||||||
<SpawnEntityOnDeath>rubble/rubble_stone_wall_long</SpawnEntityOnDeath>
|
<SpawnEntityOnDeath>rubble/rubble_stone_wall_long</SpawnEntityOnDeath>
|
||||||
</Health>
|
</Health>
|
||||||
|
<GarrisonHolder>
|
||||||
|
<Max>5</Max>
|
||||||
|
<List datatype="tokens">Infantry</List>
|
||||||
|
<EjectHealth>0.1</EjectHealth>
|
||||||
|
<EjectClassesOnDestroy datatype="tokens">Infantry</EjectClassesOnDestroy>
|
||||||
|
<BuffHeal>0</BuffHeal>
|
||||||
|
<LoadingRange>2</LoadingRange>
|
||||||
|
<VisibleGarrisonPoints>
|
||||||
|
<Archer1>
|
||||||
|
<X>0</X><Y>11.5</Y><Z>0</Z>
|
||||||
|
</Archer1>
|
||||||
|
<Archer2>
|
||||||
|
<X>8</X><Y>11.5</Y><Z>0</Z>
|
||||||
|
</Archer2>
|
||||||
|
<Archer3>
|
||||||
|
<X>-8</X><Y>11.5</Y><Z>0</Z>
|
||||||
|
</Archer3>
|
||||||
|
<Archer4>
|
||||||
|
<X>4</X><Y>11.5</Y><Z>0</Z>
|
||||||
|
</Archer4>
|
||||||
|
<Archer5>
|
||||||
|
<X>-4</X><Y>11.5</Y><Z>0</Z>
|
||||||
|
</Archer5>
|
||||||
|
</VisibleGarrisonPoints>
|
||||||
|
</GarrisonHolder>
|
||||||
<Identity>
|
<Identity>
|
||||||
<Classes datatype="tokens">LongWall</Classes>
|
<Classes datatype="tokens">LongWall</Classes>
|
||||||
<Tooltip>Long wall segments can be converted to gates.</Tooltip>
|
<Tooltip>Long wall segments can be converted to gates.</Tooltip>
|
||||||
|
@ -6,6 +6,25 @@
|
|||||||
<stone>20</stone>
|
<stone>20</stone>
|
||||||
</Resources>
|
</Resources>
|
||||||
</Cost>
|
</Cost>
|
||||||
|
<GarrisonHolder>
|
||||||
|
<Max>3</Max>
|
||||||
|
<List datatype="tokens">Infantry</List>
|
||||||
|
<EjectHealth>0.1</EjectHealth>
|
||||||
|
<EjectClassesOnDestroy datatype="tokens">Infantry</EjectClassesOnDestroy>
|
||||||
|
<BuffHeal>0</BuffHeal>
|
||||||
|
<LoadingRange>2</LoadingRange>
|
||||||
|
<VisibleGarrisonPoints>
|
||||||
|
<Archer1>
|
||||||
|
<X>0</X><Y>11.5</Y><Z>0</Z>
|
||||||
|
</Archer1>
|
||||||
|
<Archer2>
|
||||||
|
<X>4</X><Y>11.5</Y><Z>0</Z>
|
||||||
|
</Archer2>
|
||||||
|
<Archer3>
|
||||||
|
<X>-4</X><Y>11.5</Y><Z>0</Z>
|
||||||
|
</Archer3>
|
||||||
|
</VisibleGarrisonPoints>
|
||||||
|
</GarrisonHolder>
|
||||||
<Health>
|
<Health>
|
||||||
<Max>3000</Max>
|
<Max>3000</Max>
|
||||||
<SpawnEntityOnDeath>rubble/rubble_stone_wall_medium</SpawnEntityOnDeath>
|
<SpawnEntityOnDeath>rubble/rubble_stone_wall_medium</SpawnEntityOnDeath>
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
<Height>8.0</Height>
|
<Height>8.0</Height>
|
||||||
</Footprint>
|
</Footprint>
|
||||||
<GarrisonHolder>
|
<GarrisonHolder>
|
||||||
<Max>5</Max>
|
<Max>2</Max>
|
||||||
<EjectHealth>0.1</EjectHealth>
|
<EjectHealth>0.1</EjectHealth>
|
||||||
<EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy>
|
<EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy>
|
||||||
<List datatype="tokens">Support Infantry</List>
|
<List datatype="tokens">Support Infantry</List>
|
||||||
|
@ -76,10 +76,16 @@ public:
|
|||||||
entity_pos_t m_Y, m_LastYDifference; // either the relative or the absolute Y coordinate
|
entity_pos_t m_Y, m_LastYDifference; // either the relative or the absolute Y coordinate
|
||||||
bool m_RelativeToGround; // whether m_Y is relative to terrain/water plane, or an absolute height
|
bool m_RelativeToGround; // whether m_Y is relative to terrain/water plane, or an absolute height
|
||||||
|
|
||||||
|
// when the entity is a turret, only m_RotY is used, and this is the rotation
|
||||||
|
// relative to the parent entity
|
||||||
entity_angle_t m_RotX, m_RotY, m_RotZ;
|
entity_angle_t m_RotX, m_RotY, m_RotZ;
|
||||||
|
|
||||||
player_id_t m_Territory;
|
player_id_t m_Territory;
|
||||||
|
|
||||||
|
entity_id_t m_TurretParent;
|
||||||
|
CFixedVector3D m_TurretPosition;
|
||||||
|
std::set<entity_id_t> m_Turrets;
|
||||||
|
|
||||||
// not serialized:
|
// not serialized:
|
||||||
float m_InterpolatedRotX, m_InterpolatedRotY, m_InterpolatedRotZ;
|
float m_InterpolatedRotX, m_InterpolatedRotY, m_InterpolatedRotZ;
|
||||||
float m_LastInterpolatedRotX, m_LastInterpolatedRotZ; // not serialized
|
float m_LastInterpolatedRotX, m_LastInterpolatedRotZ; // not serialized
|
||||||
@ -142,6 +148,8 @@ public:
|
|||||||
m_Territory = INVALID_PLAYER;
|
m_Territory = INVALID_PLAYER;
|
||||||
|
|
||||||
m_NeedInitialXZRotation = false;
|
m_NeedInitialXZRotation = false;
|
||||||
|
m_TurretParent = INVALID_ENTITY;
|
||||||
|
m_TurretPosition = CFixedVector3D();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void Deinit()
|
virtual void Deinit()
|
||||||
@ -223,6 +231,60 @@ public:
|
|||||||
UpdateXZRotation();
|
UpdateXZRotation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void UpdateTurretPosition()
|
||||||
|
{
|
||||||
|
if (m_TurretParent == INVALID_ENTITY)
|
||||||
|
return;
|
||||||
|
CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), m_TurretParent);
|
||||||
|
if (!cmpPosition)
|
||||||
|
{
|
||||||
|
LOGERROR(L"Turret with parent without position component");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!cmpPosition->IsInWorld())
|
||||||
|
MoveOutOfWorld();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CFixedVector2D rotatedPosition = CFixedVector2D(m_TurretPosition.X, m_TurretPosition.Z);
|
||||||
|
rotatedPosition = rotatedPosition.Rotate(cmpPosition->GetRotation().Y);
|
||||||
|
CFixedVector2D rootPosition = cmpPosition->GetPosition2D();
|
||||||
|
entity_pos_t x = rootPosition.X + rotatedPosition.X;
|
||||||
|
entity_pos_t z = rootPosition.Y + rotatedPosition.Y;
|
||||||
|
if (!m_InWorld || m_X != x || m_Z != z)
|
||||||
|
MoveTo(x, z);
|
||||||
|
entity_pos_t y = cmpPosition->GetHeightOffset() + m_TurretPosition.Y;
|
||||||
|
if (!m_InWorld || GetHeightOffset() != y)
|
||||||
|
SetHeightOffset(y);
|
||||||
|
m_InWorld = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::set<entity_id_t>* GetTurrets()
|
||||||
|
{
|
||||||
|
return &m_Turrets;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void SetTurretParent(entity_id_t id, CFixedVector3D offset)
|
||||||
|
{
|
||||||
|
if (m_TurretParent != INVALID_ENTITY)
|
||||||
|
{
|
||||||
|
CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), m_TurretParent);
|
||||||
|
if (cmpPosition)
|
||||||
|
cmpPosition->GetTurrets()->erase(GetEntityId());
|
||||||
|
}
|
||||||
|
|
||||||
|
m_TurretParent = id;
|
||||||
|
m_TurretPosition = offset;
|
||||||
|
|
||||||
|
if (m_TurretParent != INVALID_ENTITY)
|
||||||
|
{
|
||||||
|
CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), m_TurretParent);
|
||||||
|
if (cmpPosition)
|
||||||
|
cmpPosition->GetTurrets()->insert(GetEntityId());
|
||||||
|
}
|
||||||
|
UpdateTurretPosition();
|
||||||
|
}
|
||||||
|
|
||||||
virtual bool IsInWorld()
|
virtual bool IsInWorld()
|
||||||
{
|
{
|
||||||
return m_InWorld;
|
return m_InWorld;
|
||||||
@ -255,7 +317,6 @@ public:
|
|||||||
{
|
{
|
||||||
m_X = x;
|
m_X = x;
|
||||||
m_Z = z;
|
m_Z = z;
|
||||||
m_RotY = ry;
|
|
||||||
|
|
||||||
if (!m_InWorld)
|
if (!m_InWorld)
|
||||||
{
|
{
|
||||||
@ -265,7 +326,8 @@ public:
|
|||||||
m_LastYDifference = entity_pos_t::Zero();
|
m_LastYDifference = entity_pos_t::Zero();
|
||||||
}
|
}
|
||||||
|
|
||||||
AdvertisePositionChanges();
|
// TurnTo will advertise the position changes
|
||||||
|
TurnTo(ry);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void JumpTo(entity_pos_t x, entity_pos_t z)
|
virtual void JumpTo(entity_pos_t x, entity_pos_t z)
|
||||||
@ -405,6 +467,12 @@ public:
|
|||||||
|
|
||||||
virtual void TurnTo(entity_angle_t y)
|
virtual void TurnTo(entity_angle_t y)
|
||||||
{
|
{
|
||||||
|
if (m_TurretParent != INVALID_ENTITY)
|
||||||
|
{
|
||||||
|
CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), m_TurretParent);
|
||||||
|
if (cmpPosition)
|
||||||
|
y -= cmpPosition->GetRotation().Y;
|
||||||
|
}
|
||||||
m_RotY = y;
|
m_RotY = y;
|
||||||
|
|
||||||
AdvertisePositionChanges();
|
AdvertisePositionChanges();
|
||||||
@ -412,6 +480,12 @@ public:
|
|||||||
|
|
||||||
virtual void SetYRotation(entity_angle_t y)
|
virtual void SetYRotation(entity_angle_t y)
|
||||||
{
|
{
|
||||||
|
if (m_TurretParent != INVALID_ENTITY)
|
||||||
|
{
|
||||||
|
CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), m_TurretParent);
|
||||||
|
if (cmpPosition)
|
||||||
|
y -= cmpPosition->GetRotation().Y;
|
||||||
|
}
|
||||||
m_RotY = y;
|
m_RotY = y;
|
||||||
m_InterpolatedRotY = m_RotY.ToFloat();
|
m_InterpolatedRotY = m_RotY.ToFloat();
|
||||||
|
|
||||||
@ -444,6 +518,13 @@ public:
|
|||||||
|
|
||||||
virtual CFixedVector3D GetRotation()
|
virtual CFixedVector3D GetRotation()
|
||||||
{
|
{
|
||||||
|
entity_angle_t y = m_RotY;
|
||||||
|
if (m_TurretParent != INVALID_ENTITY)
|
||||||
|
{
|
||||||
|
CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), m_TurretParent);
|
||||||
|
if (cmpPosition)
|
||||||
|
y += cmpPosition->GetRotation().Y;
|
||||||
|
}
|
||||||
return CFixedVector3D(m_RotX, m_RotY, m_RotZ);
|
return CFixedVector3D(m_RotX, m_RotY, m_RotZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -474,6 +555,32 @@ public:
|
|||||||
|
|
||||||
virtual CMatrix3D GetInterpolatedTransform(float frameOffset, bool forceFloating)
|
virtual CMatrix3D GetInterpolatedTransform(float frameOffset, bool forceFloating)
|
||||||
{
|
{
|
||||||
|
if (m_TurretParent != INVALID_ENTITY)
|
||||||
|
{
|
||||||
|
CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), m_TurretParent);
|
||||||
|
if (!cmpPosition)
|
||||||
|
{
|
||||||
|
LOGERROR(L"Turret with parent without position component");
|
||||||
|
CMatrix3D m;
|
||||||
|
m.SetIdentity();
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
if (!cmpPosition->IsInWorld())
|
||||||
|
{
|
||||||
|
LOGERROR(L"CCmpPosition::GetInterpolatedTransform called on turret entity when IsInWorld is false");
|
||||||
|
CMatrix3D m;
|
||||||
|
m.SetIdentity();
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CMatrix3D parentTransformMatrix = cmpPosition->GetInterpolatedTransform(frameOffset, forceFloating);
|
||||||
|
CMatrix3D ownTransformation = CMatrix3D();
|
||||||
|
ownTransformation.SetYRotation(m_InterpolatedRotY);
|
||||||
|
ownTransformation.Translate(-m_TurretPosition.X.ToFloat(), m_TurretPosition.Y.ToFloat(), -m_TurretPosition.Z.ToFloat());
|
||||||
|
return parentTransformMatrix * ownTransformation;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!m_InWorld)
|
if (!m_InWorld)
|
||||||
{
|
{
|
||||||
LOGERROR(L"CCmpPosition::GetInterpolatedTransform called on entity when IsInWorld is false");
|
LOGERROR(L"CCmpPosition::GetInterpolatedTransform called on entity when IsInWorld is false");
|
||||||
@ -562,6 +669,7 @@ public:
|
|||||||
}
|
}
|
||||||
case MT_TurnStart:
|
case MT_TurnStart:
|
||||||
{
|
{
|
||||||
|
|
||||||
m_LastInterpolatedRotX = m_InterpolatedRotX;
|
m_LastInterpolatedRotX = m_InterpolatedRotX;
|
||||||
m_LastInterpolatedRotZ = m_InterpolatedRotZ;
|
m_LastInterpolatedRotZ = m_InterpolatedRotZ;
|
||||||
|
|
||||||
@ -606,6 +714,12 @@ public:
|
|||||||
private:
|
private:
|
||||||
void AdvertisePositionChanges()
|
void AdvertisePositionChanges()
|
||||||
{
|
{
|
||||||
|
for (std::set<entity_id_t>::const_iterator it = m_Turrets.begin(); it != m_Turrets.end(); ++it)
|
||||||
|
{
|
||||||
|
CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), *it);
|
||||||
|
if (cmpPosition)
|
||||||
|
cmpPosition->UpdateTurretPosition();
|
||||||
|
}
|
||||||
if (m_InWorld)
|
if (m_InWorld)
|
||||||
{
|
{
|
||||||
CMessagePositionChanged msg(GetEntityId(), true, m_X, m_Z, m_RotY);
|
CMessagePositionChanged msg(GetEntityId(), true, m_X, m_Z, m_RotY);
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "simulation2/system/InterfaceScripted.h"
|
#include "simulation2/system/InterfaceScripted.h"
|
||||||
|
|
||||||
BEGIN_INTERFACE_WRAPPER(Position)
|
BEGIN_INTERFACE_WRAPPER(Position)
|
||||||
|
DEFINE_INTERFACE_METHOD_2("SetTurretParent", void, ICmpPosition, SetTurretParent, entity_id_t, CFixedVector3D)
|
||||||
DEFINE_INTERFACE_METHOD_0("IsInWorld", bool, ICmpPosition, IsInWorld)
|
DEFINE_INTERFACE_METHOD_0("IsInWorld", bool, ICmpPosition, IsInWorld)
|
||||||
DEFINE_INTERFACE_METHOD_0("MoveOutOfWorld", void, ICmpPosition, MoveOutOfWorld)
|
DEFINE_INTERFACE_METHOD_0("MoveOutOfWorld", void, ICmpPosition, MoveOutOfWorld)
|
||||||
DEFINE_INTERFACE_METHOD_2("MoveTo", void, ICmpPosition, MoveTo, entity_pos_t, entity_pos_t)
|
DEFINE_INTERFACE_METHOD_2("MoveTo", void, ICmpPosition, MoveTo, entity_pos_t, entity_pos_t)
|
||||||
|
@ -58,6 +58,21 @@ class CMatrix3D;
|
|||||||
class ICmpPosition : public IComponent
|
class ICmpPosition : public IComponent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* Set this as a turret of an other entity
|
||||||
|
*/
|
||||||
|
virtual void SetTurretParent(entity_id_t parent, CFixedVector3D offset) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Has to be called to update the simulation position of the turret
|
||||||
|
*/
|
||||||
|
virtual void UpdateTurretPosition() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of turrets to read or edit
|
||||||
|
*/
|
||||||
|
virtual std::set<entity_id_t>* GetTurrets() = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the entity currently exists at a defined position in the world.
|
* Returns true if the entity currently exists at a defined position in the world.
|
||||||
*/
|
*/
|
||||||
|
@ -40,6 +40,9 @@ class MockPosition : public ICmpPosition
|
|||||||
public:
|
public:
|
||||||
DEFAULT_MOCK_COMPONENT()
|
DEFAULT_MOCK_COMPONENT()
|
||||||
|
|
||||||
|
virtual void SetTurretParent(entity_id_t UNUSED(id), CFixedVector3D UNUSED(pos)) {}
|
||||||
|
virtual void UpdateTurretPosition() {}
|
||||||
|
virtual std::set<entity_id_t>* GetTurrets() { return NULL; }
|
||||||
virtual bool IsInWorld() { return true; }
|
virtual bool IsInWorld() { return true; }
|
||||||
virtual void MoveOutOfWorld() { }
|
virtual void MoveOutOfWorld() { }
|
||||||
virtual void MoveTo(entity_pos_t UNUSED(x), entity_pos_t UNUSED(z)) { }
|
virtual void MoveTo(entity_pos_t UNUSED(x), entity_pos_t UNUSED(z)) { }
|
||||||
|
Loading…
Reference in New Issue
Block a user