Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion code/weapon/weapon.h
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,7 @@ float weapon_get_lifetime_pct(const weapon& wp);
float weapon_get_age(const weapon& wp);
float weapon_get_viewing_angle(const weapon& wp);
float weapon_get_apparent_size(const weapon& wp);
float weapon_get_target_dot(const weapon& wp);

float beam_get_warmup_lifetime_pct(const beam& wp);
float beam_get_warmdown_lifetime_pct(const beam& wp);
Expand Down Expand Up @@ -798,7 +799,8 @@ struct weapon_info
>{}},
std::pair {"Parent Radius", modular_curves_submember_input<&weapon::objnum, &Objects, &object::parent, &Objects, &object::radius>{}},
std::pair {"Viewing Angle", modular_curves_functional_input<weapon_get_viewing_angle>{}},
std::pair {"Apparent Size", modular_curves_functional_input<weapon_get_apparent_size>{}}
std::pair {"Apparent Size", modular_curves_functional_input<weapon_get_apparent_size>{}},
std::pair {"Dot To Target", modular_curves_functional_input<weapon_get_target_dot>{}}
);

public:
Expand Down
21 changes: 21 additions & 0 deletions code/weapon/weapons.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10283,4 +10283,25 @@ float weapon_get_apparent_size(const weapon& wp) {
wep_objp->radius * 2.0f,
g3_get_hfov(Eye_fov),
gr_screen.max_w) / i2fl(gr_screen.max_w);
}

float weapon_get_target_dot(const weapon& wp) {
object* wep_objp = &Objects[wp.objnum];

vec3d target_pos;

if(wp.homing_object != &obj_used_list && (wp.homing_object->type != 0))
{
if (!IS_VEC_NULL(&wp.homing_pos)) {
target_pos = wp.homing_pos;
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure how this could happen, but if homing_object is valid but IS_VEC_NULL(&wp.homing_pos) is true, the inner if body is skipped, target_pos is never assigned, and the function eventually hits vm_vec_sub with bad data. Could fix this by adding an else return 0.f, IE

     } else {
            return 0.f;
        }

} else if(wp.target_num > -1)
{
target_pos = Objects[wp.target_num].pos;
} else {
return 0.f;
}
vec3d dir;
vm_vec_sub(&dir, &wep_objp->pos, &target_pos);
Copy link
Copy Markdown
Member

@wookieejedi wookieejedi Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should dir be normalized? I think vm_vec_dot on an unnormalized `dir gives a distance-scaled projection, which seems like that isn't the intent? Normalizing before the dot would fix this I reckon...IE

vm_vec_normalize(&dir);
return vm_vec_dot(&dir, &wep_objp->orient.vec.fvec);
``

Copy link
Copy Markdown
Member

@wookieejedi wookieejedi Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description says dot product between the vector that points toward the current target and the weapon's forward vector. Just want to check, are these in the right order? I think dir = weapon - target points away from the target not towards it (so switching to target_pos - wep_objp->pos` would face torwards) but perhaps someone with better dot math can chime in. @Baezon perhaps :D

return vm_vec_dot(&dir, &wep_objp->orient.vec.fvec);
}
Loading