Changeset View
Changeset View
Standalone View
Standalone View
binaries/data/mods/public/simulation/ai/petra/entityExtend.js
/** returns true if this unit should be considered as a siege unit */ | /** returns true if this unit should be considered as a siege unit */ | ||||
PETRA.isSiegeUnit = function(ent) | PETRA.isSiegeUnit = function(ent) | ||||
{ | { | ||||
return ent.hasClass("Siege") || ent.hasClass("Elephant") && ent.hasClass("Melee"); | return ent.hasClass("Siege") || ent.hasClass("Elephant") && ent.hasClass("Melee"); | ||||
}; | }; | ||||
/** returns true if this unit should be considered as "fast". */ | /** returns true if this unit should be considered as "fast". */ | ||||
PETRA.isFastMoving = function(ent) | PETRA.isFastMoving = function(ent) | ||||
{ | { | ||||
// TODO: use clever logic based on walkspeed comparisons. | // TODO: use clever logic based on walkspeed comparisons. | ||||
return ent.hasClass("FastMoving"); | return ent.hasClass("FastMoving"); | ||||
}; | }; | ||||
/** returns some sort of DPS * health factor. If you specify a class, it'll use the modifiers against that class too. */ | /** returns some sort of DPS * health factor. If you specify a class and or civ, it'll use the modifiers against that too. */ | ||||
PETRA.getMaxStrength = function(ent, debugLevel, DamageTypeImportance, againstClass) | PETRA.getMaxStrength = function(ent, debugLevel, DamageTypeImportance, againstClassList = [], civ = undefined) | ||||
{ | { | ||||
let strength = 0; | let strength = 0; | ||||
let attackTypes = ent.attackTypes(); | let attackTypes = ent.attackTypes(); | ||||
let damageTypes = Object.keys(DamageTypeImportance); | let damageTypes = Object.keys(DamageTypeImportance); | ||||
if (!attackTypes) | if (!attackTypes) | ||||
return strength; | return strength; | ||||
for (let type of attackTypes) | for (let type of attackTypes) | ||||
{ | { | ||||
if (type == "Slaughter") | if (type == "Slaughter") | ||||
continue; | continue; | ||||
let attackStrength = ent.attackStrengths(type); | let attackStrength = ent.attackStrengths(type, againstClassList, civ); | ||||
for (let str in attackStrength) | for (let damageType in attackStrength.Damage) | ||||
{ | { | ||||
let val = parseFloat(attackStrength[str]); | let val = parseFloat(attackStrength[damageType]); | ||||
if (againstClass) | if (DamageTypeImportance[damageType]) | ||||
val *= ent.getMultiplierAgainst(type, againstClass); | strength += DamageTypeImportance[damageType] * val / damageTypes.length; | ||||
if (DamageTypeImportance[str]) | |||||
strength += DamageTypeImportance[str] * val / damageTypes.length; | |||||
else if (debugLevel > 0) | else if (debugLevel > 0) | ||||
API3.warn("Petra: " + str + " unknown attackStrength in getMaxStrength (please add " + str + " to config.js)."); | API3.warn("Petra: " + str + " unknown attackStrength in getMaxStrength (please add " + str + " to config.js)."); | ||||
} | } | ||||
// TODO: Capture, Statuseffect. | |||||
let attackRange = ent.attackRange(type); | let attackRange = ent.attackRange(type); | ||||
if (attackRange) | if (attackRange) | ||||
strength += attackRange.max * 0.0125; | strength += attackRange.max * 0.0125; | ||||
let attackTimes = ent.attackTimes(type); | let attackTimes = ent.attackTimes(type); | ||||
for (let str in attackTimes) | for (let str in attackTimes) | ||||
{ | { | ||||
let val = parseFloat(attackTimes[str]); | let val = parseFloat(attackTimes[str]); | ||||
▲ Show 20 Lines • Show All 90 Lines • ▼ Show 20 Lines | PETRA.getSeaAccess = function(gameState, ent) | ||||
return sea; | return sea; | ||||
}; | }; | ||||
PETRA.setSeaAccess = function(gameState, ent) | PETRA.setSeaAccess = function(gameState, ent) | ||||
{ | { | ||||
PETRA.getSeaAccess(gameState, ent); | PETRA.getSeaAccess(gameState, ent); | ||||
}; | }; | ||||
/** Decide if we should try to capture (returns true) or destroy (return false) */ | /** | ||||
PETRA.allowCapture = function(gameState, ent, target) | * Decide which attackEffects we should ignore when choosing the attack type. | ||||
*/ | |||||
PETRA.ignoreAttackEffects = function(gameState, ent, target) | |||||
{ | { | ||||
if (!target.isCapturable() || !ent.canCapture(target)) | if (!target.isCapturable() || !ent.canCapture(target)) | ||||
return false; | return { "Capture": true }; | ||||
if (target.isInvulnerable()) | |||||
return true; | |||||
// always try to recapture cp from an allied, except if it's decaying | // always try to recapture cp from an allied, except if it's decaying | ||||
if (gameState.isPlayerAlly(target.owner())) | if (gameState.isPlayerAlly(target.owner())) | ||||
return !target.decaying(); | { | ||||
let ignoreCapture = target.decaying(); | |||||
return { "Damage": !ignoreCapture, "Capture": ignoreCapture, "ApplyStatus": !ignoreCapture }; | |||||
Freagarach: This sounds interesting: the target is allied, but we still try to damage it? | |||||
Done Inline ActionsNothing changed in that regard though. bb: Nothing changed in that regard though. | |||||
} | |||||
let antiCapture = target.defaultRegenRate(); | let antiCapture = target.defaultRegenRate(); | ||||
if (target.isGarrisonHolder() && target.garrisoned()) | if (target.isGarrisonHolder() && target.garrisoned()) | ||||
antiCapture += target.garrisonRegenRate() * target.garrisoned().length; | antiCapture += target.garrisonRegenRate() * target.garrisoned().length; | ||||
if (target.decaying()) | if (target.decaying()) | ||||
antiCapture -= target.territoryDecayRate(); | antiCapture -= target.territoryDecayRate(); | ||||
let capture; | let capture; | ||||
let capturableTargets = gameState.ai.HQ.capturableTargets; | let capturableTargets = gameState.ai.HQ.capturableTargets; | ||||
if (!capturableTargets.has(target.id())) | if (!capturableTargets.has(target.id())) | ||||
{ | { | ||||
capture = ent.captureStrength() * PETRA.getAttackBonus(ent, target, "Capture"); | capture = ent.captureStrength(target.classes(), target.civ()); | ||||
capturableTargets.set(target.id(), { "strength": capture, "ents": new Set([ent.id()]) }); | capturableTargets.set(target.id(), { "strength": capture, "ents": new Set([ent.id()]) }); | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
let capturable = capturableTargets.get(target.id()); | let capturable = capturableTargets.get(target.id()); | ||||
if (!capturable.ents.has(ent.id())) | if (!capturable.ents.has(ent.id())) | ||||
{ | { | ||||
capturable.strength += ent.captureStrength() * PETRA.getAttackBonus(ent, target, "Capture"); | capturable.strength += ent.captureStrength(target.classes(), target.civ()); | ||||
capturable.ents.add(ent.id()); | capturable.ents.add(ent.id()); | ||||
} | } | ||||
capture = capturable.strength; | capture = capturable.strength; | ||||
} | } | ||||
capture *= 1 / (0.1 + 0.9*target.healthLevel()); | capture *= 1 / (0.1 + 0.9 * target.healthLevel()); | ||||
let sumCapturePoints = target.capturePoints().reduce((a, b) => a + b); | let sumCapturePoints = target.capturePoints().reduce((a, b) => a + b); | ||||
if (target.hasDefensiveFire() && target.isGarrisonHolder() && target.garrisoned()) | let ignoreCapture = target.hasDefensiveFire() && target.isGarrisonHolder() && target.garrisoned() ? | ||||
return capture > antiCapture + sumCapturePoints/50; | capture < antiCapture + sumCapturePoints/50 : | ||||
return capture > antiCapture + sumCapturePoints/80; | capture < antiCapture + sumCapturePoints/80; | ||||
}; | |||||
PETRA.getAttackBonus = function(ent, target, type) | return { "Damage": !ignoreCapture, "Capture": ignoreCapture, "ApplyStatus": !ignoreCapture }; | ||||
{ | |||||
let attackBonus = 1; | |||||
if (!ent.get("Attack/" + type) || !ent.get("Attack/" + type + "/Bonuses")) | |||||
return attackBonus; | |||||
let bonuses = ent.get("Attack/" + type + "/Bonuses"); | |||||
for (let key in bonuses) | |||||
{ | |||||
let bonus = bonuses[key]; | |||||
if (bonus.Civ && bonus.Civ !== target.civ()) | |||||
continue; | |||||
if (bonus.Classes && bonus.Classes.split(/\s+/).some(cls => !target.hasClass(cls))) | |||||
continue; | |||||
attackBonus *= bonus.Multiplier; | |||||
} | |||||
return attackBonus; | |||||
}; | }; | ||||
/** Makes the worker deposit the currently carried resources at the closest accessible dropsite */ | /** Makes the worker deposit the currently carried resources at the closest accessible dropsite */ | ||||
PETRA.returnResources = function(gameState, ent) | PETRA.returnResources = function(gameState, ent) | ||||
{ | { | ||||
if (!ent.resourceCarrying() || !ent.resourceCarrying().length || !ent.position()) | if (!ent.resourceCarrying() || !ent.resourceCarrying().length || !ent.position()) | ||||
return false; | return false; | ||||
▲ Show 20 Lines • Show All 217 Lines • Show Last 20 Lines |
Wildfire Games · Phabricator
This sounds interesting: the target is allied, but we still try to damage it?