Files
fs2open.github.com/code/weapon/flak.cpp
T
Goober5000 4797ce55a2 use vm_vector_2_matrix_norm on normalized vectors
Most places in the code that use `vm_vector_2_matrix` do so on already-normalized vectors.  Changing these to `vm_vector_2_matrix_norm` avoids redundant normalization.
2025-03-02 23:07:09 -05:00

139 lines
3.8 KiB
C++

/*
* Copyright (C) Volition, Inc. 1999. All rights reserved.
*
* All source code herein is the property of Volition, Inc. You may not sell
* or otherwise commercially exploit the source or things you created based on the
* source.
*
*/
#include "object/object.h"
#include "weapon/flak.h"
#include "weapon/muzzleflash.h"
// --------------------------------------------------------------------------------------------------------------------------------------
// FLAK FUNCTIONS
//
/**
* Initialize flak stuff for the level
*/
void flak_level_init()
{
}
/**
* Close down flak stuff
*/
void flak_level_close()
{
}
/**
* Given a just fired flak shell, pick a detonating distance for it
*/
void flak_pick_range(object *objp, const vec3d * /*firing_pos*/, const vec3d *predicted_target_pos, float weapon_subsys_strength)
{
float final_range;
float det_range;
vec3d temp;
// make sure this flak object is valid
Assert(objp->type == OBJ_WEAPON);
Assert(objp->instance >= 0);
Assert(Weapons[objp->instance].weapon_info_index >= 0);
Assert(Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Flak]);
weapon_info* wip = &Weapon_info[Weapons[objp->instance].weapon_info_index];
// get the range to the target
vm_vec_sub(&temp, &objp->pos, predicted_target_pos);
final_range = vm_vec_mag(&temp);
//Is it larger than det_range?
det_range = wip->det_range;
if(det_range != 0.0f && final_range > det_range)
{
flak_set_range(objp, det_range);
return;
}
// add in some randomness
float random_range = ((wip->flak_detonation_accuracy + (wip->flak_detonation_accuracy * 0.65f * (1.0f - weapon_subsys_strength))) * frand_range(-1.0f, 1.0f));
final_range += random_range;
// make sure we're firing at least 10 meters away, or the weapons' arm distance if one was defined.
if (wip->arm_dist > 0.0f) {
if(final_range < wip->arm_dist){
final_range = wip->arm_dist;
}
} else {
if (final_range < 10.0f) {
final_range = 10.0f;
}
}
// set the range
flak_set_range(objp, final_range);
}
/**
* Add some jitter to a flak gun's aiming direction, take into account range to target so that we're never _too_ far off
* assumes dir is normalized
*/
void flak_jitter_aim(vec3d *dir, float dist_to_target, float weapon_subsys_strength, const weapon_info *wip)
{
vec3d rand_twist_pre, rand_twist_post;
matrix temp;
vec3d final_aim;
float error_val;
// get the matrix needed to rotate the base direction to the actual direction
vm_vector_2_matrix_norm(&temp, dir, nullptr, nullptr);
// error value
error_val = wip->flak_targeting_accuracy + (wip->flak_targeting_accuracy * 0.65f * (1.0f - weapon_subsys_strength));
// scale the rvec by some random value and make it the "pre-twist" value
float rand_dist = frand_range(0.0f, error_val);
// no jitter - so do nothing
if(rand_dist <= 0.0f){
return;
}
vm_vec_copy_scale(&rand_twist_pre, &temp.vec.rvec, rand_dist);
// now rotate the twist vector around the x axis (the base aim axis) at a random angle
vm_rot_point_around_line(&rand_twist_post, &rand_twist_pre, fl_radians(359.0f * frand_range(0.0f, 1.0f)), &vmd_zero_vector, dir);
// add the resulting vector to the base aim vector and normalize
final_aim = *dir;
vm_vec_scale(&final_aim, dist_to_target);
vm_vec_add(dir, &final_aim, &rand_twist_post);
vm_vec_normalize(dir);
}
/**
* Given a just fired flak shell, pick a detonating distance for it
*/
void flak_set_range(object *objp, float range)
{
Assert(objp->type == OBJ_WEAPON);
Assert(objp->instance >= 0);
// setup the flak info
Weapons[objp->instance].det_range = range;
}
/**
* Get the current range for the flak object
*/
float flak_get_range(object *objp)
{
Assert(objp->type == OBJ_WEAPON);
Assert(objp->instance >= 0);
return Weapons[objp->instance].det_range;
}