[modding] questions regarding modding combat services

I am getting my hands dirty into modding, and decided to try one that involved scripts.

in this particular case, I am trying to give a range advantage to archers which has higher grounds and similar penalty to archers which have lower grounds.
(theoretically, it is possible that given enough height, the archer on lower ground will never be able to hit the archer at higher ground. e.g. near vertical trajectory that the higher archer just have to drop an arrow without using bow to damage!!! lol just an example)

Anyway I tried the following, but could not be sure if it works, as although I think the range is increased, somehow it seemed to have increased the range of kobold archers at lower ground (tested at heights between 1-2 floors, i.e. 6-12 tiles). And sometimes, even when the enemy should be within range (used a large range bonus for testing), my archers aren’t attacking. (but could be ai?)

Would like to request help from veteran modders to see if I am doing things right.
Here is what I did:

in manifest.json

{
   "info" :{
      "name" : "Combat Tweak",
      "version" : 2
   },
    "overrides": {
      "stonehearth/services/server/combat/combat_service.lua" : "file(services/server/combat/combat_service_override.lua)"
   }
}

my copy of combat_service_override.lua is a copy of the original combat_service.lua except for added lines to a function (I tried to refactor it so that the modification is an insertion, and in one single chunk, so that it would be easier to maintain in future)

changed function from combat_service.lua

function CombatService:in_range(attacker, target, weapon)
   local attacker_location = attacker:add_component('mob'):get_world_grid_location()
   local target_location = target:add_component('mob'):get_world_grid_location()
   local distance = attacker_location:distance_to(target_location)
   local range = self:get_weapon_range(attacker, weapon)
   
   -- mod: range tweak begin
   local height_diff = attacker_location.y - target_location.y
   local range_bonus_per_unit_height = 2
   local height_range_bonus = height_diff * range_bonus_per_unit_height
   -- range checking range. pun not intended.
   local max_height_range_bonus = 0.5 * range 
     -- for now, 50% of weapon. by right, it should be computed using gravity 
     -- and projectile movement resistance.
   local min_height_range_bonus = - range 
     -- i.e. effective range == 0. could have used a small positive number 
     -- if we allow attacker to directly poke his opponent with the arrow.
   if height_range_bonus > max_height_range_bonus then
       height_range_bonus = max_height_range_bonus
   end
   if height_range_bonus < min_height_range_bonus then
       height_range_bonus = min_height_range_bonus
   end
    -- apply range bonus/penalty   
   range = range + height_range_bonus      
   -- mod: range tweak end   
      
    local result = distance <= range
   return result
end

Thanks in advance!

Take a look at ai/actions/combat/move_to_targetable_location_action.lua and ai/actions/combat/combat_idle_kite_action.lua. Those initially popped out because both call CombatService:get_weapon_range. But upon closer inspection move_to_targetable_location_action.lua has a competing definition of in_range_and_has_line_of_sight():

-- This code must match the implementation of combat_service:in_range_and_has_line_of_sight()
-- or we risk having ai spins.
function MoveToTargetableLocation:_in_range_and_has_line_of_sight( ... )

At the very least you’ll need to call or duplicate CombatServices:in_range(), because as it is in_range here is basically distance <= weapon_range.

I didn’t really look too closely at combat_idle_kite_action.lua, but the end of this comment seems relevant :wink:

-- Subtract one to make sure we stay inside range and don't invoke
-- pathfinding on next attack. TODO: compensate for elevation difference
1 Like