diff --git a/SConstruct b/SConstruct index e3ea88c2c..41d1d9f08 100644 --- a/SConstruct +++ b/SConstruct @@ -917,7 +917,7 @@ int main(int argc,char**argv){(void)argc;(void)argv; Result('%s: building with %s' % (self.msgprefix, s)) def _result_check_user_setting(self,context,condition,CPPDEFINES,label,int=int,str=str): if isinstance(CPPDEFINES, str): - context.sconf.Define(CPPDEFINES, int(condition)) + self._define_macro(context, CPPDEFINES, int(condition)) elif condition: self.successful_flags['CPPDEFINES'].extend(CPPDEFINES) context.Result('%s: checking whether to enable %s...%s' % (self.msgprefix, label, 'yes' if condition else 'no')) @@ -2064,8 +2064,12 @@ where the cast is useless. def check_getaddrinfo_present(self,context,_successflags={'CPPDEFINES' : ['DXX_HAVE_GETADDRINFO']}): self.Compile(context, text=''' #ifdef WIN32 +#define DXX_WIN32_MINIMUM_WIN32_WINNT 0x0600 +#if defined(_WIN32_WINNT) && (_WIN32_WINNT < DXX_WIN32_MINIMUM_WIN32_WINNT) +#undef _WIN32_WINNT +#endif #ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x0501 +#define _WIN32_WINNT DXX_WIN32_MINIMUM_WIN32_WINNT #endif #include #include @@ -2076,8 +2080,15 @@ where the cast is useless. #endif ''', main=''' addrinfo *res = nullptr; - const addrinfo *hints = nullptr; - int i = getaddrinfo("", "", hints, &res); + addrinfo hints{}; +#ifdef AI_NUMERICSERV + /* Test that it is defined to a term that can be used with bit-or */ + hints.ai_flags |= AI_NUMERICSERV; +#endif +#if DXX_USE_IPv6 + hints.ai_flags |= AI_V4MAPPED | AI_ALL; +#endif + int i = getaddrinfo("", "", &hints, &res); (void)i; freeaddrinfo(res); return 0; @@ -3650,8 +3661,8 @@ class DXXArchive(DXXCommon): class DXXProgram(DXXCommon): # version number VERSION_MAJOR = 0 - VERSION_MINOR = 58 - VERSION_MICRO = 1 + VERSION_MINOR = 59 + VERSION_MICRO = 100 static_archive_construction = {} def _apply_target_name(self,name): return os.path.join(os.path.dirname(name), '.%s.%s' % (self.target, os.path.splitext(os.path.basename(name))[0])) diff --git a/common/arch/sdl/event.cpp b/common/arch/sdl/event.cpp index 80f968e45..1c37da9c5 100644 --- a/common/arch/sdl/event.cpp +++ b/common/arch/sdl/event.cpp @@ -161,24 +161,24 @@ window_event_result event_process(void) return highest_result; event.type = EVENT_WINDOW_DRAW; // then draw all visible windows - wind = window_get_first(); - while (wind != NULL) + for (wind = window_get_first(); wind != nullptr;) { - window *prev = window_get_prev(*wind); if (window_is_visible(wind)) { + auto prev = window_get_prev(*wind); auto result = window_send_event(*wind, event); + highest_result = std::max(result, highest_result); if (result == window_event_result::deleted) { - if (!prev) // well there isn't a previous window ... - break; // ... just bail out - we've done everything for this frame we can. - wind = window_get_next(*prev); // the current window seemed to be closed. so take the next one from the previous which should be able to point to the one after the current closed + if (!prev) + { + wind = window_get_first(); + continue; + } + wind = prev; // take the previous window and get the next one from that (if prev isn't nullptr) } - else - wind = window_get_next(*wind); - - highest_result = std::max(result, highest_result); } + wind = window_get_next(*wind); } gr_flip(); diff --git a/common/include/console.h b/common/include/console.h index 204297af8..8bcbc4fc5 100644 --- a/common/include/console.h +++ b/common/include/console.h @@ -52,15 +52,15 @@ static inline void con_puts_literal(int level, const char (&str)[len]) } #define con_puts(A1,S,...) (con_puts(A1,S, _dxx_call_puts_parameter2(1, ## __VA_ARGS__, strlen(S)))) void con_printf(int level, const char *fmt, ...) __attribute_format_printf(2, 3); -#ifdef DXX_HAVE_BUILTIN_CONSTANT_P -#define _dxx_con_printf_check_trailing_newline(F) \ - (sizeof((F)) > 1 && (F)[sizeof((F)) - 2] == '\n' && \ +#ifdef DXX_CONSTANT_TRUE +#define DXX_CON_PRINTF_CHECK_TRAILING_NEWLINE(F) \ + (DXX_CONSTANT_TRUE(sizeof((F)) > 1 && (F)[sizeof((F)) - 2] == '\n') && \ (DXX_ALWAYS_ERROR_FUNCTION(dxx_trap_trailing_newline, "trailing literal newline on con_printf"), 0)), #else -#define _dxx_con_printf_check_trailing_newline(C) +#define DXX_CON_PRINTF_CHECK_TRAILING_NEWLINE(C) #endif #define con_printf(A1,F,...) \ - _dxx_con_printf_check_trailing_newline(F) \ + DXX_CON_PRINTF_CHECK_TRAILING_NEWLINE(F) \ dxx_call_printf_checked(con_printf,con_puts_literal,(A1),(F),##__VA_ARGS__) void con_showup(void); diff --git a/common/include/fmtcheck.h b/common/include/fmtcheck.h index 1ee38aeb9..2a7ec00c2 100644 --- a/common/include/fmtcheck.h +++ b/common/include/fmtcheck.h @@ -14,10 +14,10 @@ #define DXX_CALL_PRINTF_DELETE_COMMA2_(A,...) __VA_ARGS__ #define DXX_CALL_PRINTF_DELETE_COMMA_(A,...) DXX_CALL_PRINTF_DELETE_COMMA2_( A , ## __VA_ARGS__ ) -#ifdef DXX_HAVE_BUILTIN_CONSTANT_P +#ifdef DXX_CONSTANT_TRUE #define DXX_PRINTF_CHECK_HAS_NONTRIVIAL_FORMAT_STRING_(V,P,FMT) \ - ((void)((dxx_builtin_constant_p((FMT)) && (FMT)[0] == '%' && (FMT)[1] == 's' && (FMT)[2] == 0) && \ - (DXX_ALWAYS_ERROR_FUNCTION(dxx_trap_trivial_string_specifier_argument_##V, "bare %s argument to " #V "; use " #P " directly"), 0))) + static_cast(DXX_CONSTANT_TRUE((FMT) && (FMT)[0] == '%' && (FMT)[1] == 's' && (FMT)[2] == 0) && \ + (DXX_ALWAYS_ERROR_FUNCTION(dxx_trap_trivial_string_specifier_argument_##V, "bare %s argument to " #V "; use " #P " directly"), 0)) #else #define DXX_PRINTF_CHECK_HAS_NONTRIVIAL_FORMAT_STRING_(V,P,FMT) \ ((void)(FMT)) diff --git a/common/include/partial_range.h b/common/include/partial_range.h index 9bd601671..d5e945945 100644 --- a/common/include/partial_range.h +++ b/common/include/partial_range.h @@ -155,7 +155,7 @@ namespace partial_range_detail template static inline void check_range_bounds(const char *file, unsigned line, const char *estr, const void *t, const std::size_t o, const std::size_t l, const std::size_t d) { -#ifdef DXX_HAVE_BUILTIN_CONSTANT_P +#ifdef DXX_CONSTANT_TRUE /* * If EXPR and d are compile-time constant, and the (EXPR > d) * branch is optimized out, then the expansion of @@ -176,8 +176,8 @@ static inline void check_range_bounds(const char *file, unsigned line, const cha * as compile-time constant. * * If the compiler cannot optimize based on the result of - * __builtin_constant_p (such as at -O0), then configure tests set - * !DXX_HAVE_BUILTIN_CONSTANT_P and the macro expands to nothing. + * __builtin_constant_p (such as at -O0), then configure tests do + * not define DXX_CONSTANT_TRUE and the macro expands to nothing. */ #define PARTIAL_RANGE_COMPILE_CHECK_BOUND(EXPR,S) \ (DXX_CONSTANT_TRUE(EXPR > d) && (DXX_ALWAYS_ERROR_FUNCTION(partial_range_will_always_throw_##S, #S " will always throw"), 0)) @@ -237,7 +237,7 @@ template __attribute_warn_unused_result static inline partial_range_t (unchecked_partial_range)(const char *file, unsigned line, const char *estr, I range_begin, const std::size_t o, const std::size_t l, std::true_type) { -#ifdef DXX_HAVE_BUILTIN_CONSTANT_P +#ifdef DXX_CONSTANT_TRUE /* Compile-time only check. Runtime handles (o > l) correctly, and * it can happen in a correct program. If it is guaranteed to * happen, then the range is always empty, which likely indicates a diff --git a/common/include/physfsx.h b/common/include/physfsx.h index 61e0ca54d..955924de3 100644 --- a/common/include/physfsx.h +++ b/common/include/physfsx.h @@ -44,7 +44,7 @@ #include "compiler-type_traits.h" #include "partial_range.h" -#ifdef DXX_HAVE_BUILTIN_CONSTANT_P +#ifdef DXX_CONSTANT_TRUE #define _DXX_PHYSFS_CHECK_SIZE_CONSTANT(S,v) DXX_CONSTANT_TRUE((S) > (v)) #define _DXX_PHYSFS_CHECK_SIZE(S,C,v) _DXX_PHYSFS_CHECK_SIZE_CONSTANT(static_cast(S) * static_cast(C), v) #define DXX_PHYSFS_CHECK_READ_SIZE_OBJECT_SIZE(S,C,v) \ diff --git a/common/include/valptridx.h b/common/include/valptridx.h index 7fb4952b0..267833a7a 100644 --- a/common/include/valptridx.h +++ b/common/include/valptridx.h @@ -361,9 +361,9 @@ public: } template basic_ptr(const magic_constant &, array_managed_type &a) : - m_ptr(static_cast(v) < array_size ? &(a[v]) : nullptr) + m_ptr(&a[v]) { - static_assert(allow_nullptr || static_cast(v) < array_size, "invalid magic index not allowed for this policy"); + static_assert(static_cast(v) < array_size, "valid magic index required when using array"); } template basic_ptr(const basic_ptr &rhs DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_L_DECL_VARS) : diff --git a/common/main/multi.h b/common/main/multi.h index eee04015a..31265b315 100644 --- a/common/main/multi.h +++ b/common/main/multi.h @@ -25,6 +25,7 @@ COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. #pragma once +#include "dxxsconf.h" #include "fwd-player.h" #include "player-callsign.h" #include "player-flags.h" @@ -37,10 +38,20 @@ COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. #include "game.h" #ifdef _WIN32 -#ifdef _WIN32_WINNT +/* Require _WIN32_WINNT >= 0x0501 to enable getaddrinfo + * Require _WIN32_WINNT >= 0x0600 to enable some useful AI_* flags + */ +#ifdef DXX_HAVE_GETADDRINFO +#define DXX_WIN32_MINIMUM_WIN32_WINNT 0x0600 +#else +#define DXX_WIN32_MINIMUM_WIN32_WINNT 0x0500 +#endif +#if defined(_WIN32_WINNT) && (_WIN32_WINNT < DXX_WIN32_MINIMUM_WIN32_WINNT) #undef _WIN32_WINNT #endif -#define _WIN32_WINNT 0x0501 // for get/freeaddrinfo() +#ifndef _WIN32_WINNT +#define _WIN32_WINNT DXX_WIN32_MINIMUM_WIN32_WINNT +#endif #include #include #include @@ -94,7 +105,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. Reset to 0 each time the version of the game changes -#define MULTI_PROTO_VERSION static_cast(27) +#define MULTI_PROTO_VERSION static_cast(2) // PROTOCOL VARIABLES AND DEFINES - END // limits for Packets (i.e. positional updates) per sec @@ -494,17 +505,20 @@ void multi_do_frame(void); #ifdef dsx namespace dsx { + +enum class multi_endlevel_type : bool +{ + normal, #if defined(DXX_BUILD_DESCENT_I) -void multi_send_endlevel_start(bool); + secret, +#endif +}; +#if defined(DXX_BUILD_DESCENT_I) +void multi_send_endlevel_start(multi_endlevel_type); #elif defined(DXX_BUILD_DESCENT_II) void multi_send_endlevel_start(); -static inline void multi_send_endlevel_start(bool secret) +static inline void multi_send_endlevel_start(multi_endlevel_type) { -#ifdef DXX_HAVE_BUILTIN_CONSTANT_P - if (!dxx_builtin_constant_p(!!secret) || secret) - DXX_ALWAYS_ERROR_FUNCTION(multi_send_endlevel_start_with_secret, "secret not supported in Descent II"); -#endif - (void)secret; multi_send_endlevel_start(); } #endif diff --git a/common/main/multiinternal.h b/common/main/multiinternal.h index 2c595d534..1832084ec 100644 --- a/common/main/multiinternal.h +++ b/common/main/multiinternal.h @@ -10,6 +10,7 @@ #include "object.h" #include "powerup.h" #include "serial.h" +#include "fwd-player.h" #define _UNPACK_MULTIPLAYER_SERIAL_MESSAGE(A,...) A, ## __VA_ARGS__ #define DEFINE_MULTIPLAYER_SERIAL_MESSAGE(C,T,V,A) \ @@ -32,7 +33,7 @@ VALUE(MULTI_CONTROLCEN , 4) \ VALUE(MULTI_ROBOT_CLAIM , 5) \ VALUE(MULTI_CLOAK , 2) \ - VALUE(MULTI_ENDLEVEL_START , 3) \ + VALUE(MULTI_ENDLEVEL_START , DXX_MP_SIZE_ENDLEVEL_START) \ VALUE(MULTI_CREATE_EXPLOSION , 2) \ VALUE(MULTI_CONTROLCEN_FIRE , 16) \ VALUE(MULTI_CREATE_POWERUP , 19) \ @@ -56,7 +57,7 @@ VALUE(MULTI_SAVE_GAME , 2+24) /* (ubyte slot, uint id, char name[20]) */ \ VALUE(MULTI_RESTORE_GAME , 2+4) /* (ubyte slot, uint id) */ \ VALUE(MULTI_HEARTBEAT , 5) \ - VALUE(MULTI_KILLGOALS , 9) \ + VALUE(MULTI_KILLGOALS , 1 + MAX_PLAYERS) \ VALUE(MULTI_DO_BOUNTY , 2) \ VALUE(MULTI_TYPING_STATE , 3) \ VALUE(MULTI_GMODE_UPDATE , 3) \ @@ -68,12 +69,14 @@ D2X_MP_COMMANDS(VALUE) \ #if defined(DXX_BUILD_DESCENT_I) +#define DXX_MP_SIZE_ENDLEVEL_START 3 #define DXX_MP_SIZE_PLAYER_RELATED 58 #define DXX_MP_SIZE_PLAYER_INVENTORY 15 #define DXX_MP_SIZE_BEGIN_SYNC 37 #define DXX_MP_SIZE_DOOR_OPEN 4 #define D2X_MP_COMMANDS(VALUE) #elif defined(DXX_BUILD_DESCENT_II) +#define DXX_MP_SIZE_ENDLEVEL_START 2 #define DXX_MP_SIZE_PLAYER_RELATED (97+10) #define DXX_MP_SIZE_PLAYER_INVENTORY 21 #define DXX_MP_SIZE_BEGIN_SYNC 41 diff --git a/common/main/object.h b/common/main/object.h index f8eeaac97..8546ec6d4 100644 --- a/common/main/object.h +++ b/common/main/object.h @@ -96,6 +96,7 @@ struct player_info fix homing_object_dist; // Distance of nearest homing object. #if defined(DXX_BUILD_DESCENT_II) fix Omega_charge; + fix Omega_recharge_delay; #endif player_flags powerup_flags; objnum_t killer_objnum; // Who killed me.... (-1 if no one) @@ -117,6 +118,9 @@ struct player_info array Primary_last_was_super; array Secondary_last_was_super; #endif + int16_t net_killed_total; // Number of times killed total + int16_t net_kills_total; // Number of net kills total + int16_t KillGoalCount; // Num of players killed this level union { struct { int score; // Current score. diff --git a/common/main/player.h b/common/main/player.h index e4e43e444..12a103f64 100644 --- a/common/main/player.h +++ b/common/main/player.h @@ -64,9 +64,6 @@ struct player : public prohibit_void_ptr fix time_total; // Game time played (high word = seconds) - short KillGoalCount; // Num of players killed this level - short net_killed_total; // Number of times killed total - short net_kills_total; // Number of net kills total short num_kills_level; // Number of kills this level short num_kills_total; // Number of kills total short num_robots_level; // Number of initial robots this level diff --git a/similar/main/endlevel.cpp b/similar/main/endlevel.cpp index 1851066f4..1b665e3cc 100644 --- a/similar/main/endlevel.cpp +++ b/similar/main/endlevel.cpp @@ -322,7 +322,7 @@ void start_endlevel_sequence() get_local_plrobj().ctype.player_info.homing_object_dist = -F1_0; // Turn off homing sound. if (Game_mode & GM_MULTI) { - multi_send_endlevel_start(0); + multi_send_endlevel_start(multi_endlevel_type::normal); multi_do_protocol_frame(1, 1); } @@ -412,7 +412,7 @@ void start_endlevel_sequence() } if (Game_mode & GM_MULTI) { - multi_send_endlevel_start(0); + multi_send_endlevel_start(multi_endlevel_type::normal); multi_do_protocol_frame(1, 1); } #ifndef NDEBUG diff --git a/similar/main/gamerend.cpp b/similar/main/gamerend.cpp index 452905642..8dff99816 100644 --- a/similar/main/gamerend.cpp +++ b/similar/main/gamerend.cpp @@ -196,9 +196,11 @@ static void show_netplayerinfo() gr_set_fontcolor(BM_XRGB(prgb.r, prgb.g, prgb.b), -1); gr_printf(x,y,"%s\n",static_cast(Players[i].callsign)); { + auto &plrobj = *vcobjptr(Players[i].objnum); + auto &player_info = plrobj.ctype.player_info; auto v = ((Game_mode & GM_MULTI_COOP) - ? vcobjptr(Players[i].objnum)->ctype.player_info.mission.score - : (gr_printf(x + fspacx8 * 12, y,"%-6d", Players[i].net_killed_total), Players[i].net_kills_total) + ? player_info.mission.score + : (gr_printf(x + fspacx8 * 12, y,"%-6d", player_info.net_killed_total), player_info.net_kills_total) ); gr_printf(x + fspacx8 * 7, y, "%-6d", v); } diff --git a/similar/main/gameseq.cpp b/similar/main/gameseq.cpp index 9b5d14a8c..fba158a33 100644 --- a/similar/main/gameseq.cpp +++ b/similar/main/gameseq.cpp @@ -287,18 +287,18 @@ void init_player_stats_game(ubyte pnum) Players[pnum].time_total = 0; Players[pnum].hours_level = 0; Players[pnum].hours_total = 0; - Players[pnum].net_killed_total = 0; - Players[pnum].net_kills_total = 0; Players[pnum].num_kills_level = 0; Players[pnum].num_kills_total = 0; Players[pnum].num_robots_level = 0; Players[pnum].num_robots_total = 0; - Players[pnum].KillGoalCount = 0; Players[pnum].hostages_level = 0; Players[pnum].hostages_total = 0; const auto &&plobj = vobjptr(Players[pnum].objnum); auto &player_info = plobj->ctype.player_info; player_info.powerup_flags = {}; + player_info.net_killed_total = 0; + player_info.net_kills_total = 0; + player_info.KillGoalCount = 0; player_info.mission.score = 0; player_info.mission.last_score = 0; player_info.mission.hostages_rescued_total = 0; @@ -429,6 +429,7 @@ void init_player_stats_new_ship(ubyte pnum) player_info.powerup_flags &= ~(PLAYER_FLAGS_AFTERBURNER | PLAYER_FLAGS_MAP_ALL | PLAYER_FLAGS_CONVERTER | PLAYER_FLAGS_AMMO_RACK | PLAYER_FLAGS_HEADLIGHT | PLAYER_FLAGS_HEADLIGHT_ON | PLAYER_FLAGS_FLAG); if (granted_primary_weapon_flags & HAS_OMEGA_FLAG) player_info.Omega_charge = MAX_OMEGA_CHARGE; + player_info.Omega_recharge_delay = 0; #endif player_info.powerup_flags |= map_granted_flags_to_player_flags(GrantedItems); DXX_MAKE_VAR_UNDEFINED(player_info.cloak_time); diff --git a/similar/main/gauges.cpp b/similar/main/gauges.cpp index b3e3c8500..27c53669b 100644 --- a/similar/main/gauges.cpp +++ b/similar/main/gauges.cpp @@ -670,15 +670,14 @@ static void hud_show_score() gr_set_curfont( GAME_FONT ); - auto &plr = get_local_player(); const char *label; int value; + auto &player_info = get_local_plrobj().ctype.player_info; if ( ((Game_mode & GM_MULTI) && !(Game_mode & GM_MULTI_COOP)) ) { label = TXT_KILLS; - value = plr.net_kills_total; + value = player_info.net_kills_total; } else { label = TXT_SCORE; - auto &player_info = get_local_plrobj().ctype.player_info; value = player_info.mission.score; } snprintf(score_str, sizeof(score_str), "%s: %5d", label, value); @@ -769,11 +768,10 @@ static void sb_show_score(const local_multires_gauge_graphic multires_gauge_grap gr_printf(HUD_SCALE_X(SB_SCORE_LABEL_X), HUD_SCALE_Y(SB_SCORE_Y), "%s:", (Game_mode & GM_MULTI) && !(Game_mode & GM_MULTI_COOP) ? TXT_KILLS : TXT_SCORE); gr_set_curfont( GAME_FONT ); - auto &player = get_local_player(); auto &player_info = get_local_plrobj().ctype.player_info; snprintf(score_str, sizeof(score_str), "%5d", (Game_mode & GM_MULTI) && !(Game_mode & GM_MULTI_COOP) - ? player.net_kills_total + ? player_info.net_kills_total : (gr_set_fontcolor(BM_XRGB(0,31,0), -1), player_info.mission.score)); int w, h; gr_get_string_size(score_str, &w, &h, nullptr); @@ -1608,7 +1606,8 @@ static void hud_show_lives(const local_multires_gauge_graphic multires_gauge_gra if (Game_mode & GM_MULTI) { gr_set_curfont( GAME_FONT ); gr_set_fontcolor(BM_XRGB(0,31,0),-1 ); - gr_printf(x, FSPACY(1), "%s: %d", TXT_DEATHS, get_local_player().net_killed_total); + auto &player_info = get_local_plrobj().ctype.player_info; + gr_printf(x, FSPACY(1), "%s: %d", TXT_DEATHS, player_info.net_killed_total); } else if (get_local_player().lives > 1) { gr_set_curfont( GAME_FONT ); @@ -1637,7 +1636,8 @@ static void sb_show_lives(const local_multires_gauge_graphic multires_gauge_grap char killed_str[20]; static array last_x{{SB_SCORE_RIGHT_L, SB_SCORE_RIGHT_L, SB_SCORE_RIGHT_H, SB_SCORE_RIGHT_H}}; - snprintf(killed_str, sizeof(killed_str), "%5d", get_local_player().net_killed_total); + auto &player_info = get_local_plrobj().ctype.player_info; + snprintf(killed_str, sizeof(killed_str), "%5d", player_info.net_killed_total); int w, h; gr_get_string_size(killed_str, &w, &h, nullptr); const auto x = HUD_SCALE_X(SB_SCORE_RIGHT)-w-FSPACX(1); @@ -2972,6 +2972,7 @@ static void hud_show_kill_list() player_num = i; else player_num = player_list[i]; + auto &p = Players[player_num]; color_t fontcolor; rgb color; @@ -3013,14 +3014,14 @@ static void hud_show_kill_list() } gr_string(x0, y, name, sw, sh); + auto &player_info = vcobjptr(p.objnum)->ctype.player_info; if (Show_kill_list==2) { - auto &p = Players[player_num]; - const int eff = (p.net_killed_total + p.net_kills_total <= 0) + const int eff = (player_info.net_killed_total + player_info.net_kills_total <= 0) ? 0 : static_cast( - static_cast(p.net_kills_total) / ( - static_cast(p.net_killed_total) + static_cast(p.net_kills_total) + static_cast(player_info.net_kills_total) / ( + static_cast(player_info.net_killed_total) + static_cast(player_info.net_kills_total) ) * 100.0 ); gr_printf(x1, y, "%i%%", eff <= 0 ? 0 : eff); @@ -3030,9 +3031,9 @@ static void hud_show_kill_list() else if (Game_mode & GM_MULTI_COOP) gr_printf(x1, y, "%-6d", vcobjptr(Players[player_num].objnum)->ctype.player_info.mission.score); else if (Netgame.PlayTimeAllowed || Netgame.KillGoal) - gr_printf(x1,y,"%3d(%d)",Players[player_num].net_kills_total,Players[player_num].KillGoalCount); + gr_printf(x1,y,"%3d(%d)", player_info.net_kills_total, player_info.KillGoalCount); else - gr_printf(x1,y,"%3d",Players[player_num].net_kills_total); + gr_printf(x1,y,"%3d", player_info.net_kills_total); if (PlayerCfg.MultiPingHud && Show_kill_list != 3) { diff --git a/similar/main/kmatrix.cpp b/similar/main/kmatrix.cpp index 514d4f678..d20ec5ce0 100644 --- a/similar/main/kmatrix.cpp +++ b/similar/main/kmatrix.cpp @@ -72,7 +72,6 @@ static void kmatrix_redraw_coop(); static void kmatrix_draw_item(int i, playernum_array_t &sorted) { int x, y; - char temp[10]; y = FSPACY(50+i*9); const auto &&fspacx = FSPACX(); @@ -105,21 +104,19 @@ static void kmatrix_draw_item(int i, playernum_array_t &sorted) } } - { auto &p = Players[sorted[i]]; - const int eff = (p.net_killed_total + p.net_kills_total <= 0) + auto &player_info = vcobjptr(p.objnum)->ctype.player_info; + const int eff = (player_info.net_killed_total + player_info.net_kills_total <= 0) ? 0 : static_cast( - static_cast(p.net_kills_total) / ( - static_cast(p.net_killed_total) + static_cast(p.net_kills_total) + static_cast(player_info.net_kills_total) / ( + static_cast(player_info.net_killed_total) + static_cast(player_info.net_kills_total) ) * 100.0 ); - snprintf(temp, sizeof(temp), "%i%%", eff <= 0 ? 0 : eff); - } x = fspacx(60 + CENTERING_OFFSET(N_players) + N_players * 25); gr_set_fontcolor(rgb25, -1); - gr_printf( x ,y,"%4d/%s",Players[sorted[i]].net_kills_total,temp); + gr_printf(x, y, "%4d/%i%%", player_info.net_kills_total, eff <= 0 ? 0 : eff); } static void kmatrix_draw_names(playernum_array_t &sorted) @@ -271,7 +268,7 @@ static void kmatrix_redraw_coop() gr_set_fontcolor(rgb60_40_10, -1); auto &player_info = vcobjptr(plr.objnum)->ctype.player_info; gr_printf(x_centerscreen, y, "%d", player_info.mission.score); - gr_printf(x_centerscreen + fspacx50, y, "%d", plr.net_killed_total); + gr_printf(x_centerscreen + fspacx50, y, "%d", player_info.net_killed_total); } gr_palette_load(gr_palette); diff --git a/similar/main/laser.cpp b/similar/main/laser.cpp index de858a03c..bd77482f9 100644 --- a/similar/main/laser.cpp +++ b/similar/main/laser.cpp @@ -499,8 +499,6 @@ static void create_omega_blobs(const segptridx_t firing_segnum, const vms_vector #define OMEGA_CHARGE_SCALE 4 -int Last_omega_fire_time=0; - // --------------------------------------------------------------------------------- // Call this every frame to recharge the Omega Cannon. void omega_charge_frame(void) @@ -519,10 +517,16 @@ void omega_charge_frame(void) return; // Don't charge while firing. Wait 1/3 second after firing before recharging - if (Last_omega_fire_time > GameTime64) - Last_omega_fire_time = GameTime64; - if (Last_omega_fire_time + F1_0/3 > GameTime64) - return; + auto &Omega_recharge_delay = player_info.Omega_recharge_delay; + if (Omega_recharge_delay) + { + if (Omega_recharge_delay > FrameTime) + { + Omega_recharge_delay -= FrameTime; + return; + } + Omega_recharge_delay = 0; + } if (auto &energy = player_info.energy) { @@ -556,11 +560,9 @@ static void do_omega_stuff(const vobjptridx_t parent_objp, const vms_vector &fir { vms_vector goal_pos; const auto pnum = get_player_id(parent_objp); - fix fire_frame_overhead = 0; - if (pnum == Player_num) { // If charge >= min, or (some charge and zero energy), allow to fire. - auto &player_info = get_local_plrobj().ctype.player_info; + auto &player_info = parent_objp->ctype.player_info; auto &Omega_charge = player_info.Omega_charge; if (!((Omega_charge >= MIN_OMEGA_CHARGE) || (Omega_charge && !player_info.energy))) { obj_delete(weapon_objp); @@ -571,12 +573,7 @@ static void do_omega_stuff(const vobjptridx_t parent_objp, const vms_vector &fir if (Omega_charge < 0) Omega_charge = 0; - if (GameTime64 - Last_omega_fire_time + OMEGA_BASE_TIME <= FrameTime) // if firing is prolonged by FrameTime overhead, let's try to fix that. Since Next_laser_firing_time is probably changed already (in do_laser_firing_player), we need to calculate the overhead slightly different. - fire_frame_overhead = GameTime64 - Last_omega_fire_time + OMEGA_BASE_TIME; - - auto &Next_laser_fire_time = parent_objp->ctype.player_info.Next_laser_fire_time; - Next_laser_fire_time = GameTime64+OMEGA_BASE_TIME-fire_frame_overhead; - Last_omega_fire_time = GameTime64; + player_info.Omega_recharge_delay = F1_0 / 3; } weapon_objp->ctype.laser_info.parent_type = OBJ_PLAYER; @@ -1865,10 +1862,17 @@ int do_laser_firing_player(void) if (GameTime64 - Next_laser_fire_time <= FrameTime) // if firing is prolonged by FrameTime overhead, let's try to fix that. fire_frame_overhead = GameTime64 - Next_laser_fire_time; - if (!cheats.rapidfire) - Next_laser_fire_time = GameTime64 + Weapon_info[weapon_index].fire_wait - fire_frame_overhead; - else - Next_laser_fire_time = GameTime64 + (F1_0/25) - fire_frame_overhead; + Next_laser_fire_time = GameTime64 - fire_frame_overhead + (unlikely(cheats.rapidfire) + ? (F1_0 / 25) + : ( +#if defined(DXX_BUILD_DESCENT_II) + weapon_index == weapon_id_type::OMEGA_ID + ? OMEGA_BASE_TIME + : +#endif + Weapon_info[weapon_index].fire_wait + ) + ); laser_level = player_info.laser_level; @@ -2248,7 +2252,7 @@ static void create_smart_children(const vobjptridx_t objp, const uint_fast32_t n ? objptridx((numobjs == 1) ? objlist[0] : get_random_different_object()) - : objptridx(object_none); + : object_none; create_homing_missile(objp, sel_objnum, blob_id, (i==0)?1:0); } } @@ -2270,10 +2274,6 @@ void create_weapon_smart_children(const vobjptridx_t objp) create_smart_children(objp, NUM_SMART_CHILDREN, {objp->ctype.laser_info.parent_type, objp->ctype.laser_info.parent_num}); } -} - -namespace dsx { - #if defined(DXX_BUILD_DESCENT_II) void create_robot_smart_children(const vobjptridx_t objp, const uint_fast32_t num_smart_children) @@ -2376,7 +2376,7 @@ void do_missile_firing(int drop_bomb) if (Game_mode & GM_MULTI) { - multi_send_fire(weapon+MISSILE_ADJUST, 0, gun_flag, 1, Network_laser_track, weapon_index_is_player_bomb(weapon) ? objnum : objptridx(object_none)); + multi_send_fire(weapon+MISSILE_ADJUST, 0, gun_flag, 1, Network_laser_track, weapon_index_is_player_bomb(weapon) ? objnum : object_none); } // don't autoselect if dropping prox and prox not current weapon diff --git a/similar/main/multi.cpp b/similar/main/multi.cpp index 6bdfacc10..270995b7d 100644 --- a/similar/main/multi.cpp +++ b/similar/main/multi.cpp @@ -520,13 +520,15 @@ kmatrix_result multi_endlevel_score() vobjptr(i.objnum)->ctype.player_info.powerup_flags &= ~(PLAYER_FLAGS_BLUE_KEY | PLAYER_FLAGS_RED_KEY | PLAYER_FLAGS_GOLD_KEY); } -#if defined(DXX_BUILD_DESCENT_II) range_for (auto &i, partial_const_range(Players, Netgame.max_numplayers)) - vobjptr(i.objnum)->ctype.player_info.powerup_flags &= ~(PLAYER_FLAGS_FLAG); // Clear capture flag + { + auto &obj = *vobjptr(i.objnum); + auto &player_info = obj.ctype.player_info; +#if defined(DXX_BUILD_DESCENT_II) + player_info.powerup_flags &= ~(PLAYER_FLAGS_FLAG); // Clear capture flag #endif - - range_for (auto &i, Players) - i.KillGoalCount=0; + player_info.KillGoalCount = 0; + } // hide Game_wind again if we brought it up if (Game_wind && game_wind_visible) @@ -558,9 +560,6 @@ void multi_new_game() { sorted_kills[i] = i; Players[i].connected = CONNECT_DISCONNECTED; - Players[i].net_killed_total = 0; - Players[i].net_kills_total = 0; - Players[i].KillGoalCount=0; } multi_sending_message.fill(msgsend_none); @@ -635,29 +634,28 @@ void multi_sort_kill_list() array kills; for (uint_fast32_t i = 0; i < MAX_PLAYERS; i++) { + auto &player_info = vcobjptr(Players[i].objnum)->ctype.player_info; if (Game_mode & GM_MULTI_COOP) { - auto &player_info = vcobjptr(Players[i].objnum)->ctype.player_info; kills[i] = player_info.mission.score; } #if defined(DXX_BUILD_DESCENT_II) else if (Show_kill_list==2) { - auto &p = Players[i]; - const auto kk = p.net_killed_total + p.net_kills_total; + const auto kk = player_info.net_killed_total + player_info.net_kills_total; // always draw the ones without any ratio last kills[i] = kk <= 0 ? kk - 1 : static_cast( - static_cast(p.net_kills_total) / ( - static_cast(p.net_killed_total) + static_cast(p.net_kills_total) + static_cast(player_info.net_kills_total) / ( + static_cast(player_info.net_killed_total) + static_cast(player_info.net_kills_total) ) * 100.0 ); } #endif else - kills[i] = Players[i].net_kills_total; + kills[i] = player_info.net_kills_total; } const auto predicate = [&](unsigned a, unsigned b) { @@ -722,9 +720,9 @@ static void multi_compute_kill(const objptridx_t killer, const vobjptridx_t kill { if (Game_mode & GM_TEAM) -- team_kills[get_team(killed_pnum)]; - Players[killed_pnum].net_killed_total++; - Players[killed_pnum].net_kills_total--; - -- Players[killed_pnum].KillGoalCount; + ++ killed->ctype.player_info.net_killed_total; + -- killed->ctype.player_info.net_kills_total; + -- killed->ctype.player_info.KillGoalCount; if (Newdemo_state == ND_STATE_RECORDING) newdemo_record_multi_kill(killed_pnum, -1); @@ -761,7 +759,7 @@ static void multi_compute_kill(const objptridx_t killer, const vobjptridx_t kill else HUD_init_message(HM_MULTI, "%s %s %s.", killed_name, TXT_WAS, TXT_KILLED_BY_ROBOT ); } - Players[killed_pnum].net_killed_total++; + ++ killed->ctype.player_info.net_killed_total; return; } @@ -787,9 +785,9 @@ static void multi_compute_kill(const objptridx_t killer, const vobjptridx_t kill team_kills[get_team(killed_pnum)] -= 1; } - Players[killed_pnum].net_killed_total += 1; - Players[killed_pnum].net_kills_total -= 1; - -- Players[killed_pnum].KillGoalCount; + ++ killed->ctype.player_info.net_killed_total; + -- killed->ctype.player_info.net_kills_total; + -- killed->ctype.player_info.KillGoalCount; if (Newdemo_state == ND_STATE_RECORDING) newdemo_record_multi_kill(killed_pnum, -1); @@ -842,8 +840,8 @@ static void multi_compute_kill(const objptridx_t killer, const vobjptridx_t kill if (is_team_game) { team_kills[killer_team] += adjust; - Players[killer_pnum].net_kills_total += adjust; - Players[killer_pnum].KillGoalCount += adjust; + killer->ctype.player_info.net_kills_total += adjust; + killer->ctype.player_info.KillGoalCount += adjust; } else if( Game_mode & GM_BOUNTY ) { @@ -851,8 +849,8 @@ static void multi_compute_kill(const objptridx_t killer, const vobjptridx_t kill if( killed_pnum == Bounty_target || killer_pnum == Bounty_target ) { /* Increment kill counts */ - Players[killer_pnum].net_kills_total++; - Players[killer_pnum].KillGoalCount++; + ++ killer->ctype.player_info.net_kills_total; + ++ killer->ctype.player_info.KillGoalCount; /* If the target died, the new one is set! */ if( killed_pnum == Bounty_target ) @@ -861,15 +859,15 @@ static void multi_compute_kill(const objptridx_t killer, const vobjptridx_t kill } else { - Players[killer_pnum].net_kills_total += 1; - Players[killer_pnum].KillGoalCount+=1; + ++ killer->ctype.player_info.net_kills_total; + ++ killer->ctype.player_info.KillGoalCount; } if (Newdemo_state == ND_STATE_RECORDING) newdemo_record_multi_kill(killer_pnum, 1); } - Players[killed_pnum].net_killed_total += 1; + ++ killed->ctype.player_info.net_killed_total; const char *name0, *name1; if (killer_pnum == Player_num) { if (Game_mode & GM_MULTI_COOP) @@ -898,7 +896,7 @@ static void multi_compute_kill(const objptridx_t killer, const vobjptridx_t kill const auto TheGoal = Netgame.KillGoal * 5; if (((Game_mode & GM_TEAM) ? team_kills[get_team(killer_pnum)] - : Players[killer_pnum].KillGoalCount + : killer->ctype.player_info.KillGoalCount ) >= TheGoal) { if (killer_pnum==Player_num) @@ -975,18 +973,22 @@ void multi_do_frame(void) multi_send_gmode_update(); last_gmode_time = timer_query(); } - // Send out inventory three times per second - if (timer_query() >= last_inventory_time + (F1_0/3)) + + if (Network_status == NETSTAT_PLAYING) { - multi_send_player_inventory(0); - last_inventory_time = timer_query(); + // Send out inventory three times per second + if (timer_query() >= last_inventory_time + (F1_0/3)) + { + multi_send_player_inventory(0); + last_inventory_time = timer_query(); + } + // Repopulate the level if necessary + if (timer_query() >= last_repo_time + (F1_0/2)) + { + MultiLevelInv_Repopulate((F1_0/2)); + last_repo_time = timer_query(); + } } - // Repopulate the level if necessary - if (timer_query() >= last_repo_time + (F1_0/2)) - { - MultiLevelInv_Repopulate((F1_0/2)); - last_repo_time = timer_query(); - } multi_send_message(); // Send any waiting messages @@ -1929,24 +1931,30 @@ static void multi_do_controlcen_destroy(const ubyte *buf) static void multi_do_escape(const ubyte *buf) { - const auto objnum = vobjptridx(Players[buf[1]].objnum); digi_play_sample(SOUND_HUD_MESSAGE, F1_0); + auto &plr = Players[buf[1]]; + const auto &&objnum = vobjptridx(plr.objnum); #if defined(DXX_BUILD_DESCENT_II) digi_kill_sound_linked_to_object (objnum); #endif - if (buf[2] == 0) + const char *txt; + int connected; +#if defined(DXX_BUILD_DESCENT_I) + if (buf[2] == static_cast(multi_endlevel_type::secret)) { - HUD_init_message(HM_MULTI, "%s %s", static_cast(Players[static_cast(buf[1])].callsign), TXT_HAS_ESCAPED); - if (Game_mode & GM_NETWORK) - Players[static_cast(buf[1])].connected = CONNECT_ESCAPE_TUNNEL; + txt = TXT_HAS_FOUND_SECRET; + connected = CONNECT_FOUND_SECRET; } - else if (buf[2] == 1) + else +#endif { - HUD_init_message(HM_MULTI, "%s %s", static_cast(Players[static_cast(buf[1])].callsign), TXT_HAS_FOUND_SECRET); - if (Game_mode & GM_NETWORK) - Players[static_cast(buf[1])].connected = CONNECT_FOUND_SECRET; + txt = TXT_HAS_ESCAPED; + connected = CONNECT_ESCAPE_TUNNEL; } + HUD_init_message(HM_MULTI, "%s %s", static_cast(plr.callsign), txt); + if (Game_mode & GM_NETWORK) + plr.connected = connected; create_player_appearance_effect(objnum); multi_make_player_ghost(buf[1]); } @@ -2569,18 +2577,18 @@ void multi_send_markers() #endif #if defined(DXX_BUILD_DESCENT_I) -void multi_send_endlevel_start(const bool secret) +void multi_send_endlevel_start(const multi_endlevel_type secret) #elif defined(DXX_BUILD_DESCENT_II) void multi_send_endlevel_start() #endif { -#if defined(DXX_BUILD_DESCENT_II) - const bool secret = false; + array buf; + buf[1] = Player_num; +#if defined(DXX_BUILD_DESCENT_I) + buf[2] = static_cast(secret); #endif - multibuf[1] = Player_num; - multibuf[2] = static_cast(secret); - multi_send_data(multibuf, 3, 2); + multi_send_data(buf.data(), buf.size(), 2); if (Game_mode & GM_NETWORK) { get_local_player().connected = CONNECT_ESCAPE_TUNNEL; @@ -3412,10 +3420,9 @@ int multi_level_sync(void) namespace dsx { #if defined(DXX_BUILD_DESCENT_II) -static void apply_segment_goal_texture(const vsegptr_t seg, ubyte team_mask) +static void apply_segment_goal_texture(const vsegptr_t seg, const std::size_t tex) { seg->static_light = i2f(100); //make static light bright - std::size_t tex = find_goal_texture(game_mode_hoard() ? TMI_GOAL_HOARD : team_mask); if (tex < TmapInfo.size()) range_for (auto &s, seg->sides) { @@ -3427,21 +3434,29 @@ static void apply_segment_goal_texture(const vsegptr_t seg, ubyte team_mask) void multi_apply_goal_textures() { + std::size_t tex_blue, tex_red; + if (game_mode_hoard()) + tex_blue = tex_red = find_goal_texture(TMI_GOAL_HOARD); + else + { + tex_blue = find_goal_texture(TMI_GOAL_BLUE); + tex_red = find_goal_texture(TMI_GOAL_RED); + } range_for (const auto &&seg, vsegptr) { - uint8_t team_mask; + std::size_t tex; if (seg->special==SEGMENT_IS_GOAL_BLUE) { - team_mask = TMI_GOAL_BLUE; + tex = tex_blue; } else if (seg->special==SEGMENT_IS_GOAL_RED) { // Make both textures the same if Hoard mode - team_mask = TMI_GOAL_RED; + tex = tex_red; } else continue; - apply_segment_goal_texture(seg, team_mask); + apply_segment_goal_texture(seg, tex); } } @@ -3764,14 +3779,15 @@ static void multi_do_wall_status (const ubyte *buf) void multi_send_kill_goal_counts() { - int i,count=1; + int count=1; - for (i=0;i(multibuf, count, 2); } @@ -3781,7 +3797,9 @@ static void multi_do_kill_goal_counts(const ubyte *buf) range_for (auto &i, Players) { - i.KillGoalCount = buf[count]; + auto &obj = *vobjptr(i.objnum); + auto &player_info = obj.ctype.player_info; + player_info.KillGoalCount = buf[count]; count++; } @@ -3832,7 +3850,9 @@ void multi_check_for_killgoal_winner () int highest_kill_goal_count = 0; range_for (auto &i, partial_const_range(Players, N_players)) { - const auto KillGoalCount = i.KillGoalCount; + auto &obj = *vcobjptr(i.objnum); + auto &player_info = obj.ctype.player_info; + const auto KillGoalCount = player_info.KillGoalCount; if (highest_kill_goal_count < KillGoalCount) { highest_kill_goal_count = KillGoalCount; @@ -4023,17 +4043,19 @@ void multi_do_capture_bonus(const playernum_t pnum) : SOUND_HUD_BLUE_GOT_GOAL ), F1_0*2); - vobjptr(Players[pnum].objnum)->ctype.player_info.powerup_flags &= ~(PLAYER_FLAGS_FLAG); // Clear capture flag team_kills[get_team(pnum)] += 5; - Players[static_cast(pnum)].net_kills_total += 5; - Players[static_cast(pnum)].KillGoalCount+=5; + auto &plr = Players[pnum]; + auto &player_info = vobjptr(plr.objnum)->ctype.player_info; + player_info.powerup_flags &= ~PLAYER_FLAGS_FLAG; // Clear capture flag + player_info.net_kills_total += 5; + player_info.KillGoalCount += 5; if (Netgame.KillGoal>0) { TheGoal=Netgame.KillGoal*5; - if (Players[static_cast(pnum)].KillGoalCount>=TheGoal) + if (player_info.KillGoalCount >= TheGoal) { if (pnum==Player_num) { @@ -4093,21 +4115,23 @@ void multi_do_orb_bonus(const playernum_t pnum, const ubyte *buf) PhallicLimit=bonus; } - vobjptr(Players[pnum].objnum)->ctype.player_info.powerup_flags &= ~(PLAYER_FLAGS_FLAG); // Clear orb flag team_kills[get_team(pnum)] += bonus; - Players[static_cast(pnum)].net_kills_total += bonus; - Players[static_cast(pnum)].KillGoalCount+=bonus; + auto &plr = Players[pnum]; + auto &player_info = vobjptr(plr.objnum)->ctype.player_info; + player_info.powerup_flags &= ~PLAYER_FLAGS_FLAG; // Clear orb flag + player_info.net_kills_total += bonus; + player_info.KillGoalCount += bonus; team_kills[get_team(pnum)]%=1000; - Players[static_cast(pnum)].net_kills_total%=1000; - Players[static_cast(pnum)].KillGoalCount%=1000; + player_info.net_kills_total%=1000; + player_info.KillGoalCount %= 1000; if (Netgame.KillGoal>0) { TheGoal=Netgame.KillGoal*5; - if (Players[static_cast(pnum)].KillGoalCount>=TheGoal) + if (player_info.KillGoalCount >= TheGoal) { if (pnum==Player_num) { @@ -5131,7 +5155,7 @@ void MultiLevelInv_Recount() namespace dsx { bool MultiLevelInv_AllowSpawn(powerup_type_t powerup_type) { - if ((Game_mode & GM_MULTI_COOP) || Control_center_destroyed || (Network_status == NETSTAT_ENDLEVEL)) + if ((Game_mode & GM_MULTI_COOP) || Control_center_destroyed || (Network_status != NETSTAT_PLAYING)) return 0; int req_amount = 1; // required amount of item to drop a powerup. @@ -5156,7 +5180,7 @@ bool MultiLevelInv_AllowSpawn(powerup_type_t powerup_type) // Repopulate the level with missing items. void MultiLevelInv_Repopulate(fix frequency) { - if (!multi_i_am_master() || (Game_mode & GM_MULTI_COOP) || Control_center_destroyed || (Network_status == NETSTAT_ENDLEVEL)) + if (!multi_i_am_master() || (Game_mode & GM_MULTI_COOP) || Control_center_destroyed) return; MultiLevelInv_Recount(); // recount current items diff --git a/similar/main/net_udp.cpp b/similar/main/net_udp.cpp index cc41dffe8..ca360ebe8 100644 --- a/similar/main/net_udp.cpp +++ b/similar/main/net_udp.cpp @@ -563,7 +563,12 @@ int udp_dns_filladdr_t::apply(sockaddr &addr, socklen_t addrlen, int ai_family, hints.ai_family = ai_family; // We are always UDP hints.ai_socktype = SOCK_DGRAM; - hints.ai_flags = AI_V4MAPPED | AI_ALL | AI_NUMERICSERV; +#ifdef AI_NUMERICSERV + hints.ai_flags |= AI_NUMERICSERV; +#endif +#if DXX_USE_IPv6 + hints.ai_flags |= AI_V4MAPPED | AI_ALL; +#endif // Numeric address only? if (numeric_only) hints.ai_flags |= AI_NUMERICHOST; @@ -1484,14 +1489,14 @@ static void net_udp_new_player(UDP_sequence_packet *const their) Netgame.players[pnum].rank=their->player.rank; Players[pnum].connected = CONNECT_PLAYING; - Players[pnum].net_kills_total = 0; - Players[pnum].net_killed_total = 0; kill_matrix[pnum] = {}; const auto &&objp = vobjptr(Players[pnum].objnum); auto &player_info = objp->ctype.player_info; + player_info.net_killed_total = 0; + player_info.net_kills_total = 0; player_info.mission.score = 0; player_info.powerup_flags = {}; - Players[pnum].KillGoalCount=0; + player_info.KillGoalCount = 0; if (pnum == N_players) { @@ -1652,7 +1657,9 @@ static void net_udp_welcome_player(UDP_sequence_packet *their) net_udp_noloss_clear_mdata_trace(player_num); } - Players[player_num].KillGoalCount=0; + auto &obj = *vobjptr(Players[player_num].objnum); + auto &player_info = obj.ctype.player_info; + player_info.KillGoalCount = 0; // Send updated Objects data to the new/returning player @@ -2113,10 +2120,10 @@ void net_udp_send_rejoin_sync(int player_num) Netgame.kills = kill_matrix; for (int j=0; jplayer.protocol.udp.addr; Netgame.players[N_players].rank=p->player.rank; Netgame.players[N_players].connected = CONNECT_PLAYING; - Players[N_players].KillGoalCount=0; + auto &obj = *vobjptr(Players[N_players].objnum); + auto &player_info = obj.ctype.player_info; + player_info.KillGoalCount = 0; Players[N_players].connected = CONNECT_PLAYING; Netgame.players[N_players].LastPacketTime = timer_query(); N_players++; @@ -2271,10 +2280,10 @@ void net_udp_update_netgame(void) for (int i = 0; i < MAX_PLAYERS; i++) { Netgame.players[i].connected = Players[i].connected; - Netgame.killed[i] = Players[i].net_killed_total; - Netgame.player_kills[i] = Players[i].net_kills_total; auto &objp = *vcobjptr(Players[i].objnum); auto &player_info = objp.ctype.player_info; + Netgame.killed[i] = player_info.net_killed_total; + Netgame.player_kills[i] = player_info.net_kills_total; #if defined(DXX_BUILD_DESCENT_II) Netgame.player_score[i] = player_info.mission.score; #endif @@ -2299,8 +2308,12 @@ void net_udp_send_endlevel_packet(void) range_for (auto &i, Players) { buf[len] = i.connected; len++; - PUT_INTEL_SHORT(&buf[len], i.net_kills_total); len += 2; - PUT_INTEL_SHORT(&buf[len], i.net_killed_total); len += 2; + auto &objp = *vcobjptr(i.objnum); + auto &player_info = objp.ctype.player_info; + PUT_INTEL_SHORT(&buf[len], player_info.net_kills_total); + len += 2; + PUT_INTEL_SHORT(&buf[len], player_info.net_killed_total); + len += 2; } range_for (auto &i, kill_matrix) @@ -2322,8 +2335,11 @@ void net_udp_send_endlevel_packet(void) buf[len] = Player_num; len++; buf[len] = get_local_player().connected; len++; buf[len] = Countdown_seconds_left; len++; - PUT_INTEL_SHORT(&buf[len], get_local_player().net_kills_total); len += 2; - PUT_INTEL_SHORT(&buf[len], get_local_player().net_killed_total); len += 2; + auto &player_info = get_local_plrobj().ctype.player_info; + PUT_INTEL_SHORT(&buf[len], player_info.net_kills_total); + len += 2; + PUT_INTEL_SHORT(&buf[len], player_info.net_killed_total); + len += 2; range_for (auto &i, kill_matrix[Player_num]) { @@ -2984,8 +3000,12 @@ void net_udp_read_endlevel_packet(const uint8_t *data, const _sockaddr &sender_a tmpvar = data[len]; len++; if ((Network_status != NETSTAT_PLAYING) && (Players[pnum].connected == CONNECT_PLAYING) && (tmpvar < Countdown_seconds_left)) Countdown_seconds_left = tmpvar; - Players[pnum].net_kills_total = GET_INTEL_SHORT(&(data[len])); len += 2; - Players[pnum].net_killed_total = GET_INTEL_SHORT(&(data[len])); len += 2; + auto &objp = *vobjptr(Players[pnum].objnum); + auto &player_info = objp.ctype.player_info; + player_info.net_kills_total = GET_INTEL_SHORT(&data[len]); + len += 2; + player_info.net_killed_total = GET_INTEL_SHORT(&data[len]); + len += 2; range_for (auto &i, kill_matrix[pnum]) { @@ -3015,9 +3035,13 @@ void net_udp_read_endlevel_packet(const uint8_t *data, const _sockaddr &sender_a if (static_cast(data[len]) == CONNECT_DISCONNECTED) multi_disconnect_player(i); + auto &objp = *vobjptr(Players[i].objnum); + auto &player_info = objp.ctype.player_info; Players[i].connected = data[len]; len++; - Players[i].net_kills_total = GET_INTEL_SHORT(&(data[len])); len += 2; - Players[i].net_killed_total = GET_INTEL_SHORT(&(data[len])); len += 2; + player_info.net_kills_total = GET_INTEL_SHORT(&data[len]); + len += 2; + player_info.net_killed_total = GET_INTEL_SHORT(&data[len]); + len += 2; if (Players[i].connected) Netgame.players[i].LastPacketTime = timer_query(); @@ -3936,11 +3960,6 @@ void net_udp_read_sync_packet(const uint8_t * data, uint_fast32_t data_len, cons Player_num = MULTI_PNUM_UNDEF; - range_for (auto &i, Players) - { - i.net_kills_total = 0; - } - for (int i=0; i timer_query() || TrackerAckStatus == TrackerAckState::TACK_SEQCOMPL) + if (!Netgame.Tracker || !multi_i_am_master() || TrackerAckTime + F1_0*10 > timer_query() || TrackerAckStatus == TrackerAckState::TACK_SEQCOMPL) return; if (TrackerAckStatus == TrackerAckState::TACK_NOCONNECTION) { diff --git a/similar/main/newdemo.cpp b/similar/main/newdemo.cpp index de5971581..0758ded79 100644 --- a/similar/main/newdemo.cpp +++ b/similar/main/newdemo.cpp @@ -1031,11 +1031,12 @@ void newdemo_record_start_demo() nd_write_string(static_cast(i.callsign)); nd_write_byte(i.connected); + auto &pl_info = vcobjptr(i.objnum)->ctype.player_info; if (Game_mode & GM_MULTI_COOP) { - nd_write_int(vcobjptr(i.objnum)->ctype.player_info.mission.score); + nd_write_int(pl_info.mission.score); } else { - nd_write_short(i.net_killed_total); - nd_write_short(i.net_kills_total); + nd_write_short(pl_info.net_killed_total); + nd_write_short(pl_info.net_kills_total); } } } else @@ -1450,8 +1451,9 @@ void newdemo_record_multi_connect(int pnum, int new_player, const char *new_call nd_write_byte(static_cast(new_player)); if (!new_player) { nd_write_string(static_cast(Players[pnum].callsign)); - nd_write_int(Players[pnum].net_killed_total); - nd_write_int(Players[pnum].net_kills_total); + auto &player_info = vcobjptr(Players[pnum].objnum)->ctype.player_info; + nd_write_int(player_info.net_killed_total); + nd_write_int(player_info.net_kills_total); } nd_write_string(new_callsign); } @@ -1757,12 +1759,12 @@ static int newdemo_read_demo_start(enum purpose_type purpose) if (purpose == PURPOSE_REWRITE) nd_write_int(player_info.mission.score); } else { - nd_read_short(&i.net_killed_total); - nd_read_short(&i.net_kills_total); + nd_read_short(&player_info.net_killed_total); + nd_read_short(&player_info.net_kills_total); if (purpose == PURPOSE_REWRITE) { - nd_write_short(i.net_killed_total); - nd_write_short(i.net_kills_total); + nd_write_short(player_info.net_killed_total); + nd_write_short(player_info.net_kills_total); } } } @@ -2770,10 +2772,11 @@ static int newdemo_read_frame_information(int rewrite) nd_write_byte(pnum); break; } + auto &player_info = vobjptr(Players[pnum].objnum)->ctype.player_info; if ((Newdemo_vcr_state == ND_STATE_REWINDING) || (Newdemo_vcr_state == ND_STATE_ONEFRAMEBACKWARD)) - Players[pnum].net_killed_total--; + player_info.net_killed_total--; else if ((Newdemo_vcr_state == ND_STATE_PLAYBACK) || (Newdemo_vcr_state == ND_STATE_FASTFORWARD) || (Newdemo_vcr_state == ND_STATE_ONEFRAMEFORWARD)) - Players[pnum].net_killed_total++; + player_info.net_killed_total++; break; } @@ -2788,12 +2791,13 @@ static int newdemo_read_frame_information(int rewrite) nd_write_byte(kill); break; } + auto &player_info = vobjptr(Players[pnum].objnum)->ctype.player_info; if ((Newdemo_vcr_state == ND_STATE_REWINDING) || (Newdemo_vcr_state == ND_STATE_ONEFRAMEBACKWARD)) { - Players[pnum].net_kills_total -= kill; + player_info.net_kills_total -= kill; if (Newdemo_game_mode & GM_TEAM) team_kills[get_team(pnum)] -= kill; } else if ((Newdemo_vcr_state == ND_STATE_PLAYBACK) || (Newdemo_vcr_state == ND_STATE_FASTFORWARD) || (Newdemo_vcr_state == ND_STATE_ONEFRAMEFORWARD)) { - Players[pnum].net_kills_total += kill; + player_info.net_kills_total += kill; if (Newdemo_game_mode & GM_TEAM) team_kills[get_team(pnum)] += kill; } @@ -2828,19 +2832,20 @@ static int newdemo_read_frame_information(int rewrite) nd_write_string(static_cast(new_callsign)); break; } + auto &player_info = vobjptr(Players[pnum].objnum)->ctype.player_info; if ((Newdemo_vcr_state == ND_STATE_REWINDING) || (Newdemo_vcr_state == ND_STATE_ONEFRAMEBACKWARD)) { Players[pnum].connected = CONNECT_DISCONNECTED; if (!new_player) { Players[pnum].callsign = old_callsign; - Players[pnum].net_killed_total = killed_total; - Players[pnum].net_kills_total = kills_total; + player_info.net_killed_total = killed_total; + player_info.net_kills_total = kills_total; } else { N_players--; } } else if ((Newdemo_vcr_state == ND_STATE_PLAYBACK) || (Newdemo_vcr_state == ND_STATE_FASTFORWARD) || (Newdemo_vcr_state == ND_STATE_ONEFRAMEFORWARD)) { Players[pnum].connected = CONNECT_PLAYING; - Players[pnum].net_kills_total = 0; - Players[pnum].net_killed_total = 0; + player_info.net_kills_total = 0; + player_info.net_killed_total = 0; Players[pnum].callsign = new_callsign; if (new_player) N_players++; @@ -3399,12 +3404,12 @@ void newdemo_goto_end(int to_rewrite) range_for (auto &i, partial_range(Players, N_players)) { nd_read_string(i.callsign.buffer()); nd_read_byte(&i.connected); + auto &pl_info = vobjptr(i.objnum)->ctype.player_info; if (Newdemo_game_mode & GM_MULTI_COOP) { - auto &pl_info = vobjptr(i.objnum)->ctype.player_info; nd_read_int(&pl_info.mission.score); } else { - nd_read_short(&i.net_killed_total); - nd_read_short(&i.net_kills_total); + nd_read_short(&pl_info.net_killed_total); + nd_read_short(&pl_info.net_kills_total); } } } else { @@ -3797,13 +3802,13 @@ static void newdemo_write_end() nd_write_string(static_cast(i.callsign)); byte_count += (strlen(static_cast(i.callsign)) + 2); nd_write_byte(i.connected); + auto &pl_info = vcobjptr(i.objnum)->ctype.player_info; if (Game_mode & GM_MULTI_COOP) { - auto &pl_info = vcobjptr(i.objnum)->ctype.player_info; nd_write_int(pl_info.mission.score); byte_count += 5; } else { - nd_write_short(i.net_killed_total); - nd_write_short(i.net_kills_total); + nd_write_short(pl_info.net_killed_total); + nd_write_short(pl_info.net_kills_total); byte_count += 5; } } diff --git a/similar/main/state.cpp b/similar/main/state.cpp index 16ccf99f6..8b754f082 100644 --- a/similar/main/state.cpp +++ b/similar/main/state.cpp @@ -496,10 +496,10 @@ static void state_player_to_player_rw(const fix pl_shields, const player *pl, pl else pl_rw->invulnerable_time = pl_info.invulnerable_time - GameTime64; #if defined(DXX_BUILD_DESCENT_II) - pl_rw->KillGoalCount = pl->KillGoalCount; + pl_rw->KillGoalCount = pl_info.KillGoalCount; #endif - pl_rw->net_killed_total = pl->net_killed_total; - pl_rw->net_kills_total = pl->net_kills_total; + pl_rw->net_killed_total = pl_info.net_killed_total; + pl_rw->net_kills_total = pl_info.net_kills_total; pl_rw->num_kills_level = pl->num_kills_level; pl_rw->num_kills_total = pl->num_kills_total; pl_rw->num_robots_level = pl->num_robots_level; @@ -541,10 +541,10 @@ static void state_player_rw_to_player(const player_rw *pl_rw, player *pl, player pl_info.cloak_time = pl_rw->cloak_time; pl_info.invulnerable_time = pl_rw->invulnerable_time; #if defined(DXX_BUILD_DESCENT_II) - pl->KillGoalCount = pl_rw->KillGoalCount; + pl_info.KillGoalCount = pl_rw->KillGoalCount; #endif - pl->net_killed_total = pl_rw->net_killed_total; - pl->net_kills_total = pl_rw->net_kills_total; + pl_info.net_killed_total = pl_rw->net_killed_total; + pl_info.net_kills_total = pl_rw->net_kills_total; pl->num_kills_level = pl_rw->num_kills_level; pl->num_kills_total = pl_rw->num_kills_total; pl->num_robots_level = pl_rw->num_robots_level; @@ -1815,7 +1815,13 @@ int state_restore_all_sub(const char *filename, const secret_restore secret) { auto i = PHYSFSX_readSXE32(fp, swap); if (secret != secret_restore::survived) + { player_info.Omega_charge = i; + /* The savegame does not record this, so pick a value. Be + * nice to the player: let the cannon recharge immediately. + */ + player_info.Omega_recharge_delay = 0; + } } #endif @@ -1910,9 +1916,9 @@ int state_restore_all_sub(const char *filename, const secret_restore secret) Netgame.level_time = PHYSFSX_readSXE32(fp, swap); for (playernum_t i = 0; i < MAX_PLAYERS; i++) { - Netgame.killed[i] = Players[i].net_killed_total; const auto &&objp = vobjptr(Players[i].objnum); auto &pi = objp->ctype.player_info; + Netgame.killed[i] = pi.net_killed_total; Netgame.player_score[i] = pi.mission.score; Netgame.net_player_flags[i] = pi.powerup_flags; } diff --git a/similar/main/switch.cpp b/similar/main/switch.cpp index 3b86d57fe..e95d66b1e 100644 --- a/similar/main/switch.cpp +++ b/similar/main/switch.cpp @@ -302,7 +302,7 @@ int check_trigger_sub(object &plrobj, const trgnum_t trigger_num, int pnum,int s Newdemo_state = ND_STATE_PAUSED; if (Game_mode & GM_MULTI) - multi_send_endlevel_start(1); + multi_send_endlevel_start(multi_endlevel_type::secret); if (Game_mode & GM_NETWORK) multi_do_protocol_frame(1, 1); PlayerFinishedLevel(1); //1 means go to secret level diff --git a/similar/main/wall.cpp b/similar/main/wall.cpp index b1132ca0a..321c78ff0 100644 --- a/similar/main/wall.cpp +++ b/similar/main/wall.cpp @@ -56,6 +56,33 @@ namespace dsx { array CloakingWalls; unsigned Num_cloaking_walls; + +namespace { + +struct cwframe +{ + wall &w; + array &uvls; + cwframe(wall &wr) : + w(wr), + uvls(vsegptr(w.segnum)->sides[w.sidenum].uvls) + { + } +}; + +struct cwresult +{ + bool remove; + bool record; + cwresult() = default; + explicit cwresult(bool r) : + remove(false), record(r) + { + } +}; + +} + } #endif @@ -1118,143 +1145,89 @@ void reset_walls() } #if defined(DXX_BUILD_DESCENT_II) -static void do_cloaking_wall_frame(int cloaking_wall_num) +static void copy_cloaking_wall_light_to_wall(array &back_uvls, array &front_uvls, const cloaking_wall &d) { - cloaking_wall *d; - sbyte old_cloak; // for demo recording + for (uint_fast32_t i = 0; i != 4; ++i) + { + back_uvls[i].l = d.back_ls[i]; + front_uvls[i].l = d.front_ls[i]; + } +} - if ( Newdemo_state==ND_STATE_PLAYBACK ) return; +static void scale_cloaking_wall_light_to_wall(array &back_uvls, array &front_uvls, const cloaking_wall &d, const fix light_scale) +{ + for (uint_fast32_t i = 0; i != 4; ++i) + { + back_uvls[i].l = fixmul(d.back_ls[i], light_scale); + front_uvls[i].l = fixmul(d.front_ls[i], light_scale); + } +} - d = &CloakingWalls[cloaking_wall_num]; - wall *const wfront = vwallptr(d->front_wallnum); - wall *const wback = wallptr(d->back_wallnum); - - old_cloak = wfront->cloak_value; - - d->time += FrameTime; - - if (d->time > CLOAKING_WALL_TIME) { - int i; - - wfront->type = WALL_OPEN; - wfront->state = WALL_DOOR_CLOSED; //why closed? why not? - if (wback) { - wback->type = WALL_OPEN; - wback->state = WALL_DOOR_CLOSED; //why closed? why not? +static cwresult do_cloaking_wall_frame(const bool initial, cloaking_wall &d, const cwframe front, const cwframe back) +{ + cwresult r(initial); + if (d.time > CLOAKING_WALL_TIME) { + front.w.type = back.w.type = WALL_OPEN; + front.w.state = back.w.state = WALL_DOOR_CLOSED; //why closed? why not? + r.remove = true; + } + else if (d.time > CLOAKING_WALL_TIME/2) { + const int8_t cloak_value = ((d.time - CLOAKING_WALL_TIME / 2) * (GR_FADE_LEVELS - 2)) / (CLOAKING_WALL_TIME / 2); + if (front.w.cloak_value != cloak_value) + { + r.record = true; + front.w.cloak_value = back.w.cloak_value = cloak_value; } - for (i=cloaking_wall_num;itime > CLOAKING_WALL_TIME/2) { - int old_type=wfront->type; - - wfront->cloak_value = ((d->time - CLOAKING_WALL_TIME/2) * (GR_FADE_LEVELS-2)) / (CLOAKING_WALL_TIME/2); - if (wback) - wback->cloak_value = wfront->cloak_value; - - if (old_type != WALL_CLOAKED) { //just switched - int i; - - wfront->type = WALL_CLOAKED; - if (wback) - wback->type = WALL_CLOAKED; - - for (i=0;i<4;i++) { - Segments[wfront->segnum].sides[wfront->sidenum].uvls[i].l = d->front_ls[i]; - if (wback) - Segments[wback->segnum].sides[wback->sidenum].uvls[i].l = d->back_ls[i]; - } + if (front.w.type != WALL_CLOAKED) + { //just switched + front.w.type = back.w.type = WALL_CLOAKED; + copy_cloaking_wall_light_to_wall(back.uvls, front.uvls, d); } } else { //fading out fix light_scale; - int i; - - light_scale = fixdiv(CLOAKING_WALL_TIME/2-d->time,CLOAKING_WALL_TIME/2); - - for (i=0;i<4;i++) { - Segments[wfront->segnum].sides[wfront->sidenum].uvls[i].l = fixmul(d->front_ls[i],light_scale); - if (wback) - Segments[wback->segnum].sides[wback->sidenum].uvls[i].l = fixmul(d->back_ls[i],light_scale); - } + light_scale = fixdiv(CLOAKING_WALL_TIME / 2 - d.time, CLOAKING_WALL_TIME / 2); + scale_cloaking_wall_light_to_wall(back.uvls, front.uvls, d, light_scale); } - - // check if the actual cloak_value changed in this frame to prevent redundant recordings and wasted bytes - if ( Newdemo_state == ND_STATE_RECORDING && (wfront->cloak_value != old_cloak || d->time == FrameTime) ) - newdemo_record_cloaking_wall(d->front_wallnum, d->back_wallnum, wfront->type, wfront->state, wfront->cloak_value, Segments[wfront->segnum].sides[wfront->sidenum].uvls[0].l, Segments[wfront->segnum].sides[wfront->sidenum].uvls[1].l, Segments[wfront->segnum].sides[wfront->sidenum].uvls[2].l, Segments[wfront->segnum].sides[wfront->sidenum].uvls[3].l); - + return r; } -static void do_decloaking_wall_frame(int cloaking_wall_num) +static cwresult do_decloaking_wall_frame(const bool initial, cloaking_wall &d, const cwframe front, const cwframe back) { - cloaking_wall *d; - sbyte old_cloak; // for demo recording - - if ( Newdemo_state==ND_STATE_PLAYBACK ) return; - - d = &CloakingWalls[cloaking_wall_num]; - wall *const wfront = vwallptr(d->front_wallnum); - wall *const wback = wallptr(d->back_wallnum); - - old_cloak = wfront->cloak_value; - - d->time += FrameTime; - - if (d->time > CLOAKING_WALL_TIME) { - int i; - - wfront->state = WALL_DOOR_CLOSED; - if (wback) - wback->state = WALL_DOOR_CLOSED; - - for (i=0;i<4;i++) { - Segments[wfront->segnum].sides[wfront->sidenum].uvls[i].l = d->front_ls[i]; - if (wback) - Segments[wback->segnum].sides[wback->sidenum].uvls[i].l = d->back_ls[i]; - } - - for (i=cloaking_wall_num;i CLOAKING_WALL_TIME) { + back.w.state = WALL_DOOR_CLOSED; + front.w.state = WALL_DOOR_CLOSED; + copy_cloaking_wall_light_to_wall(back.uvls, front.uvls, d); + r.remove = true; } - else if (d->time > CLOAKING_WALL_TIME/2) { //fading in + else if (d.time > CLOAKING_WALL_TIME/2) { //fading in fix light_scale; - int i; + front.w.type = back.w.type = WALL_CLOSED; - wfront->type = wback->type = WALL_CLOSED; - - light_scale = fixdiv(d->time-CLOAKING_WALL_TIME/2,CLOAKING_WALL_TIME/2); - - for (i=0;i<4;i++) { - Segments[wfront->segnum].sides[wfront->sidenum].uvls[i].l = fixmul(d->front_ls[i],light_scale); - if (wback) - Segments[wback->segnum].sides[wback->sidenum].uvls[i].l = fixmul(d->back_ls[i],light_scale); - } + light_scale = fixdiv(d.time - CLOAKING_WALL_TIME / 2, CLOAKING_WALL_TIME / 2); + scale_cloaking_wall_light_to_wall(back.uvls, front.uvls, d, light_scale); } else { //cloaking in - wfront->cloak_value = ((CLOAKING_WALL_TIME/2 - d->time) * (GR_FADE_LEVELS-2)) / (CLOAKING_WALL_TIME/2); - wfront->type = WALL_CLOAKED; - if (wback) { - wback->cloak_value = wfront->cloak_value; - wback->type = WALL_CLOAKED; + const int8_t cloak_value = ((CLOAKING_WALL_TIME / 2 - d.time) * (GR_FADE_LEVELS - 2)) / (CLOAKING_WALL_TIME / 2); + if (front.w.cloak_value != cloak_value) + { + front.w.cloak_value = back.w.cloak_value = cloak_value; + r.record = true; } + front.w.type = WALL_CLOAKED; + back.w.type = WALL_CLOAKED; } - - // check if the actual cloak_value changed in this frame to prevent redundant recordings and wasted bytes - if ( Newdemo_state == ND_STATE_RECORDING && (wfront->cloak_value != old_cloak || d->time == FrameTime) ) - newdemo_record_cloaking_wall(d->front_wallnum, d->back_wallnum, wfront->type, wfront->state, wfront->cloak_value, Segments[wfront->segnum].sides[wfront->sidenum].uvls[0].l, Segments[wfront->segnum].sides[wfront->sidenum].uvls[1].l, Segments[wfront->segnum].sides[wfront->sidenum].uvls[2].l, Segments[wfront->segnum].sides[wfront->sidenum].uvls[3].l); - + return r; } #endif namespace dsx { void wall_frame_process() { - int i; + unsigned i; for (i=0;ifront_wallnum); + const auto &&wpback = wallptr(d->back_wallnum); + const cwframe front(*w); + const cwframe back = (wpback ? cwframe(*wpback) : front); + const bool initial = (d->time == 0); + d->time += FrameTime; + cwresult r; if (w->state == WALL_DOOR_CLOAKING) - do_cloaking_wall_frame(i); + r = do_cloaking_wall_frame(initial, *d, front, back); else if (w->state == WALL_DOOR_DECLOAKING) - do_decloaking_wall_frame(i); -#ifdef _DEBUG + r = do_decloaking_wall_frame(initial, *d, front, back); else + { Int3(); //unexpected wall state -#endif + continue; + } + if (r.record) + { + // check if the actual cloak_value changed in this frame to prevent redundant recordings and wasted bytes + if (Newdemo_state == ND_STATE_RECORDING && r.record) + newdemo_record_cloaking_wall(d->front_wallnum, d->back_wallnum, front.w.type, front.w.state, front.w.cloak_value, front.uvls[0].l, front.uvls[1].l, front.uvls[2].l, front.uvls[3].l); + } + if (r.remove) + { + const auto &&cr = partial_range(CloakingWalls, i, Num_cloaking_walls--); + std::move(std::next(cr.begin()), cr.end(), cr.begin()); + } } #endif }