2006-03-20 17:12:09 +00:00
/*
2014-06-01 17:55:23 +00:00
* Portions of this file are copyright Rebirth contributors and licensed as
* described in COPYING . txt .
* Portions of this file are copyright Parallax Software and licensed
* according to the Parallax license below .
* See COPYING . txt for license details .
2006-03-20 17:12:09 +00:00
THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
SOFTWARE CORPORATION ( " PARALLAX " ) . PARALLAX , IN DISTRIBUTING THE CODE TO
END - USERS , AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN , GRANTS A
ROYALTY - FREE , PERPETUAL LICENSE TO SUCH END - USERS FOR USE BY SUCH END - USERS
IN USING , DISPLAYING , AND CREATING DERIVATIVE WORKS THEREOF , SO LONG AS
SUCH USE , DISPLAY OR CREATION IS FOR NON - COMMERCIAL , ROYALTY OR REVENUE
FREE PURPOSES . IN NO EVENT SHALL THE END - USER USE THE COMPUTER CODE
CONTAINED HEREIN FOR REVENUE - BEARING PURPOSES . THE END - USER UNDERSTANDS
AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE .
COPYRIGHT 1993 - 1999 PARALLAX SOFTWARE CORPORATION . ALL RIGHTS RESERVED .
*/
/*
*
* Defines and exported variables for multi . c
*
*/
2014-12-07 00:00:22 +00:00
# pragma once
2006-03-20 17:12:09 +00:00
2017-06-25 20:46:03 +00:00
# include <type_traits>
2016-11-12 20:58:16 +00:00
# include "dxxsconf.h"
2015-07-25 23:10:45 +00:00
# include "fwd-player.h"
# include "player-callsign.h"
2015-10-30 02:52:55 +00:00
# include "player-flags.h"
2015-07-25 23:10:45 +00:00
# include "weapon.h"
2013-12-26 04:18:28 +00:00
# include "mission.h"
2009-04-09 07:41:30 +00:00
# include "newmenu.h"
2012-11-11 00:12:17 +00:00
# include "powerup.h"
2015-10-10 03:44:14 +00:00
# include "fwd-object.h"
2016-12-05 00:26:09 +00:00
# include "fwd-wall.h"
2015-07-25 23:10:45 +00:00
# include "window.h"
# include "game.h"
2020-04-19 20:47:07 +00:00
# include "gameplayopt.h"
2009-11-29 16:46:13 +00:00
2009-03-20 12:10:38 +00:00
# ifdef _WIN32
2011-04-05 00:24:34 +00:00
# include <winsock2.h>
# include <ws2tcpip.h>
2009-11-24 09:48:53 +00:00
# include <io.h>
2009-03-20 12:10:38 +00:00
# else
2009-11-24 09:48:53 +00:00
# include <sys/socket.h>
# include <netinet/in.h>
# include <netdb.h>
# include <arpa/inet.h>
# include <unistd.h>
2010-09-02 00:07:37 +00:00
# include <stdint.h>
2009-11-24 09:48:53 +00:00
# include <sys/time.h>
2009-03-20 12:10:38 +00:00
# endif
2012-11-11 22:12:51 +00:00
# ifdef __cplusplus
2014-12-07 00:00:22 +00:00
# include <stdexcept>
2018-05-13 03:14:34 +00:00
# include "digi.h"
2014-06-26 02:27:16 +00:00
# include "pack.h"
2014-07-04 03:54:18 +00:00
# include "compiler-array.h"
2014-12-22 04:35:48 +00:00
# include "ntstring.h"
2015-06-05 02:34:40 +00:00
# include "compiler-static_assert.h"
2012-11-11 22:12:51 +00:00
2015-12-13 18:00:49 +00:00
namespace dcx {
2015-12-13 18:00:48 +00:00
2015-01-18 01:58:34 +00:00
struct _sockaddr
{
union {
sockaddr sa ;
sockaddr_in sin ;
2016-09-11 18:49:15 +00:00
# if DXX_USE_IPv6
2015-01-18 01:58:34 +00:00
sockaddr_in6 sin6 ;
# define DXX_IPv6(v4,v6) v6
2009-03-20 12:10:38 +00:00
# else
2015-01-18 01:58:34 +00:00
# define DXX_IPv6(v4,v6) v4
2009-11-29 16:46:13 +00:00
# endif
2015-01-18 01:58:34 +00:00
} ;
2017-03-25 19:34:02 +00:00
enum {
presentation_buffer_size = DXX_IPv6 ( INET_ADDRSTRLEN , INET6_ADDRSTRLEN ) ,
} ;
2015-01-18 01:58:34 +00:00
static int address_family ( )
{
return DXX_IPv6 ( AF_INET , AF_INET6 ) ;
}
static int protocol_family ( )
{
return DXX_IPv6 ( PF_INET , PF_INET6 ) ;
}
# undef DXX_IPv6
} ;
2006-03-20 17:12:09 +00:00
2009-04-09 07:41:30 +00:00
// PROTOCOL VARIABLES AND DEFINES
extern int multi_protocol ; // set and determinate used protocol
2015-12-13 18:00:48 +00:00
}
2011-09-13 23:15:32 +00:00
# define MULTI_PROTO_UDP 1 // UDP protocol
2009-03-20 12:10:38 +00:00
2013-12-19 13:03:00 +00:00
// What version of the multiplayer protocol is this? Increment each time something drastic changes in Multiplayer without the version number changes. Reset to 0 each time the version of the game changes
2019-06-27 03:26:20 +00:00
# define MULTI_PROTO_VERSION static_cast<uint16_t>(10)
2009-04-09 07:41:30 +00:00
// PROTOCOL VARIABLES AND DEFINES - END
2006-03-20 17:12:09 +00:00
2013-12-09 13:25:32 +00:00
// limits for Packets (i.e. positional updates) per sec
2016-05-10 11:45:08 +00:00
# define DEFAULT_PPS 30
2013-12-09 13:25:32 +00:00
# define MIN_PPS 5
# define MAX_PPS 40
2006-03-20 17:12:09 +00:00
2009-04-09 07:41:30 +00:00
# define MAX_MESSAGE_LEN 35
2006-03-20 17:12:09 +00:00
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
# define MAX_NET_CREATE_OBJECTS 20
# define MAX_MULTI_MESSAGE_LEN 90 //didn't change it, just moved it up
# elif defined(DXX_BUILD_DESCENT_II)
# define MAX_NET_CREATE_OBJECTS 40
# define MAX_MULTI_MESSAGE_LEN 120
2013-12-16 22:15:38 +00:00
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
2009-11-24 09:48:53 +00:00
# define NETGAME_ANARCHY 0
# define NETGAME_TEAM_ANARCHY 1
# define NETGAME_ROBOT_ANARCHY 2
# define NETGAME_COOPERATIVE 3
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2009-11-24 09:48:53 +00:00
# define NETGAME_CAPTURE_FLAG 4
# define NETGAME_HOARD 5
# define NETGAME_TEAM_HOARD 6
2013-03-03 01:03:33 +00:00
# endif
2011-01-19 01:19:17 +00:00
# define NETGAME_BOUNTY 7
2009-11-24 09:48:53 +00:00
2009-03-20 12:10:38 +00:00
# define NETSTAT_MENU 0
# define NETSTAT_PLAYING 1
# define NETSTAT_BROWSING 2
# define NETSTAT_WAITING 3
# define NETSTAT_STARTING 4
# define NETSTAT_ENDLEVEL 5
# define CONNECT_DISCONNECTED 0
# define CONNECT_PLAYING 1
# define CONNECT_WAITING 2
# define CONNECT_DIED_IN_MINE 3
# define CONNECT_FOUND_SECRET 4
# define CONNECT_ESCAPE_TUNNEL 5
# define CONNECT_END_MENU 6
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2009-03-20 12:10:38 +00:00
# define CONNECT_KMATRIX_WAITING 7 // Like CONNECT_WAITING but used especially in kmatrix.c to seperate "escaped" and "waiting"
2013-03-03 01:03:33 +00:00
# endif
2009-03-20 12:10:38 +00:00
2009-11-24 09:48:53 +00:00
// reasons for a packet with type PID_DUMP
# define DUMP_CLOSED 0 // no new players allowed after game started
# define DUMP_FULL 1 // player cound maxed out
# define DUMP_ENDLEVEL 2
# define DUMP_DORK 3
# define DUMP_ABORTED 4
# define DUMP_CONNECTED 5 // never used
# define DUMP_LEVEL 6
# define DUMP_KICKED 7
2011-09-19 11:01:11 +00:00
# define DUMP_PKTTIMEOUT 8
2009-11-24 09:48:53 +00:00
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I) || defined(DXX_BUILD_DESCENT_II)
2015-03-28 17:18:02 +00:00
# define NETFLAG_LABEL_QUAD "Quad Lasers"
# define NETFLAG_LABEL_VULCAN "Vulcan cannon"
# define NETFLAG_LABEL_SPREAD "Spreadfire cannon"
# define NETFLAG_LABEL_PLASMA "Plasma cannon"
# define NETFLAG_LABEL_FUSION "Fusion cannon"
2013-06-09 21:28:55 +00:00
# define for_each_netflag_value(VALUE) \
2013-06-22 02:26:08 +00:00
VALUE ( NETFLAG_DOLASER , " Laser upgrade " ) \
2015-03-28 17:18:02 +00:00
VALUE ( NETFLAG_DOQUAD , NETFLAG_LABEL_QUAD ) \
VALUE ( NETFLAG_DOVULCAN , NETFLAG_LABEL_VULCAN ) \
VALUE ( NETFLAG_DOSPREAD , NETFLAG_LABEL_SPREAD ) \
VALUE ( NETFLAG_DOPLASMA , NETFLAG_LABEL_PLASMA ) \
VALUE ( NETFLAG_DOFUSION , NETFLAG_LABEL_FUSION ) \
2013-06-22 02:26:08 +00:00
VALUE ( NETFLAG_DOHOMING , " Homing Missiles " ) \
VALUE ( NETFLAG_DOPROXIM , " Proximity Bombs " ) \
VALUE ( NETFLAG_DOSMART , " Smart Missiles " ) \
VALUE ( NETFLAG_DOMEGA , " Mega Missiles " ) \
VALUE ( NETFLAG_DOCLOAK , " Cloaking " ) \
VALUE ( NETFLAG_DOINVUL , " Invulnerability " ) \
2013-03-03 01:03:33 +00:00
D2X_MP_NETFLAGS ( VALUE ) \
2015-03-28 17:18:02 +00:00
# define for_each_netgrant_value(VALUE) \
VALUE ( NETGRANT_QUAD , NETFLAG_LABEL_QUAD ) \
VALUE ( NETGRANT_VULCAN , NETFLAG_LABEL_VULCAN ) \
VALUE ( NETGRANT_SPREAD , NETFLAG_LABEL_SPREAD ) \
VALUE ( NETGRANT_PLASMA , NETFLAG_LABEL_PLASMA ) \
VALUE ( NETGRANT_FUSION , NETFLAG_LABEL_FUSION ) \
D2X_MP_NETGRANT ( VALUE )
2013-03-03 01:03:33 +00:00
# define MULTI_GAME_TYPE_COUNT 8
2016-07-09 17:58:35 +00:00
namespace dsx {
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
2017-10-14 17:10:30 +00:00
constexpr std : : integral_constant < unsigned , 13 > MULTI_GAME_NAME_LENGTH { } ;
constexpr std : : integral_constant < unsigned , 18 > MULTI_ALLOW_POWERUP_TEXT_LENGTH { } ;
2013-03-03 01:03:33 +00:00
# define MULTI_ALLOW_POWERUP_MAX 12
# define D2X_MP_NETFLAGS(VALUE)
2015-03-28 17:18:02 +00:00
# define DXX_GRANT_LASER_LEVEL_BITS 2
# define D2X_MP_NETGRANT(VALUE)
2013-03-03 01:03:33 +00:00
# elif defined(DXX_BUILD_DESCENT_II)
2017-10-14 17:10:30 +00:00
constexpr std : : integral_constant < unsigned , 17 > MULTI_GAME_NAME_LENGTH { } ;
constexpr std : : integral_constant < unsigned , 21 > MULTI_ALLOW_POWERUP_TEXT_LENGTH { } ;
2013-03-03 01:03:33 +00:00
# define MULTI_ALLOW_POWERUP_MAX 26
2015-03-28 17:18:02 +00:00
# define NETFLAG_LABEL_GAUSS "Gauss cannon"
# define NETFLAG_LABEL_HELIX "Helix cannon"
# define NETFLAG_LABEL_PHOENIX "Phoenix cannon"
# define NETFLAG_LABEL_OMEGA "Omega cannon"
# define NETFLAG_LABEL_AFTERBURNER "Afterburners"
# define NETFLAG_LABEL_AMMORACK "Ammo rack"
# define NETFLAG_LABEL_CONVERTER "Energy Converter"
# define NETFLAG_LABEL_HEADLIGHT "Headlight"
2013-03-03 01:03:33 +00:00
# define D2X_MP_NETFLAGS(VALUE) \
2013-06-22 02:26:08 +00:00
VALUE ( NETFLAG_DOSUPERLASER , " Super lasers " ) \
2015-03-28 17:18:02 +00:00
VALUE ( NETFLAG_DOGAUSS , NETFLAG_LABEL_GAUSS ) \
VALUE ( NETFLAG_DOHELIX , NETFLAG_LABEL_HELIX ) \
VALUE ( NETFLAG_DOPHOENIX , NETFLAG_LABEL_PHOENIX ) \
VALUE ( NETFLAG_DOOMEGA , NETFLAG_LABEL_OMEGA ) \
2013-06-22 02:26:08 +00:00
VALUE ( NETFLAG_DOFLASH , " Flash Missiles " ) \
VALUE ( NETFLAG_DOGUIDED , " Guided Missiles " ) \
VALUE ( NETFLAG_DOSMARTMINE , " Smart Mines " ) \
VALUE ( NETFLAG_DOMERCURY , " Mercury Missiles " ) \
2015-03-28 17:18:02 +00:00
VALUE ( NETFLAG_DOSHAKER , " Earthshaker Missiles " ) \
VALUE ( NETFLAG_DOAFTERBURNER , NETFLAG_LABEL_AFTERBURNER ) \
VALUE ( NETFLAG_DOAMMORACK , NETFLAG_LABEL_AMMORACK ) \
VALUE ( NETFLAG_DOCONVERTER , NETFLAG_LABEL_CONVERTER ) \
2015-04-19 04:18:53 +00:00
VALUE ( NETFLAG_DOHEADLIGHT , NETFLAG_LABEL_HEADLIGHT )
2015-03-28 17:18:02 +00:00
# define DXX_GRANT_LASER_LEVEL_BITS 3
# define D2X_MP_NETGRANT(VALUE) \
VALUE ( NETGRANT_GAUSS , NETFLAG_LABEL_GAUSS ) \
VALUE ( NETGRANT_HELIX , NETFLAG_LABEL_HELIX ) \
VALUE ( NETGRANT_PHOENIX , NETFLAG_LABEL_PHOENIX ) \
VALUE ( NETGRANT_OMEGA , NETFLAG_LABEL_OMEGA ) \
VALUE ( NETGRANT_AFTERBURNER , NETFLAG_LABEL_AFTERBURNER ) \
VALUE ( NETGRANT_AMMORACK , NETFLAG_LABEL_AMMORACK ) \
VALUE ( NETGRANT_CONVERTER , NETFLAG_LABEL_CONVERTER ) \
VALUE ( NETGRANT_HEADLIGHT , NETFLAG_LABEL_HEADLIGHT )
2013-06-22 02:26:08 +00:00
2013-03-03 01:03:33 +00:00
# endif
2016-07-09 17:58:35 +00:00
}
2013-03-03 01:03:33 +00:00
2013-06-22 02:26:08 +00:00
# define define_netflag_bit_enum(NAME,STR) BIT_##NAME,
2017-06-25 20:46:03 +00:00
# define define_netflag_bit_mask(NAME,STR) static constexpr auto NAME = std::integral_constant<unsigned, (1 << BIT_##NAME)>{};
2013-06-22 02:26:08 +00:00
# define define_netflag_powerup_mask(NAME,STR) | (NAME)
2013-06-09 21:28:55 +00:00
enum { for_each_netflag_value ( define_netflag_bit_enum ) } ;
2009-03-20 12:10:38 +00:00
// Bitmask for netgame_info->AllowedItems to set allowed items in Netgame
2015-06-05 02:34:40 +00:00
for_each_netflag_value ( define_netflag_bit_mask ) ;
2013-06-09 21:28:55 +00:00
enum { NETFLAG_DOPOWERUP = 0 for_each_netflag_value ( define_netflag_powerup_mask ) } ;
2015-03-28 17:18:02 +00:00
enum {
BIT_NETGRANT_LASER = DXX_GRANT_LASER_LEVEL_BITS - 1 ,
for_each_netgrant_value ( define_netflag_bit_enum )
2015-04-19 04:18:53 +00:00
BIT_NETGRANT_MAXIMUM
2015-03-28 17:18:02 +00:00
} ;
2015-06-05 02:34:40 +00:00
for_each_netgrant_value ( define_netflag_bit_mask ) ;
2015-03-28 17:18:02 +00:00
# undef define_netflag_bit_enum
# undef define_netflag_bit_mask
# undef define_netflag_powerup_mask
2015-12-13 18:00:49 +00:00
namespace dsx {
2015-12-13 18:00:48 +00:00
2015-04-19 04:18:53 +00:00
struct packed_spawn_granted_items
{
# if defined(DXX_BUILD_DESCENT_I)
typedef uint8_t mask_type ;
# elif defined(DXX_BUILD_DESCENT_II)
typedef uint16_t mask_type ;
# endif
mask_type mask ;
static_assert ( BIT_NETGRANT_MAXIMUM < = sizeof ( mask ) < < 3 , " mask too small " ) ;
packed_spawn_granted_items ( ) = default ;
constexpr packed_spawn_granted_items ( mask_type m ) :
mask ( m )
{
}
2015-06-05 02:34:40 +00:00
template < unsigned U >
2017-06-25 20:46:03 +00:00
constexpr packed_spawn_granted_items ( std : : integral_constant < unsigned , U > ) :
2015-06-05 02:34:40 +00:00
mask ( U )
{
assert_equal ( U , static_cast < mask_type > ( U ) , " truncation error " ) ;
}
2015-04-19 04:18:53 +00:00
explicit operator bool ( ) const { return mask ; }
bool has_quad_laser ( ) const { return mask & NETGRANT_QUAD ; }
# if defined(DXX_BUILD_DESCENT_II)
bool has_afterburner ( ) const { return mask & NETGRANT_AFTERBURNER ; }
# endif
} ;
2015-04-19 04:18:53 +00:00
class packed_netduplicate_items
{
public :
enum
{
primary_shift = 0 ,
primary_width = 3 ,
secondary_shift = primary_shift + primary_width ,
secondary_width = 3 ,
# if defined(DXX_BUILD_DESCENT_II)
accessory_shift = secondary_shift + secondary_width ,
accessory_width = 3 ,
# endif
} ;
private :
# if defined(DXX_BUILD_DESCENT_I)
typedef uint8_t count_type ;
# elif defined(DXX_BUILD_DESCENT_II)
typedef uint16_t count_type ;
# endif
count_type count ;
template < uint_fast32_t shift , uint_fast32_t width >
uint_fast32_t get_sub_field ( ) const
{
static_assert ( shift + width < = sizeof ( count ) < < 3 , " shift+width too big " ) ;
constexpr auto low_mask = ( 1 < < width ) - 1 ;
return ( count > > shift ) & low_mask ;
}
public :
template < uint_fast32_t shift , uint_fast32_t width >
void set_sub_field ( uint_fast32_t value )
{
constexpr auto low_mask = ( 1 < < width ) - 1 ;
constexpr auto shifted_mask = low_mask < < shift ;
count = ( count & ~ shifted_mask ) | ( value < < shift ) ;
}
# define DEFINE_ACCESSOR(N) \
uint_fast32_t get_ # # N # # _count ( ) const \
{ \
return get_sub_field < N # # _shift , N # # _width > ( ) ; \
} \
void set_ # # N # # _count ( uint_fast32_t value ) \
{ \
set_sub_field < N # # _shift , N # # _width > ( value ) ; \
}
DEFINE_ACCESSOR ( primary ) ;
DEFINE_ACCESSOR ( secondary ) ;
# if defined(DXX_BUILD_DESCENT_II)
DEFINE_ACCESSOR ( accessory ) ;
# endif
count_type get_packed_field ( ) const
{
return count ;
}
void set_packed_field ( count_type c )
{
count = c ;
}
} ;
2015-04-26 20:15:56 +00:00
static inline laser_level_t map_granted_flags_to_laser_level ( const packed_spawn_granted_items & grant )
2015-03-28 17:18:02 +00:00
{
/* Laser level in lowest bits */
2015-04-26 20:15:56 +00:00
return laser_level_t ( grant . mask & ( ( 1 < < DXX_GRANT_LASER_LEVEL_BITS ) - 1 ) ) ;
2015-03-28 17:18:02 +00:00
}
2015-10-30 02:52:55 +00:00
player_flags map_granted_flags_to_player_flags ( packed_spawn_granted_items grant ) ;
2015-04-19 04:18:53 +00:00
uint_fast32_t map_granted_flags_to_primary_weapon_flags ( packed_spawn_granted_items grant ) ;
uint16_t map_granted_flags_to_vulcan_ammo ( packed_spawn_granted_items grant ) ;
2019-03-03 00:31:09 +00:00
void multi_digi_link_sound_to_pos ( int soundnum , vcsegptridx_t segnum , unsigned sidenum , const vms_vector & pos , int forever , fix max_volume ) ;
2019-12-22 05:34:08 +00:00
void multi_object_to_object_rw ( object & obj , object_rw * obj_rw ) ;
void multi_object_rw_to_object ( object_rw * obj_rw , object & obj ) ;
2009-03-20 12:10:38 +00:00
2020-05-02 21:18:42 +00:00
using GMNames_array = std : : array < char [ MULTI_GAME_NAME_LENGTH ] , MULTI_GAME_TYPE_COUNT > ;
2016-07-09 17:58:35 +00:00
extern const GMNames_array GMNames ;
2020-05-02 21:18:42 +00:00
using multi_allow_powerup_text_array = std : : array < char [ MULTI_ALLOW_POWERUP_TEXT_LENGTH ] , MULTI_ALLOW_POWERUP_MAX > ;
2016-07-09 17:58:35 +00:00
extern const multi_allow_powerup_text_array multi_allow_powerup_text ;
2020-05-02 21:18:42 +00:00
extern const std : : array < char [ 8 ] , MULTI_GAME_TYPE_COUNT > GMNamesShrt ;
2015-12-13 18:00:48 +00:00
}
2013-12-21 23:16:19 +00:00
2015-12-13 18:00:49 +00:00
namespace dcx {
2020-05-02 21:18:42 +00:00
extern std : : array < objnum_t , MAX_NET_CREATE_OBJECTS > Net_create_objnums ;
2015-02-14 22:48:27 +00:00
extern unsigned Net_create_loc ;
2015-12-13 18:00:48 +00:00
}
2013-12-21 23:16:19 +00:00
2016-10-02 19:35:34 +00:00
namespace dsx {
2015-04-19 04:18:53 +00:00
2017-06-10 03:31:02 +00:00
void multi_send_fire ( int laser_gun , int laser_level , int laser_flags , int laser_fired , objnum_t laser_track , imobjptridx_t is_bomb_objnum ) ;
2017-08-13 20:38:32 +00:00
void multi_send_destroy_controlcen ( objnum_t objnum , playernum_t player ) ;
2019-12-22 05:34:08 +00:00
void multi_send_position ( object & objnum ) ;
2017-06-10 03:31:02 +00:00
void multi_send_kill ( vmobjptridx_t objnum ) ;
2019-12-22 05:34:08 +00:00
void multi_send_remobj ( vmobjidx_t objnum ) ;
2016-12-05 00:26:09 +00:00
void multi_send_door_open ( vcsegidx_t segnum , unsigned side , uint8_t flag ) ;
2017-06-10 03:31:02 +00:00
void multi_send_drop_weapon ( vmobjptridx_t objnum , int seed ) ;
2019-12-22 05:34:08 +00:00
void multi_reset_player_object ( object & objp ) ;
2017-03-18 18:07:36 +00:00
int multi_maybe_disable_friendly_fire ( const object * killer ) ;
2015-12-13 18:00:48 +00:00
}
2013-12-21 23:16:19 +00:00
# endif
2013-12-13 21:47:46 +00:00
enum msgsend_state_t {
msgsend_none ,
msgsend_typing ,
2013-12-13 22:48:42 +00:00
msgsend_automap ,
2013-12-13 21:47:46 +00:00
} ;
2013-12-16 22:59:31 +00:00
enum deres_type_t {
deres_explode ,
deres_drop ,
} ;
2006-03-20 17:12:09 +00:00
// Exported functions
2014-09-13 23:45:13 +00:00
struct owned_remote_objnum
{
int8_t owner ;
2015-06-13 22:42:15 +00:00
uint16_t objnum ;
2014-09-13 23:45:13 +00:00
} ;
2009-04-09 07:41:30 +00:00
extern int GetMyNetRanking ( ) ;
2009-11-24 09:48:53 +00:00
extern void ClipRank ( ubyte * rank ) ;
2015-03-22 22:48:47 +00:00
objnum_t objnum_remote_to_local ( uint16_t remote_obj , int8_t owner ) ;
uint16_t objnum_local_to_remote ( objnum_t local_obj , int8_t * owner ) ;
2014-09-13 23:45:13 +00:00
owned_remote_objnum objnum_local_to_remote ( objnum_t local ) ;
2006-03-20 17:12:09 +00:00
void map_objnum_local_to_remote ( int local , int remote , int owner ) ;
2013-12-29 04:28:07 +00:00
void map_objnum_local_to_local ( objnum_t objnum ) ;
2006-03-20 17:12:09 +00:00
void reset_network_objects ( ) ;
2013-12-29 04:28:07 +00:00
int multi_objnum_is_past ( objnum_t objnum ) ;
2009-04-09 07:41:30 +00:00
void multi_do_ping_frame ( ) ;
2006-03-20 17:12:09 +00:00
void multi_init_objects ( void ) ;
2009-03-20 12:10:38 +00:00
void multi_do_protocol_frame ( int force , int listen ) ;
2017-01-10 06:10:39 +00:00
window_event_result multi_do_frame ( ) ;
2006-03-20 17:12:09 +00:00
2016-01-09 16:38:15 +00:00
# ifdef dsx
2015-12-13 18:00:49 +00:00
namespace dsx {
2016-11-12 18:10:09 +00:00
enum class multi_endlevel_type : bool
{
normal ,
# if defined(DXX_BUILD_DESCENT_I)
secret ,
# endif
} ;
2015-08-03 03:11:25 +00:00
# if defined(DXX_BUILD_DESCENT_I)
2016-11-12 18:10:09 +00:00
void multi_send_endlevel_start ( multi_endlevel_type ) ;
2015-08-03 03:11:25 +00:00
# elif defined(DXX_BUILD_DESCENT_II)
void multi_send_endlevel_start ( ) ;
2016-11-12 18:10:09 +00:00
static inline void multi_send_endlevel_start ( multi_endlevel_type )
2015-08-03 03:11:25 +00:00
{
multi_send_endlevel_start ( ) ;
}
# endif
2013-12-16 22:59:31 +00:00
void multi_send_player_deres ( deres_type_t type ) ;
2016-12-05 00:26:09 +00:00
void multi_send_create_powerup ( powerup_type_t powerup_type , vcsegidx_t segnum , vcobjidx_t objnum , const vms_vector & pos ) ;
2015-12-13 18:00:48 +00:00
}
2018-05-13 03:14:34 +00:00
void multi_send_play_sound ( int sound_num , fix volume , sound_stack once ) ;
2015-12-13 18:00:48 +00:00
# endif
2006-03-20 17:12:09 +00:00
void multi_send_reappear ( ) ;
2014-09-21 22:10:12 +00:00
void multi_send_create_explosion ( playernum_t ) ;
2015-02-14 22:48:29 +00:00
void multi_send_controlcen_fire ( const vms_vector & to_target , int gun_num , objnum_t objnum ) ;
2015-12-13 18:00:49 +00:00
namespace dcx {
2006-03-20 17:12:09 +00:00
void multi_send_cloak ( void ) ;
void multi_send_decloak ( void ) ;
2015-12-13 18:00:48 +00:00
}
2015-08-05 02:59:02 +00:00
void multi_digi_play_sample ( int sndnum , fix max_volume ) ;
void multi_digi_play_sample_once ( int soundnum , fix max_volume ) ;
2006-03-20 17:12:09 +00:00
void multi_send_score ( void ) ;
void multi_send_trigger ( int trigger ) ;
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2015-12-13 18:00:49 +00:00
namespace dsx {
2012-11-11 00:14:30 +00:00
extern char Multi_is_guided ;
2014-09-21 22:10:12 +00:00
void multi_send_flags ( playernum_t ) ;
2013-12-28 18:56:34 +00:00
struct marker_message_text_t ;
2013-12-29 20:52:17 +00:00
void multi_send_drop_marker ( int player , const vms_vector & position , char messagenum , const marker_message_text_t & text ) ;
2012-06-10 09:26:29 +00:00
void multi_send_markers ( ) ;
2018-10-08 03:58:48 +00:00
void multi_send_guided_info ( const object_base & miss , char ) ;
2017-03-18 18:07:36 +00:00
void multi_send_orb_bonus ( playernum_t pnum , uint8_t ) ;
2014-09-21 22:10:12 +00:00
void multi_send_got_orb ( playernum_t pnum ) ;
2016-12-05 00:26:10 +00:00
void multi_send_effect_blowup ( vcsegidx_t segnum , unsigned side , const vms_vector & pnt ) ;
2017-06-10 03:31:02 +00:00
void multi_send_vulcan_weapon_ammo_adjust ( const vmobjptridx_t objnum ) ;
2015-12-13 18:00:48 +00:00
}
2015-11-21 18:12:13 +00:00
# ifndef RELEASE
2015-11-27 03:56:13 +00:00
void multi_add_lifetime_kills ( int count ) ;
2015-11-21 18:12:13 +00:00
# endif
# endif
2011-01-19 01:19:17 +00:00
void multi_send_bounty ( void ) ;
2006-03-20 17:12:09 +00:00
2009-11-24 09:48:53 +00:00
void multi_consistency_error ( int reset ) ;
2017-01-10 05:02:59 +00:00
window_event_result multi_level_sync ( ) ;
2006-03-20 17:12:09 +00:00
int multi_endlevel ( int * secret ) ;
2016-01-26 03:45:06 +00:00
using multi_endlevel_poll = int ( newmenu * menu , const d_event & event , const unused_newmenu_userdata_t * ) ;
multi_endlevel_poll * get_multi_endlevel_poll2 ( ) ;
2009-04-09 07:41:30 +00:00
void multi_send_endlevel_packet ( ) ;
2016-01-09 16:38:15 +00:00
# ifdef dsx
2015-12-13 18:00:49 +00:00
namespace dsx {
2016-12-05 00:26:09 +00:00
void multi_send_hostage_door_status ( vcwallptridx_t wallnum ) ;
2018-10-21 00:24:07 +00:00
void multi_prep_level_objects ( const d_vclip_array & Vclip ) ;
2016-02-25 13:11:08 +00:00
void multi_prep_level_player ( ) ;
2006-03-20 17:12:09 +00:00
void multi_leave_game ( void ) ;
2015-12-13 18:00:48 +00:00
}
# endif
2014-09-21 22:10:21 +00:00
void multi_process_bigdata ( playernum_t pnum , const ubyte * buf , uint_fast32_t len ) ;
2006-03-20 17:12:09 +00:00
void multi_do_death ( int objnum ) ;
2016-01-09 16:38:15 +00:00
# ifdef dsx
2015-12-13 18:00:49 +00:00
namespace dsx {
2014-09-21 22:10:12 +00:00
void multi_make_ghost_player ( playernum_t ) ;
void multi_make_player_ghost ( playernum_t ) ;
2015-12-13 18:00:48 +00:00
}
# endif
2006-03-20 17:12:09 +00:00
void multi_define_macro ( int key ) ;
void multi_send_macro ( int key ) ;
2014-09-21 22:10:12 +00:00
int multi_get_kill_list ( playernum_array_t & sorted_kills ) ;
2006-03-20 17:12:09 +00:00
void multi_new_game ( void ) ;
2016-01-09 16:38:15 +00:00
# ifdef dsx
2015-12-13 18:00:49 +00:00
namespace dsx {
2006-03-20 17:12:09 +00:00
void multi_sort_kill_list ( void ) ;
2015-12-13 18:00:48 +00:00
}
# endif
2006-03-20 17:12:09 +00:00
void multi_reset_stuff ( void ) ;
2014-09-21 22:10:12 +00:00
int get_team ( playernum_t pnum ) ;
void multi_disconnect_player ( playernum_t ) ;
2006-03-20 17:12:09 +00:00
2016-01-09 16:38:15 +00:00
# ifdef dsx
2015-12-13 18:00:49 +00:00
namespace dsx {
2019-08-06 02:59:40 +00:00
void multi_initiate_save_game ( ) ;
void multi_initiate_restore_game ( ) ;
2020-04-26 17:26:23 +00:00
void multi_execute_save_game ( d_game_unique_state : : save_slot slot , const d_game_unique_state : : savegame_description & desc , partial_range_t < const player * > player_range ) ;
2013-09-21 23:34:05 +00:00
# if defined(DXX_BUILD_DESCENT_I)
2015-11-26 02:56:55 +00:00
static inline void multi_send_got_flag ( playernum_t ) { }
2013-09-21 23:34:05 +00:00
# elif defined(DXX_BUILD_DESCENT_II)
2014-09-21 22:10:12 +00:00
void multi_send_got_flag ( playernum_t ) ;
2013-09-21 23:34:05 +00:00
# endif
2015-12-13 18:00:48 +00:00
}
# endif
2006-03-20 17:12:09 +00:00
2009-04-09 07:41:30 +00:00
// Exported variables
2006-03-20 17:12:09 +00:00
2015-12-13 18:00:49 +00:00
namespace dcx {
2009-03-20 12:10:38 +00:00
extern int Network_status ;
2009-04-09 07:41:30 +00:00
// IMPORTANT: These variables needed for player rejoining done by protocol-specific code
extern int Network_send_objects ;
2009-11-24 09:48:53 +00:00
extern int Network_send_object_mode ;
2009-04-09 07:41:30 +00:00
extern int Network_send_objnum ;
2009-03-20 12:10:38 +00:00
extern int Network_rejoined ;
2009-11-24 09:48:53 +00:00
extern int Network_sending_extras ;
2010-11-22 21:44:03 +00:00
extern int VerifyPlayerJoined ;
2009-11-24 09:48:53 +00:00
extern int Player_joining_extras ;
extern int Network_player_added ;
2006-03-20 17:12:09 +00:00
2020-05-02 21:18:42 +00:00
extern std : : array < std : : array < uint16_t , MAX_PLAYERS > , MAX_PLAYERS > kill_matrix ;
extern std : : array < int16_t , 2 > team_kills ;
2006-03-20 17:12:09 +00:00
2009-03-20 12:10:38 +00:00
extern ushort my_segments_checksum ;
2006-03-20 17:12:09 +00:00
//do we draw the kill list on the HUD?
extern int Show_kill_list ;
extern int Show_reticle_name ;
extern fix Show_kill_list_timer ;
// Used to send network messages
2015-01-12 00:26:02 +00:00
extern ntstring < MAX_MESSAGE_LEN - 1 > Network_message ;
2006-03-20 17:12:09 +00:00
extern int Network_message_reciever ;
// Which player 'owns' each local object for network purposes
2020-05-02 21:18:42 +00:00
extern std : : array < sbyte , MAX_OBJECTS > object_owner ;
2006-03-20 17:12:09 +00:00
extern int multi_quit_game ;
2020-05-02 21:18:42 +00:00
extern std : : array < msgsend_state_t , MAX_PLAYERS > multi_sending_message ;
2006-03-20 17:12:09 +00:00
extern int multi_defining_message ;
2015-12-13 18:00:48 +00:00
}
2014-08-06 02:10:49 +00:00
window_event_result multi_message_input_sub ( int key ) ;
2006-03-20 17:12:09 +00:00
extern void multi_send_message_start ( ) ;
2013-12-13 22:48:42 +00:00
void multi_send_msgsend_state ( msgsend_state_t state ) ;
2006-03-20 17:12:09 +00:00
2015-12-13 18:00:48 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2015-12-13 18:00:49 +00:00
namespace dsx {
2020-05-02 21:18:42 +00:00
extern std : : array < grs_main_bitmap , 2 > Orb_icons ;
2017-08-13 20:38:32 +00:00
struct hoard_highest_record
{
unsigned points ;
unsigned player = UINT_MAX ;
} ;
extern hoard_highest_record hoard_highest_record_stats ;
2015-12-13 18:00:48 +00:00
}
# endif
2015-12-13 18:00:49 +00:00
namespace dcx {
2017-08-13 20:38:32 +00:00
extern playernum_t Bounty_target ;
2009-04-09 07:41:30 +00:00
2020-05-02 21:18:42 +00:00
extern std : : array < std : : array < bitmap_index , N_PLAYER_SHIP_TEXTURES > , MAX_PLAYERS > multi_player_textures ;
2006-03-20 17:12:09 +00:00
2020-05-02 21:18:42 +00:00
extern const std : : array < char [ 16 ] , 10 > RankStrings ;
2015-10-30 02:52:55 +00:00
# define GetRankStringWithSpace(I) (PlayerCfg.NoRankings ? std::pair<const char *, const char *>("", "") : std::pair<const char *, const char *>(RankStrings[I], " "))
2009-04-09 07:41:30 +00:00
2009-11-24 09:48:53 +00:00
// Globals for protocol-bound Refuse-functions
extern char RefuseThisPlayer , WaitForRefuseAnswer , RefuseTeam , RefusePlayerName [ 12 ] ;
2010-12-10 23:18:17 +00:00
extern fix64 RefuseTimeLimit ;
2009-11-24 09:48:53 +00:00
# define REFUSE_INTERVAL (F1_0*8)
2015-12-13 18:00:48 +00:00
}
2009-11-24 09:48:53 +00:00
2016-01-09 16:38:15 +00:00
# ifdef dsx
2015-12-13 18:00:49 +00:00
namespace dsx {
2013-12-22 22:03:07 +00:00
struct bit_game_flags {
2013-08-24 16:33:51 +00:00
unsigned closed : 1 ;
unsigned : 1 ;
unsigned show_on_map : 1 ;
/*
* These # define are written to . NGP files and to the network .
* Changing them breaks ABI compatibility .
* The bit flags need not match in value , and are converted below in
* pack_game_flags / unpack_game_flags .
*/
2006-03-20 17:12:09 +00:00
# define NETGAME_FLAG_CLOSED 1
# define NETGAME_FLAG_SHOW_MAP 4
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2013-08-24 16:33:51 +00:00
unsigned hoard : 1 ;
unsigned team_hoard : 1 ;
unsigned endlevel : 1 ;
unsigned forming : 1 ;
2006-03-20 17:12:09 +00:00
# define NETGAME_FLAG_HOARD 8
# define NETGAME_FLAG_TEAM_HOARD 16
# define NETGAME_FLAG_REALLY_ENDLEVEL 32
# define NETGAME_FLAG_REALLY_FORMING 64
2013-03-03 01:03:33 +00:00
# endif
2013-12-22 22:03:07 +00:00
} __pack__ ;
2015-12-13 18:00:48 +00:00
}
2013-08-24 16:33:51 +00:00
2015-12-13 18:00:49 +00:00
namespace dcx {
2013-12-22 22:03:07 +00:00
struct packed_game_flags
2013-08-24 16:33:51 +00:00
{
unsigned char value ;
2013-12-22 22:03:07 +00:00
} ;
2018-06-21 03:08:36 +00:00
# if DXX_USE_TRACKER
enum TrackerNATHolePunchWarn : uint8_t
{
Unset ,
UserEnabledHP ,
UserRejectedHP ,
} ;
# endif
2015-12-13 18:00:48 +00:00
}
2015-12-13 18:00:49 +00:00
namespace dsx {
2013-08-24 16:33:51 +00:00
static inline bit_game_flags unpack_game_flags ( const packed_game_flags * p )
{
bit_game_flags flags ;
flags . closed = ! ! ( p - > value & NETGAME_FLAG_CLOSED ) ;
flags . show_on_map = ! ! ( p - > value & NETGAME_FLAG_SHOW_MAP ) ;
# if defined(DXX_BUILD_DESCENT_II)
flags . hoard = ! ! ( p - > value & NETGAME_FLAG_HOARD ) ;
flags . team_hoard = ! ! ( p - > value & NETGAME_FLAG_TEAM_HOARD ) ;
flags . endlevel = ! ! ( p - > value & NETGAME_FLAG_REALLY_ENDLEVEL ) ;
flags . forming = ! ! ( p - > value & NETGAME_FLAG_REALLY_FORMING ) ;
# endif
return flags ;
}
static inline packed_game_flags pack_game_flags ( const bit_game_flags * flags )
{
packed_game_flags p ;
p . value =
( flags - > closed ? NETGAME_FLAG_CLOSED : 0 ) |
( flags - > show_on_map ? NETGAME_FLAG_SHOW_MAP : 0 ) |
# if defined(DXX_BUILD_DESCENT_II)
( flags - > hoard ? NETGAME_FLAG_HOARD : 0 ) |
( flags - > team_hoard ? NETGAME_FLAG_TEAM_HOARD : 0 ) |
( flags - > endlevel ? NETGAME_FLAG_REALLY_ENDLEVEL : 0 ) |
( flags - > forming ? NETGAME_FLAG_REALLY_FORMING : 0 ) |
# endif
0 ;
return p ;
}
2006-03-20 17:12:09 +00:00
2018-09-22 04:31:21 +00:00
constexpr std : : size_t NETGAME_NAME_LEN = 25 ;
2006-03-20 17:12:09 +00:00
extern struct netgame_info Netgame ;
2015-12-13 18:00:48 +00:00
}
# endif
2006-03-20 17:12:09 +00:00
2015-07-25 23:10:46 +00:00
# define multi_i_am_master() (Player_num == 0)
2017-08-13 20:38:32 +00:00
void change_playernum_to ( playernum_t new_pnum ) ;
2006-03-20 17:12:09 +00:00
2011-01-14 13:29:08 +00:00
// Multiplayer powerup capping
2016-07-14 01:59:03 +00:00
void MultiLevelInv_InitializeCount ( ) ;
void MultiLevelInv_Recount ( ) ;
2016-08-25 04:05:32 +00:00
# ifdef dsx
namespace dsx {
2016-02-25 13:11:08 +00:00
extern bool MultiLevelInv_AllowSpawn ( powerup_type_t powerup_type ) ;
2016-08-25 04:05:32 +00:00
}
# endif
2016-02-25 13:11:08 +00:00
extern void MultiLevelInv_Repopulate ( fix frequency ) ;
2016-01-09 16:38:15 +00:00
# ifdef dsx
2015-12-13 18:00:49 +00:00
namespace dsx {
2015-12-13 18:00:48 +00:00
uint_fast32_t multi_powerup_is_allowed ( const unsigned id , const unsigned AllowedItems ) ;
uint_fast32_t multi_powerup_is_allowed ( const unsigned id , const unsigned AllowedItems , const unsigned SpawnGrantedItems ) ;
2016-05-30 11:49:06 +00:00
void show_netgame_info ( const netgame_info & netgame ) ;
2016-02-25 13:11:08 +00:00
extern void multi_send_player_inventory ( int priority ) ;
2020-04-19 20:47:07 +00:00
const char * multi_common_deny_save_game ( const fvcobjptr & vcobjptr , partial_range_t < const player * > player_range ) ;
const char * multi_interactive_deny_save_game ( const fvcobjptr & vcobjptr , partial_range_t < const player * > player_range , const d_level_unique_control_center_state & ) ;
2016-08-25 04:05:32 +00:00
}
# endif
2013-01-03 15:33:57 +00:00
extern void multi_send_kill_goal_counts ( ) ;
2012-11-11 00:14:30 +00:00
void multi_check_for_killgoal_winner ( ) ;
2013-08-09 15:21:03 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2015-12-13 18:00:49 +00:00
namespace dsx {
2013-03-03 01:03:33 +00:00
extern void multi_send_stolen_items ( ) ;
2017-08-11 23:43:53 +00:00
void multi_send_trigger_specific ( playernum_t pnum , uint8_t trig ) ;
2016-12-05 00:26:10 +00:00
void multi_send_door_open_specific ( playernum_t pnum , vcsegidx_t segnum , unsigned side , uint8_t flag ) ;
2015-04-02 02:36:52 +00:00
void multi_send_wall_status_specific ( playernum_t pnum , uint16_t wallnum , ubyte type , ubyte flags , ubyte state ) ;
2016-12-10 17:51:07 +00:00
void multi_send_light_specific ( playernum_t pnum , vcsegptridx_t segnum , uint8_t val ) ;
2014-09-21 22:10:12 +00:00
void multi_send_capture_bonus ( playernum_t pnum ) ;
2020-04-19 20:47:07 +00:00
int multi_all_players_alive ( const fvcobjptr & , partial_range_t < const player * > ) ;
2015-02-14 22:48:29 +00:00
void multi_send_seismic ( fix ) ;
2014-09-21 22:10:12 +00:00
void multi_send_drop_blobs ( playernum_t ) ;
2012-11-11 00:14:30 +00:00
void multi_send_sound_function ( char , char ) ;
void DropFlag ( ) ;
void multi_send_finish_game ( ) ;
2018-10-21 00:24:07 +00:00
void init_hoard_data ( d_vclip_array & Vclip ) ;
2012-11-11 00:14:30 +00:00
void multi_apply_goal_textures ( ) ;
2019-06-27 03:26:20 +00:00
void multi_send_escort_goal ( const d_unique_buddy_state & ) ;
void multi_recv_escort_goal ( d_unique_buddy_state & , const uint8_t * ) ;
2011-01-14 13:29:08 +00:00
2009-11-24 09:48:53 +00:00
int HoardEquipped ( ) ;
2016-09-11 18:49:16 +00:00
# if DXX_USE_EDITOR
2006-10-02 13:29:04 +00:00
void save_hoard_data ( void ) ;
# endif
2015-12-13 18:00:48 +00:00
}
2013-03-03 01:03:33 +00:00
# endif
2006-10-02 13:29:04 +00:00
2013-08-09 15:21:03 +00:00
//how to encode missiles & flares in weapon packets
# define MISSILE_ADJUST 100
# define FLARE_ADJUST 127
2009-03-20 12:10:38 +00:00
/*
* The Network Players structure
2011-09-13 23:15:32 +00:00
* Contains protocol - specific data with designated prefixes and general player - related data .
2009-03-20 12:10:38 +00:00
* Note that not all of these infos will be sent to other users - some are used and / or set locally , only .
*/
2014-06-26 02:27:16 +00:00
struct netplayer_info : prohibit_void_ptr < netplayer_info >
2009-03-20 12:10:38 +00:00
{
2016-09-11 18:49:15 +00:00
# if DXX_USE_UDP
2009-03-20 12:10:38 +00:00
union
{
2016-09-11 18:49:15 +00:00
# if DXX_USE_UDP
2009-03-20 12:10:38 +00:00
struct
{
struct _sockaddr addr ; // IP address of this peer
} udp ;
2009-11-29 16:46:13 +00:00
# endif
2009-03-20 12:10:38 +00:00
} protocol ;
2009-11-29 16:46:13 +00:00
# endif
2014-07-05 16:48:12 +00:00
callsign_t callsign ;
2009-03-20 12:10:38 +00:00
sbyte connected ;
ubyte rank ;
2009-04-09 07:41:30 +00:00
fix ping ;
2010-12-10 23:18:17 +00:00
fix64 LastPacketTime ;
2014-06-26 02:27:16 +00:00
} ;
2009-03-20 12:10:38 +00:00
2016-01-09 16:38:15 +00:00
# ifdef dsx
Allow players to remove thief at level start
Commit f4b21088a039 ("Track vulcan ammo explicitly") fixed an original
retail bug that prevented the thief from stealing energy weapons,
because the thief could only steal weapons for which the player had ammo
and energy weapons never have ammo. This went unremarked for several
years, until a recent report of the new semantics as a game-breaking
regression because the thief is now "ridiculously potent".
Address this report, as well as an intermittently raised issue from
various users over time, by adding two new knobs to both the single
player "Gameplay" menu and the multiplayer setup screen: "Remove Thief
at level start" and "Prevent Thief Stealing Energy Weapons".
"Remove Thief" deletes the thief object during level load. It has no
impact on save games, and changing it after entering a level has no
effect on any thief already in the level.
"Prevent Thief Stealing" is checked at the moment of theft and, when
enabled, prevents stealing primary weapons other than Vulcan/Gauss.
This can be changed at will in single player and is immediately
effective. In multiplayer, this option can only be changed by the game
host in the pre-game setup.
For both knobs, there is one pair of checkboxes to control this as a
player preference, which applies in single player games. There is a
second pair of checkboxes in the multiplayer setup, which applies only
to multiplayer games. Therefore, in multiplayer, the host chooses thief
settings and all clients use the host's choice. The host may configure
the thief differently in multiplayer from how the host plays in single
player.
For users who wanted to remove the thief, no specific tally has been
kept for who requested it or when. Now that the code is being updated,
this is thrown in as an easy addition.
Reported-by: MegaDescent <http://forum.dxx-rebirth.com/showthread.php?tid=980> (for the thief stealing energy weapons as a game-breaking regression)
2017-08-26 19:47:52 +00:00
# if defined(DXX_BUILD_DESCENT_II)
struct ThiefModifier
{
enum Flags : uint8_t {
Absent = 1 ,
NoEnergyWeapons ,
} ;
} ;
# endif
2015-12-13 18:00:49 +00:00
namespace dsx {
2009-03-20 12:10:38 +00:00
/*
* The Network Game structure
2011-09-13 23:15:32 +00:00
* Contains protocol - specific data with designated prefixes and general game - related data .
2009-03-20 12:10:38 +00:00
* Note that not all of these infos will be sent to clients - some are used and / or set locally , only .
*/
2014-09-07 18:06:59 +00:00
struct netgame_info : prohibit_void_ptr < netgame_info > , ignore_window_pointer_t
2009-03-20 12:10:38 +00:00
{
2020-04-19 20:47:07 +00:00
using play_time_allowed_abi_ratio = std : : ratio < 5 * 60 > ;
2016-09-11 18:49:15 +00:00
# if DXX_USE_UDP
2009-03-20 12:10:38 +00:00
union
{
2016-09-11 18:49:15 +00:00
# if DXX_USE_UDP
2009-03-20 12:10:38 +00:00
struct
{
2011-05-04 22:16:37 +00:00
struct _sockaddr addr ; // IP address of this netgame's host
2020-05-02 21:18:42 +00:00
std : : array < short , 4 > program_iver ; // IVER of program for version checking
2009-11-24 09:48:53 +00:00
sbyte valid ; // Status of Netgame info: -1 = Failed, Wrong version; 0 = No info, yet; 1 = Success
2014-08-16 21:56:46 +00:00
uint8_t your_index ; // Tell player his designated (re)join position in players[]
2010-12-22 13:55:26 +00:00
fix GameID ;
2009-03-20 12:10:38 +00:00
} udp ;
2009-11-29 16:46:13 +00:00
# endif
2009-03-20 12:10:38 +00:00
} protocol ;
2009-11-29 16:46:13 +00:00
# endif
2014-12-22 04:35:48 +00:00
ntstring < NETGAME_NAME_LEN > game_name ;
2014-12-22 04:35:48 +00:00
ntstring < MISSION_NAME_LEN > mission_title ;
2015-01-03 23:44:32 +00:00
ntstring < 8 > mission_name ;
2009-03-20 12:10:38 +00:00
int levelnum ;
2018-05-12 18:24:19 +00:00
Difficulty_level_type difficulty ;
2009-03-20 12:10:38 +00:00
ubyte gamemode ;
ubyte RefusePlayers ;
ubyte game_status ;
ubyte numplayers ;
ubyte max_numplayers ;
ubyte numconnected ;
2013-08-24 16:33:51 +00:00
bit_game_flags game_flag ;
2009-03-20 12:10:38 +00:00
ubyte team_vector ;
2015-07-04 21:01:18 +00:00
uint8_t SecludedSpawns ;
2017-03-25 19:34:02 +00:00
uint8_t MouselookFlags ;
2015-01-03 06:34:13 +00:00
uint32_t AllowedItems ;
2015-04-19 04:18:53 +00:00
packed_spawn_granted_items SpawnGrantedItems ;
2015-04-19 04:18:53 +00:00
packed_netduplicate_items DuplicatePowerups ;
2018-04-12 04:19:35 +00:00
unsigned ShufflePowerupSeed ;
2020-04-19 20:47:07 +00:00
d_mp_gameplay_options MPGameplayOptions ;
2014-09-28 21:09:22 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2017-08-26 19:47:51 +00:00
uint8_t Allow_marker_view ;
uint8_t AlwaysLighting ;
Allow players to remove thief at level start
Commit f4b21088a039 ("Track vulcan ammo explicitly") fixed an original
retail bug that prevented the thief from stealing energy weapons,
because the thief could only steal weapons for which the player had ammo
and energy weapons never have ammo. This went unremarked for several
years, until a recent report of the new semantics as a game-breaking
regression because the thief is now "ridiculously potent".
Address this report, as well as an intermittently raised issue from
various users over time, by adding two new knobs to both the single
player "Gameplay" menu and the multiplayer setup screen: "Remove Thief
at level start" and "Prevent Thief Stealing Energy Weapons".
"Remove Thief" deletes the thief object during level load. It has no
impact on save games, and changing it after entering a level has no
effect on any thief already in the level.
"Prevent Thief Stealing" is checked at the moment of theft and, when
enabled, prevents stealing primary weapons other than Vulcan/Gauss.
This can be changed at will in single player and is immediately
effective. In multiplayer, this option can only be changed by the game
host in the pre-game setup.
For both knobs, there is one pair of checkboxes to control this as a
player preference, which applies in single player games. There is a
second pair of checkboxes in the multiplayer setup, which applies only
to multiplayer games. Therefore, in multiplayer, the host chooses thief
settings and all clients use the host's choice. The host may configure
the thief differently in multiplayer from how the host plays in single
player.
For users who wanted to remove the thief, no specific tally has been
kept for who requested it or when. Now that the code is being updated,
this is thrown in as an easy addition.
Reported-by: MegaDescent <http://forum.dxx-rebirth.com/showthread.php?tid=980> (for the thief stealing energy weapons as a game-breaking regression)
2017-08-26 19:47:52 +00:00
uint8_t ThiefModifierFlags ;
2019-06-27 03:26:20 +00:00
uint8_t AllowGuidebot ;
2014-09-28 21:09:22 +00:00
# endif
2017-08-26 19:47:51 +00:00
uint8_t ShowEnemyNames ;
uint8_t BrightPlayers ;
uint8_t InvulAppear ;
2009-03-20 12:10:38 +00:00
ushort segments_checksum ;
2011-05-04 22:16:37 +00:00
int KillGoal ;
2020-04-19 20:47:07 +00:00
/* The UI enforces that this steps in units of 5 minutes, but for
* efficiency , it is stored as ticks ( 1 second = F1_0 ) . The UI
* imposes a maximum value that is small enough that overflow is
* impossible .
*/
d_time_fix PlayTimeAllowed ;
2011-05-04 22:16:37 +00:00
fix level_time ;
int control_invul_time ;
int monitor_vector ;
2009-03-20 12:10:38 +00:00
short PacketsPerSec ;
2009-11-29 16:46:13 +00:00
ubyte PacketLossPrevention ;
2011-01-14 18:48:48 +00:00
ubyte NoFriendlyFire ;
2020-05-02 21:18:42 +00:00
std : : array < callsign_t , 2 > team_name ;
std : : array < uint32_t , MAX_PLAYERS > locations ;
std : : array < std : : array < uint16_t , MAX_PLAYERS > , MAX_PLAYERS > kills ;
std : : array < int16_t , 2 > team_kills ;
std : : array < uint16_t , MAX_PLAYERS > killed ;
std : : array < uint16_t , MAX_PLAYERS > player_kills ;
std : : array < uint32_t , MAX_PLAYERS > player_score ;
std : : array < player_flags , MAX_PLAYERS > net_player_flags ;
std : : array < netplayer_info , MAX_PLAYERS > players ;
2016-09-11 18:49:15 +00:00
# if DXX_USE_TRACKER
2011-04-05 00:24:34 +00:00
ubyte Tracker ;
2018-06-21 03:08:36 +00:00
TrackerNATHolePunchWarn TrackerNATWarned ;
2011-04-05 00:24:34 +00:00
# endif
2014-06-26 02:27:16 +00:00
} ;
2016-02-25 13:11:08 +00:00
/*
* Structure holding all powerup types we want to keep track of . Used to cap or respawn powerups and keep the level inventory steady .
* Using uint32_t because we don ' t count powerup units but what the powerup contains ( 1 or 4 missiles , vulcam amount , etc ) so we can keep track of overhead .
* I ' m sorry if this isn ' t very optimized but I found this easier to handle than a single variable per powerup .
*/
struct multi_level_inv
{
2020-05-02 21:18:42 +00:00
std : : array < uint32_t , MAX_POWERUP_TYPES > Initial ; // initial (level start) count of this powerup type
std : : array < uint32_t , MAX_POWERUP_TYPES > Current ; // current count of this powerup type
std : : array < fix , MAX_POWERUP_TYPES > RespawnTimer ; // incremented by FrameTime if initial-current > 0 and triggers respawn after 2 seconds. Since we deal with a certain delay from clients, their inventory updates may happen a while after they remove the powerup object and we do not want to respawn it on accident during that time window!
2016-02-25 13:11:08 +00:00
} ;
2015-12-13 18:00:48 +00:00
}
2015-07-04 21:01:17 +00:00
# endif
2012-11-11 22:12:51 +00:00
2014-12-07 00:00:22 +00:00
namespace multi
{
struct level_checksum_mismatch : std : : runtime_error
{
level_checksum_mismatch ( ) :
runtime_error ( " level checksum mismatch " )
{
}
} ;
struct local_player_not_playing : std : : runtime_error
{
local_player_not_playing ( ) :
runtime_error ( " local player not playing " )
{
}
} ;
}
2015-03-09 03:33:07 +00:00
/* Stub for mods that remap player colors */
static inline unsigned get_player_color ( unsigned pnum )
{
return pnum ;
}
static inline unsigned get_team_color ( unsigned tnum )
{
return tnum ;
}
static inline unsigned get_player_or_team_color ( unsigned pnum )
{
return Game_mode & GM_TEAM
? get_team_color ( get_team ( pnum ) )
: get_player_color ( pnum ) ;
}
2012-11-11 22:12:51 +00:00
# endif