Added MULTI_EFFECT_BLOWUP to remotely blast switches connected to triggers, ensuring sync and preventing misguided (i.e. delayed) player fire accidentially make puzzles or game progress impossible

This commit is contained in:
zico 2013-12-19 13:48:33 +01:00
parent d2c2dfe95c
commit 5f005baa3b
6 changed files with 79 additions and 23 deletions

View file

@ -48,7 +48,7 @@ extern void collide_player_and_nasty_robot(object * player, object * robot, vms_
extern void net_destroy_controlcen(object *controlcen);
extern void collide_player_and_powerup(object * player, object * powerup, vms_vector *collision_point);
extern int check_effect_blowup(segment *seg,int side,vms_vector *pnt, object *blower, int force_blowup_flag);
extern int check_effect_blowup(segment *seg,int side,vms_vector *pnt, object *blower, int force_blowup_flag, int remote);
extern void apply_damage_to_controlcen(object *controlcen, fix damage, short who);
extern void bump_one_object(object *obj0, vms_vector *hit_dir, fix damage);
void drop_player_eggs(struct object *playerobj);

View file

@ -62,7 +62,7 @@ extern int multi_protocol; // set and determinate used protocol
#define MULTI_PROTO_UDP 1 // UDP protocol
// What version of the multiplayer protocol is this? Increment each time something drastic changes in Multiplayer without the version number changes. Can be reset to 0 each time the version of the game changes
#define MULTI_PROTO_VERSION 10
#define MULTI_PROTO_VERSION 11
// PROTOCOL VARIABLES AND DEFINES - END
// limits for Packets (i.e. positional updates) per sec
@ -159,6 +159,7 @@ extern int multi_protocol; // set and determinate used protocol
VALUE(MULTI_MODEM_PING_RETURN , 1) \
VALUE(MULTI_ORB_BONUS , 3) \
VALUE(MULTI_GOT_ORB , 2) \
VALUE(MULTI_EFFECT_BLOWUP , 17) \
#endif
for_each_multiplayer_command(enum {, define_multiplayer_command, });
@ -313,6 +314,7 @@ void multi_send_markers();
void multi_send_guided_info (object *miss,char);
void multi_send_orb_bonus( char pnum );
void multi_send_got_orb( char pnum );
void multi_send_effect_blowup(short segnum, int side, vms_vector *pnt);
#endif
void multi_add_lifetime_kills(void);
void multi_send_bounty( void );

View file

@ -527,32 +527,28 @@ static int effect_parent_is_guidebot(const object *effect)
//if an effect is hit, and it can blow up, then blow it up
//returns true if it blew up
int check_effect_blowup(segment *seg,int side,vms_vector *pnt, object *blower, int force_blowup_flag)
int check_effect_blowup(segment *seg,int side,vms_vector *pnt, object *blower, int force_blowup_flag, int remote)
{
int tm,db;
#if defined(DXX_BUILD_DESCENT_I)
(void)blower;
force_blowup_flag = 0;
(void)remote;
#elif defined(DXX_BUILD_DESCENT_II)
int trigger_check = 0, is_trigger = 0, wall_num = seg->sides[side].wall_num;
db=0;
// If this wall has a trigger and the blower-upper is not the player or the buddy, abort!
{
int ok_to_blow = effect_parent_is_guidebot(blower);
if (!(ok_to_blow || (blower->ctype.laser_info.parent_type == OBJ_PLAYER))) {
int trigger_num, wall_num;
wall_num = seg->sides[side].wall_num;
if ( wall_num != -1 ) {
trigger_num = Walls[wall_num].trigger;
if (trigger_num != -1)
return 0;
}
}
}
// If this wall has a trigger and the blower-upper is not the player or the buddy, abort!
trigger_check = (!(effect_parent_is_guidebot(blower) || blower->ctype.laser_info.parent_type == OBJ_PLAYER));
// For Multiplayer perform an additional check to see if it's a local-player hit. If a remote player hits, a packet is expected (remote 1) which would be followed by MULTI_TRIGGER to ensure sync with the switch and the actual trigger.
if (Game_mode & GM_MULTI)
trigger_check = (!(blower->ctype.laser_info.parent_type == OBJ_PLAYER && (blower->ctype.laser_info.parent_num == Players[Player_num].objnum || remote)));
if ( wall_num != -1 )
if (Walls[wall_num].trigger != -1)
is_trigger = 1;
if (trigger_check && is_trigger)
return(0);
#endif
if ((tm=seg->sides[side].tmap_num2) != 0) {
@ -609,6 +605,10 @@ int check_effect_blowup(segment *seg,int side,vms_vector *pnt, object *blower, i
//because we use the light value of the texture to change
//the static light in the segment
subtract_light(seg-Segments,side);
// we blew up something connected to a trigger. Send it to others!
if ((Game_mode & GM_MULTI) && is_trigger && !remote && !force_blowup_flag)
multi_send_effect_blowup(seg-Segments, side, pnt);
#endif
if (Newdemo_state == ND_STATE_RECORDING)
newdemo_record_effect_blowup( seg-Segments, side, pnt);
@ -747,7 +747,7 @@ static void collide_weapon_and_wall( object * weapon, fix hitspeed, short hitseg
return;
}
blew_up = check_effect_blowup(seg,hitwall,hitpt, weapon, 0);
blew_up = check_effect_blowup(seg,hitwall,hitpt, weapon, 0, 0);
//if ((seg->sides[hitwall].tmap_num2==0) && (TmapInfo[seg->sides[hitwall].tmap_num].flags & TMI_VOLATILE)) {

View file

@ -2273,6 +2273,33 @@ static multi_do_trigger(const ubyte *buf)
}
#if defined(DXX_BUILD_DESCENT_II)
void
static multi_do_effect_blowup(const ubyte *buf)
{
int pnum = buf[1], segnum, side;
vms_vector hitpnt;
object dummy;
if ((pnum < 0) || (pnum >= N_players) || (pnum == Player_num))
return;
multi_do_protocol_frame(1, 0); // force packets to be sent, ensuring this packet will be attached to following MULTI_TRIGGER
segnum = GET_INTEL_SHORT(buf + 2);
side = buf[4];
hitpnt.x = GET_INTEL_INT(buf + 5);
hitpnt.y = GET_INTEL_INT(buf + 9);
hitpnt.z = GET_INTEL_INT(buf + 13);
//create a dummy object which will be the weapon that hits
//the monitor. the blowup code wants to know who the parent of the
//laser is, so create a laser whose parent is the player
dummy.ctype.laser_info.parent_type = OBJ_PLAYER;
dummy.ctype.laser_info.parent_num = pnum;
check_effect_blowup(&(Segments[segnum]), side, &hitpnt, &dummy, 0, 1);
}
static void multi_do_drop_marker (const ubyte *buf)
{
int i;
@ -3250,6 +3277,30 @@ multi_send_trigger(int triggernum)
multi_send_data(multibuf, count, 2);
}
#if defined(DXX_BUILD_DESCENT_II)
void
multi_send_effect_blowup(short segnum, int side, vms_vector *pnt)
{
// We blew up something connected to a trigger. Send this blowup result to other players shortly before MULTI_TRIGGER.
// NOTE: The reason this is now a separate packet is to make sure trigger-connected switches/monitors are in sync with MULTI_TRIGGER.
// If a fire packet is late it might blow up a switch for some clients without the shooter actually registering this hit,
// not sending MULTI_TRIGGER and making puzzles or progress impossible.
int count = 0;
multi_do_protocol_frame(1, 0); // force packets to be sent, ensuring this packet will be attached to following MULTI_TRIGGER
multibuf[count] = MULTI_EFFECT_BLOWUP; count += 1;
multibuf[count] = Player_num; count += 1;
PUT_INTEL_SHORT(multibuf+count, segnum); count += 2;
multibuf[count] = (sbyte)side; count += 1;
PUT_INTEL_INT(multibuf+count, pnt->x); count += 4;
PUT_INTEL_INT(multibuf+count, pnt->y); count += 4;
PUT_INTEL_INT(multibuf+count, pnt->z); count += 4;
multi_send_data(multibuf, count, 0);
}
#endif
void
multi_send_hostage_door_status(int wallnum)
{
@ -5314,6 +5365,8 @@ multi_process_data(const ubyte *buf, int len)
#if defined(DXX_BUILD_DESCENT_II)
case MULTI_START_TRIGGER:
if (!Endlevel_sequence) multi_do_start_trigger(buf); break;
case MULTI_EFFECT_BLOWUP:
if (!Endlevel_sequence) multi_do_effect_blowup(buf); break;
case MULTI_FLAGS:
if (!Endlevel_sequence) multi_do_flags(buf); break;
case MULTI_DROP_BLOB:

View file

@ -2448,6 +2448,7 @@ static int newdemo_read_frame_information(int rewrite)
//the monitor. the blowup code wants to know who the parent of the
//laser is, so create a laser whose parent is the player
dummy.ctype.laser_info.parent_type = OBJ_PLAYER;
dummy.ctype.laser_info.parent_num = Player_num;
#endif
nd_read_short(&segnum);
@ -2462,9 +2463,9 @@ static int newdemo_read_frame_information(int rewrite)
}
if (Newdemo_vcr_state != ND_STATE_PAUSED)
#if defined(DXX_BUILD_DESCENT_I)
check_effect_blowup(&(Segments[segnum]), side, &pnt, NULL, 0);
check_effect_blowup(&(Segments[segnum]), side, &pnt, NULL, 0, 0);
#elif defined(DXX_BUILD_DESCENT_II)
check_effect_blowup(&(Segments[segnum]), side, &pnt, &dummy, 0);
check_effect_blowup(&(Segments[segnum]), side, &pnt, &dummy, 0, 0);
#endif
break;
}

View file

@ -1670,7 +1670,7 @@ static void bng_process_segment(object *objp, fix damage, segment *segp, int dep
if (dist < damage/2) {
dist = find_connected_distance(&pnt, segp-Segments, &objp->pos, objp->segnum, MAX_BLAST_GLASS_DEPTH, WID_RENDPAST_FLAG);
if ((dist > 0) && (dist < damage/2))
check_effect_blowup(segp, sidenum, &pnt, &Objects[objp->ctype.laser_info.parent_num], 1);
check_effect_blowup(segp, sidenum, &pnt, &Objects[objp->ctype.laser_info.parent_num], 1, 0);
}
}
}