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 @@ -