feat: 360-degree omni marking option
- omni_mark: full-sphere sweep (linear_sphere_sweep capsule covering max_range around the player) replaces the forward-only ping raycast, so enemies behind you / off-screen become mark candidates - omni_mark_ignore_los: optional sub-toggle, skips line-of-sight checks entirely - prefer nearest unit on score ties (sweep hit order is arbitrary) - bypass FOV dot gate in is_target_pingable when omni_mark is on - LOS check budget 10 -> 16 per frame
This commit is contained in:
@@ -72,6 +72,8 @@ local mod_settings = {
|
||||
focus_target_switch_override_manual = mod:get("focus_target_switch_override_manual") or false,
|
||||
focus_target_switch_melee = mod:get("focus_target_switch_melee") or false,
|
||||
focus_target_switch_range = mod:get("focus_target_switch_range") or false,
|
||||
omni_mark = mod:get("omni_mark") or false,
|
||||
omni_mark_ignore_los = mod:get("omni_mark_ignore_los") or false,
|
||||
}
|
||||
mod.settings = mod_settings
|
||||
if mod:get("capacitance_retention_elite_threshold_negative_zero") then
|
||||
|
||||
@@ -169,6 +169,18 @@ local widgets = {
|
||||
type = "checkbox",
|
||||
default_value = false
|
||||
},
|
||||
{
|
||||
setting_id = "omni_mark",
|
||||
type = "checkbox",
|
||||
default_value = false,
|
||||
sub_widgets = {
|
||||
{
|
||||
setting_id = "omni_mark_ignore_los",
|
||||
type = "checkbox",
|
||||
default_value = false,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -57,6 +57,26 @@ local localization = {
|
||||
["zh-cn"] = "调试模式",
|
||||
["zh-tw"] = "除錯模式",
|
||||
},
|
||||
omni_mark = {
|
||||
en = "360° Marking",
|
||||
["zh-cn"] = "全向标记",
|
||||
["zh-tw"] = "全向標記",
|
||||
},
|
||||
omni_mark_tooltip = {
|
||||
en = "Find mark targets in all directions, including off-screen enemies behind you, instead of only under the crosshair.",
|
||||
["zh-cn"] = "向所有方向寻找标记目标,包括屏幕外和身后的敌人,而不再仅限准星下方。",
|
||||
["zh-tw"] = "向所有方向尋找標記目標,包括螢幕外和身後的敵人,而不再僅限準星下方。",
|
||||
},
|
||||
omni_mark_ignore_los = {
|
||||
en = "Ignore Line of Sight",
|
||||
["zh-cn"] = "忽略视线",
|
||||
["zh-tw"] = "忽略視線",
|
||||
},
|
||||
omni_mark_ignore_los_tooltip = {
|
||||
en = "Mark enemies even without a clear line of sight (through walls).",
|
||||
["zh-cn"] = "即使没有清晰视线也能标记敌人(穿墙)。",
|
||||
["zh-tw"] = "即使沒有清晰視線也能標記敵人(穿牆)。",
|
||||
},
|
||||
-- arbites settings
|
||||
adamant_settings = {
|
||||
en = "Arbites Settings",
|
||||
|
||||
@@ -53,13 +53,14 @@ local INDEX_NORMAL = 3
|
||||
local INDEX_ACTOR = 4
|
||||
local COLLISION_FILTER = "filter_player_ping_target_selection"
|
||||
local EMPTY_TABLE = {}
|
||||
local MAX_VISIBILITY_CHECKS_PER_FRAME = 10
|
||||
local MAX_VISIBILITY_CHECKS_PER_FRAME = 16
|
||||
local VIEW_CHECK_MIN_DISTANCE = 3
|
||||
local VIEW_CHECK_MIN_DOT = 0.75
|
||||
local AIM_CHECK_FILTER = "filter_player_ping_target_selection"
|
||||
local AIM_CHECK_MAX_HITS = 64
|
||||
local AIM_CHECK_MIN_RADIUS = 1
|
||||
local AIM_CHECK_RADIUS_PER_METER = 0.052
|
||||
local OMNI_MAX_HITS = 128
|
||||
|
||||
-- Params
|
||||
local visibility_raycast_object = nil
|
||||
@@ -524,7 +525,7 @@ function mod:is_target_pingable(target_unit)
|
||||
local forward = Vector3_flat(Quaternion_forward(first_person_component.rotation))
|
||||
local dot = Vector3_dot(Vector3_normalize(forward), Vector3_normalize(to_target))
|
||||
if dot < VIEW_CHECK_MIN_DOT then
|
||||
return false
|
||||
return mod_settings.omni_mark == true
|
||||
end
|
||||
|
||||
local first_person_extension = ScriptUnit_extension(player_unit, "first_person_system")
|
||||
@@ -578,9 +579,16 @@ function mod:find_auto_mark_target_unit(min_range, max_range, tag_name, tag_cont
|
||||
return
|
||||
end
|
||||
|
||||
-- raycast for hit unit list
|
||||
-- hit unit list: forward raycast, or full-sphere sweep when omni mark is enabled
|
||||
local omni_mark = mod_settings.omni_mark
|
||||
local ray_origin, forward, right, up = smart_targeting_extension:_targeting_parameters()
|
||||
local hits, num_hits = PhysicsWorld_raycast(smart_targeting_extension._physics_world, ray_origin, forward, max_range, "all", "collision_filter", COLLISION_FILTER)
|
||||
local hits, num_hits, hits_use_actor
|
||||
if omni_mark then
|
||||
hits, num_hits = PhysicsWorld_linear_sphere_sweep(smart_targeting_extension._physics_world, ray_origin, ray_origin + forward * max_range, max_range, OMNI_MAX_HITS, "types", "both", "collision_filter", COLLISION_FILTER, "report_initial_overlap", true)
|
||||
hits_use_actor = true
|
||||
else
|
||||
hits, num_hits = PhysicsWorld_raycast(smart_targeting_extension._physics_world, ray_origin, forward, max_range, "all", "collision_filter", COLLISION_FILTER)
|
||||
end
|
||||
|
||||
if not hits or num_hits <= 0 then
|
||||
return
|
||||
@@ -624,9 +632,11 @@ function mod:find_auto_mark_target_unit(min_range, max_range, tag_name, tag_cont
|
||||
local best_unit_is_dormant_daemonhost = false
|
||||
local best_unit_marked_by_execution_order = false
|
||||
local best_unit_is_sticky_targeting = false
|
||||
local best_unit_distance = math.huge
|
||||
local marked_unit = marked_tag and marked_tag._target_unit
|
||||
if marked_unit then
|
||||
best_unit = marked_unit
|
||||
best_unit_distance = Vector3_length(Unit_world_position(best_unit, 1) - ray_origin)
|
||||
local best_unit_data_extension = ScriptUnit_extension(best_unit, "unit_data_system")
|
||||
local best_unit_breed_data = best_unit_data_extension and best_unit_data_extension._breed
|
||||
best_unit_breed_name = best_unit_breed_data and best_unit_breed_data.name
|
||||
@@ -640,7 +650,7 @@ function mod:find_auto_mark_target_unit(min_range, max_range, tag_name, tag_cont
|
||||
|
||||
for i = 1, num_hits do
|
||||
local hit = hits[i]
|
||||
local hit_actor = hit[INDEX_ACTOR]
|
||||
local hit_actor = hits_use_actor and hit.actor or hit[INDEX_ACTOR]
|
||||
if not hit_actor then
|
||||
goto continue
|
||||
end
|
||||
@@ -695,7 +705,7 @@ function mod:find_auto_mark_target_unit(min_range, max_range, tag_name, tag_cont
|
||||
best_unit_score = best_unit_score + (best_unit_is_attacking_player and 100 or 0)
|
||||
end
|
||||
|
||||
if hit_unit_score <= best_unit_score then
|
||||
if hit_unit_score < best_unit_score then
|
||||
goto continue
|
||||
end
|
||||
|
||||
@@ -707,6 +717,11 @@ function mod:find_auto_mark_target_unit(min_range, max_range, tag_name, tag_cont
|
||||
goto continue
|
||||
end
|
||||
|
||||
-- prefer the closer unit on score ties (hit order is arbitrary for the omni sweep)
|
||||
if hit_unit_score == best_unit_score and distance >= best_unit_distance then
|
||||
goto continue
|
||||
end
|
||||
|
||||
local hit_unit_tag = smart_tag_system:unit_tag(hit_unit)
|
||||
if tag_name == TAG_NAMES.ENEMY_TAG then
|
||||
if hit_unit_tag then
|
||||
@@ -733,7 +748,9 @@ function mod:find_auto_mark_target_unit(min_range, max_range, tag_name, tag_cont
|
||||
end
|
||||
|
||||
local visible
|
||||
if tag_name == TAG_NAMES.SERVO_SKULL_TAG then
|
||||
if omni_mark and mod_settings.omni_mark_ignore_los then
|
||||
visible = true
|
||||
elseif tag_name == TAG_NAMES.SERVO_SKULL_TAG then
|
||||
visible = is_servo_skull_target_visible(companion_position, hit_unit, fixed_frame)
|
||||
elseif tag_name == TAG_NAMES.COMPANION_TAG then
|
||||
local half_height = Breed_height(hit_unit, hit_unit_breed_data) * 0.5
|
||||
@@ -755,6 +772,7 @@ function mod:find_auto_mark_target_unit(min_range, max_range, tag_name, tag_cont
|
||||
best_unit_is_dormant_daemonhost = hit_unit_is_dormant_daemonhost
|
||||
best_unit_marked_by_execution_order = hit_unit_marked_by_execution_order
|
||||
best_unit_is_sticky_targeting = false
|
||||
best_unit_distance = distance
|
||||
|
||||
::continue::
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user