forked from 0ad/0ad
125 lines
3.5 KiB
JavaScript
125 lines
3.5 KiB
JavaScript
var PETRA = function(m)
|
|
{
|
|
|
|
// returns some sort of DPS * health factor. If you specify a class, it'll use the modifiers against that class too.
|
|
m.getMaxStrength = function(ent, againstClass)
|
|
{
|
|
var strength = 0.0;
|
|
var attackTypes = ent.attackTypes();
|
|
if (!attackTypes)
|
|
return strength;
|
|
|
|
var armourStrength = ent.armourStrengths();
|
|
var hp = ent.maxHitpoints() / 100.0; // some normalization
|
|
for (let type of attackTypes)
|
|
{
|
|
if (type == "Slaughter" || type == "Charged")
|
|
continue;
|
|
|
|
var attackStrength = ent.attackStrengths(type);
|
|
var attackRange = ent.attackRange(type);
|
|
var attackTimes = ent.attackTimes(type);
|
|
for (var str in attackStrength) {
|
|
var val = parseFloat(attackStrength[str]);
|
|
if (againstClass)
|
|
val *= ent.getMultiplierAgainst(type, againstClass);
|
|
switch (str) {
|
|
case "crush":
|
|
strength += (val * 0.085) / 3;
|
|
break;
|
|
case "hack":
|
|
strength += (val * 0.075) / 3;
|
|
break;
|
|
case "pierce":
|
|
strength += (val * 0.065) / 3;
|
|
break;
|
|
}
|
|
}
|
|
if (attackRange){
|
|
strength += (attackRange.max * 0.0125) ;
|
|
}
|
|
for (var str in attackTimes) {
|
|
var val = parseFloat(attackTimes[str]);
|
|
switch (str){
|
|
case "repeat":
|
|
strength += (val / 100000);
|
|
break;
|
|
case "prepare":
|
|
strength -= (val / 100000);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
for (var str in armourStrength) {
|
|
var val = parseFloat(armourStrength[str]);
|
|
switch (str) {
|
|
case "crush":
|
|
strength += (val * 0.085) / 3;
|
|
break;
|
|
case "hack":
|
|
strength += (val * 0.075) / 3;
|
|
break;
|
|
case "pierce":
|
|
strength += (val * 0.065) / 3;
|
|
break;
|
|
}
|
|
}
|
|
return strength * hp;
|
|
};
|
|
|
|
// Makes the worker deposit the currently carried resources at the closest accessible dropsite
|
|
m.returnResources = function(ent, gameState)
|
|
{
|
|
if (!ent.resourceCarrying() || ent.resourceCarrying().length == 0 || !ent.position())
|
|
return false;
|
|
|
|
var resource = ent.resourceCarrying()[0].type;
|
|
|
|
var closestDropsite = undefined;
|
|
var distmin = Math.min();
|
|
var access = gameState.ai.accessibility.getAccessValue(ent.position());
|
|
gameState.getOwnDropsites(resource).forEach(function(dropsite) {
|
|
if (!dropsite.position() || dropsite.getMetadata(PlayerID, "access") !== access)
|
|
return;
|
|
var dist = API3.SquareVectorDistance(ent.position(), dropsite.position());
|
|
if (dist > distmin)
|
|
return;
|
|
distmin = dist;
|
|
closestDropsite = dropsite;
|
|
});
|
|
|
|
if (!closestDropsite)
|
|
return false;
|
|
ent.returnResources(closestDropsite);
|
|
return true;
|
|
};
|
|
|
|
m.getHolder = function(ent, gameState)
|
|
{
|
|
var found = undefined;
|
|
gameState.getEntities().forEach(function (holder) {
|
|
if (found || !holder.isGarrisonHolder())
|
|
return;
|
|
if (holder.garrisoned().indexOf(ent.id()) !== -1)
|
|
found = holder;
|
|
});
|
|
return found;
|
|
};
|
|
|
|
m.dumpEntity = function(ent)
|
|
{
|
|
if (!ent)
|
|
return;
|
|
API3.warn(" >>> id " + ent.id() + " name " + ent.genericName() + " pos " + ent.position()
|
|
+ " state " + ent.unitAIState());
|
|
API3.warn(" base " + ent.getMetadata(PlayerID, "base") + " >>> role " + ent.getMetadata(PlayerID, "role")
|
|
+ " subrole " + ent.getMetadata(PlayerID, "subrole"));
|
|
API3.warn(" garrisoning " + ent.getMetadata(PlayerID, "garrisoning") + " garrisonHolder " + ent.getMetadata(PlayerID, "garrisonHolder")
|
|
+ " plan " + ent.getMetadata(PlayerID, "plan") + " transport " + ent.getMetadata(PlayerID, "transport")
|
|
+ " gather-type " + ent.getMetadata(PlayerID, "gather-type") + " target-foundation " + ent.getMetadata(PlayerID, "target-foundation")
|
|
+ " PartOfArmy " + ent.getMetadata(PlayerID, "PartOfArmy"));
|
|
};
|
|
|
|
return m;
|
|
}(PETRA);
|