Skip to content

Commit d0c5fe6

Browse files
fix series of bugs due to improper multi targeting (#6916)
Multiple issues were discovered to be from improper targeting data in multi tracing back to the addition of multi-lock. This was due to differences in how targeting works in single/multi and de-sync of this info between server and client. Collecting accurate targeting data on the server and making sure that the client will use that data resolves the tracking and sync issues.
1 parent 726c954 commit d0c5fe6

File tree

4 files changed

+45
-43
lines changed

4 files changed

+45
-43
lines changed

code/network/multimsgs.cpp

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3044,14 +3044,13 @@ void process_cargo_hidden_packet( ubyte *data, header *hinfo )
30443044
#define SFPF_TARGET_LOCKED (1<<5)
30453045

30463046
// send a packet indicating a secondary weapon was fired
3047-
void send_secondary_fired_packet( ship *shipp, ushort starting_sig, int /*starting_count*/, int num_fired, int allow_swarm )
3047+
void send_secondary_fired_packet( ship *shipp, ushort starting_sig, tracking_info &tinfo, int num_fired, int allow_swarm )
30483048
{
30493049
int packet_size, net_player_num;
30503050
ubyte data[MAX_PACKET_SIZE], sinfo, current_bank;
30513051
object *objp;
30523052
ushort target_net_signature;
30533053
int s_index;
3054-
ai_info *aip;
30553054

30563055
// Assert ( starting_count < UCHAR_MAX );
30573056

@@ -3064,8 +3063,6 @@ void send_secondary_fired_packet( ship *shipp, ushort starting_sig, int /*start
30643063
}
30653064
}
30663065

3067-
aip = &Ai_info[shipp->ai_index];
3068-
30693066
current_bank = (ubyte)shipp->weapons.current_secondary_bank;
30703067
Assert( (current_bank < MAX_SHIP_SECONDARY_BANKS) );
30713068

@@ -3086,7 +3083,7 @@ void send_secondary_fired_packet( ship *shipp, ushort starting_sig, int /*start
30863083
sinfo |= SFPF_DUAL_FIRE;
30873084
}
30883085

3089-
if ( aip->current_target_is_locked ){
3086+
if ( tinfo.locked ){
30903087
sinfo |= SFPF_TARGET_LOCKED;
30913088
}
30923089

@@ -3095,14 +3092,14 @@ void send_secondary_fired_packet( ship *shipp, ushort starting_sig, int /*start
30953092
// add the ship's target and any targeted subsystem
30963093
target_net_signature = 0;
30973094
s_index = -1;
3098-
if ( aip->target_objnum != -1) {
3099-
target_net_signature = Objects[aip->target_objnum].net_signature;
3100-
if ( (Objects[aip->target_objnum].type == OBJ_SHIP) && (aip->targeted_subsys != NULL) ) {
3101-
s_index = ship_get_subsys_index( aip->targeted_subsys );
3095+
if (tinfo.objnum != -1) {
3096+
target_net_signature = Objects[tinfo.objnum].net_signature;
3097+
if ( (Objects[tinfo.objnum].type == OBJ_SHIP) && (tinfo.subsys != nullptr) ) {
3098+
s_index = ship_get_subsys_index( tinfo.subsys );
31023099
}
31033100

3104-
if ( Objects[aip->target_objnum].type == OBJ_WEAPON ) {
3105-
Assert(Weapon_info[Weapons[Objects[aip->target_objnum].instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Bomb]);
3101+
if ( Objects[tinfo.objnum].type == OBJ_WEAPON ) {
3102+
Assert(Weapon_info[Weapons[Objects[tinfo.objnum].instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Bomb]);
31063103
}
31073104

31083105
}

code/network/multimsgs.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class ship_subsys;
3030
struct log_entry;
3131
struct beam_fire_info;
3232
namespace animation { enum class ModelAnimationDirection; }
33+
struct tracking_info;
3334

3435
// macros for building up packets -- to save on time and typing. Important to note that local variables
3536
// must be named correctly
@@ -270,7 +271,7 @@ void send_game_info_packet( void );
270271
void send_leave_game_packet(short player_id = -1,int kicked_reason = -1,net_player *target = NULL);
271272

272273
// send a packet indicating a secondary weapon was fired
273-
void send_secondary_fired_packet( ship *shipp, ushort starting_sig, int starting_count, int num_fired, int allow_swarm );
274+
void send_secondary_fired_packet( ship *shipp, ushort starting_sig, tracking_info &tinfo, int num_fired, int allow_swarm );
274275

275276
// send a packet indicating a countermeasure was fired
276277
void send_countermeasure_fired_packet( object *objp, int cmeasure_count, int rand_val );

code/ship/ship.cpp

Lines changed: 23 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -13836,7 +13836,7 @@ extern void ai_maybe_announce_shockwave_weapon(object *firing_objp, int weapon_i
1383613836
// need to avoid firing when normally called
1383713837
int ship_fire_secondary( object *obj, int allow_swarm, bool rollback_shot )
1383813838
{
13839-
int n, weapon_idx, j, bank, bank_adjusted, starting_bank_count = -1, num_fired;
13839+
int n, weapon_idx, j, bank, bank_adjusted, num_fired;
1384013840
ushort starting_sig = 0;
1384113841
ship *shipp;
1384213842
ship_weapon *swp;
@@ -13846,6 +13846,7 @@ int ship_fire_secondary( object *obj, int allow_swarm, bool rollback_shot )
1384613846
polymodel *pm;
1384713847
vec3d missile_point, pnt, firing_pos;
1384813848
bool has_fired = false; // Used to determine whether to fire the scripting hook
13849+
tracking_info tinfo;
1384913850

1385013851
Assert( obj != NULL );
1385113852

@@ -13932,14 +13933,13 @@ int ship_fire_secondary( object *obj, int allow_swarm, bool rollback_shot )
1393213933

1393313934
if ( MULTIPLAYER_MASTER ) {
1393413935
starting_sig = multi_get_next_network_signature( MULTI_SIG_NON_PERMANENT );
13935-
starting_bank_count = swp->secondary_bank_ammo[bank];
1393613936
}
1393713937

1393813938
if (ship_fire_secondary_detonate(obj, swp)) {
1393913939
// in multiplayer, master sends a secondary fired packet with starting signature of -1 -- indicates
1394013940
// to client code to set the detonate timer to 0.
1394113941
if ( MULTIPLAYER_MASTER ) {
13942-
send_secondary_fired_packet( shipp, 0, starting_bank_count, 1, allow_swarm );
13942+
send_secondary_fired_packet( shipp, 0, tinfo, 1, allow_swarm );
1394313943
}
1394413944

1394513945
// For all banks, if ok to fire a weapon, make it wait a bit.
@@ -14112,10 +14112,6 @@ int ship_fire_secondary( object *obj, int allow_swarm, bool rollback_shot )
1411214112
return 0; // we can make a quick out here!!!
1411314113
}
1411414114

14115-
int target_objnum;
14116-
ship_subsys *target_subsys;
14117-
int locked;
14118-
1411914115
if ( obj == Player_obj || ( MULTIPLAYER_MASTER && obj->flags[Object::Object_Flags::Player_ship] ) ) {
1412014116
// use missile lock slots
1412114117
if ( !shipp->missile_locks_firing.empty() ) {
@@ -14132,39 +14128,35 @@ int ship_fire_secondary( object *obj, int allow_swarm, bool rollback_shot )
1413214128
}
1413314129

1413414130
if (lock_data.obj != nullptr) {
14135-
target_objnum = OBJ_INDEX(lock_data.obj);
14136-
target_subsys = lock_data.subsys;
14137-
locked = 1;
14131+
tinfo.objnum = OBJ_INDEX(lock_data.obj);
14132+
tinfo.subsys = lock_data.subsys;
14133+
tinfo.locked = true;
1413814134
} else {
14139-
target_objnum = -1;
14140-
target_subsys = nullptr;
14141-
locked = 0;
14135+
tinfo.objnum = -1;
14136+
tinfo.subsys = nullptr;
14137+
tinfo.locked = false;
1414214138
}
14143-
} else if (wip->wi_flags[Weapon::Info_Flags::Homing_heat]) {
14144-
target_objnum = aip->target_objnum;
14145-
target_subsys = aip->targeted_subsys;
14146-
locked = aip->current_target_is_locked;
1414714139
} else {
14148-
target_objnum = -1;
14149-
target_subsys = nullptr;
14150-
locked = 0;
14140+
tinfo.objnum = aip->target_objnum;
14141+
tinfo.subsys = aip->targeted_subsys;
14142+
tinfo.locked = aip->current_target_is_locked == 1;
1415114143
}
1415214144
} else if (wip->multi_lock && !aip->ai_missile_locks_firing.empty()) {
14153-
target_objnum = aip->ai_missile_locks_firing.back().first;
14154-
target_subsys = aip->ai_missile_locks_firing.back().second;
14155-
locked = 1;
14145+
tinfo.objnum = aip->ai_missile_locks_firing.back().first;
14146+
tinfo.subsys = aip->ai_missile_locks_firing.back().second;
14147+
tinfo.locked = true;
1415614148
aip->ai_missile_locks_firing.pop_back();
1415714149
} else {
14158-
target_objnum = aip->target_objnum;
14159-
target_subsys = aip->targeted_subsys;
14160-
locked = aip->current_target_is_locked;
14150+
tinfo.objnum = aip->target_objnum;
14151+
tinfo.subsys = aip->targeted_subsys;
14152+
tinfo.locked = aip->current_target_is_locked == 1;
1416114153
}
1416214154

1416314155
num_slots = pm->missile_banks[bank].num_slots;
1416414156
float target_radius = 0.f;
1416514157

14166-
if (target_objnum >= 0) {
14167-
target_radius = Objects[target_objnum].radius;
14158+
if (tinfo.objnum >= 0) {
14159+
target_radius = Objects[tinfo.objnum].radius;
1416814160
}
1416914161

1417014162
auto launch_curve_data = WeaponLaunchCurveData {
@@ -14286,7 +14278,7 @@ int ship_fire_secondary( object *obj, int allow_swarm, bool rollback_shot )
1428614278

1428714279
// create the weapon -- for multiplayer, the net_signature is assigned inside
1428814280
// of weapon_create
14289-
weapon_num = weapon_create( &firing_pos, &firing_orient, weapon_idx, OBJ_INDEX(obj), -1, locked, false, 0.f, nullptr, launch_curve_data);
14281+
weapon_num = weapon_create( &firing_pos, &firing_orient, weapon_idx, OBJ_INDEX(obj), -1, tinfo.locked, false, 0.f, nullptr, launch_curve_data);
1429014282

1429114283
if (weapon_num == -1) {
1429214284
// Weapon most likely failed to fire
@@ -14298,7 +14290,7 @@ int ship_fire_secondary( object *obj, int allow_swarm, bool rollback_shot )
1429814290

1429914291
if (weapon_num >= 0) {
1430014292
weapon_idx = Weapons[Objects[weapon_num].instance].weapon_info_index;
14301-
weapon_set_tracking_info(weapon_num, OBJ_INDEX(obj), target_objnum, locked, target_subsys);
14293+
weapon_set_tracking_info(weapon_num, OBJ_INDEX(obj), tinfo);
1430214294
has_fired = true;
1430314295

1430414296
// create the muzzle flash effect
@@ -14362,7 +14354,7 @@ int ship_fire_secondary( object *obj, int allow_swarm, bool rollback_shot )
1436214354
// Cyborg17 - If this is a rollback shot, the server will let the player know within the packet.
1436314355
if ( MULTIPLAYER_MASTER ) {
1436414356
Assert(starting_sig != 0);
14365-
send_secondary_fired_packet( shipp, starting_sig, starting_bank_count, num_fired, allow_swarm );
14357+
send_secondary_fired_packet( shipp, starting_sig, tinfo, num_fired, allow_swarm );
1436614358
}
1436714359

1436814360
// Handle Player only stuff, including stats and client secondary packets

code/weapon/weapon.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -938,6 +938,13 @@ extern SCP_vector<int> Player_weapon_precedence; // Vector of weapon types, prec
938938

939939
#define WEAPON_INDEX(wp) (int)(wp-Weapons)
940940

941+
typedef struct tracking_info {
942+
ship_subsys *subsys;
943+
int objnum;
944+
bool locked;
945+
946+
tracking_info() : subsys(nullptr), objnum(-1), locked(false) {}
947+
} tracking_info;
941948

942949
int weapon_info_lookup(const char *name);
943950
int weapon_info_get_index(const weapon_info *wip);
@@ -990,6 +997,11 @@ int weapon_create( const vec3d *pos,
990997
});
991998
void weapon_set_tracking_info(int weapon_objnum, int parent_objnum, int target_objnum, int target_is_locked = 0, ship_subsys *target_subsys = NULL);
992999

1000+
inline void weapon_set_tracking_info(int weapon_objnum, int parent_objnum, tracking_info &tinfo)
1001+
{
1002+
weapon_set_tracking_info(weapon_objnum, parent_objnum, tinfo.objnum, tinfo.locked, tinfo.subsys);
1003+
}
1004+
9931005
// gets the substitution pattern pointer for a given weapon
9941006
// src_turret may be null
9951007
size_t* get_pointer_to_weapon_fire_pattern_index(int weapon_type, int ship_idx, ship_subsys* src_turret);

0 commit comments

Comments
 (0)