Added Building AI, and some small changes to GarrisonHolder
This was SVN commit r8636.
This commit is contained in:
parent
404456ee8e
commit
222095fa44
@ -8,6 +8,7 @@
|
|||||||
<prop actor="props/structures/celts/outpost_windows.xml" attachpoint="root"/>
|
<prop actor="props/structures/celts/outpost_windows.xml" attachpoint="root"/>
|
||||||
<prop actor="props/structures/celts/outpost_door.xml" attachpoint="root"/>
|
<prop actor="props/structures/celts/outpost_door.xml" attachpoint="root"/>
|
||||||
<prop actor="props/structures/celts/outpost_shields.xml" attachpoint="root"/>
|
<prop actor="props/structures/celts/outpost_shields.xml" attachpoint="root"/>
|
||||||
|
<prop actor="props/units/weapons/arrow_front.xml" attachpoint="projectile"/>
|
||||||
</props>
|
</props>
|
||||||
</variant>
|
</variant>
|
||||||
<variant frequency="1" name="celt outpost b">
|
<variant frequency="1" name="celt outpost b">
|
||||||
@ -16,6 +17,7 @@
|
|||||||
<prop actor="props/structures/celts/outpost2_windows.xml" attachpoint="root"/>
|
<prop actor="props/structures/celts/outpost2_windows.xml" attachpoint="root"/>
|
||||||
<prop actor="props/structures/celts/outpost_shields.xml" attachpoint="root"/>
|
<prop actor="props/structures/celts/outpost_shields.xml" attachpoint="root"/>
|
||||||
<prop actor="props/structures/celts/outpost_door.xml" attachpoint="root"/>
|
<prop actor="props/structures/celts/outpost_door.xml" attachpoint="root"/>
|
||||||
|
<prop actor="props/units/weapons/arrow_front.xml" attachpoint="projectile"/>
|
||||||
</props>
|
</props>
|
||||||
</variant>
|
</variant>
|
||||||
</group>
|
</group>
|
||||||
|
138
binaries/data/mods/public/simulation/components/BuildingAI.js
Normal file
138
binaries/data/mods/public/simulation/components/BuildingAI.js
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
function BuildingAI() {}
|
||||||
|
|
||||||
|
BuildingAI.prototype.Schema =
|
||||||
|
"<element name='DefaultArrowCount'>" +
|
||||||
|
"<data type='nonNegativeInteger'/>" +
|
||||||
|
"</element>" +
|
||||||
|
"<element name='GarrisonArrowMultiplier'>" +
|
||||||
|
"<ref name='nonNegativeDecimal'/>" +
|
||||||
|
"</element>";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize BuildingAI Component
|
||||||
|
*/
|
||||||
|
BuildingAI.prototype.Init = function()
|
||||||
|
{
|
||||||
|
if (this.template.DefaultArrowCount > 0 || this.template.GarrisonArrowMultiplier > 0)
|
||||||
|
{
|
||||||
|
var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
|
||||||
|
this.timer = cmpTimer.SetTimeout(this.entity, IID_BuildingAI, "FireArrows", 1000, {});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BuildingAI.prototype.OnOwnershipChanged = function(msg)
|
||||||
|
{
|
||||||
|
if (msg.to != -1)
|
||||||
|
this.SetupRangeQuery(msg.to);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cleanup on destroy
|
||||||
|
*/
|
||||||
|
BuildingAI.prototype.OnDestroy = function()
|
||||||
|
{
|
||||||
|
if (this.timer)
|
||||||
|
{
|
||||||
|
var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
|
||||||
|
cmpTimer.CancelTimer(this.timer);
|
||||||
|
this.timer = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up range queries
|
||||||
|
var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
|
||||||
|
if (this.enemyUnitsQuery)
|
||||||
|
cmpRangeManager.DestroyActiveQuery(this.enemyUnitsQuery);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup the Range Query to detect units coming in & out of range
|
||||||
|
*/
|
||||||
|
BuildingAI.prototype.SetupRangeQuery = function(owner)
|
||||||
|
{
|
||||||
|
var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
|
||||||
|
var cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
|
||||||
|
|
||||||
|
var players = [];
|
||||||
|
|
||||||
|
var player = Engine.QueryInterface(cmpPlayerManager.GetPlayerByID(owner), IID_Player);
|
||||||
|
|
||||||
|
// Get our diplomacy array
|
||||||
|
var diplomacy = player.GetDiplomacy();
|
||||||
|
var numPlayers = cmpPlayerManager.GetNumPlayers();
|
||||||
|
|
||||||
|
for (var i = 1; i < numPlayers; ++i)
|
||||||
|
{ // Exclude gaia, allies, and self
|
||||||
|
// TODO: How to handle neutral players - Special query to attack military only?
|
||||||
|
if ((i != owner) && (diplomacy[i - 1] < 0))
|
||||||
|
players.push(i);
|
||||||
|
}
|
||||||
|
var cmpAttack = Engine.QueryInterface(this.entity, IID_Attack);
|
||||||
|
if (cmpAttack)
|
||||||
|
{
|
||||||
|
var range = cmpAttack.GetRange("Ranged");
|
||||||
|
this.enemyUnitsQuery = cmpRangeManager.CreateActiveQuery(this.entity, range.min, range.max, players, 0);
|
||||||
|
cmpRangeManager.EnableActiveQuery(this.enemyUnitsQuery);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when units enter or leave range
|
||||||
|
*/
|
||||||
|
BuildingAI.prototype.OnRangeUpdate = function(msg)
|
||||||
|
{
|
||||||
|
var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
|
||||||
|
var targetUnits = cmpRangeManager.ResetActiveQuery(this.enemyUnitsQuery);
|
||||||
|
if (targetUnits.length > 0)
|
||||||
|
this.targetUnit = targetUnits[0];
|
||||||
|
else
|
||||||
|
this.targetUnit = undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of arrows which needs to be fired.
|
||||||
|
* DefaultArrowCount + Garrisoned Archers(ie., any unit capable
|
||||||
|
* of shooting arrows from inside buildings)
|
||||||
|
*/
|
||||||
|
BuildingAI.prototype.GetArrowCount = function()
|
||||||
|
{
|
||||||
|
var count = +this.template.DefaultArrowCount;
|
||||||
|
var cmpGarrisonHolder = Engine.QueryInterface(this.entity, IID_GarrisonHolder);
|
||||||
|
if (cmpGarrisonHolder)
|
||||||
|
{
|
||||||
|
//Need to get garrisoned infantry count
|
||||||
|
count += Math.round(cmpGarrisonHolder.GetGarrisonedArcherCount() * this.template.GarrisonArrowMultiplier);
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fires arrows. Called every N times every 2 seconds
|
||||||
|
* where N is the number of Arrows
|
||||||
|
*/
|
||||||
|
BuildingAI.prototype.FireArrows = function()
|
||||||
|
{
|
||||||
|
var cmpAttack = Engine.QueryInterface(this.entity, IID_Attack);
|
||||||
|
if (cmpAttack)
|
||||||
|
{
|
||||||
|
var timerInterval;
|
||||||
|
var arrowCount = this.GetArrowCount();
|
||||||
|
if (arrowCount > 0)
|
||||||
|
{
|
||||||
|
timerInterval = Math.round(2000 / arrowCount);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
timerInterval = 1000;
|
||||||
|
}
|
||||||
|
var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
|
||||||
|
this.timer = cmpTimer.SetTimeout(this.entity, IID_BuildingAI, "FireArrows", timerInterval, {});
|
||||||
|
|
||||||
|
if ((this.targetUnit != undefined) && (arrowCount > 0))
|
||||||
|
{
|
||||||
|
cmpAttack.PerformAttack("Ranged", this.targetUnit);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Engine.RegisterComponentType(IID_BuildingAI, "BuildingAI", BuildingAI);
|
@ -55,6 +55,42 @@ GarrisonHolder.prototype.GetCapacity = function()
|
|||||||
return this.template.Max;
|
return this.template.Max;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get number of garrisoned units capable of shooting arrows
|
||||||
|
* Not necessarily archers
|
||||||
|
*/
|
||||||
|
GarrisonHolder.prototype.GetGarrisonedArcherCount = function()
|
||||||
|
{
|
||||||
|
var count = 0;
|
||||||
|
for each (var entity in this.entities)
|
||||||
|
{
|
||||||
|
var cmpIdentity = Engine.QueryInterface(entity, IID_Identity);
|
||||||
|
var classes = cmpIdentity.GetClassesList();
|
||||||
|
if (classes.indexOf("Infantry") != -1 || classes.indexOf("Ranged") != -1)
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Checks if an entity can be allowed to garrison in the building
|
||||||
|
* based on it's class
|
||||||
|
*/
|
||||||
|
GarrisonHolder.prototype.AllowedToGarrison = function(entity)
|
||||||
|
{
|
||||||
|
var allowedClasses = this.GetAllowedClassesList();
|
||||||
|
var entityClasses = (Engine.QueryInterface(entity, IID_Identity)).GetClassesList();
|
||||||
|
var classNotAllowed = true;
|
||||||
|
// Check if the unit is allowed to be garrisoned inside the building
|
||||||
|
for each (var allowedClass in allowedClasses)
|
||||||
|
{
|
||||||
|
if (entityClasses.indexOf(allowedClass) != -1)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Garrison a unit inside.
|
* Garrison a unit inside.
|
||||||
* Returns true if successful, false if not
|
* Returns true if successful, false if not
|
||||||
@ -65,22 +101,12 @@ GarrisonHolder.prototype.Garrison = function(entity)
|
|||||||
var entityPopCost = (Engine.QueryInterface(entity, IID_Cost)).GetPopCost();
|
var entityPopCost = (Engine.QueryInterface(entity, IID_Cost)).GetPopCost();
|
||||||
var entityClasses = (Engine.QueryInterface(entity, IID_Identity)).GetClassesList();
|
var entityClasses = (Engine.QueryInterface(entity, IID_Identity)).GetClassesList();
|
||||||
var allowedClasses = this.GetAllowedClassesList();
|
var allowedClasses = this.GetAllowedClassesList();
|
||||||
var classNotAllowed = true;
|
|
||||||
|
|
||||||
if (!this.HasEnoughHealth())
|
if (!this.HasEnoughHealth())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Check if the unit is allowed to be garrisoned inside the building
|
// Check if the unit is allowed to be garrisoned inside the building
|
||||||
for each (var allowedClass in allowedClasses)
|
if(!this.AllowedToGarrison(entity))
|
||||||
{
|
|
||||||
if (entityClasses.indexOf(allowedClass) != -1)
|
|
||||||
{
|
|
||||||
classNotAllowed = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (classNotAllowed)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (this.GetCapacity() < this.spaceOccupied + 1)
|
if (this.GetCapacity() < this.spaceOccupied + 1)
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
Engine.RegisterInterface("BuildingAI");
|
@ -57,4 +57,8 @@
|
|||||||
<death>attack/destruction/explode_debris.xml</death>
|
<death>attack/destruction/explode_debris.xml</death>
|
||||||
</SoundGroups>
|
</SoundGroups>
|
||||||
</Sound>
|
</Sound>
|
||||||
|
<BuildingAI>
|
||||||
|
<DefaultArrowCount>0</DefaultArrowCount>
|
||||||
|
<GarrisonArrowMultiplier>0</GarrisonArrowMultiplier>
|
||||||
|
</BuildingAI>
|
||||||
</Entity>
|
</Entity>
|
||||||
|
@ -60,4 +60,8 @@
|
|||||||
<RepeatTime>2000</RepeatTime>
|
<RepeatTime>2000</RepeatTime>
|
||||||
</Ranged>
|
</Ranged>
|
||||||
</Attack>
|
</Attack>
|
||||||
|
<BuildingAI>
|
||||||
|
<DefaultArrowCount>1</DefaultArrowCount>
|
||||||
|
<GarrisonArrowMultiplier>1</GarrisonArrowMultiplier>
|
||||||
|
</BuildingAI>
|
||||||
</Entity>
|
</Entity>
|
||||||
|
Loading…
Reference in New Issue
Block a user