Skip to content

Commit 66d9335

Browse files
authored
Weapon launch curves (#6732)
* it's broken and i don't like it * it's fixed and i approve * add multi support maybe * appease clang * appease clang ii: electric boogaloo * const refs * increment multi version
1 parent b3c3627 commit 66d9335

File tree

9 files changed

+176
-50
lines changed

9 files changed

+176
-50
lines changed

code/ai/aiturret.cpp

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "weapon/muzzleflash.h"
2727
#include "weapon/swarm.h"
2828
#include "weapon/weapon.h"
29+
#include "utils/modular_curves.h"
2930

3031
#include <climits>
3132

@@ -1549,22 +1550,26 @@ bool turret_should_pick_new_target(ship_subsys *turret)
15491550
/**
15501551
* Set the next fire timestamp for a turret, based on weapon type and ai class
15511552
*/
1552-
void turret_set_next_fire_timestamp(int weapon_num, const weapon_info *wip, ship_subsys *turret, const ai_info *aip)
1553+
void turret_set_next_fire_timestamp(int weapon_num, const weapon_info *wip, ship_subsys *turret, const ai_info *aip, const WeaponLaunchCurveData& launch_curve_data)
15531554
{
15541555
Assert(weapon_num < MAX_SHIP_WEAPONS);
15551556
float wait = 1000.0f;
15561557
// should subtract 1 from firepoints to match behavior of wip->burst_shots
15571558
int burst_shots = (wip->burst_flags[Weapon::Burst_Flags::Num_firepoints_burst_shots] ? turret->system_info->turret_num_firing_points - 1 : wip->burst_shots);
1559+
burst_shots = fl2i(i2fl(burst_shots) * wip->weapon_launch_curves.get_output(weapon_info::WeaponLaunchCurveOutputs::BURST_SHOTS_MULT, launch_curve_data));
15581560

15591561
if (burst_shots > turret->weapons.burst_counter[weapon_num]) {
15601562
wait *= wip->burst_delay;
1563+
wait *= wip->weapon_launch_curves.get_output(weapon_info::WeaponLaunchCurveOutputs::BURST_DELAY_MULT, launch_curve_data);
15611564
turret->weapons.burst_counter[weapon_num]++;
15621565
} else {
15631566
// Random fire delay (DahBlount) used in ship_fire_primary(), added here by wookieejedi to correct oversight
15641567
if (wip->max_delay != 0.0f && wip->min_delay != 0.0f) {
15651568
wait *= frand_range(wip->min_delay, wip->max_delay);
1569+
wait *= wip->weapon_launch_curves.get_output(weapon_info::WeaponLaunchCurveOutputs::FIRE_WAIT_MULT, launch_curve_data);
15661570
} else {
15671571
wait *= wip->fire_wait;
1572+
wait *= wip->weapon_launch_curves.get_output(weapon_info::WeaponLaunchCurveOutputs::FIRE_WAIT_MULT, launch_curve_data);
15681573
}
15691574
if ((burst_shots > 0) && (wip->burst_flags[Weapon::Burst_Flags::Random_length])) {
15701575
turret->weapons.burst_counter[weapon_num] = Random::next(burst_shots);
@@ -1690,7 +1695,15 @@ void turret_update_enemy_in_range(ship_subsys *turret, float seconds)
16901695
/**
16911696
* Fire a weapon from a turret
16921697
*/
1693-
bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum, const vec3d *orig_firing_pos, const vec3d *orig_firing_vec, const vec3d *predicted_pos = nullptr, float flak_range_override = 100.0f, bool play_sound = true)
1698+
bool turret_fire_weapon(int weapon_num,
1699+
ship_subsys *turret,
1700+
int parent_objnum,
1701+
const WeaponLaunchCurveData& launch_curve_data,
1702+
const vec3d *orig_firing_pos,
1703+
const vec3d *orig_firing_vec,
1704+
const vec3d *predicted_pos = nullptr,
1705+
float flak_range_override = 100.0f,
1706+
bool play_sound = true)
16941707
{
16951708
matrix firing_orient;
16961709
int weapon_objnum;
@@ -1790,7 +1803,7 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
17901803

17911804
// set next fire timestamp for the turret
17921805
if (last_shot_in_salvo)
1793-
turret_set_next_fire_timestamp(weapon_num, wip, turret, parent_aip);
1806+
turret_set_next_fire_timestamp(weapon_num, wip, turret, parent_aip, launch_curve_data);
17941807

17951808
// if this weapon is a beam weapon, handle it specially
17961809
if (wip->wi_flags[Weapon::Info_Flags::Beam]) {
@@ -1875,7 +1888,8 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
18751888
}
18761889
// now do anything else
18771890
else {
1878-
for (int i = 0; i < wip->shots; i++) {
1891+
int shots = fl2i(i2fl(wip->shots) * wip->weapon_launch_curves.get_output(weapon_info::WeaponLaunchCurveOutputs::SHOTS_MULT, launch_curve_data));
1892+
for (int i = 0; i < shots; i++) {
18791893
if (!in_lab && turret->system_info->flags[Model::Subsystem_Flags::Turret_use_ammo]) {
18801894
int bank_to_fire, num_slots = turret->system_info->turret_num_firing_points;
18811895
if (wip->subtype == WP_LASER) {
@@ -1971,7 +1985,7 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
19711985
// so we need to get the position info separately for each shot
19721986
ship_get_global_turret_gun_info(&Objects[parent_objnum], turret, &firing_pos_buf, false, nullptr, true, nullptr);
19731987

1974-
weapon_objnum = weapon_create(firing_pos, &firing_orient, turret_weapon_class, parent_objnum, -1, 1, 0, 0.0f, turret);
1988+
weapon_objnum = weapon_create(firing_pos, &firing_orient, turret_weapon_class, parent_objnum, -1, true, false, 0.0f, turret, launch_curve_data);
19751989
weapon_set_tracking_info(weapon_objnum, parent_objnum, turret->turret_enemy_objnum, 1, turret->targeted_subsys);
19761990

19771991
//nprintf(("AI", "Turret_time_enemy_in_range = %7.3f\n", ss->turret_time_enemy_in_range));
@@ -2033,9 +2047,9 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
20332047
subsys_index = ship_get_subsys_index(turret);
20342048
Assert( subsys_index != -1 );
20352049
if(wip->wi_flags[Weapon::Info_Flags::Flak]){
2036-
send_flak_fired_packet( parent_objnum, subsys_index, weapon_objnum, flak_range );
2050+
send_flak_fired_packet( parent_objnum, subsys_index, weapon_objnum, flak_range, launch_curve_data.distance_to_target );
20372051
} else {
2038-
send_turret_fired_packet( parent_objnum, subsys_index, weapon_objnum );
2052+
send_turret_fired_packet( parent_objnum, subsys_index, weapon_objnum, launch_curve_data.distance_to_target );
20392053
}
20402054
}
20412055

@@ -2105,8 +2119,13 @@ void turret_swarm_fire_from_turret(turret_swarm_info *tsi)
21052119
// make firing_orient from turret_fvec -- turret->turret_last_fire_direction
21062120
vm_vector_2_matrix_norm(&firing_orient, &turret_fvec, nullptr, nullptr);
21072121

2122+
auto launch_curve_data = WeaponLaunchCurveData {
2123+
tsi->turret->system_info->turret_num_firing_points,
2124+
0.f,
2125+
};
2126+
21082127
// create weapon and homing info
2109-
weapon_objnum = weapon_create(&turret_pos, &firing_orient, tsi->weapon_class, tsi->parent_objnum, -1, 1, 0, 0.0f, tsi->turret);
2128+
weapon_objnum = weapon_create(&turret_pos, &firing_orient, tsi->weapon_class, tsi->parent_objnum, -1, true, false, 0.0f, tsi->turret, launch_curve_data);
21102129
weapon_set_tracking_info(weapon_objnum, tsi->parent_objnum, tsi->target_objnum, 1, tsi->target_subsys);
21112130

21122131
// do other cool stuff if weapon is created.
@@ -2157,7 +2176,7 @@ void turret_swarm_fire_from_turret(turret_swarm_info *tsi)
21572176

21582177
subsys_index = ship_get_subsys_index(tsi->turret);
21592178
Assert( subsys_index != -1 );
2160-
send_turret_fired_packet( tsi->parent_objnum, subsys_index, weapon_objnum );
2179+
send_turret_fired_packet( tsi->parent_objnum, subsys_index, weapon_objnum, 0.f);
21612180
}
21622181
}
21632182
}
@@ -2325,6 +2344,12 @@ void ai_turret_execute_behavior(const ship *shipp, ship_subsys *ss)
23252344

23262345
float turret_barrel_length = -1.0f;
23272346

2347+
// grab the data for the launch curve inputs
2348+
auto launch_curve_data = WeaponLaunchCurveData {
2349+
ss->system_info->turret_num_firing_points,
2350+
dist_to_enemy,
2351+
};
2352+
23282353
//WMC - go through all valid weapons. Fire spawns if there are any.
23292354
int valid_weapons[MAX_SHIP_WEAPONS];
23302355
int num_valid = 0;
@@ -2356,7 +2381,7 @@ void ai_turret_execute_behavior(const ship *shipp, ship_subsys *ss)
23562381
if (!in_lab && (wip->wi_flags[Weapon::Info_Flags::Spawn]) && !(wip->wi_flags[Weapon::Info_Flags::Smart_spawn]) )
23572382
{
23582383
if (( num_ships_nearby >= 3 ) || ((num_ships_nearby >= 2) && (frand() < 0.1f))) {
2359-
turret_fire_weapon(i, ss, parent_objnum, &global_gun_pos, &ss->turret_last_fire_direction);
2384+
turret_fire_weapon(i, ss, parent_objnum, launch_curve_data, &global_gun_pos, &ss->turret_last_fire_direction);
23602385
} else {
23612386
// Regardless of firing rate, don't check whether should fire for awhile.
23622387
if (tp->flags[Model::Subsystem_Flags::Use_multiple_guns])
@@ -2809,7 +2834,7 @@ void ai_turret_execute_behavior(const ship *shipp, ship_subsys *ss)
28092834
flak_jitter_aim(&shoot_vector, dist_to_enemy, ship_get_subsystem_strength(shipp, SUBSYSTEM_WEAPONS), wip);
28102835
}
28112836

2812-
turret_fire_weapon(valid_weapons[valid_index], ss, parent_objnum, &global_gun_pos, &shoot_vector, &predicted_enemy_pos, 100.0f, play_sound);
2837+
turret_fire_weapon(valid_weapons[valid_index], ss, parent_objnum, launch_curve_data, &global_gun_pos, &shoot_vector, &predicted_enemy_pos, 100.0f, play_sound);
28132838
}
28142839
else
28152840
{
@@ -2822,7 +2847,7 @@ void ai_turret_execute_behavior(const ship *shipp, ship_subsys *ss)
28222847
// make sure salvo fire mode does not turn into autofire
28232848
if ((tp->flags[Model::Subsystem_Flags::Turret_salvo]) && ((i + 1) == number_of_firings)) {
28242849
ai_info *parent_aip = &Ai_info[shipp->ai_index];
2825-
turret_set_next_fire_timestamp(valid_weapons[valid_index], wip, ss, parent_aip);
2850+
turret_set_next_fire_timestamp(valid_weapons[valid_index], wip, ss, parent_aip, launch_curve_data);
28262851
}
28272852
}
28282853

code/hud/hudartillery.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,7 @@ void ssm_process()
463463
}
464464
} else {
465465
// fire the missile and flash the screen
466-
weapon_objnum = weapon_create(&moveup->sinfo.start_pos[idx], &orient, si->weapon_info_index, -1, -1, 1);
466+
weapon_objnum = weapon_create(&moveup->sinfo.start_pos[idx], &orient, si->weapon_info_index, -1, -1, true);
467467

468468
if (weapon_objnum >= 0) {
469469
Weapons[Objects[weapon_objnum].instance].team = moveup->sinfo.ssm_team;

code/network/multi.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,10 @@ class player;
7575
// Version 59 - 12/9/2022 - New IDs for SEXP operators
7676
// Version 60 - 3/27/2023 - Added generic lua data packet
7777
// Version 61 - 4/17/2023 - Added compatibility for whackable asteroids (added force)
78+
// Version 62 - 5/26/2025 - Added some modular curve input data to turret firing packets
7879
// STANDALONE_ONLY
7980

80-
#define MULTI_FS_SERVER_VERSION 61
81+
#define MULTI_FS_SERVER_VERSION 62
8182

8283
#define MULTI_FS_SERVER_COMPATIBLE_VERSION MULTI_FS_SERVER_VERSION
8384

code/network/multimsgs.cpp

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3315,7 +3315,7 @@ void process_countermeasure_fired_packet( ubyte *data, header *hinfo )
33153315
}
33163316

33173317
// send a packet indicating that a turret has been fired
3318-
void send_turret_fired_packet( int ship_objnum, int subsys_index, int weapon_objnum )
3318+
void send_turret_fired_packet( int ship_objnum, int subsys_index, int weapon_objnum, float dist_to_target )
33193319
{
33203320
int packet_size;
33213321
ushort pnet_signature;
@@ -3370,6 +3370,8 @@ void send_turret_fired_packet( int ship_objnum, int subsys_index, int weapon_obj
33703370
else {
33713371
ADD_FLOAT(ZERO_VALUE);
33723372
}
3373+
3374+
ADD_FLOAT(dist_to_target);
33733375

33743376
multi_io_send_to_all(data, packet_size);
33753377

@@ -3390,6 +3392,7 @@ void process_turret_fired_packet( ubyte *data, header *hinfo )
33903392
ubyte has_sig = 0;
33913393
ship *shipp;
33923394
float angle1, angle2;
3395+
float dist_to_target;
33933396

33943397
// get the data for the turret fired packet
33953398
offset = HEADER_LENGTH;
@@ -3405,6 +3408,7 @@ void process_turret_fired_packet( ubyte *data, header *hinfo )
34053408
GET_SHORT( turret_index );
34063409
GET_FLOAT( angle1 );
34073410
GET_FLOAT( angle2 );
3411+
GET_FLOAT( dist_to_target );
34083412
PACKET_SET_SIZE(); // move our counter forward the number of bytes we have read
34093413

34103414
// if we don't have a valid weapon index then bail
@@ -3448,12 +3452,17 @@ void process_turret_fired_packet( ubyte *data, header *hinfo )
34483452
// get the world position of the weapon
34493453
ship_get_global_turret_info(objp, ssp->system_info, &pos, &temp);
34503454

3455+
auto launch_curve_data = WeaponLaunchCurveData {
3456+
ssp->system_info->turret_num_firing_points,
3457+
dist_to_target,
3458+
};
3459+
34513460
// create the weapon object
34523461
if(wnet_signature != 0){
34533462
multi_set_network_signature( wnet_signature, MULTI_SIG_NON_PERMANENT );
34543463
}
34553464

3456-
weapon_objnum = weapon_create( &pos, &orient, wid, OBJ_INDEX(objp), -1, 1, 0, 0.0f, ssp);
3465+
weapon_objnum = weapon_create( &pos, &orient, wid, OBJ_INDEX(objp), -1, true, false, 0.0f, ssp, launch_curve_data);
34573466

34583467
if (weapon_objnum != -1) {
34593468
if ( Weapon_info[wid].launch_snd.isValid() ) {
@@ -8620,7 +8629,7 @@ void process_weapon_detonate_packet(ubyte *data, header *hinfo)
86208629
}
86218630

86228631
// flak fired packet
8623-
void send_flak_fired_packet(int ship_objnum, int subsys_index, int weapon_objnum, float flak_range)
8632+
void send_flak_fired_packet(int ship_objnum, int subsys_index, int weapon_objnum, float flak_range, float dist_to_target)
86248633
{
86258634
int packet_size;
86268635
ushort pnet_signature;
@@ -8668,6 +8677,8 @@ void send_flak_fired_packet(int ship_objnum, int subsys_index, int weapon_objnum
86688677
ADD_FLOAT(ZERO_VALUE);
86698678
}
86708679
ADD_FLOAT( flak_range );
8680+
8681+
ADD_FLOAT( dist_to_target );
86718682

86728683
multi_io_send_to_all(data, packet_size);
86738684

@@ -8687,6 +8698,7 @@ void process_flak_fired_packet(ubyte *data, header *hinfo)
86878698
ship *shipp;
86888699
float angle1, angle2;
86898700
float flak_range;
8701+
float dist_to_target;
86908702

86918703
// get the data for the turret fired packet
86928704
offset = HEADER_LENGTH;
@@ -8697,6 +8709,7 @@ void process_flak_fired_packet(ubyte *data, header *hinfo)
86978709
GET_FLOAT( angle1 );
86988710
GET_FLOAT( angle2 );
86998711
GET_FLOAT( flak_range );
8712+
GET_FLOAT( dist_to_target );
87008713
PACKET_SET_SIZE(); // move our counter forward the number of bytes we have read
87018714

87028715
// if we don't have a valid weapon index then bail
@@ -8739,8 +8752,13 @@ void process_flak_fired_packet(ubyte *data, header *hinfo)
87398752
// get the world position of the weapon
87408753
ship_get_global_turret_info(objp, ssp->system_info, &pos, &dir);
87418754

8755+
auto launch_curve_data = WeaponLaunchCurveData {
8756+
ssp->system_info->turret_num_firing_points,
8757+
dist_to_target,
8758+
};
8759+
87428760
// create the weapon object
8743-
weapon_objnum = weapon_create( &pos, &orient, wid, OBJ_INDEX(objp), -1, 1, 0, 0.0f, ssp);
8761+
weapon_objnum = weapon_create( &pos, &orient, wid, OBJ_INDEX(objp), -1, true, false, 0.0f, ssp, launch_curve_data);
87448762
if (weapon_objnum != -1) {
87458763
if ( Weapon_info[wid].launch_snd.isValid() ) {
87468764
snd_play_3d( gamesnd_get_game_sound(Weapon_info[wid].launch_snd), &pos, &View_position );

code/network/multimsgs.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -530,11 +530,11 @@ void send_weapon_detonate_packet(object *objp);
530530
void process_weapon_detonate_packet(ubyte *data, header *hinfo);
531531

532532
// turret fired packet
533-
void send_turret_fired_packet( int objnum, int subsys_index, int weapon_objnum );
533+
void send_turret_fired_packet( int objnum, int subsys_index, int weapon_objnum, float dist_to_target );
534534
void process_turret_fired_packet( ubyte *data, header *hinfo );
535535

536536
// flak fired packet
537-
void send_flak_fired_packet(int ship_objnum, int subsys_index, int weapon_objnum, float flak_range);
537+
void send_flak_fired_packet(int ship_objnum, int subsys_index, int weapon_objnum, float flak_range, float dist_to_target);
538538
void process_flak_fired_packet(ubyte *data, header *hinfo);
539539

540540
// player pain packet

code/scripting/api/objs/subsystem.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
#include "network/multiutil.h"
1616

1717
void sexp_beam_or_turret_free_one(ship_subsys *turret, bool is_beam, bool free);
18-
bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum, const vec3d *orig_firing_pos, const vec3d *orig_firing_vec, const vec3d *predicted_pos = nullptr, float flak_range_override = 100.0f, bool play_sound = true);
18+
bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum, const WeaponLaunchCurveData& launch_curve_data, const vec3d *orig_firing_pos, const vec3d *orig_firing_vec, const vec3d *predicted_pos = nullptr, float flak_range_override = 100.0f, bool play_sound = true);
1919

2020
namespace scripting {
2121
namespace api {
@@ -891,7 +891,13 @@ ADE_FUNC(fireWeapon, l_Subsystem, "[number TurretWeaponIndex = 1, number FlakRan
891891
if (override_gvec != nullptr)
892892
vm_vec_copy_normalize(&gvec, override_gvec);
893893

894-
bool rtn = turret_fire_weapon(wnum, sso->ss, sso->objh.objnum, &gpos, &gvec, NULL, flak_range);
894+
// we don't have a target, so just set the range to 0
895+
auto launch_curve_data = WeaponLaunchCurveData {
896+
sso->ss->system_info->turret_num_firing_points,
897+
0.f,
898+
};
899+
900+
bool rtn = turret_fire_weapon(wnum, sso->ss, sso->objh.objnum, launch_curve_data, &gpos, &gvec, nullptr, flak_range);
895901

896902
sso->ss->turret_next_fire_pos++;
897903

0 commit comments

Comments
 (0)