diff --git a/lua/drill.lua b/lua/drill.lua
deleted file mode 100644
index 95fba5d..0000000
--- a/lua/drill.lua
+++ /dev/null
@@ -1,32 +0,0 @@
--- Make autorepair reroll everytime the drill is jammed and fix swapped values
-Hooks:PreHook(Drill, "set_jammed", "shc_set_jammed", function(self, jammed)
- if Network:is_server() and jammed and not self._jammed then
- local current_auto_repair_level_1 = self._skill_upgrades.auto_repair_level_1 or 0
- local current_auto_repair_level_2 = self._skill_upgrades.auto_repair_level_2 or 0
- local drill_autorepair_chance = 0
-
- if current_auto_repair_level_1 > 0 then
- drill_autorepair_chance = drill_autorepair_chance + tweak_data.upgrades.values.player.drill_autorepair_1[1]
- end
- if current_auto_repair_level_2 > 0 then
- drill_autorepair_chance = drill_autorepair_chance + tweak_data.upgrades.values.player.drill_autorepair_2[1]
- end
-
- self:set_autorepair(math.random() < drill_autorepair_chance, true)
- end
-end)
-
--- Reduce time it takes for autorepair to kick in
-function Drill:set_autorepair(state, jammed)
- self._autorepair = state
-
- if self._autorepair_clbk_id then
- managers.enemy:remove_delayed_clbk(self._autorepair_clbk_id)
- self._autorepair_clbk_id = nil
- end
-
- if state and (self._jammed or jammed) then
- self._autorepair_clbk_id = "Drill_autorepair" .. tostring(self._unit:key())
- managers.enemy:add_delayed_clbk(self._autorepair_clbk_id, callback(self, self, "clbk_autorepair"), TimerManager:game():time() + 5 + 5 * math.random())
- end
-end
diff --git a/lua/raycastweaponbase.lua b/lua/raycastweaponbase.lua
index 7ede047..5a26007 100644
--- a/lua/raycastweaponbase.lua
+++ b/lua/raycastweaponbase.lua
@@ -29,6 +29,11 @@ local mvec_to = Vector3()
local mvec_right_ax = Vector3()
local mvec_up_ay = Vector3()
local mvec_spread_direction = Vector3()
+local mvec3_norm = mvector3.normalize
+local mvec3_set = mvector3.set
+local mvec3_mul = mvector3.multiply
+local mvec3_add = mvector3.add
+local math_clamp = math.clamp
-- lower damage on shield pen
function RaycastWeaponBase:_fire_raycast(user_unit, from_pos, direction, dmg_mul, shoot_player, spread_mul, autohit_mul, suppr_mul)
@@ -43,54 +48,56 @@ function RaycastWeaponBase:_fire_raycast(user_unit, from_pos, direction, dmg_mul
spread_mul = spread_mul or 1
mvector3.cross(mvec_right_ax, direction, math.UP)
- mvector3.normalize(mvec_right_ax)
+ mvec3_norm(mvec_right_ax)
mvector3.cross(mvec_up_ay, direction, mvec_right_ax)
- mvector3.normalize(mvec_up_ay)
- mvector3.set(mvec_spread_direction, direction)
+ mvec3_norm(mvec_up_ay)
+ mvec3_set(mvec_spread_direction, direction)
local theta = math.random() * 360
- mvector3.multiply(mvec_right_ax, math.rad(math.sin(theta) * math.random() * spread_x * spread_mul))
- mvector3.multiply(mvec_up_ay, math.rad(math.cos(theta) * math.random() * spread_y * spread_mul))
- mvector3.add(mvec_spread_direction, mvec_right_ax)
- mvector3.add(mvec_spread_direction, mvec_up_ay)
- mvector3.set(mvec_to, mvec_spread_direction)
- mvector3.multiply(mvec_to, ray_distance)
- mvector3.add(mvec_to, from_pos)
+ mvec3_mul(mvec_right_ax, math.rad(math.sin(theta) * math.random() * spread_x * spread_mul))
+ mvec3_mul(mvec_up_ay, math.rad(math.cos(theta) * math.random() * spread_y * spread_mul))
+ mvec3_add(mvec_spread_direction, mvec_right_ax)
+ mvec3_add(mvec_spread_direction, mvec_up_ay)
+ mvec3_set(mvec_to, mvec_spread_direction)
+ mvec3_mul(mvec_to, ray_distance)
+ mvec3_add(mvec_to, from_pos)
- local ray_hits, hit_enemy = self:_collect_hits(from_pos, mvec_to)
- local auto_hit_candidate, suppression_enemies = self:check_autoaim(from_pos, direction)
+ local ray_hits, hit_enemy, enemies_hit = self:_collect_hits(from_pos, mvec_to)
- if suppression_enemies and self._suppression then
- result.enemies_in_cone = suppression_enemies
- end
-
- if self._autoaim then
+ if self._autoaim and self._autohit_data then
local weight = 0.1
- if auto_hit_candidate and not hit_enemy then
- local autohit_chance = 1 - math.clamp((self._autohit_current - self._autohit_data.MIN_RATIO) / (self._autohit_data.MAX_RATIO - self._autohit_data.MIN_RATIO), 0, 1)
+ if hit_enemy then
+ self._autohit_current = (self._autohit_current + weight) / (1 + weight)
+ else
+ local auto_hit_candidate, enemies_to_suppress = self:check_autoaim(from_pos, direction, nil, nil, nil, true)
+ result.enemies_in_cone = enemies_to_suppress or false
- if autohit_mul then
- autohit_chance = autohit_chance * autohit_mul
- end
+ if auto_hit_candidate then
+ local autohit_chance = self:get_current_autohit_chance_for_roll()
- if math.random() < autohit_chance then
- self._autohit_current = (self._autohit_current + weight) / (1 + weight)
+ if autohit_mul then
+ autohit_chance = autohit_chance * autohit_mul
+ end
+
+ if math.random() < autohit_chance then
+ self._autohit_current = (self._autohit_current + weight) / (1 + weight)
- mvector3.set(mvec_spread_direction, auto_hit_candidate.ray)
- mvector3.set(mvec_to, mvec_spread_direction)
- mvector3.multiply(mvec_to, ray_distance)
- mvector3.add(mvec_to, from_pos)
+ mvec3_set(mvec_spread_direction, auto_hit_candidate.ray)
+ mvec3_set(mvec_to, mvec_spread_direction)
+ mvec3_mul(mvec_to, ray_distance)
+ mvec3_add(mvec_to, from_pos)
- ray_hits, hit_enemy = self:_collect_hits(from_pos, mvec_to)
+ ray_hits, hit_enemy, enemies_hit = self:_collect_hits(from_pos, mvec_to)
+ end
end
- end
- if hit_enemy then
- self._autohit_current = (self._autohit_current + weight) / (1 + weight)
- elseif auto_hit_candidate then
- self._autohit_current = self._autohit_current / (1 + weight)
+ if hit_enemy then
+ self._autohit_current = (self._autohit_current + weight) / (1 + weight)
+ elseif auto_hit_candidate then
+ self._autohit_current = self._autohit_current / (1 + weight)
+ end
end
end
@@ -115,7 +122,9 @@ function RaycastWeaponBase:_fire_raycast(user_unit, from_pos, direction, dmg_mul
end
if dmg > 0 then
- local hit_result = self._bullet_class:on_collision(hit, self._unit, user_unit, dmg)
+ local hit_result = self:bullet_class():on_collision(hit, self._unit, user_unit, dmg)
+ hit_through_wall = hit_through_wall or hit.unit:in_slot(self.wall_mask)
+ hit_through_shield = hit_through_shield or hit.unit:in_slot(self.shield_mask) and alive(hit.unit:parent())
if hit_result then
hit.damage_result = hit_result
@@ -123,17 +132,15 @@ function RaycastWeaponBase:_fire_raycast(user_unit, from_pos, direction, dmg_mul
hit_count = hit_count + 1
if hit_result.type == "death" then
- local unit_type = hit.unit:base() and hit.unit:base()._tweak_table
+ local unit_base = hit.unit:base()
+ local unit_type = unit_base and unit_base._tweak_table
local is_civilian = unit_type and is_civ_f(unit_type)
if not is_civilian then
cop_kill_count = cop_kill_count + 1
end
- hit_through_wall = hit_through_wall or hit.unit:in_slot(self.wall_mask)
- hit_through_shield = hit_through_shield or hit.unit:in_slot(self.shield_mask) and alive(hit.unit:parent())
-
- self:_check_kill_achievements(cop_kill_count, unit_type, is_civilian, hit_through_wall, hit_through_shield)
+ self:_check_kill_achievements(cop_kill_count, unit_base, unit_type, is_civilian, hit_through_wall, hit_through_shield)
end
end
end
@@ -147,7 +154,7 @@ function RaycastWeaponBase:_fire_raycast(user_unit, from_pos, direction, dmg_mul
self._shot_fired_stats_table.hit = hit_anyone
self._shot_fired_stats_table.hit_count = hit_count
- if (not self._ammo_data or not self._ammo_data.ignore_statistic) and not self._rays then
+ if not self._ammo_data or not self._ammo_data.ignore_statistic then
managers.statistics:shot_fired(self._shot_fired_stats_table)
end
end
@@ -156,12 +163,28 @@ function RaycastWeaponBase:_fire_raycast(user_unit, from_pos, direction, dmg_mul
if (not furthest_hit or furthest_hit.distance > 600) and alive(self._obj_fire) then
self._obj_fire:m_position(self._trail_effect_table.position)
- mvector3.set(self._trail_effect_table.normal, mvec_spread_direction)
+ mvec3_set(self._trail_effect_table.normal, mvec_spread_direction)
local trail = World:effect_manager():spawn(self._trail_effect_table)
if furthest_hit then
- World:effect_manager():set_remaining_lifetime(trail, math.clamp((furthest_hit.distance - 600) / 10000, 0, furthest_hit.distance))
+ World:effect_manager():set_remaining_lifetime(trail, math_clamp((furthest_hit.distance - 600) / 10000, 0, furthest_hit.distance))
+ end
+ end
+
+ if result.enemies_in_cone == nil then
+ result.enemies_in_cone = self._suppression and self:check_suppression(from_pos, direction, enemies_hit) or nil
+ elseif enemies_hit and self._suppression then
+ result.enemies_in_cone = result.enemies_in_cone or {}
+ local all_enemies = managers.enemy:all_enemies()
+
+ for u_key, enemy in pairs(enemies_hit) do
+ if all_enemies[u_key] then
+ result.enemies_in_cone[u_key] = {
+ error_mul = 1,
+ unit = enemy
+ }
+ end
end
end
@@ -191,7 +214,9 @@ function RaycastWeaponBase.collect_hits(from, to, setup_data)
hit_enemy = hit.unit:in_slot(enemy_mask)
end
- return ray_hits, hit_enemy
+ return ray_hits, hit_enemy, hit_enemy and {
+ [hit.unit:key()] = hit.unit
+ } or nil
end
local can_shoot_through_wall = setup_data.can_shoot_through_wall
@@ -208,31 +233,41 @@ function RaycastWeaponBase.collect_hits(from, to, setup_data)
ray_hits = World:raycast_all("ray", from, to, "slot_mask", bullet_slotmask, "ignore_unit", ignore_unit)
end
- local units_hit = {}
local unique_hits = {}
+ local enemies_hit = {}
+ local unit, u_key, is_enemy = nil
+ local units_hit = {}
+ local in_slot_func = Unit.in_slot
+ local has_ray_type_func = Body.has_ray_type
for i, hit in ipairs(ray_hits) do
- if not units_hit[hit.unit:key()] then
- units_hit[hit.unit:key()] = true
+ unit = hit.unit
+ u_key = unit:key()
+
+ if not units_hit[u_key] then
+ units_hit[u_key] = true
unique_hits[#unique_hits + 1] = hit
hit.hit_position = hit.position
- hit_enemy = hit_enemy or hit.unit:in_slot(enemy_mask)
- local weak_body = hit.body:has_ray_type(ai_vision_ids)
- weak_body = weak_body or hit.body:has_ray_type(bulletproof_ids)
+ is_enemy = in_slot_func(unit, enemy_mask)
+
+ if is_enemy then
+ enemies_hit[u_key] = unit
+ hit_enemy = true
+ end
- if not can_shoot_through_enemy and hit_enemy then
+ if not can_shoot_through_enemy and is_enemy then
break
- elseif not can_shoot_through_wall and hit.unit:in_slot(wall_mask) and weak_body then
+ elseif not can_shoot_through_shield and in_slot_func(unit, shield_mask) then
break
- elseif not can_shoot_through_shield and hit.unit:in_slot(shield_mask) then
+ elseif not can_shoot_through_wall and in_slot_func(unit, wall_mask) and (has_ray_type_func(hit.body, ai_vision_ids) or has_ray_type_func(hit.body, bulletproof_ids)) then
break
- elseif hit.unit:in_slot(shield_mask) and (hit.unit:name():key() == "af254947f0288a6c" or hit.unit:name():key() == "15cbabccf0841ff8") and not can_shoot_through_titan_shield then -- hi thanks resmod if you're reading this :)
+ elseif hit.unit:in_slot(shield_mask) and (hit.unit:name():key() == "af254947f0288a6c" or hit.unit:name():key() == "15cbabccf0841ff8") then -- hi thanks resmod if you're reading this :)
break
end
end
end
- return unique_hits, hit_enemy
+ return unique_hits, hit_enemy, hit_enemy and enemies_hit or nil
end
-- Auto Fire Sound Fix
diff --git a/supermod.xml b/supermod.xml
index c5e7057..2e27228 100644
--- a/supermod.xml
+++ b/supermod.xml
@@ -198,7 +198,6 @@
-