|
|
|
|
|
PlaceObj('AIArchetype', { |
|
BaseAttackWeight = 0, |
|
Behaviors = { |
|
PlaceObj('StandardAI', { |
|
'EndTurnPolicies', { |
|
PlaceObj('AIPolicyDealDamage', { |
|
'Weight', 600, |
|
}), |
|
PlaceObj('AIPolicyWeaponRange', { |
|
'Weight', 300, |
|
'RangeBase', "Absolute", |
|
'RangeMin', 2, |
|
'RangeMax', 2, |
|
}), |
|
}, |
|
}), |
|
}, |
|
MoveStance = "", |
|
OptLocPolicies = { |
|
PlaceObj('AIPolicyWeaponRange', { |
|
'RangeBase', "Absolute", |
|
'RangeMin', 2, |
|
'RangeMax', 2, |
|
}), |
|
PlaceObj('AIPolicyLosToEnemy', nil), |
|
}, |
|
OptLocSearchRadius = 80, |
|
PrefStance = "", |
|
TargetChangePolicy = "restart", |
|
group = "Beasts", |
|
id = "Beast_Crocodile", |
|
}) |
|
|
|
PlaceObj('AIArchetype', { |
|
BaseAttackWeight = 0, |
|
Behaviors = { |
|
PlaceObj('StandardAI', { |
|
'EndTurnPolicies', { |
|
PlaceObj('AIPolicyDealDamage', { |
|
'Weight', 600, |
|
}), |
|
}, |
|
'SignatureActions', { |
|
PlaceObj('AIActionHyenaCharge', nil), |
|
}, |
|
}), |
|
}, |
|
MoveStance = "", |
|
OptLocPolicies = { |
|
PlaceObj('AIPolicyWeaponRange', { |
|
'RangeBase', "Melee", |
|
'RangeMin', 1000, |
|
'RangeMax', 1000, |
|
}), |
|
PlaceObj('AIPolicyLosToEnemy', nil), |
|
}, |
|
OptLocSearchRadius = 80, |
|
PrefStance = "", |
|
SignatureActions = { |
|
PlaceObj('AIActionCharge', { |
|
'BiasId', "HyenaCharge", |
|
'Weight', 200, |
|
'OnActivationBiases', { |
|
PlaceObj('AIBiasModification', { |
|
'BiasId', "HyenaCharge", |
|
'Effect', "disable", |
|
}), |
|
}, |
|
'ForbiddenInState', set( "RainHeavy" ), |
|
'DestPreference', "nearest", |
|
}), |
|
}, |
|
TargetChangePolicy = "restart", |
|
group = "Beasts", |
|
id = "Beast_Hyena", |
|
}) |
|
|
|
PlaceObj('AIArchetype', { |
|
Behaviors = { |
|
PlaceObj('CustomAI', { |
|
'EndTurnPolicies', { |
|
PlaceObj('AIPolicyTakeCover', { |
|
'visibility_mode', "team", |
|
}), |
|
}, |
|
'TakeCoverChance', 100, |
|
'EnumDests', function (self, unit, context, debug_data) |
|
if g_Encounter then |
|
return g_Encounter:EnumDestsInAssignedArea(unit, context) |
|
end |
|
end, |
|
'PickEndTurnPolicies', function (self, unit, context, debug_data) |
|
if g_Encounter then |
|
return g_Encounter:SelectEndTurnPolicies(unit, context) |
|
end |
|
end, |
|
'PickOptimalLoc', function (self, unit, context, debug_data) |
|
if g_Encounter then |
|
return g_Encounter:FindOptimalLocationInAssignedArea(unit, context) |
|
end |
|
end, |
|
'PickEndTurnLoc', function (self, unit, context, debug_data) |
|
AITacticCalcPathDistances(unit, context, "disable bias") |
|
|
|
local policies = self:PickEndTurnPolicies(unit, context) or self.EndTurnPolicies |
|
context.ai_destination = AIScoreReachableVoxels(context, policies, self.OptLocWeight, nil, "prefer") |
|
return true |
|
end, |
|
'SelectSignatureActions', function (self, unit, context, debug_data) |
|
if g_Encounter then |
|
return g_Encounter:SelectSignatureActions(unit, context) |
|
end |
|
end, |
|
}), |
|
}, |
|
Comment = "generic implementation, try reaching assigned area, valid positions are in assigned & current areas only", |
|
group = "BossFights", |
|
id = "Bossfight_GuardArea", |
|
}) |
|
|
|
PlaceObj('AIArchetype', { |
|
Behaviors = { |
|
PlaceObj('CustomAI', { |
|
'turn_phase', "Early", |
|
'EndTurnPolicies', { |
|
PlaceObj('AIPolicyTakeCover', { |
|
'visibility_mode', "team", |
|
}), |
|
}, |
|
'TakeCoverChance', 100, |
|
'EnumDests', function (self, unit, context, debug_data) |
|
if not g_Encounter then return end |
|
|
|
return CorazonEnumDestsInAssignedArea(unit, context) |
|
end, |
|
'PickOptimalLoc', function (self, unit, context, debug_data) |
|
if g_Encounter:GetUnitArea(unit) == g_Encounter.areaFinalRoom then |
|
context.best_dest = GetPackedPosAndStance(unit) |
|
return true |
|
end |
|
|
|
local _, positions = CorazonGetAreaMarkerPositions(g_Encounter.areaFinalRoom) |
|
positions = positions or empty_table |
|
if #positions > 0 then |
|
local goto_pos = table.interaction_rand(positions, "Behavior") |
|
local x, y, z = point_unpack(goto_pos) |
|
context.best_dest = stance_pos_pack(x, y, z, StancesList.Standing) |
|
return true |
|
end |
|
end, |
|
'PickEndTurnLoc', function (self, unit, context, debug_data) |
|
CorazonCalcPathDistances(unit, context, "disable bias") |
|
end, |
|
}), |
|
}, |
|
group = "BossFights", |
|
id = "Corazon_BossRetreating", |
|
}) |
|
|
|
PlaceObj('AIArchetype', { |
|
Behaviors = { |
|
PlaceObj('CustomAI', { |
|
'EndTurnPolicies', { |
|
PlaceObj('AIPolicyTakeCover', { |
|
'visibility_mode', "team", |
|
}), |
|
}, |
|
'TakeCoverChance', 100, |
|
'EnumDests', function (self, unit, context, debug_data) |
|
if not g_Encounter then return end |
|
|
|
return CorazonEnumDestsInAssignedArea(unit, context) |
|
end, |
|
'PickEndTurnPolicies', function (self, unit, context, debug_data) |
|
if IsKindOf(g_Encounter, "BossfightCorazon") then |
|
return g_Encounter:SelectEndTurnPolicies(unit, context) |
|
end |
|
end, |
|
'PickOptimalLoc', function (self, unit, context, debug_data) |
|
return CorazonOptimalLocationInAssignedArea(unit, context) |
|
end, |
|
'PickEndTurnLoc', function (self, unit, context, debug_data) |
|
CorazonCalcPathDistances(unit, context, "disable bias") |
|
|
|
local policies = self:PickEndTurnPolicies(unit, context) or self.EndTurnPolicies |
|
context.ai_destination = AIScoreReachableVoxels(context, policies, self.OptLocWeight, nil, "prefer") |
|
return true |
|
end, |
|
'SelectSignatureActions', function (self, unit, context, debug_data) |
|
if IsKindOf(g_Encounter, "BossfightCorazon") then |
|
return g_Encounter:SelectSignatureActions(unit, context) |
|
end |
|
end, |
|
'Execute', function (self, unit, context, debug_data) |
|
|
|
|
|
end, |
|
}), |
|
}, |
|
Comment = "basic logic: move to assigned area, engange enemies in/from it until assigned elsewhere", |
|
group = "BossFights", |
|
id = "Corazon_GuardArea", |
|
}) |
|
|
|
PlaceObj('AIArchetype', { |
|
Behaviors = { |
|
PlaceObj('CustomAI', { |
|
'EndTurnPolicies', { |
|
PlaceObj('AIPolicyTakeCover', { |
|
'visibility_mode', "team", |
|
}), |
|
}, |
|
'TakeCoverChance', 100, |
|
'EnumDests', function (self, unit, context, debug_data) |
|
if not g_Encounter then return end |
|
|
|
return CorazonEnumDestsInAssignedArea(unit, context) |
|
end, |
|
'PickOptimalLoc', function (self, unit, context, debug_data) |
|
return CorazonOptimalLocationInAssignedArea(unit, context) |
|
end, |
|
'PickEndTurnLoc', function (self, unit, context, debug_data) |
|
CorazonCalcPathDistances(unit, context, "disable bias") |
|
end, |
|
'SelectSignatureActions', function (self, unit, context, debug_data) |
|
if IsKindOf(g_Encounter, "BossfightCorazon") then |
|
return g_Encounter:SelectSignatureActions(unit, context) |
|
end |
|
end, |
|
'Execute', function (self, unit, context, debug_data) |
|
|
|
|
|
end, |
|
}), |
|
}, |
|
Comment = "right corridor kite back - similar to GuardArea but maybe more defensive?", |
|
group = "BossFights", |
|
id = "Corazon_KiteBack", |
|
}) |
|
|
|
PlaceObj('AIArchetype', { |
|
Behaviors = { |
|
PlaceObj('CustomAI', { |
|
'EndTurnPolicies', { |
|
PlaceObj('AIPolicyTakeCover', { |
|
'visibility_mode', "team", |
|
}), |
|
}, |
|
'TakeCoverChance', 100, |
|
'EnumDests', function (self, unit, context, debug_data) |
|
if not g_Encounter then return end |
|
|
|
return CorazonEnumDestsInAssignedArea(unit, context) |
|
end, |
|
'EvalDamageScore', function (self, unit, context, debug_data) |
|
context.max_attacks = 1 |
|
AIPrecalcDamageScore(context) |
|
end, |
|
'PickOptimalLoc', function (self, unit, context, debug_data) |
|
return CorazonOptimalLocationInAssignedArea(unit, context) |
|
end, |
|
'PickEndTurnLoc', function (self, unit, context, debug_data) |
|
|
|
local hide_dests = {} |
|
local attack_dest, attack_score, scoot_ap |
|
|
|
for _, dest in ipairs(context.destinations) do |
|
if not g_AIDestEnemyLOSCache[dest] then |
|
hide_dests[#hide_dests+1] = dest |
|
else |
|
local score = context.dest_target_score or 0 |
|
if score > 0 then |
|
|
|
local move_stance_idx = context.dest_combat_path[dest] |
|
local cpath = context.combat_paths[move_stance_idx] |
|
local ap_at_dest = cpath:GetAP(dest) |
|
score = MulDivRound(score, ap_at_dest, Max(1, unit.ActionPoints)) |
|
|
|
if score > (attack_score or 0) then |
|
attack_dest, attack_score, scoot_ap = dest, score, ap_at_dest - context.default_attack_cost |
|
end |
|
end |
|
end |
|
end |
|
|
|
if not attack_dest or #hide_dests < 1 or not scoot_ap then return end |
|
|
|
|
|
local x, y, z, stance_idx = stance_pos_unpack(attack_dest) |
|
local atk_pos = point(x, y, z) |
|
local combat_path = CombatPath:new() |
|
local weights, total_weight = {}, 0 |
|
local hide_dest |
|
|
|
combat_path:RebuildPaths(unit, scoot_ap, atk_pos, StancesList[stance_idx]) |
|
for i, dest in ipairs(hide_dests) do |
|
local x, y, z = stance_pos_unpack(dest) |
|
local pos = point_pack(x, y, z) |
|
local ap = combat_path:GetAP(pos) |
|
weights[i] = ap |
|
total_weight = total_weight + ap |
|
end |
|
|
|
if total_weight < 1 then return end |
|
local roll = unit:Random(total_weight) |
|
for i = 1, #hide_dests - 1 do |
|
local w = weights[i] |
|
if w >= roll then |
|
hide_dest = hide_dests[i] |
|
break |
|
end |
|
end |
|
|
|
context.ai_destination = attack_dest |
|
context.scoot_and_shoot_dest = hide_dest or hide_dests[#hide_dests] |
|
DoneObject(combat_path) |
|
return true |
|
end, |
|
'SelectSignatureActions', function (self, unit, context, debug_data) |
|
if IsKindOf(g_Encounter, "BossfightCorazon") then |
|
return g_Encounter:SelectSignatureActions(unit, context) |
|
end |
|
end, |
|
'Execute', function (self, unit, context, debug_data) |
|
if not context.scoot_and_shoot_dest then return end |
|
|
|
|
|
local dest = GetPackedPosAndStance(unit) |
|
AIPrecalcDamageScore(context, {dest}) |
|
local target = (context.dest_target or empty_table)[dest] |
|
|
|
local args = { target = target } |
|
AIPlayCombatAction(context.default_attack.id, unit, nil, args) |
|
|
|
|
|
local x, y, z = stance_pos_unpack(context.scoot_and_shoot_dest) |
|
local combat_path = CombatPath:new() |
|
combat_path:RebuildPaths(unit) |
|
|
|
if not combat_path:GetAP(point_pack(x, y, z)) then |
|
local hide_dests = {} |
|
for _, dest in ipairs(context.destinations) do |
|
local x, y, z = stance_pos_unpack(dest) |
|
if not g_AIDestEnemyLOSCache[dest] and combat_path:GetAP(point_pack(x, y, z)) then |
|
hide_dests[#hide_dests+1] = dest |
|
end |
|
end |
|
if #hide_dests > 0 then |
|
local dest = table.interaction_rand(hide_dests, "Behavior") |
|
local x, y, z = stance_point_unpack(dest) |
|
AIPlayCombatAction("Move", unit, unit.ActionPoints, { goto_pos = point(x, y, z) }) |
|
else |
|
AIPlayAttacks(unit, context) |
|
end |
|
else |
|
AIPlayCombatAction("Move", unit, unit.ActionPoints, { goto_pos = point(x, y, z) }) |
|
end |
|
AITakeCover(unit) |
|
DoneObject(combat_path) |
|
return "done" |
|
end, |
|
}), |
|
}, |
|
Comment = "right corridor shoot-and-scoot action", |
|
group = "BossFights", |
|
id = "Corazon_ShootAndScoot", |
|
}) |
|
|
|
PlaceObj('AIArchetype', { |
|
Behaviors = { |
|
PlaceObj('CustomAI', { |
|
'turn_phase', "Early", |
|
'EndTurnPolicies', { |
|
PlaceObj('AIPolicyTakeCover', { |
|
'visibility_mode', "team", |
|
}), |
|
}, |
|
'TakeCoverChance', 100, |
|
'EnumDests', function (self, unit, context, debug_data) |
|
if g_TacticalMap then |
|
return g_TacticalMap:EnumDestsInAssignedArea(unit, context) |
|
end |
|
end, |
|
'PickOptimalLoc', function (self, unit, context, debug_data) |
|
if g_TacticalMap then |
|
return g_TacticalMap:FindOptimalLocationInAssignedArea(unit, context) |
|
end |
|
end, |
|
'PickEndTurnLoc', function (self, unit, context, debug_data) |
|
AITacticCalcPathDistances(unit, context, "disable bias") |
|
|
|
local policies = self:PickEndTurnPolicies(unit, context) or self.EndTurnPolicies |
|
context.ai_destination = AIScoreReachableVoxels(context, policies, self.OptLocWeight, nil, "avoid") |
|
return true |
|
end, |
|
'SelectSignatureActions', function (self, unit, context, debug_data) |
|
return AITacticSelectSignatureActions(unit, context) |
|
end, |
|
}), |
|
}, |
|
group = "BossFights", |
|
id = "Faucheaux_BossRetreating", |
|
}) |
|
|
|
PlaceObj('AIArchetype', { |
|
BaseAttackWeight = 0, |
|
Behaviors = { |
|
PlaceObj('StandardAI', { |
|
'EndTurnPolicies', { |
|
PlaceObj('AIPolicyTakeCover', { |
|
'Weight', 50, |
|
}), |
|
PlaceObj('AIPolicyProximity', { |
|
'MinScore', 12, |
|
}), |
|
PlaceObj('AIPolicyLosToEnemy', { |
|
'Invert', true, |
|
}), |
|
}, |
|
}), |
|
}, |
|
MoveStance = "Crouch", |
|
OptLocPolicies = { |
|
PlaceObj('AIPolicyProximity', { |
|
'MinScore', 12, |
|
}), |
|
PlaceObj('AIPolicyLosToEnemy', { |
|
'Invert', true, |
|
}), |
|
PlaceObj('AIPolicyTakeCover', nil), |
|
}, |
|
OptLocSearchRadius = 80, |
|
PrefStance = "Crouch", |
|
group = "Civilian", |
|
id = "ActiveCivilian", |
|
}) |
|
|
|
PlaceObj('AIArchetype', { |
|
BaseAttackWeight = 0, |
|
Behaviors = { |
|
PlaceObj('HoldPositionAI', { |
|
'Priority', true, |
|
}), |
|
PlaceObj('StandardAI', { |
|
'Weight', 0, |
|
}), |
|
}, |
|
MoveStance = "Crouch", |
|
OptLocPolicies = { |
|
PlaceObj('AIPolicyTakeCover', nil), |
|
}, |
|
PrefStance = "Crouch", |
|
group = "Civilian", |
|
id = "AnimTestDummy_Crouched", |
|
}) |
|
|
|
PlaceObj('AIArchetype', { |
|
BaseAttackWeight = 0, |
|
Behaviors = { |
|
PlaceObj('HoldPositionAI', { |
|
'Priority', true, |
|
}), |
|
PlaceObj('StandardAI', { |
|
'Weight', 0, |
|
}), |
|
}, |
|
MoveStance = "Prone", |
|
OptLocPolicies = { |
|
PlaceObj('AIPolicyTakeCover', nil), |
|
}, |
|
PrefStance = "Prone", |
|
group = "Civilian", |
|
id = "AnimTestDummy_Prone", |
|
}) |
|
|
|
PlaceObj('AIArchetype', { |
|
BaseAttackWeight = 0, |
|
Behaviors = { |
|
PlaceObj('HoldPositionAI', { |
|
'Priority', true, |
|
}), |
|
PlaceObj('StandardAI', { |
|
'Weight', 0, |
|
}), |
|
}, |
|
OptLocPolicies = { |
|
PlaceObj('AIPolicyTakeCover', nil), |
|
}, |
|
group = "Civilian", |
|
id = "AnimTestDummy_Standing", |
|
}) |
|
|
|
PlaceObj('AIArchetype', { |
|
BaseMovementWeight = 10, |
|
Behaviors = { |
|
PlaceObj('StandardAI', { |
|
'EndTurnPolicies', { |
|
PlaceObj('AIPolicyTakeCover', { |
|
'visibility_mode', "team", |
|
}), |
|
PlaceObj('AIPolicyProximity', { |
|
'Weight', 1000, |
|
'MinScore', 10, |
|
}), |
|
}, |
|
'TakeCoverChance', 100, |
|
}), |
|
}, |
|
OptLocPolicies = { |
|
PlaceObj('AIPolicyTakeCover', { |
|
'visibility_mode', "team", |
|
}), |
|
PlaceObj('AIPolicyProximity', { |
|
'Weight', 1000, |
|
'MinScore', 10, |
|
}), |
|
}, |
|
OptLocSearchRadius = 80, |
|
PrefStance = "Crouch", |
|
SignatureActions = { |
|
PlaceObj('AIActionMobileShot', { |
|
'Weight', 200, |
|
'NotificationText', "", |
|
'action_id', "RunAndGun", |
|
}), |
|
}, |
|
TargetScoreRandomization = 40, |
|
group = "Lieutenants", |
|
id = "CorazonBoss", |
|
}) |
|
|
|
PlaceObj('AIArchetype', { |
|
BaseAttackTargeting = set( "Neck", "Torso" ), |
|
BaseMovementWeight = 10, |
|
Behaviors = { |
|
PlaceObj('StandardAI', { |
|
'EndTurnPolicies', { |
|
PlaceObj('AIPolicyDealDamage', nil), |
|
}, |
|
'TakeCoverChance', 0, |
|
}), |
|
}, |
|
OptLocPolicies = { |
|
PlaceObj('AIPolicyWeaponRange', { |
|
'RangeBase', "Melee", |
|
'RangeMin', 0, |
|
'RangeMax', 6, |
|
}), |
|
PlaceObj('AIPolicyLosToEnemy', nil), |
|
}, |
|
OptLocSearchRadius = 80, |
|
SignatureActions = { |
|
PlaceObj('AIActionThrowGrenade', { |
|
'BiasId', "StunGrenade", |
|
'OnActivationBiases', { |
|
PlaceObj('AIBiasModification', { |
|
'BiasId', "StunGrenade", |
|
'Effect', "disable", |
|
}), |
|
}, |
|
'min_score', 100, |
|
'MinDist', 3000, |
|
'AllowedAoeTypes', set( "fire", "none", "teargas", "toxicgas" ), |
|
}), |
|
PlaceObj('AIActionCharge', { |
|
'BiasId', "PierreCharge", |
|
'Weight', 300, |
|
}), |
|
}, |
|
TargetChangePolicy = "restart", |
|
TargetScoreRandomization = 10, |
|
group = "Lieutenants", |
|
id = "Pierre", |
|
}) |
|
|
|
PlaceObj('AIArchetype', { |
|
BaseAttackTargeting = set( "Arms", "Groin", "Legs", "Torso" ), |
|
BaseMovementWeight = 10, |
|
Behaviors = { |
|
PlaceObj('StandardAI', { |
|
'BiasId', "Standard", |
|
'Weight', 150, |
|
'EndTurnPolicies', { |
|
PlaceObj('AIPolicyTakeCover', { |
|
'Weight', 50, |
|
'visibility_mode', "team", |
|
}), |
|
PlaceObj('AIPolicyDealDamage', nil), |
|
}, |
|
}), |
|
}, |
|
MoveStance = "Crouch", |
|
OptLocPolicies = { |
|
PlaceObj('AIPolicyTakeCover', nil), |
|
PlaceObj('AIPolicyLosToEnemy', { |
|
'Weight', 300, |
|
}), |
|
PlaceObj('AIPolicyWeaponRange', { |
|
'Weight', 10, |
|
'RangeMin', 10, |
|
'RangeMax', 25, |
|
}), |
|
PlaceObj('AIPolicyWeaponRange', { |
|
'Weight', 20, |
|
'RangeMin', 26, |
|
'RangeMax', 49, |
|
}), |
|
PlaceObj('AIPolicyWeaponRange', { |
|
'RangeMin', 50, |
|
'RangeMax', 100, |
|
}), |
|
}, |
|
OptLocSearchRadius = 80, |
|
PrefStance = "Crouch", |
|
SignatureActions = { |
|
PlaceObj('AIActionHeavyWeaponAttack', { |
|
'BiasId', "PierreGuardLauncherFire", |
|
'Weight', 1000, |
|
'OnActivationBiases', { |
|
PlaceObj('AIBiasModification', { |
|
'BiasId', "PierreGuardLauncherFire", |
|
'Effect', "disable", |
|
'Period', 10, |
|
}), |
|
PlaceObj('AIBiasModification', { |
|
'BiasId', "PierreGuardLauncherFire", |
|
'Effect', "disable", |
|
'Value', -50, |
|
'Period', 10, |
|
'ApplyTo', "Team", |
|
}), |
|
}, |
|
'self_score_mod', -1000, |
|
'min_score', 100, |
|
'MinDist', 5000, |
|
}), |
|
}, |
|
TargetScoreRandomization = 10, |
|
group = "Lieutenants", |
|
id = "PierreGuard", |
|
}) |
|
|
|
PlaceObj('AIArchetype', { |
|
BaseMovementWeight = 10, |
|
Behaviors = { |
|
PlaceObj('StandardAI', { |
|
'BiasId', "Standard", |
|
'Weight', 80, |
|
'EndTurnPolicies', { |
|
PlaceObj('AIPolicyTakeCover', { |
|
'Weight', 50, |
|
'visibility_mode', "team", |
|
}), |
|
PlaceObj('AIPolicyDealDamage', { |
|
'Weight', 400, |
|
}), |
|
}, |
|
}), |
|
PlaceObj('StandardAI', { |
|
'Fallback', false, |
|
'EndTurnPolicies', { |
|
PlaceObj('AIPolicyDealDamage', nil), |
|
}, |
|
'SignatureActions', { |
|
PlaceObj('AIAttackSingleTarget', { |
|
'BiasId', "Autofire", |
|
'Weight', 70, |
|
'Priority', true, |
|
'NotificationText', "", |
|
'action_id', "AutoFire", |
|
'AttackTargeting', set( "Torso" ), |
|
}), |
|
}, |
|
}), |
|
}, |
|
Comment = "basic flank and attack AI", |
|
OptLocPolicies = { |
|
PlaceObj('AIPolicyWeaponRange', { |
|
'Weight', 600, |
|
'RangeBase', "Absolute", |
|
'RangeMin', 4, |
|
'RangeMax', 8, |
|
}), |
|
PlaceObj('AIPolicyHighGround', { |
|
'Weight', 30, |
|
}), |
|
PlaceObj('AIPolicyLosToEnemy', nil), |
|
}, |
|
OptLocSearchRadius = 80, |
|
PrefStance = "Crouch", |
|
SignatureActions = { |
|
PlaceObj('AIAttackSingleTarget', { |
|
'BiasId', "Autofire", |
|
'Weight', 70, |
|
'OnActivationBiases', { |
|
PlaceObj('AIBiasModification', { |
|
'BiasId', "Autofire", |
|
'Value', -500, |
|
'Period', 2, |
|
}), |
|
}, |
|
'NotificationText', "", |
|
'action_id', "AutoFire", |
|
'Aiming', "Remaining AP", |
|
'AttackTargeting', set( "Torso" ), |
|
}), |
|
PlaceObj('AIActionThrowGrenade', { |
|
'BiasId', "WildThrowGrenade", |
|
'Weight', 300, |
|
'Priority', true, |
|
'OnActivationBiases', { |
|
PlaceObj('AIBiasModification', { |
|
'BiasId', "WildThrowGrenade", |
|
'Effect', "disable", |
|
'Value', -300, |
|
'Period', 0, |
|
}), |
|
}, |
|
'team_score', 0, |
|
'self_score_mod', -1000, |
|
'AllowedAoeTypes', set( "fire", "none", "teargas", "toxicgas" ), |
|
}), |
|
}, |
|
TargetingPolicies = { |
|
PlaceObj('AITargetingCancelShot', { |
|
'Weight', 80, |
|
}), |
|
}, |
|
group = "Lieutenants", |
|
id = "TheMajor", |
|
}) |
|
|
|
PlaceObj('AIArchetype', { |
|
BaseAttackTargeting = set( "Torso" ), |
|
BaseAttackWeight = 50, |
|
BaseMovementWeight = 0, |
|
Behaviors = { |
|
PlaceObj('HoldPositionAI', { |
|
'BiasId', "HoldPositionBehavior", |
|
'EndTurnPolicies', { |
|
PlaceObj('AIPolicyDealDamage', nil), |
|
}, |
|
'SignatureActions', { |
|
PlaceObj('AIAttackSingleTarget', { |
|
'BiasId', "LegShot", |
|
'Weight', 120, |
|
'OnActivationBiases', { |
|
PlaceObj('AIBiasModification', { |
|
'BiasId', "LegShot", |
|
'Effect', "disable", |
|
}), |
|
PlaceObj('AIBiasModification', { |
|
'BiasId', "DefensiveOverwatch", |
|
'Effect', "priority", |
|
'Period', 0, |
|
}), |
|
}, |
|
'Aiming', "Remaining AP", |
|
'AttackTargeting', set( "Legs" ), |
|
}), |
|
PlaceObj('AIAttackSingleTarget', { |
|
'BiasId', "ArmShot", |
|
'Weight', 120, |
|
'OnActivationBiases', { |
|
PlaceObj('AIBiasModification', { |
|
'BiasId', "ArmShot", |
|
'Effect', "disable", |
|
}), |
|
PlaceObj('AIBiasModification', { |
|
'BiasId', "DefensiveOverwatch", |
|
'Effect', "priority", |
|
'Period', 0, |
|
}), |
|
}, |
|
'Aiming', "Remaining AP", |
|
'AttackTargeting', set( "Groin" ), |
|
}), |
|
PlaceObj('AIConeAttack', { |
|
'BiasId', "DefensiveOverwatch", |
|
'Weight', 10, |
|
'team_score', 0, |
|
'min_score', 100, |
|
'action_id', "Overwatch", |
|
}), |
|
}, |
|
'TakeCoverChance', 0, |
|
}), |
|
}, |
|
OptLocPolicies = { |
|
PlaceObj('AIPolicyWeaponRange', { |
|
'RangeMin', 25, |
|
'RangeMax', 100, |
|
}), |
|
PlaceObj('AIPolicyLosToEnemy', nil), |
|
}, |
|
OptLocSearchRadius = 80, |
|
PrefStance = "Crouch", |
|
group = "Lieutenants", |
|
id = "TurretBoss", |
|
}) |
|
|
|
PlaceObj('AIArchetype', { |
|
Behaviors = { |
|
PlaceObj('StandardAI', { |
|
'EndTurnPolicies', { |
|
PlaceObj('AIPolicyDealDamage', { |
|
'CheckLOS', false, |
|
}), |
|
}, |
|
}), |
|
}, |
|
MoveStance = "Crouch", |
|
OptLocPolicies = { |
|
PlaceObj('AIPolicyWeaponRange', { |
|
'RangeBase', "Absolute", |
|
'RangeMin', 20, |
|
'RangeMax', 50, |
|
}), |
|
}, |
|
OptLocSearchRadius = 80, |
|
PrefStance = "Crouch", |
|
SignatureActions = { |
|
PlaceObj('AIActionHeavyWeaponAttack', { |
|
'BiasId', "MortarShot", |
|
'Priority', true, |
|
'OnActivationBiases', { |
|
PlaceObj('AIBiasModification', { |
|
'BiasId', "MortarShot", |
|
'Effect', "disable", |
|
}), |
|
}, |
|
'team_score', 0, |
|
'self_score_mod', 0, |
|
'MinDist', 12000, |
|
'action_id', "Bombard", |
|
}), |
|
}, |
|
TargetScoreRandomization = 10, |
|
group = "Simplified", |
|
id = "Artillery", |
|
}) |
|
|
|
PlaceObj('AIArchetype', { |
|
BaseAttackTargeting = set( "Neck", "Torso" ), |
|
BaseMovementWeight = 10, |
|
Behaviors = { |
|
PlaceObj('StandardAI', { |
|
'EndTurnPolicies', { |
|
PlaceObj('AIPolicyDealDamage', nil), |
|
}, |
|
'TakeCoverChance', 0, |
|
}), |
|
}, |
|
Comment = "Keywords: Explosives", |
|
OptLocPolicies = { |
|
PlaceObj('AIPolicyWeaponRange', { |
|
'RangeBase', "Melee", |
|
'RangeMin', 0, |
|
'RangeMax', 6, |
|
}), |
|
PlaceObj('AIPolicyLosToEnemy', nil), |
|
}, |
|
OptLocSearchRadius = 80, |
|
SignatureActions = { |
|
PlaceObj('AIActionMobileShot', { |
|
'Priority', true, |
|
'NotificationText', "", |
|
'RequiredKeywords', { |
|
"RunAndGun", |
|
}, |
|
'action_id', "RunAndGun", |
|
}), |
|
PlaceObj('AIActionMobileShot', { |
|
'Priority', true, |
|
'NotificationText', "", |
|
'RequiredKeywords', { |
|
"MobileShot", |
|
}, |
|
}), |
|
PlaceObj('AIActionThrowGrenade', { |
|
'BiasId', "StunGrenade", |
|
'OnActivationBiases', { |
|
PlaceObj('AIBiasModification', { |
|
'BiasId', "StunGrenade", |
|
'Effect', "disable", |
|
}), |
|
}, |
|
'RequiredKeywords', { |
|
"Explosives", |
|
}, |
|
'min_score', 100, |
|
'MinDist', 3000, |
|
'AllowedAoeTypes', set( "fire", "none", "teargas", "toxicgas" ), |
|
}), |
|
PlaceObj('AIActionThrowGrenade', { |
|
'BiasId', "Nova", |
|
'Weight', 300, |
|
'OnActivationBiases', { |
|
PlaceObj('AIBiasModification', { |
|
'BiasId', "Nova", |
|
'Effect', "disable", |
|
}), |
|
}, |
|
'RequiredKeywords', { |
|
"Nova", |
|
}, |
|
'team_score', 0, |
|
'self_score_mod', 100, |
|
'MinDist', 0, |
|
'MaxDist', 3000, |
|
'AllowedAoeTypes', set( "fire", "none", "teargas", "toxicgas" ), |
|
}), |
|
}, |
|
TargetChangePolicy = "restart", |
|
TargetScoreRandomization = 10, |
|
group = "Simplified", |
|
id = "Brute", |
|
}) |
|
|
|
PlaceObj('AIArchetype', { |
|
BaseAttackTargeting = set( "Torso" ), |
|
Behaviors = { |
|
PlaceObj('StandardAI', { |
|
'EndTurnPolicies', { |
|
PlaceObj('AIPolicyDealDamage', { |
|
'Weight', 1000, |
|
}), |
|
PlaceObj('AIPolicyWeaponRange', { |
|
'RangeMin', 30, |
|
'RangeMax', 80, |
|
}), |
|
}, |
|
'SignatureActions', { |
|
PlaceObj('AIActionMGSetup', { |
|
'Priority', true, |
|
'team_score', 0, |
|
'min_score', 100, |
|
'cur_zone_mod', 140, |
|
}), |
|
PlaceObj('AIActionMGBurstFire', { |
|
'AttackTargeting', set( "Torso" ), |
|
}), |
|
}, |
|
'TakeCoverChance', 0, |
|
'override_attack_id', "BurstFire", |
|
'override_cost_id', "MGSetup", |
|
}), |
|
}, |
|
OptLocPolicies = { |
|
PlaceObj('AIPolicyWeaponRange', { |
|
'Weight', 600, |
|
'RangeMin', 40, |
|
'RangeMax', 80, |
|
}), |
|
PlaceObj('AIPolicyLosToEnemy', { |
|
'Weight', 200, |
|
}), |
|
}, |
|
OptLocSearchRadius = 80, |
|
PrefStance = "Prone", |
|
TargetScoreRandomization = 10, |
|
TargetingPolicies = { |
|
PlaceObj('AITargetingEnemyHealth', { |
|
'Health', 50, |
|
'AboveHealth', true, |
|
}), |
|
PlaceObj('AITargetingEnemyWeapon', nil), |
|
PlaceObj('AITargetingEnemyWeapon', { |
|
'EnemyWeapon', "SMG", |
|
}), |
|
PlaceObj('AITargetingEnemyWeapon', { |
|
'EnemyWeapon', "Shotgun", |
|
}), |
|
}, |
|
group = "Simplified", |
|
id = "HeavyGunner", |
|
}) |
|
|
|
PlaceObj('AIArchetype', { |
|
BaseAttackTargeting = set( "Arms", "Torso" ), |
|
BaseAttackWeight = 80, |
|
BaseMovementWeight = 10, |
|
Behaviors = { |
|
PlaceObj('StandardAI', { |
|
'BiasId', "Standard", |
|
'EndTurnPolicies', { |
|
PlaceObj('AIPolicyDealDamage', { |
|
'Weight', 20, |
|
}), |
|
PlaceObj('AIPolicyTakeCover', { |
|
'visibility_mode', "team", |
|
}), |
|
PlaceObj('AIPolicyWeaponRange', { |
|
'RangeMin', 60, |
|
'RangeMax', 100, |
|
}), |
|
}, |
|
'SignatureActions', { |
|
PlaceObj('AIActionMobileShot', { |
|
'Priority', true, |
|
'NotificationText', "", |
|
}), |
|
}, |
|
'TakeCoverChance', 50, |
|
}), |
|
PlaceObj('StandardAI', { |
|
'BiasId', "Healer", |
|
'Priority', true, |
|
'Fallback', false, |
|
'Score', function (self, unit, proto_context, debug_data) |
|
for _, ally in ipairs(unit.team.units) do |
|
if not ally:IsDead() and ally.HitPoints < MulDivRound(ally.MaxHitPoints, 70, 100) then |
|
return self.Weight |
|
end |
|
end |
|
return 0 |
|
end, |
|
'turn_phase', "Late", |
|
'OptLocWeight', 1, |
|
'EndTurnPolicies', { |
|
PlaceObj('AIPolicyHealingRange', { |
|
'Weight', 300, |
|
'CanUseMod', 1000, |
|
}), |
|
}, |
|
'SignatureActions', { |
|
PlaceObj('AIActionBandage', { |
|
'Priority', true, |
|
'RequiredKeywords', { |
|
"Heal", |
|
}, |
|
'CanUseMod', 1000, |
|
}), |
|
PlaceObj('AIActionStim', { |
|
'Priority', true, |
|
'RequiredKeywords', { |
|
"Stim", |
|
}, |
|
'TargetRules', { |
|
PlaceObj('AIStimRule', { |
|
'Keyword', "Flank", |
|
'Weight', 100, |
|
}), |
|
PlaceObj('AIStimRule', { |
|
'Keyword', "Control", |
|
'Weight', 50, |
|
}), |
|
PlaceObj('AIStimRule', { |
|
'Keyword', "Explosives", |
|
'Weight', 50, |
|
}), |
|
PlaceObj('AIStimRule', { |
|
'Keyword', "Ordnance", |
|
'Weight', 50, |
|
}), |
|
PlaceObj('AIStimRule', { |
|
'Keyword', "RunAndGun", |
|
'Weight', 100, |
|
}), |
|
}, |
|
}), |
|
}, |
|
'TakeCoverChance', 0, |
|
}), |
|
}, |
|
OptLocPolicies = { |
|
PlaceObj('AIPolicyTakeCover', { |
|
'visibility_mode', "team", |
|
}), |
|
PlaceObj('AIPolicyLosToEnemy', nil), |
|
}, |
|
OptLocSearchRadius = 80, |
|
PrefStance = "Crouch", |
|
TargetScoreRandomization = 10, |
|
TargetingPolicies = { |
|
PlaceObj('AITargetingCancelShot', { |
|
'Weight', 200, |
|
}), |
|
}, |
|
group = "Simplified", |
|
id = "Medic", |
|
}) |
|
|
|
PlaceObj('AIArchetype', { |
|
BaseAttackTargeting = set( "Arms", "Legs", "Torso" ), |
|
BaseAttackWeight = 10, |
|
BaseMovementWeight = 10, |
|
Behaviors = { |
|
PlaceObj('StandardAI', { |
|
'Weight', 10, |
|
'EndTurnPolicies', { |
|
PlaceObj('AIPolicyDealDamage', nil), |
|
PlaceObj('AIPolicyTakeCover', { |
|
'visibility_mode', "team", |
|
}), |
|
}, |
|
'TakeCoverChance', 50, |
|
}), |
|
PlaceObj('PositioningAI', { |
|
'BiasId', "Flanking", |
|
'Weight', 500, |
|
'Fallback', false, |
|
'RequiredKeywords', { |
|
"Flank", |
|
}, |
|
'OptLocWeight', 20, |
|
'EndTurnPolicies', { |
|
PlaceObj('AIPolicyFlanking', { |
|
'Weight', 1000, |
|
'Required', true, |
|
'ReserveAttackAP', true, |
|
}), |
|
PlaceObj('AIPolicyDealDamage', nil), |
|
}, |
|
'TakeCoverChance', 0, |
|
'VoiceResponse', "AIFlanking", |
|
}), |
|
}, |
|
Comment = "Keywords: Flank, Explosives", |
|
OptLocPolicies = { |
|
PlaceObj('AIPolicyWeaponRange', { |
|
'Weight', 300, |
|
'RangeBase', "Absolute", |
|
'RangeMin', 2, |
|
'RangeMax', 8, |
|
}), |
|
PlaceObj('AIPolicyLosToEnemy', nil), |
|
}, |
|
OptLocSearchRadius = 80, |
|
PrefStance = "Crouch", |
|
SignatureActions = { |
|
PlaceObj('AIActionMobileShot', { |
|
'Priority', true, |
|
'NotificationText', "", |
|
'RequiredKeywords', { |
|
"RunAndGun", |
|
}, |
|
'action_id', "RunAndGun", |
|
}), |
|
PlaceObj('AIActionMobileShot', { |
|
'Priority', true, |
|
'NotificationText', "", |
|
'RequiredKeywords', { |
|
"MobileShot", |
|
}, |
|
}), |
|
PlaceObj('AIActionThrowGrenade', { |
|
'BiasId', "AssaultGrenadeThrow", |
|
'Weight', 200, |
|
'OnActivationBiases', { |
|
PlaceObj('AIBiasModification', { |
|
'BiasId', "AssaultGrenadeThrow", |
|
'Effect', "disable", |
|
}), |
|
PlaceObj('AIBiasModification', { |
|
'BiasId', "AssaultGrenadeThrow", |
|
'Value', -50, |
|
'Period', 0, |
|
'ApplyTo', "Team", |
|
}), |
|
}, |
|
'RequiredKeywords', { |
|
"Explosives", |
|
}, |
|
'AllowedAoeTypes', set( "fire", "none", "teargas", "toxicgas" ), |
|
}), |
|
}, |
|
TargetScoreRandomization = 10, |
|
TargetingPolicies = { |
|
PlaceObj('AITargetingEnemyHealth', { |
|
'Health', 50, |
|
}), |
|
PlaceObj('AITargetingEnemyWeapon', { |
|
'EnemyWeapon', "Sniper", |
|
}), |
|
}, |
|
group = "Simplified", |
|
id = "Skirmisher", |
|
}) |
|
|
|
PlaceObj('AIArchetype', { |
|
BaseAttackTargeting = set( "Torso" ), |
|
BaseMovementWeight = 10, |
|
Behaviors = { |
|
PlaceObj('StandardAI', { |
|
'BiasId', "Standard", |
|
'Weight', 150, |
|
'EndTurnPolicies', { |
|
PlaceObj('AIPolicyTakeCover', { |
|
'Weight', 50, |
|
'visibility_mode', "team", |
|
}), |
|
PlaceObj('AIPolicyDealDamage', nil), |
|
}, |
|
'TakeCoverChance', 50, |
|
}), |
|
}, |
|
Comment = "Keywords: Soldier, Sniper, Control, Ordnance, Smoke, Explosives", |
|
MoveStance = "Crouch", |
|
OptLocPolicies = { |
|
PlaceObj('AIPolicyTakeCover', { |
|
'Weight', 50, |
|
}), |
|
PlaceObj('AIPolicyHighGround', { |
|
'RequiredKeywords', { |
|
"Sniper", |
|
}, |
|
'Weight', 200, |
|
}), |
|
PlaceObj('AIPolicyLosToEnemy', { |
|
'Weight', 300, |
|
}), |
|
PlaceObj('AIPolicyWeaponRange', { |
|
'Weight', 50, |
|
'RangeMin', 10, |
|
'RangeMax', 25, |
|
}), |
|
PlaceObj('AIPolicyWeaponRange', { |
|
'RangeMin', 26, |
|
'RangeMax', 49, |
|
}), |
|
PlaceObj('AIPolicyWeaponRange', { |
|
'Weight', 150, |
|
'RangeMin', 50, |
|
'RangeMax', 100, |
|
}), |
|
}, |
|
OptLocSearchRadius = 80, |
|
PrefStance = "Crouch", |
|
SignatureActions = { |
|
PlaceObj('AIAttackSingleTarget', { |
|
'BiasId', "Autofire", |
|
'Weight', 150, |
|
'OnActivationBiases', { |
|
PlaceObj('AIBiasModification', { |
|
'BiasId', "Autofire", |
|
'Effect', "disable", |
|
'Period', 0, |
|
'ApplyTo', "Team", |
|
}), |
|
}, |
|
'NotificationText', "", |
|
'RequiredKeywords', { |
|
"Soldier", |
|
}, |
|
'action_id', "AutoFire", |
|
'AttackTargeting', set( "Torso" ), |
|
}), |
|
PlaceObj('AIActionPinDown', { |
|
'BiasId', "PinDownAttack", |
|
'Weight', 80, |
|
'OnActivationBiases', { |
|
PlaceObj('AIBiasModification', { |
|
'BiasId', "PinDownAttack", |
|
'Value', -50, |
|
'ApplyTo', "Team", |
|
}), |
|
}, |
|
'RequiredKeywords', { |
|
"Sniper", |
|
}, |
|
}), |
|
PlaceObj('AIActionThrowGrenade', { |
|
'BiasId', "AssaultGrenadeThrow", |
|
'OnActivationBiases', { |
|
PlaceObj('AIBiasModification', { |
|
'BiasId', "AssaultGrenadeThrow", |
|
'Effect', "disable", |
|
}), |
|
PlaceObj('AIBiasModification', { |
|
'BiasId', "AssaultGrenadeThrow", |
|
'Effect', "disable", |
|
'Period', 0, |
|
'ApplyTo', "Team", |
|
}), |
|
}, |
|
'RequiredKeywords', { |
|
"Explosives", |
|
}, |
|
'self_score_mod', -1000, |
|
'AllowedAoeTypes', set( "fire", "none", "teargas", "toxicgas" ), |
|
}), |
|
PlaceObj('AIActionThrowGrenade', { |
|
'BiasId', "SmokeGrenade", |
|
'OnActivationBiases', { |
|
PlaceObj('AIBiasModification', { |
|
'BiasId', "SmokeGrenade", |
|
'Effect', "disable", |
|
}), |
|
PlaceObj('AIBiasModification', { |
|
'BiasId', "SmokeGrenade", |
|
'Effect', "disable", |
|
'Period', 0, |
|
'ApplyTo', "Team", |
|
}), |
|
}, |
|
'RequiredKeywords', { |
|
"Smoke", |
|
}, |
|
'enemy_score', 0, |
|
'team_score', 100, |
|
'self_score_mod', 100, |
|
'MinDist', 0, |
|
'AllowedAoeTypes', set( "smoke" ), |
|
}), |
|
PlaceObj('AIActionHeavyWeaponAttack', { |
|
'BiasId', "LauncherFire", |
|
'OnActivationBiases', { |
|
PlaceObj('AIBiasModification', { |
|
'BiasId', "LauncherFire", |
|
'Effect', "disable", |
|
'Period', 0, |
|
}), |
|
PlaceObj('AIBiasModification', { |
|
'BiasId', "LauncherFire", |
|
'Value', -50, |
|
'Period', 0, |
|
'ApplyTo', "Team", |
|
}), |
|
}, |
|
'RequiredKeywords', { |
|
"Ordnance", |
|
}, |
|
'self_score_mod', -1000, |
|
'MinDist', 5000, |
|
'LimitRange', true, |
|
'MaxTargetRange', 30, |
|
}), |
|
PlaceObj('AIActionHeavyWeaponAttack', { |
|
'BiasId', "RocketFire", |
|
'Weight', 200, |
|
'OnActivationBiases', { |
|
PlaceObj('AIBiasModification', { |
|
'BiasId', "RocketFire", |
|
'Effect', "disable", |
|
}), |
|
}, |
|
'RequiredKeywords', { |
|
"Ordnance", |
|
}, |
|
'self_score_mod', -1000, |
|
'MinDist', 5000, |
|
'action_id', "RocketLauncherFire", |
|
'LimitRange', true, |
|
'MaxTargetRange', 30, |
|
}), |
|
PlaceObj('AIAttackSingleTarget', { |
|
'BiasId', "GroinShot", |
|
'OnActivationBiases', { |
|
PlaceObj('AIBiasModification', { |
|
'BiasId', "GroinShot", |
|
'Effect', "disable", |
|
'Period', 0, |
|
'ApplyTo', "Team", |
|
}), |
|
PlaceObj('AIBiasModification', { |
|
'BiasId', "GroinShot", |
|
'Effect', "disable", |
|
}), |
|
}, |
|
'RequiredKeywords', { |
|
"Sniper", |
|
}, |
|
'Aiming', "Remaining AP", |
|
'AttackTargeting', set( "Groin" ), |
|
}), |
|
PlaceObj('AIConeAttack', { |
|
'BiasId', "Overwatch", |
|
'OnActivationBiases', { |
|
PlaceObj('AIBiasModification', { |
|
'BiasId', "Overwatch", |
|
'Value', -50, |
|
'ApplyTo', "Team", |
|
}), |
|
PlaceObj('AIBiasModification', { |
|
'BiasId', "Overwatch", |
|
'Effect', "disable", |
|
'Value', -50, |
|
'Period', 2, |
|
}), |
|
}, |
|
'RequiredKeywords', { |
|
"Soldier", |
|
}, |
|
'team_score', 0, |
|
'min_score', 300, |
|
'action_id', "Overwatch", |
|
}), |
|
PlaceObj('AIConeAttack', { |
|
'BiasId', "SpamOverwatch", |
|
'Weight', 200, |
|
'OnActivationBiases', { |
|
PlaceObj('AIBiasModification', { |
|
'BiasId', "SpamOverwatch", |
|
'Effect', "disable", |
|
'Value', -50, |
|
'ApplyTo', "Team", |
|
}), |
|
}, |
|
'RequiredKeywords', { |
|
"Control", |
|
}, |
|
'team_score', 0, |
|
'min_score', 100, |
|
'action_id', "Overwatch", |
|
}), |
|
}, |
|
TargetScoreRandomization = 10, |
|
group = "Simplified", |
|
id = "Soldier", |
|
}) |
|
|
|
PlaceObj('AIArchetype', { |
|
BaseAttackTargeting = set( "Arms", "Legs", "Torso" ), |
|
BaseAttackWeight = 50, |
|
BaseMovementWeight = 0, |
|
Behaviors = { |
|
PlaceObj('HoldPositionAI', { |
|
'BiasId', "HoldPositionBehavior", |
|
'EndTurnPolicies', { |
|
PlaceObj('AIPolicyDealDamage', nil), |
|
}, |
|
'TakeCoverChance', 0, |
|
}), |
|
}, |
|
OptLocPolicies = { |
|
PlaceObj('AIPolicyLosToEnemy', nil), |
|
}, |
|
OptLocSearchRadius = 80, |
|
PrefStance = "Crouch", |
|
SignatureActions = { |
|
PlaceObj('AIAttackSingleTarget', { |
|
'BiasId', "Autofire", |
|
'OnActivationBiases', { |
|
PlaceObj('AIBiasModification', { |
|
'BiasId', "Autofire", |
|
'Effect', "disable", |
|
}), |
|
}, |
|
'NotificationText', "", |
|
'action_id', "AutoFire", |
|
'Aiming', "Remaining AP", |
|
'AttackTargeting', set( "Torso" ), |
|
}), |
|
}, |
|
TargetScoreRandomization = 10, |
|
group = "Simplified", |
|
id = "Turret", |
|
}) |
|
|
|
PlaceObj('AIArchetype', { |
|
Behaviors = { |
|
PlaceObj('StandardAI', { |
|
'EndTurnPolicies', { |
|
PlaceObj('AIPolicyDealDamage', { |
|
'Required', true, |
|
}), |
|
}, |
|
}), |
|
}, |
|
OptLocPolicies = { |
|
PlaceObj('AIPolicyLosToEnemy', { |
|
'Required', true, |
|
}), |
|
PlaceObj('AIPolicyWeaponRange', { |
|
'Required', true, |
|
'RangeBase', "Melee", |
|
'RangeMin', 1, |
|
'RangeMax', 5, |
|
}), |
|
}, |
|
OptLocSearchRadius = 10, |
|
SignatureActions = { |
|
PlaceObj('AIActionBasicAttack', { |
|
'BiasId', "MeleeAttack", |
|
'Priority', true, |
|
}), |
|
PlaceObj('AIActionMGSetup', { |
|
'BiasId', "MGSetup", |
|
'team_score', 0, |
|
'min_score', 100, |
|
'cur_zone_mod', 140, |
|
}), |
|
PlaceObj('AIActionMGBurstFire', { |
|
'BiasId', "MGBurst", |
|
}), |
|
PlaceObj('AIActionBandage', { |
|
'BiasId', "Bandage", |
|
'MaxHp', 90, |
|
'SelfHealMod', 500, |
|
}), |
|
PlaceObj('AIActionHeavyWeaponAttack', { |
|
'BiasId', "RPGFire", |
|
'action_id', "RocketLauncherFire", |
|
}), |
|
PlaceObj('AIActionHeavyWeaponAttack', { |
|
'BiasId', "LauncherFire", |
|
}), |
|
PlaceObj('AIActionHeavyWeaponAttack', { |
|
'BiasId', "MortarShot", |
|
'action_id', "Bombard", |
|
}), |
|
PlaceObj('AIActionMobileShot', { |
|
'BiasId', "RunAndGun", |
|
'NotificationText', "", |
|
'action_id', "RunAndGun", |
|
}), |
|
PlaceObj('AIAttackSingleTarget', { |
|
'BiasId', "SingleShot", |
|
}), |
|
PlaceObj('AIAttackSingleTarget', { |
|
'BiasId', "BurstFire", |
|
'action_id', "BurstFire", |
|
}), |
|
PlaceObj('AIAttackSingleTarget', { |
|
'BiasId', "Autofire", |
|
'NotificationText', "", |
|
'action_id', "AutoFire", |
|
}), |
|
PlaceObj('AIAttackSingleTarget', { |
|
'BiasId', "Buckshot", |
|
'action_id', "Buckshot", |
|
}), |
|
PlaceObj('AIAttackSingleTarget', { |
|
'BiasId', "DoubleBarrel", |
|
'NotificationText', "", |
|
'action_id', "DoubleBarrel", |
|
}), |
|
PlaceObj('AIActionPinDown', { |
|
'BiasId', "PinDown", |
|
}), |
|
PlaceObj('AIConeAttack', { |
|
'BiasId', "Overwatch", |
|
'team_score', 0, |
|
'min_score', 1, |
|
'action_id', "Overwatch", |
|
}), |
|
PlaceObj('AIActionThrowGrenade', { |
|
'BiasId', "FragGrenade", |
|
'team_score', 0, |
|
'AllowedAoeTypes', set( "fire", "none", "teargas", "toxicgas" ), |
|
}), |
|
PlaceObj('AIActionThrowGrenade', { |
|
'BiasId', "SmokeGrenade", |
|
'team_score', 0, |
|
'AllowedAoeTypes', set( "smoke" ), |
|
}), |
|
}, |
|
group = "System", |
|
id = "AITestArchetype", |
|
}) |
|
|
|
PlaceObj('AIArchetype', { |
|
BaseMovementWeight = 10, |
|
Behaviors = { |
|
PlaceObj('StandardAI', { |
|
'Weight', 50, |
|
'EndTurnPolicies', { |
|
PlaceObj('AIPolicyDealDamage', nil), |
|
}, |
|
'TakeCoverChance', 0, |
|
}), |
|
}, |
|
Comment = "morale-related (cloned Assault)", |
|
OptLocPolicies = { |
|
PlaceObj('AIPolicyWeaponRange', { |
|
'Weight', 600, |
|
'RangeBase', "Absolute", |
|
'RangeMin', 4, |
|
'RangeMax', 8, |
|
}), |
|
PlaceObj('AIPolicyLosToEnemy', nil), |
|
}, |
|
OptLocSearchRadius = 80, |
|
PrefStance = "Crouch", |
|
SignatureActions = { |
|
PlaceObj('AIAttackSingleTarget', { |
|
'BiasId', "Autofire", |
|
'Weight', 200, |
|
'NotificationText', "", |
|
'action_id', "AutoFire", |
|
'AttackTargeting', set( "Torso" ), |
|
}), |
|
PlaceObj('AIActionThrowGrenade', { |
|
'BiasId', "AssaultGrenadeThrow", |
|
'AllowedAoeTypes', set( "fire", "none", "teargas", "toxicgas" ), |
|
}), |
|
}, |
|
group = "System", |
|
id = "Berserk", |
|
}) |
|
|
|
PlaceObj('AIArchetype', { |
|
Behaviors = { |
|
PlaceObj('RetreatAI', { |
|
'EndTurnPolicies', { |
|
PlaceObj('AIPolicyTakeCover', { |
|
'Weight', 10, |
|
}), |
|
PlaceObj('AIPolicyLosToEnemy', { |
|
'Weight', 300, |
|
'Invert', true, |
|
}), |
|
PlaceObj('AIRetreatPolicy', { |
|
'Weight', 1000, |
|
'Required', false, |
|
}), |
|
}, |
|
'TakeCoverChance', 0, |
|
}), |
|
}, |
|
Comment = "retreat", |
|
OptLocPolicies = { |
|
PlaceObj('AIRetreatPolicy', nil), |
|
}, |
|
OptLocSearchRadius = 80, |
|
group = "System", |
|
id = "Deserter", |
|
}) |
|
|
|
PlaceObj('AIArchetype', { |
|
Behaviors = { |
|
PlaceObj('ApproachInteractableAI', { |
|
'Comment', "approach/man the selected emplacement", |
|
'Score', function (self, unit, proto_context, debug_data) |
|
local emplacement = g_Combat and g_Combat:GetEmplacementAssignment(unit) |
|
if not emplacement or emplacement.manned_by then |
|
return 0 |
|
end |
|
return self.Weight |
|
end, |
|
'OptLocWeight', 1000, |
|
'TakeCoverChance', 0, |
|
}), |
|
PlaceObj('HoldPositionAI', { |
|
'Comment', "when manning emplacement", |
|
'Score', function (self, unit, proto_context, debug_data) |
|
local emplacement = g_Combat and g_Combat:GetEmplacementAssignment(unit) |
|
if not emplacement or emplacement.manned_by ~= unit then |
|
return 0 |
|
end |
|
return self.Weight |
|
end, |
|
'TakeCoverChance', 0, |
|
}), |
|
}, |
|
OptLocSearchRadius = 80, |
|
group = "System", |
|
id = "EmplacementGunner", |
|
}) |
|
|
|
PlaceObj('AIArchetype', { |
|
Behaviors = { |
|
PlaceObj('CustomAI', { |
|
'EndTurnPolicies', { |
|
PlaceObj('AIPolicyTakeCover', { |
|
'visibility_mode', "team", |
|
}), |
|
}, |
|
'TakeCoverChance', 100, |
|
'EnumDests', function (self, unit, context, debug_data) |
|
if g_TacticalMap then |
|
return g_TacticalMap:EnumDestsInAssignedArea(unit, context) |
|
end |
|
end, |
|
'PickEndTurnPolicies', function (self, unit, context, debug_data) |
|
return AITacticSelectEndTurnPolicies(unit, context) |
|
end, |
|
'PickOptimalLoc', function (self, unit, context, debug_data) |
|
if g_TacticalMap then |
|
return g_TacticalMap:FindOptimalLocationInAssignedArea(unit, context) |
|
end |
|
end, |
|
'PickEndTurnLoc', function (self, unit, context, debug_data) |
|
AITacticCalcPathDistances(unit, context, "disable bias") |
|
|
|
local policies = self:PickEndTurnPolicies(unit, context) or self.EndTurnPolicies |
|
local weight = self.OptLocWeight |
|
if context.optimal_dest_in_assigned_area and context.assigned_area_unreachable then |
|
weight = weight * 10 |
|
end |
|
context.ai_destination = AIScoreReachableVoxels(context, policies, weight, debug_data and debug_data.reachable_scores, "prefer") |
|
return true |
|
end, |
|
'SelectSignatureActions', function (self, unit, context, debug_data) |
|
return AITacticSelectSignatureActions(unit, context) |
|
end, |
|
}), |
|
}, |
|
FallbackAction = "overwatch", |
|
group = "System", |
|
id = "GuardArea", |
|
}) |
|
|
|
PlaceObj('AIArchetype', { |
|
Behaviors = { |
|
PlaceObj('RetreatAI', { |
|
'turn_phase', "Early", |
|
'EndTurnPolicies', { |
|
PlaceObj('AIPolicyTakeCover', { |
|
'Weight', 10, |
|
}), |
|
PlaceObj('AIPolicyLosToEnemy', { |
|
'Weight', 300, |
|
'Invert', true, |
|
}), |
|
PlaceObj('AIPolicyProximity', { |
|
'Weight', 1000, |
|
}), |
|
}, |
|
'TakeCoverChance', 50, |
|
'DespawnAllowed', false, |
|
}), |
|
}, |
|
Comment = "morale-related (based on Deserter)", |
|
OptLocPolicies = { |
|
PlaceObj('AIRetreatPolicy', nil), |
|
}, |
|
OptLocSearchRadius = 100, |
|
group = "System", |
|
id = "Panicked", |
|
}) |
|
|
|
PlaceObj('AIArchetype', { |
|
Behaviors = { |
|
PlaceObj('StandardAI', { |
|
'Priority', true, |
|
'Comment', "breaking pindown", |
|
'Score', function (self, unit, proto_context, debug_data) |
|
local enemies = {} |
|
for _, descr in pairs(g_Pindown) do |
|
if descr.target == self then |
|
enemies[#enemies + 1] = enemy |
|
end |
|
end |
|
return #enemies > 0 and self.Weight or 0 |
|
end, |
|
'EndTurnPolicies', { |
|
PlaceObj('AIPolicyLosToEnemy', { |
|
'Invert', true, |
|
}), |
|
PlaceObj('AIPolicyDealDamage', nil), |
|
}, |
|
'TakeCoverChance', 0, |
|
}), |
|
PlaceObj('StandardAI', { |
|
'Comment', "fallback (aggressive)", |
|
'Fallback', false, |
|
'EndTurnPolicies', { |
|
PlaceObj('AIPolicyDealDamage', { |
|
'Weight', 600, |
|
}), |
|
PlaceObj('AIPolicyWeaponRange', { |
|
'RangeBase', "Absolute", |
|
'RangeMin', 0, |
|
'RangeMax', 5, |
|
}), |
|
}, |
|
'TakeCoverChance', 0, |
|
}), |
|
}, |
|
OptLocPolicies = { |
|
PlaceObj('AIPolicyLosToEnemy', nil), |
|
}, |
|
OptLocSearchRadius = 80, |
|
group = "System", |
|
id = "PinnedDown", |
|
}) |
|
|
|
PlaceObj('AIArchetype', { |
|
BaseMovementWeight = 10, |
|
Behaviors = { |
|
PlaceObj('StandardAI', { |
|
'TakeCoverChance', 0, |
|
}), |
|
}, |
|
Comment = "used to advance toward last known enemy location", |
|
OptLocPolicies = { |
|
PlaceObj('AIPolicyLastEnemyPos', nil), |
|
}, |
|
OptLocSearchRadius = 80, |
|
group = "System", |
|
id = "Scout_LastLocation", |
|
}) |
|
|
|
PlaceObj('AIArchetype', { |
|
Behaviors = { |
|
PlaceObj('StandardAI', { |
|
'EndTurnPolicies', { |
|
PlaceObj('AIPolicyDealDamage', { |
|
'Weight', 600, |
|
}), |
|
PlaceObj('AIPolicyTakeCover', { |
|
'visibility_mode', "team", |
|
}), |
|
}, |
|
'TakeCoverChance', 0, |
|
}), |
|
}, |
|
OptLocPolicies = { |
|
PlaceObj('AIPolicyTakeCover', nil), |
|
PlaceObj('AIPolicyWeaponRange', { |
|
'Weight', 600, |
|
'RangeMin', 25, |
|
'RangeMax', 50, |
|
}), |
|
}, |
|
OptLocSearchRadius = 80, |
|
group = "Tutorial", |
|
id = "TutorialMinion", |
|
}) |
|
|
|
|