-
April 04, 2015, 04:20 AM
#1
Foederatus
Help needed on idea to stop AI defenders from counter attacking
The defending AI in most battles sets up a very good defensive position, usually on a hill, only to abandon it in immediate counter attack - even before the attackers reach the prepared defences! Not only is this unrealistic it makes it too easy for the player because the AI has thrown away its defensive advantage.
I believe this behaviour is triggered in the BAI by the attacker/defender ratio of missile superiority, which seems very low. The logic behind this is to stop the defenders standing inert under missile fire. But it actually makes more sense for the defenders to hold their position and hunker down behind their shields than to abandon the hill in a charge towards a superior enemy. The battle of Hastings would have been over in 5 minutes if Harold had done this!
I understand the BAI in Attila cant be modded directly as one could do in medieval 2. But what if the type/category of missile units could be altered so the BAI perceives them as say a light melee unit so it doesn't factor them into its missile superiority equation. This would have to focus on the designation of a missile unit without affecting its behaviour.
A tall order I know but could any of you experienced modders suggest how I could achieve this?
-
April 04, 2015, 01:07 PM
#2
Re: Help needed on idea to stop AI defenders from counter attacking
I would be interested in something like this. The days of skirmishing are gone, even with equal skirmishers. As soon as mine get in range their entire army rambo charges me.
Its even worse when you use onagers in your armies.
The possibility of this depends on whether or not the AI triggers its charges by ranged units coming in range or by any units coming in range. I've never tested. They are far more aggressive in this game than in past games.
The unit type/weights/ranged weapons and stuff like that are controlled by the land_units table and main_units table. I'm not sure what effect it would have to change a ranged unit to a melee category while still giving them a proper ranged weapon, but let me know how it turns out.
-
April 05, 2015, 12:52 PM
#3
Foederatus
Re: Help needed on idea to stop AI defenders from counter attacking
Thanks Murderin, I'll start some experiments when the Easter family stuff is over and let you know the results.
I also want to find a way to stop the AI from using run most of the time. This is unrealistic and makes it easier for the player - large formations of men need to march to maintain cohesion and save their strength. The AI even uses run when altering its army formation, imagine the chaos if that happened in real life! So if you or anyone else knows a way to change the default AI move to walk please let me know.
Last edited by JamesL; April 05, 2015 at 12:54 PM.
-
April 05, 2015, 01:24 PM
#4
Re: Help needed on idea to stop AI defenders from counter attacking
That is something CA will have to change most likely. They almost never walk anywhere, which is strange behavior given the huge changes to fatigue in this game.
The most you can do is reduce the fatigue rate of running in the kv_fatigue table. I'm no expert on AI behavior though, so it may be possible to change the triggers for what they do during a battle.
-
April 06, 2015, 03:07 AM
#5
Foederatus
Re: Help needed on idea to stop AI defenders from counter attacking
Experiment results: in land_units_tables/land_units I changed the category and class of all missile units into melee units. Then I played a battle - result: absolutely no change in the premature charge behaviour of the defenders and no change in the ui designation of the altered missile units.
Next I attacked with just melee units and the defenders did hold their position and only charge at the last moment. So if the AI could perceive missile units as non-missile units then the defenders may just stay on the hill.
Back to the drawing board...
Last edited by JamesL; April 06, 2015 at 03:11 AM.
-
April 06, 2015, 12:26 PM
#6
Re: Help needed on idea to stop AI defenders from counter attacking
I'll have a look through some more tables and see if I can figure it out. I will edit if so.
So in land_units as you already figured out we have class, category, and attributes, which determines what abilities the unit has.
In main_units we have the unknown37 column, I'm not sure what it is. But it has references to unit types.
This is probably the key table, unit_set_to_unit_junctions. I'm not sure how I missed it, but it sets the unit to a specific category.
Let me know how those work out.
Last edited by Murderin; April 06, 2015 at 12:58 PM.
-
April 08, 2015, 04:10 AM
#7
Foederatus
Re: Help needed on idea to stop AI defenders from counter attacking
Thanks Murderin - I changed the missile unit designation to sword units in column 37 - It did change the missile unit UI icons and titles but alas the AI still perceived them as missile units and charged off the hill abandoning their prepared defences ect ect. But I'm sure the key to stopping this behaviour is in there somewhere....
-
May 16, 2015, 03:20 PM
#8
Re: Help needed on idea to stop AI defenders from counter attacking
You can edit the battle.script in Script/lib/lib_battlemanager.lua and you can change also the routing or attacking behaviour under the ROUTE MANAGER (all the way down, f.e. change the 2,5 in any number you like agressive or passive units behaviour.
This is the subroutine for routing you are looking for:
-- rout manager performs its internal check
function battle_manager:check_rout_manager()
local alliances = self:alliances();
local non_routing_enemy_units = num_units_routing(alliances:item(2));
local non_routing_allied_units = num_units_routing(alliances:item(1));
if non_routing_enemy_units < self.rout_threshold and non_routing_allied_units > non_routing_enemy_units * 2.5 then
return true;
end;
return false;
end;
The rest of the script is in lib_script_ai_planner.lua. Here you can change all kinds of attackoptions, active behaviour, distance, time between attacks and reorder attacks, create your own booleans and callbacks, etc, etc. The Ai is scripted to attack every 15 seconds if a platoon still has units left and status standing around its reorderd at 30 secs. You can changes this to 45 seconds by "reorder_interval"=45000 f.e. Note : This will slow down the whole battle btw. The defending units probably attack because there attitude changes from defend to attack based on the number of units they face, which is calculated by their own units and allied units (same force;self) within their radius compared to the units of you/player they are facing. I will look further into that.
Greetz
T
Last edited by OpusDei; May 16, 2015 at 04:36 PM.
-
May 16, 2015, 06:14 PM
#9
Re: Help needed on idea to stop AI defenders from counter attacking
This routine seems to let the defenders go out 25 mtrs from their initial (pos, radius) starting defending point before returning back to ther inital pos/radios/nil/vector. Maybe you can lower this too f.e. 15 mtrs and see the effect.
Routine:
Name "function script_ai_planner:defend_position_of_sunit(sunit, radius, rout_callback, internal)"
Context:
-- watch for our target unit moving and update if it moves too far away from our current destination
self.bm:watch(
function()
return sunit.unit:position():distance(self.current_dest) > 25
end,
0,
function()
self:defend_position_action(sunit.unit:position(), radius)
end,
self.name
 
;
Last edited by OpusDei; May 16, 2015 at 06:43 PM.
-
May 16, 2015, 03:46 PM
#10
Re: Help needed on idea to stop AI defenders from counter attacking
Very nice indeed
-
May 16, 2015, 04:44 PM
#11
Re: Help needed on idea to stop AI defenders from counter attacking
This is the subroutine that changes the defenders into attackers:
function script_ai_planner:attack_force(enemy_force, reorder, defend_radius)
-- should we attack or actually defend
local function_name = "attack_force()";
local should_defend = false; ****** If true; defenders defend QQ
if is_number(defend_radius) and defend_radius > 0 then
function_name = "defend_force()";
should_defend = true
end;
if not is_table(enemy_force) then
script_error(self.name .. " ERROR: " .. function_name .. " called but supplied force [" .. tostring(enemy_force) .. "] is not a table!");
return false;
end;
-- check that we have some non-routing units to order
if is_routing_or_dead(self.sunit_list) then
if (self.is_debug or __script_ai_planner_debug) then
self.bm:out(self.name .. ":" .. function_name .. " called but all controlled units are routing, doing nothing");
return;
end;
end;
-- get closest enemy
local closest_enemy = nil;
local closest_enemy_dist = 5000;
for i = 1, #enemy_force do
local curr_enemy_sunit = enemy_force[i];
if is_scriptunit(curr_enemy_sunit) then
if not is_routing_or_dead(curr_enemy_sunit.unit) then
local closest_standing_unit = get_closest_standing_unit(self.sunit_list, curr_enemy_sunit.unit:position());
if closest_standing_unit then
local curr_enemy_sunit_dist = closest_standing_unit:position():distance(curr_enemy_sunit.unit:position());
if curr_enemy_sunit_dist < closest_enemy_dist then
closest_enemy = curr_enemy_sunit;
closest_enemy_dist = curr_enemy_sunit_dist;
end;
end;
end;
else
script_error(self.name .. " ERROR: " .. function_name .. " called but item " .. i .. " [" .. tostring(curr_enemy_sunit) .. " ] of supplied force [" .. tostring(enemy_force) .. "] is not a scriptunit!");
return false;
end;
end;
-- only give the order if we have a valid target
if closest_enemy then
-- if we're rescanning, only re-order if our target has changed
if reorder and self.current_target == closest_enemy then
-- reorder every so often, so that we continually home on the nearest target
self.bm:callback(
function()
if self:any_controlled_sunit_standing() then
self:attack_force(enemy_force, true, defend_radius);
end;
end,
self.attack_force_reorder_interval,
self.name
 
;
return;
end;
self.bm:remove_process(self.name);
-- reorder every so often, so that we continually home on the nearest target
self.bm:callback(function() self:attack_force(enemy_force, true, defend_radius) end, self.attack_force_reorder_interval, self.name);
self.enemy_force = enemy_force;
self.current_target = closest_enemy;
if (self.is_debug or __script_ai_planner_debug) then
if reorder then
if should_defend then
self.bm:out(self.name .. " defend_force() now defending closest target " .. closest_enemy.name .. " at " .. v_to_s(closest_enemy.unit:position()));
else
self.bm:out(self.name .. " attack_force() now targeting closest enemy " .. closest_enemy.name .. " at " .. v_to_s(closest_enemy.unit:position()));
end;
else
if should_defend then
self.bm:out(self.name .. " defend_force() called, defending closest target " .. closest_enemy.name .. " at " .. v_to_s(closest_enemy.unit:position()));
else
self.bm:out(self.name .. " attack_force() called, targeting closest enemy " .. closest_enemy.name .. " at " .. v_to_s(closest_enemy.unit:position()));
end;
end;
end;
-- give the order itself
if should_defend then ****** True; defenders defend QQ
self.current_order = SCRIPT_AI_PLANNER_DEFEND_FORCE;
self:defend_position_of_sunit(closest_enemy, defend_radius, nil, true);
else
self.current_order = SCRIPT_AI_PLANNER_ATTACK_FORCE;
self:move_to_position_of_sunit(closest_enemy, nil, false, true);
end;
-- watch for target unit routing
self.bm:watch(
function()
return is_routing_or_dead(closest_enemy.unit)
end,
0,
function()
self:attack_force(enemy_force, true, defend_radius);
end,
self.name
 
;
elseif (self.is_debug or __script_ai_planner_debug) then
self.bm:out(self.name .. ":attack_force() called but couldn't find any non-routing targets!");
end;
end;
*********
Then to make things worse the script AI_Planner_Defend_force is set to attack (subroutine 10):
"
function script_ai_planner:defend_force(enemy_force, radius) self:attack_force(enemy_force, false, radius);
end;
"
So this seems on purpose by the programmer!
Last edited by OpusDei; May 16, 2015 at 06:39 PM.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules