Merge branch 'master' into capsules-improvement

This commit is contained in:
Sally Coolatta 2022-12-19 01:12:07 -05:00
commit a7ff0afc8b
48 changed files with 2446 additions and 1577 deletions

1
.gitignore vendored
View file

@ -22,3 +22,4 @@ Win32_LIB_ASM_Release
/make
/bin
/build
/CMakeUserPresets.json

View file

@ -63,6 +63,7 @@ option(
"Link dependencies using CMake's find_package and do not use internal builds"
${SRB2_CONFIG_SYSTEM_LIBRARIES_DEFAULT}
)
option(SRB2_CONFIG_ENABLE_TESTS "Build the test suite" ON)
# This option isn't recommended for distribution builds and probably won't work (yet).
cmake_dependent_option(
SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES
@ -81,6 +82,25 @@ option(SRB2_CONFIG_ZDEBUG "Compile with ZDEBUG defined." OFF)
option(SRB2_CONFIG_PROFILEMODE "Compile for profiling (GCC only)." OFF)
set(SRB2_CONFIG_ASSET_DIRECTORY "" CACHE PATH "Path to directory that contains all asset files for the installer. If set, assets will be part of installation and cpack.")
if(SRB2_CONFIG_ENABLE_TESTS)
# https://github.com/catchorg/Catch2
CPMAddPackage(
NAME Catch2
VERSION 3.1.1
GITHUB_REPOSITORY catchorg/Catch2
OPTIONS
"CATCH_INSTALL_DOCS OFF"
)
list(APPEND CMAKE_MODULE_PATH "${Catch2_SOURCE_DIR}/extras")
include(CTest)
include(Catch)
add_executable(srb2tests)
# To add tests, use target_sources to add individual test files to the target in subdirs.
target_link_libraries(srb2tests PRIVATE Catch2::Catch2 Catch2::Catch2WithMain)
target_compile_features(srb2tests PRIVATE c_std_11 cxx_std_17)
catch_discover_tests(srb2tests)
endif()
# Enable CCache
# (Set USE_CCACHE=ON to use, CCACHE_OPTIONS for options)
if("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL Windows)
@ -125,13 +145,6 @@ if ((${SRB2_USE_CCACHE}) AND (${CMAKE_C_COMPILER} MATCHES "clang"))
message(WARNING "Using clang and CCache: You may want to set environment variable CCACHE_CPP2=yes to prevent include errors during compile.")
endif()
# Add sources from Sourcefile
function(target_sourcefile type)
file(STRINGS Sourcefile list
REGEX "[-0-9A-Za-z_]+\.${type}")
target_sources(SRB2SDL2 PRIVATE ${list})
endfunction()
# bitness check
set(SRB2_SYSTEM_BITS 0)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)

View file

@ -1,15 +1,143 @@
add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32)
add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32
comptime.c
md5.c
config.h.in
string.c
d_main.c
d_clisrv.c
d_net.c
d_netfil.c
d_netcmd.c
dehacked.c
deh_soc.c
deh_lua.c
deh_tables.c
z_zone.c
f_finale.c
f_wipe.c
g_demo.c
g_game.c
g_input.c
g_splitscreen.c
am_map.c
command.c
console.c
font.c
hu_stuff.c
i_time.c
y_inter.c
st_stuff.c
m_aatree.c
m_anigif.c
m_argv.c
m_bbox.c
m_cheat.c
m_cond.c
m_easing.c
m_fixed.c
m_misc.c
m_perfstats.c
m_random.c
m_queue.c
info.c
p_ceilng.c
p_enemy.c
p_floor.c
p_inter.c
p_lights.c
p_map.c
p_maputl.c
p_mobj.c
p_polyobj.c
p_saveg.c
p_setup.c
p_sight.c
p_spec.c
p_telept.c
p_tick.c
p_user.c
p_slopes.c
tables.c
r_bsp.c
r_data.c
r_draw.c
r_fps.c
r_main.c
r_plane.c
r_segs.c
r_skins.c
r_sky.c
r_splats.c
r_things.c
r_bbox.c
r_textures.c
r_patch.c
r_patchrotation.c
r_picformats.c
r_portal.c
screen.c
taglist.c
v_video.c
s_sound.c
sounds.c
w_wad.c
filesrch.c
mserv.c
http-mserv.c
i_tcp.c
lzf.c
vid_copy.s
lua_script.c
lua_baselib.c
lua_mathlib.c
lua_hooklib.c
lua_consolelib.c
lua_infolib.c
lua_mobjlib.c
lua_playerlib.c
lua_skinlib.c
lua_thinkerlib.c
lua_maplib.c
lua_taglib.c
lua_polyobjlib.c
lua_blockmaplib.c
lua_hudlib.c
lua_hudlib_drawlist.c
k_kart.c
k_respawn.c
k_collide.c
k_color.c
k_race.c
k_battle.c
k_pwrlv.c
k_waypoint.c
k_pathfind.c
k_bheap.c
k_bot.c
k_botitem.c
k_botsearch.c
k_grandprix.c
k_boss.c
k_hud.c
k_menudef.c
k_menufunc.c
k_menudraw.c
k_terrain.c
k_brightmap.c
k_terrain.c
k_director.c
k_follower.c
k_profiles.c
k_specialstage.c
k_roulette.c
)
if("${CMAKE_COMPILER_IS_GNUCC}" AND "${CMAKE_SYSTEM_NAME}" MATCHES "Windows" AND NOT "${SRB2_CONFIG_SYSTEM_LIBRARIES}" AND NOT "${SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES}")
# On MinGW with internal libraries, link the standard library statically
target_link_options(SRB2SDL2 PRIVATE "-static")
endif()
set_property(TARGET SRB2SDL2 PROPERTY C_STANDARD 11)
# Core sources
target_sourcefile(c)
target_sources(SRB2SDL2 PRIVATE comptime.c md5.c config.h.in)
target_compile_features(SRB2SDL2 PRIVATE c_std_11 cxx_std_17)
set(SRB2_ASM_SOURCES vid_copy.s)
@ -370,6 +498,7 @@ endif()
add_subdirectory(sdl)
add_subdirectory(objects)
add_subdirectory(tests)
# strip debug symbols into separate file when using gcc.
# to be consistent with Makefile, don't generate for OS X.

View file

@ -1,127 +0,0 @@
string.c
d_main.c
d_clisrv.c
d_net.c
d_netfil.c
d_netcmd.c
dehacked.c
deh_soc.c
deh_lua.c
deh_tables.c
z_zone.c
f_finale.c
f_wipe.c
g_demo.c
g_game.c
g_input.c
g_splitscreen.c
am_map.c
command.c
console.c
font.c
hu_stuff.c
i_time.c
y_inter.c
st_stuff.c
m_aatree.c
m_anigif.c
m_argv.c
m_bbox.c
m_cheat.c
m_cond.c
m_easing.c
m_fixed.c
m_misc.c
m_perfstats.c
m_random.c
m_queue.c
info.c
p_ceilng.c
p_enemy.c
p_floor.c
p_inter.c
p_lights.c
p_map.c
p_maputl.c
p_mobj.c
p_polyobj.c
p_saveg.c
p_setup.c
p_sight.c
p_spec.c
p_telept.c
p_tick.c
p_user.c
p_slopes.c
tables.c
r_bsp.c
r_data.c
r_draw.c
r_fps.c
r_main.c
r_plane.c
r_segs.c
r_skins.c
r_sky.c
r_splats.c
r_things.c
r_bbox.c
r_textures.c
r_patch.c
r_patchrotation.c
r_picformats.c
r_portal.c
screen.c
taglist.c
v_video.c
s_sound.c
sounds.c
w_wad.c
filesrch.c
mserv.c
http-mserv.c
i_tcp.c
lzf.c
vid_copy.s
lua_script.c
lua_baselib.c
lua_mathlib.c
lua_hooklib.c
lua_consolelib.c
lua_infolib.c
lua_mobjlib.c
lua_playerlib.c
lua_skinlib.c
lua_thinkerlib.c
lua_maplib.c
lua_taglib.c
lua_polyobjlib.c
lua_blockmaplib.c
lua_hudlib.c
lua_hudlib_drawlist.c
k_kart.c
k_respawn.c
k_collide.c
k_color.c
k_race.c
k_battle.c
k_pwrlv.c
k_waypoint.c
k_pathfind.c
k_bheap.c
k_bot.c
k_botitem.c
k_botsearch.c
k_grandprix.c
k_boss.c
k_hud.c
k_menudef.c
k_menufunc.c
k_menudraw.c
k_terrain.c
k_brightmap.c
k_terrain.c
k_director.c
k_follower.c
k_profiles.c
k_specialstage.c

View file

@ -1 +1,27 @@
target_sourcefile(c)
target_sources(SRB2SDL2 PRIVATE
lapi.c
lbaselib.c
ldo.c
lfunc.c
linit.c
liolib.c
llex.c
lmem.c
lobject.c
lstate.c
lstrlib.c
ltablib.c
lundump.c
lzio.c
lauxlib.c
lcode.c
ldebug.c
ldump.c
lgc.c
lopcodes.c
lparser.c
lstring.c
ltable.c
ltm.c
lvm.c
)

View file

@ -1,25 +0,0 @@
lapi.c
lbaselib.c
ldo.c
lfunc.c
linit.c
liolib.c
llex.c
lmem.c
lobject.c
lstate.c
lstrlib.c
ltablib.c
lundump.c
lzio.c
lauxlib.c
lcode.c
ldebug.c
ldump.c
lgc.c
lopcodes.c
lparser.c
lstring.c
ltable.c
ltm.c
lvm.c

37
src/cxxutil.hpp Normal file
View file

@ -0,0 +1,37 @@
#ifndef __SRB2_CXXUTIL_HPP__
#define __SRB2_CXXUTIL_HPP__
#include <type_traits>
#include <utility>
namespace srb2 {
template <class F>
class Finally {
public:
explicit Finally(const F& f) noexcept : f_(f) {}
explicit Finally(F&& f) noexcept : f_(f) {}
Finally(Finally&& from) noexcept : f_(std::move(from.f_)), call_(std::exchange(from.call_, false)) {}
Finally(const Finally& from) = delete;
void operator=(const Finally& from) = delete;
void operator=(Finally&& from) = delete;
~Finally() noexcept {
f_();
}
private:
F f_;
bool call_ = true;
};
template <class F>
Finally<std::decay_t<F>> finally(F&& f) noexcept {
return Finally {std::forward<F>(f)};
}
}
#endif // __SRB2_CXXUTIL_HPP__

View file

@ -360,37 +360,38 @@ consvar_t cv_joyscale[MAXSPLITSCREENPLAYERS] = { //Alam: Dummy for save
#endif
// SRB2kart
consvar_t cv_sneaker = CVAR_INIT ("sneaker", "On", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_rocketsneaker = CVAR_INIT ("rocketsneaker", "On", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_invincibility = CVAR_INIT ("invincibility", "On", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_banana = CVAR_INIT ("banana", "On", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_eggmanmonitor = CVAR_INIT ("eggmanmonitor", "On", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_orbinaut = CVAR_INIT ("orbinaut", "On", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_jawz = CVAR_INIT ("jawz", "On", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_mine = CVAR_INIT ("mine", "On", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_landmine = CVAR_INIT ("landmine", "On", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_ballhog = CVAR_INIT ("ballhog", "On", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_selfpropelledbomb = CVAR_INIT ("selfpropelledbomb", "On", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_grow = CVAR_INIT ("grow", "On", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_shrink = CVAR_INIT ("shrink", "On", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_lightningshield = CVAR_INIT ("lightningshield", "On", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_bubbleshield = CVAR_INIT ("bubbleshield", "On", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_flameshield = CVAR_INIT ("flameshield", "On", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_hyudoro = CVAR_INIT ("hyudoro", "On", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_pogospring = CVAR_INIT ("pogospring", "On", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_superring = CVAR_INIT ("superring", "On", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_kitchensink = CVAR_INIT ("kitchensink", "On", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_droptarget = CVAR_INIT ("droptarget", "On", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_gardentop = CVAR_INIT ("gardentop", "On", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_gachabom = CVAR_INIT ("gachabom", "On", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_dualsneaker = CVAR_INIT ("dualsneaker", "On", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_triplesneaker = CVAR_INIT ("triplesneaker", "On", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_triplebanana = CVAR_INIT ("triplebanana", "On", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_tripleorbinaut = CVAR_INIT ("tripleorbinaut", "On", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_quadorbinaut = CVAR_INIT ("quadorbinaut", "On", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_dualjawz = CVAR_INIT ("dualjawz", "On", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_triplegachabom = CVAR_INIT ("triplegachabom", "On", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_items[NUMKARTRESULTS-1] = {
CVAR_INIT ("sneaker", "On", CV_NETVAR, CV_OnOff, NULL),
CVAR_INIT ("rocketsneaker", "On", CV_NETVAR, CV_OnOff, NULL),
CVAR_INIT ("invincibility", "On", CV_NETVAR, CV_OnOff, NULL),
CVAR_INIT ("banana", "On", CV_NETVAR, CV_OnOff, NULL),
CVAR_INIT ("eggmanmonitor", "On", CV_NETVAR, CV_OnOff, NULL),
CVAR_INIT ("orbinaut", "On", CV_NETVAR, CV_OnOff, NULL),
CVAR_INIT ("jawz", "On", CV_NETVAR, CV_OnOff, NULL),
CVAR_INIT ("mine", "On", CV_NETVAR, CV_OnOff, NULL),
CVAR_INIT ("landmine", "On", CV_NETVAR, CV_OnOff, NULL),
CVAR_INIT ("ballhog", "On", CV_NETVAR, CV_OnOff, NULL),
CVAR_INIT ("selfpropelledbomb", "On", CV_NETVAR, CV_OnOff, NULL),
CVAR_INIT ("grow", "On", CV_NETVAR, CV_OnOff, NULL),
CVAR_INIT ("shrink", "On", CV_NETVAR, CV_OnOff, NULL),
CVAR_INIT ("lightningshield", "On", CV_NETVAR, CV_OnOff, NULL),
CVAR_INIT ("bubbleshield", "On", CV_NETVAR, CV_OnOff, NULL),
CVAR_INIT ("flameshield", "On", CV_NETVAR, CV_OnOff, NULL),
CVAR_INIT ("hyudoro", "On", CV_NETVAR, CV_OnOff, NULL),
CVAR_INIT ("pogospring", "On", CV_NETVAR, CV_OnOff, NULL),
CVAR_INIT ("superring", "On", CV_NETVAR, CV_OnOff, NULL),
CVAR_INIT ("kitchensink", "On", CV_NETVAR, CV_OnOff, NULL),
CVAR_INIT ("droptarget", "On", CV_NETVAR, CV_OnOff, NULL),
CVAR_INIT ("gardentop", "On", CV_NETVAR, CV_OnOff, NULL),
CVAR_INIT ("gachabom", "On", CV_NETVAR, CV_OnOff, NULL),
CVAR_INIT ("dualsneaker", "On", CV_NETVAR, CV_OnOff, NULL),
CVAR_INIT ("triplesneaker", "On", CV_NETVAR, CV_OnOff, NULL),
CVAR_INIT ("triplebanana", "On", CV_NETVAR, CV_OnOff, NULL),
CVAR_INIT ("tripleorbinaut", "On", CV_NETVAR, CV_OnOff, NULL),
CVAR_INIT ("quadorbinaut", "On", CV_NETVAR, CV_OnOff, NULL),
CVAR_INIT ("dualjawz", "On", CV_NETVAR, CV_OnOff, NULL),
CVAR_INIT ("triplegachabom", "On", CV_NETVAR, CV_OnOff, NULL)
};
consvar_t cv_kartspeed = CVAR_INIT ("gamespeed", "Auto", CV_NETVAR|CV_CALL|CV_NOINIT, kartspeed_cons_t, KartSpeed_OnChange);
static CV_PossibleValue_t kartbumpers_cons_t[] = {{1, "MIN"}, {12, "MAX"}, {0, NULL}};
@ -5661,7 +5662,7 @@ static void Got_Cheat(UINT8 **cp, INT32 playernum)
K_StripItems(player);
// Cancel roulette if rolling
player->itemroulette = 0;
player->itemRoulette.active = false;
player->itemtype = item;
player->itemamount = amt;

View file

@ -16,6 +16,7 @@
#define __D_NETCMD__
#include "command.h"
#include "d_player.h"
// console vars
extern consvar_t cv_playername[MAXSPLITSCREENPLAYERS];
@ -72,39 +73,7 @@ extern consvar_t cv_pause;
extern consvar_t cv_restrictskinchange, cv_allowteamchange, cv_maxplayers, cv_respawntime;
// SRB2kart items
extern consvar_t
cv_sneaker,
cv_rocketsneaker,
cv_invincibility,
cv_banana,
cv_eggmanmonitor,
cv_orbinaut,
cv_jawz,
cv_mine,
cv_landmine,
cv_ballhog,
cv_selfpropelledbomb,
cv_grow,
cv_shrink,
cv_lightningshield,
cv_bubbleshield,
cv_flameshield,
cv_hyudoro,
cv_pogospring,
cv_superring,
cv_kitchensink,
cv_droptarget,
cv_gardentop,
cv_gachabom;
extern consvar_t
cv_dualsneaker,
cv_triplesneaker,
cv_triplebanana,
cv_tripleorbinaut,
cv_quadorbinaut,
cv_dualjawz,
cv_triplegachabom;
extern consvar_t cv_items[NUMKARTRESULTS-1];
extern consvar_t cv_kartspeed;
extern consvar_t cv_kartbumpers;

View file

@ -227,6 +227,7 @@ typedef enum
// Item box
khud_itemblink, // Item flashing after roulette, serves as a mashing indicator
khud_itemblinkmode, // Type of flashing: 0 = white (normal), 1 = red (mashing), 2 = rainbow (enhanced items)
khud_rouletteoffset,// Roulette stop height
// Rings
khud_ringframe, // Ring spin frame
@ -331,6 +332,41 @@ struct skybox_t {
mobj_t * centerpoint;
};
// player_t struct for item roulette variables
// Doing this the right way is causing problems.
// so FINE, it's a static length now.
#define ITEM_LIST_SIZE (NUMKARTRESULTS << 3)
struct itemroulette_t
{
boolean active;
#ifdef ITEM_LIST_SIZE
size_t itemListLen;
SINT8 itemList[ITEM_LIST_SIZE];
#else
size_t itemListCap;
size_t itemListLen;
SINT8 *itemList;
#endif
UINT8 useOdds;
UINT8 playing, exiting;
UINT32 dist, baseDist;
UINT32 firstDist, secondDist;
UINT32 secondToFirst;
size_t index;
UINT8 sound;
tic_t speed;
tic_t tics;
tic_t elapsed;
boolean eggman;
};
// ========================================================================
// PLAYER STRUCTURE
// ========================================================================
@ -479,8 +515,7 @@ struct player_t
UINT8 tripwirePass; // see tripwirepass_t
UINT16 tripwireLeniency; // When reaching a state that lets you go thru tripwire, you get an extra second leniency after it ends to still go through it.
UINT16 itemroulette; // Used for the roulette when deciding what item to give you (was "pw_kartitem")
UINT8 roulettetype; // Used for the roulette, for deciding type (0 = normal, 1 = better, 2 = eggman mark)
itemroulette_t itemRoulette; // Item roulette data
// Item held stuff
SINT8 itemtype; // KITEM_ constant for item number

View file

@ -5629,6 +5629,8 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t
"MT_PAPERITEMSPOT",
"MT_BEAMPOINT",
"MT_BROLY",
};
const char *const MOBJFLAG_LIST[] = {

View file

@ -126,10 +126,10 @@ extern char logfilename[1024];
// VERSIONSTRING_RC is for the resource-definition script used by windows builds
#else
#ifdef BETAVERSION
#define VERSIONSTRING "v"SRB2VERSION" "BETAVERSION
#define VERSIONSTRING "v" SRB2VERSION " " BETAVERSION
#define VERSIONSTRING_RC SRB2VERSION " " BETAVERSION "\0"
#else
#define VERSIONSTRING "v"SRB2VERSION
#define VERSIONSTRING "v" SRB2VERSION
#define VERSIONSTRING_RC SRB2VERSION "\0"
#endif
// Hey! If you change this, add 1 to the MODVERSION below!
@ -614,12 +614,14 @@ UINT32 quickncasehash (const char *p, size_t n)
return x;
}
#ifndef __cplusplus
#ifndef min // Double-Check with WATTCP-32's cdefs.h
#define min(x, y) (((x) < (y)) ? (x) : (y))
#endif
#ifndef max // Double-Check with WATTCP-32's cdefs.h
#define max(x, y) (((x) > (y)) ? (x) : (y))
#endif
#endif
// Max gamepad/joysticks that can be detected/used.
#define MAX_JOYSTICKS 4

View file

@ -17,6 +17,10 @@
#ifndef __DOOMTYPE__
#define __DOOMTYPE__
#ifdef __cplusplus
extern "C" {
#endif
#ifdef _WIN32
//#define WIN32_LEAN_AND_MEAN
#define RPC_NO_WINDOWS_H
@ -88,7 +92,9 @@ typedef long ssize_t;
#endif
#define strncasecmp strnicmp
#define strcasecmp stricmp
#ifndef __cplusplus
#define inline __inline
#endif
#elif defined (__WATCOMC__)
#include <dos.h>
#include <sys\types.h>
@ -107,24 +113,6 @@ typedef long ssize_t;
char *strcasestr(const char *in, const char *what);
#define stristr strcasestr
#if defined (macintosh) //|| defined (__APPLE__) //skip all boolean/Boolean crap
#define true 1
#define false 0
#define min(x,y) (((x)<(y)) ? (x) : (y))
#define max(x,y) (((x)>(y)) ? (x) : (y))
#ifdef macintosh
#define stricmp strcmp
#define strnicmp strncmp
#endif
#define boolean INT32
#ifndef O_BINARY
#define O_BINARY 0
#endif
#endif //macintosh
#if defined (PC_DOS) || defined (_WIN32) || defined (__HAIKU__)
#define HAVE_DOSSTR_FUNCS
#endif
@ -151,22 +139,24 @@ size_t strlcpy(char *dst, const char *src, size_t siz);
/* Boolean type definition */
// \note __BYTEBOOL__ used to be set above if "macintosh" was defined,
// if macintosh's version of boolean type isn't needed anymore, then isn't this macro pointless now?
#ifndef __BYTEBOOL__
#define __BYTEBOOL__
// Note: C++ bool and C99/C11 _Bool are NOT compatible.
// Historically, boolean was win32 BOOL on Windows. For equivalence, it's now
// int32_t. "true" and "false" are only declared for C code; in C++, conversion
// between "bool" and "int32_t" takes over.
#ifndef _WIN32
typedef int32_t boolean;
#else
#define boolean BOOL
#endif
//faB: clean that up !!
#if defined( _MSC_VER) && (_MSC_VER >= 1800) // MSVC 2013 and forward
#include "stdbool.h"
#elif defined (_WIN32)
#define false FALSE // use windows types
#define true TRUE
#define boolean BOOL
#else
typedef enum {false, true} boolean;
#endif
#endif // __BYTEBOOL__
#ifndef __cplusplus
#ifndef _WIN32
enum {false = 0, true = 1};
#else
#define false FALSE
#define true TRUE
#endif
#endif
/* 7.18.2.1 Limits of exact-width integer types */
@ -408,4 +398,8 @@ typedef UINT64 precise_t;
#include "typedef.h"
#ifdef __cplusplus
} // extern "C"
#endif
#endif //__DOOMTYPE__

View file

@ -2260,11 +2260,10 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
SINT8 xtralife;
// SRB2kart
itemroulette_t itemRoulette;
respawnvars_t respawn;
INT32 itemtype;
INT32 itemamount;
INT32 itemroulette;
INT32 roulettetype;
INT32 growshrinktimer;
INT32 bumper;
boolean songcredit = false;
@ -2323,10 +2322,13 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
pflags = (players[player].pflags & (PF_WANTSTOJOIN|PF_KICKSTARTACCEL|PF_SHRINKME|PF_SHRINKACTIVE));
// SRB2kart
memcpy(&itemRoulette, &players[player].itemRoulette, sizeof (itemRoulette));
memcpy(&respawn, &players[player].respawn, sizeof (respawn));
if (betweenmaps || leveltime < introtime)
{
itemroulette = 0;
roulettetype = 0;
itemRoulette.active = false;
itemtype = 0;
itemamount = 0;
growshrinktimer = 0;
@ -2348,9 +2350,6 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
}
else
{
itemroulette = (players[player].itemroulette > 0 ? 1 : 0);
roulettetype = players[player].roulettetype;
if (players[player].pflags & PF_ITEMOUT)
{
itemtype = 0;
@ -2406,8 +2405,6 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
P_SetTarget(&players[player].follower, NULL);
}
memcpy(&respawn, &players[player].respawn, sizeof (respawn));
p = &players[player];
memset(p, 0, sizeof (*p));
@ -2453,8 +2450,6 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
p->xtralife = xtralife;
// SRB2kart
p->itemroulette = itemroulette;
p->roulettetype = roulettetype;
p->itemtype = itemtype;
p->itemamount = itemamount;
p->growshrinktimer = growshrinktimer;
@ -2470,6 +2465,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
p->botvars.rubberband = FRACUNIT;
p->botvars.controller = UINT16_MAX;
memcpy(&p->itemRoulette, &itemRoulette, sizeof (p->itemRoulette));
memcpy(&p->respawn, &respawn, sizeof (p->respawn));
if (follower)
@ -2481,7 +2477,6 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
//p->follower = NULL; // respawn a new one with you, it looks better.
// ^ Not necessary anyway since it will be respawned regardless considering it doesn't exist anymore.
p->playerstate = PST_LIVE;
p->panim = PA_STILL; // standing animation

View file

@ -1 +1,15 @@
target_sourcefile(c)
target_sources(SRB2SDL2 PRIVATE
hw_bsp.c
hw_draw.c
hw_light.c
hw_main.c
hw_clip.c
hw_md2.c
hw_cache.c
hw_md2load.c
hw_md3load.c
hw_model.c
u_list.c
hw_batching.c
r_opengl/r_opengl.c
)

View file

@ -1,13 +0,0 @@
hw_bsp.c
hw_draw.c
hw_light.c
hw_main.c
hw_clip.c
hw_md2.c
hw_cache.c
hw_md2load.c
hw_md3load.c
hw_model.c
u_list.c
hw_batching.c
r_opengl/r_opengl.c

View file

@ -249,7 +249,7 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p
if ((cx + fwidth) > clip->right)
{
const float n = (clip->right - clip->left);
const float n = (clip->right - cx);
s_max = (s_min + ((n / fwidth) * s_max));
fwidth = n;
@ -257,7 +257,7 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p
if ((cy + fheight) > clip->bottom)
{
const float n = (clip->bottom - clip->top);
const float n = (clip->bottom - cy);
t_max = (t_min + ((n / fheight) * t_max));
fheight = n;

View file

@ -938,8 +938,7 @@ static void HU_TickSongCredits(void)
if (cursongcredit.anim > 0)
{
char *str = va("\x1F"" %s", cursongcredit.def->source);
INT32 len = V_ThinStringWidth(str, V_ALLOWLOWERCASE|V_6WIDTHSPACE);
INT32 len = V_ThinStringWidth(cursongcredit.text, V_ALLOWLOWERCASE|V_6WIDTHSPACE);
fixed_t destx = (len+7) * FRACUNIT;
if (cursongcredit.trans > 0)
@ -2045,29 +2044,28 @@ static void HU_DrawDemoInfo(void)
//
void HU_DrawSongCredits(void)
{
char *str;
fixed_t x;
fixed_t y = (r_splitscreen ? (BASEVIDHEIGHT/2)-4 : 32) * FRACUNIT;
INT32 bgt;
if (!cursongcredit.def) // No def
if (!cursongcredit.def || cursongcredit.trans >= NUMTRANSMAPS) // No def
{
return;
}
str = va("\x1F"" %s", cursongcredit.def->source);
bgt = (NUMTRANSMAPS/2) + (cursongcredit.trans / 2);
x = R_InterpolateFixed(cursongcredit.old_x, cursongcredit.x);
if (bgt < NUMTRANSMAPS)
{
V_DrawFixedPatch(x, y - (2 * FRACUNIT), FRACUNIT, V_SNAPTOLEFT|(bgt<<V_ALPHASHIFT), songcreditbg, NULL);
V_DrawFixedPatch(x, y - (2 * FRACUNIT),
FRACUNIT, V_SNAPTOLEFT|(bgt<<V_ALPHASHIFT),
songcreditbg, NULL);
}
if (cursongcredit.trans < NUMTRANSMAPS)
{
V_DrawRightAlignedThinStringAtFixed(x, y, V_ALLOWLOWERCASE|V_6WIDTHSPACE|V_SNAPTOLEFT|(cursongcredit.trans<<V_ALPHASHIFT), str);
}
V_DrawRightAlignedThinStringAtFixed(x, y,
V_ALLOWLOWERCASE|V_6WIDTHSPACE|V_SNAPTOLEFT|(cursongcredit.trans<<V_ALPHASHIFT),
cursongcredit.text);
}

View file

@ -29057,6 +29057,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIPTHING|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags
S_NULL // raisestate
},
{ // MT_BROLY
-1, // doomednum
S_BROLY1, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
0, // radius
0, // height
0, // display offset
100, // mass
1, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPTHING|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags
S_NULL // raisestate
},
};
skincolor_t skincolors[MAXSKINCOLORS] = {

View file

@ -6684,6 +6684,8 @@ typedef enum mobj_type
MT_BEAMPOINT,
MT_BROLY,
MT_FIRSTFREESLOT,
MT_LASTFREESLOT = MT_FIRSTFREESLOT + NUMMOBJFREESLOTS - 1,
NUMMOBJTYPES

View file

@ -26,6 +26,7 @@
#include "d_ticcmd.h"
#include "m_random.h"
#include "r_things.h" // numskins
#include "k_roulette.h"
/*--------------------------------------------------
static inline boolean K_ItemButtonWasDown(player_t *player)
@ -739,7 +740,7 @@ static void K_BotItemEggman(player_t *player, ticcmd_t *cmd)
tryLookback = true;
}
if (stealth > 1 || player->itemroulette > 0)
if (stealth > 1 || player->itemRoulette.active == true)
{
player->botvars.itemconfirm += player->botvars.difficulty * 4;
throwdir = -1;
@ -1393,27 +1394,15 @@ static void K_BotItemRings(player_t *player, ticcmd_t *cmd)
--------------------------------------------------*/
static void K_BotItemRouletteMash(player_t *player, ticcmd_t *cmd)
{
boolean mash = false;
if (K_ItemButtonWasDown(player) == true)
{
return;
}
if (player->rings < 0 && cv_superring.value)
{
// Uh oh, we need a loan!
// It'll be better in the long run for bots to lose an item set for 10 free rings.
mash = true;
}
// TODO: Would be nice to implement smarter behavior
// for selecting items.
// TODO: Mash based on how far behind you are, when items are
// almost garantueed to be in your favor.
if (mash == true)
{
cmd->buttons |= BT_ATTACK;
}
cmd->buttons |= BT_ATTACK;
}
/*--------------------------------------------------
@ -1441,7 +1430,7 @@ void K_BotItemUsage(player_t *player, ticcmd_t *cmd, INT16 turnamt)
return;
}
if (player->itemroulette)
if (player->itemRoulette.active == true)
{
// Mashing behaviors
K_BotItemRouletteMash(player, cmd);

View file

@ -12,6 +12,7 @@
#include "doomdef.h" // Sink snipe print
#include "g_game.h" // Sink snipe print
#include "k_objects.h"
#include "k_roulette.h"
angle_t K_GetCollideAngle(mobj_t *t1, mobj_t *t2)
{
@ -158,10 +159,7 @@ boolean K_EggItemCollide(mobj_t *t1, mobj_t *t2)
}
else
{
K_DropItems(t2->player); //K_StripItems(t2->player);
//K_StripOther(t2->player);
t2->player->itemroulette = 1;
t2->player->roulettetype = 2;
K_StartEggmanRoulette(t2->player);
}
if (t2->player->flamedash && t2->player->itemtype == KITEM_FLAMESHIELD)
@ -319,7 +317,7 @@ tic_t K_MineExplodeAttack(mobj_t *actor, fixed_t size, boolean spin)
if (!spin)
{
K_SpawnBrolyKi(actor, minehitlag);
Obj_SpawnBrolyKi(actor, minehitlag);
return minehitlag;
}
@ -345,7 +343,7 @@ boolean K_MineCollide(mobj_t *t1, mobj_t *t2)
// Bomb punting
if ((t1->state >= &states[S_SSMINE1] && t1->state <= &states[S_SSMINE4])
|| (t1->state >= &states[S_SSMINE_DEPLOY8] && t1->state <= &states[S_SSMINE_DEPLOY13]))
|| (t1->state >= &states[S_SSMINE_DEPLOY8] && t1->state <= &states[S_SSMINE_EXPLODE2]))
{
P_KillMobj(t1, t2, t2, DMG_NORMAL);
}

View file

@ -24,11 +24,18 @@
--------------------------------------------------*/
UINT8 K_ColorRelativeLuminance(UINT8 r, UINT8 g, UINT8 b)
{
UINT32 redweight = 1063 * r;
UINT32 greenweight = 3576 * g;
UINT32 blueweight = 361 * b;
UINT32 brightness = (redweight + greenweight + blueweight) / 5000;
return min(brightness, UINT8_MAX);
double redWeight = ((r * 1.0) / UINT8_MAX);
double greenWeight = ((g * 1.0) / UINT8_MAX);
double blueWeight = ((b * 1.0) / UINT8_MAX);
double brightness = 0.5;
redWeight = pow(redWeight, 2.2) * 0.2126;
greenWeight = pow(greenWeight, 2.2) * 0.7152;
blueWeight = pow(greenWeight, 2.2) * 0.0722;
brightness = pow(redWeight + greenWeight + blueWeight, 1.0 / 2.2);
return (UINT8)(brightness * UINT8_MAX);
}
/*--------------------------------------------------

View file

@ -36,6 +36,7 @@
#include "r_things.h"
#include "r_fps.h"
#include "m_random.h"
#include "k_roulette.h"
//{ Patch Definitions
static patch_t *kp_nodraw;
@ -1069,64 +1070,83 @@ static void K_drawKartItem(void)
// Why write V_DrawScaledPatch calls over and over when they're all the same?
// Set to 'no item' just in case.
const UINT8 offset = ((r_splitscreen > 1) ? 1 : 0);
patch_t *localpatch = kp_nodraw;
patch_t *localpatch[3] = { kp_nodraw, kp_nodraw, kp_nodraw };
patch_t *localbg = ((offset) ? kp_itembg[2] : kp_itembg[0]);
patch_t *localinv = ((offset) ? kp_invincibility[((leveltime % (6*3)) / 3) + 7] : kp_invincibility[(leveltime % (7*3)) / 3]);
INT32 fx = 0, fy = 0, fflags = 0; // final coords for hud and flags...
const INT32 numberdisplaymin = ((!offset && stplyr->itemtype == KITEM_ORBINAUT) ? 5 : 2);
INT32 itembar = 0;
INT32 maxl = 0; // itembar's normal highest value
const INT32 barlength = (r_splitscreen > 1 ? 12 : 26);
UINT16 localcolor = SKINCOLOR_NONE;
SINT8 colormode = TC_RAINBOW;
UINT8 *colmap = NULL;
const INT32 barlength = (offset ? 12 : 26);
UINT16 localcolor[3] = { stplyr->skincolor };
SINT8 colormode[3] = { TC_RAINBOW };
boolean flipamount = false; // Used for 3P/4P splitscreen to flip item amount stuff
if (stplyr->itemroulette)
fixed_t rouletteOffset = 0;
fixed_t rouletteSpace = ROULETTE_SPACING;
vector2_t rouletteCrop = {7, 7};
INT32 i;
if (stplyr->itemRoulette.itemListLen > 0)
{
const INT32 item = K_GetRollingRouletteItem(stplyr);
if (stplyr->skincolor)
localcolor = stplyr->skincolor;
switch (item)
// Init with item roulette stuff.
for (i = 0; i < 3; i++)
{
case KITEM_INVINCIBILITY:
localpatch = localinv;
break;
const SINT8 indexOfs = i-1;
const size_t index = (stplyr->itemRoulette.index + indexOfs) % stplyr->itemRoulette.itemListLen;
case KITEM_ORBINAUT:
localpatch = kp_orbinaut[3 + offset];
break;
const SINT8 result = stplyr->itemRoulette.itemList[index];
const SINT8 item = K_ItemResultToType(result);
const UINT8 amt = K_ItemResultToAmount(result);
default:
localpatch = K_GetCachedItemPatch(item, offset);
break;
switch (item)
{
case KITEM_INVINCIBILITY:
localpatch[i] = localinv;
break;
case KITEM_ORBINAUT:
localpatch[i] = kp_orbinaut[(offset ? 4 : min(amt-1, 3))];
break;
default:
localpatch[i] = K_GetCachedItemPatch(item, offset);
break;
}
}
}
if (stplyr->itemRoulette.active == true)
{
rouletteOffset = K_GetRouletteOffset(&stplyr->itemRoulette, rendertimefrac);
}
else
{
// I'm doing this a little weird and drawing mostly in reverse order
// The only actual reason is to make sneakers line up this way in the code below
// This shouldn't have any actual baring over how it functions
// Hyudoro is first, because we're drawing it on top of the player's current item
localcolor[1] = SKINCOLOR_NONE;
rouletteOffset = stplyr->karthud[khud_rouletteoffset];
if (stplyr->stealingtimer < 0)
{
if (leveltime & 2)
localpatch = kp_hyudoro[offset];
localpatch[1] = kp_hyudoro[offset];
else
localpatch = kp_nodraw;
localpatch[1] = kp_nodraw;
}
else if ((stplyr->stealingtimer > 0) && (leveltime & 2))
{
localpatch = kp_hyudoro[offset];
localpatch[1] = kp_hyudoro[offset];
}
else if (stplyr->eggmanexplode > 1)
{
if (leveltime & 1)
localpatch = kp_eggman[offset];
localpatch[1] = kp_eggman[offset];
else
localpatch = kp_nodraw;
localpatch[1] = kp_nodraw;
}
else if (stplyr->ballhogcharge > 0)
{
@ -1134,9 +1154,9 @@ static void K_drawKartItem(void)
maxl = (((stplyr->itemamount-1) * BALLHOGINCREMENT) + 1);
if (leveltime & 1)
localpatch = kp_ballhog[offset];
localpatch[1] = kp_ballhog[offset];
else
localpatch = kp_nodraw;
localpatch[1] = kp_nodraw;
}
else if (stplyr->rocketsneakertimer > 1)
{
@ -1144,31 +1164,31 @@ static void K_drawKartItem(void)
maxl = (itemtime*3) - barlength;
if (leveltime & 1)
localpatch = kp_rocketsneaker[offset];
localpatch[1] = kp_rocketsneaker[offset];
else
localpatch = kp_nodraw;
localpatch[1] = kp_nodraw;
}
else if (stplyr->sadtimer > 0)
{
if (leveltime & 2)
localpatch = kp_sadface[offset];
localpatch[1] = kp_sadface[offset];
else
localpatch = kp_nodraw;
localpatch[1] = kp_nodraw;
}
else
{
if (stplyr->itemamount <= 0)
return;
switch(stplyr->itemtype)
switch (stplyr->itemtype)
{
case KITEM_INVINCIBILITY:
localpatch = localinv;
localpatch[1] = localinv;
localbg = kp_itembg[offset+1];
break;
case KITEM_ORBINAUT:
localpatch = kp_orbinaut[(offset ? 4 : min(stplyr->itemamount-1, 3))];
localpatch[1] = kp_orbinaut[(offset ? 4 : min(stplyr->itemamount-1, 3))];
break;
case KITEM_SPB:
@ -1179,44 +1199,45 @@ static void K_drawKartItem(void)
/*FALLTHRU*/
default:
localpatch = K_GetCachedItemPatch(stplyr->itemtype, offset);
localpatch[1] = K_GetCachedItemPatch(stplyr->itemtype, offset);
if (localpatch == NULL)
localpatch = kp_nodraw; // diagnose underflows
if (localpatch[1] == NULL)
localpatch[1] = kp_nodraw; // diagnose underflows
break;
}
if ((stplyr->pflags & PF_ITEMOUT) && !(leveltime & 1))
localpatch = kp_nodraw;
localpatch[1] = kp_nodraw;
}
if (stplyr->karthud[khud_itemblink] && (leveltime & 1))
{
colormode = TC_BLINK;
colormode[1] = TC_BLINK;
switch (stplyr->karthud[khud_itemblinkmode])
{
case 2:
localcolor = K_RainbowColor(leveltime);
localcolor[1] = K_RainbowColor(leveltime);
break;
case 1:
localcolor = SKINCOLOR_RED;
localcolor[1] = SKINCOLOR_RED;
break;
default:
localcolor = SKINCOLOR_WHITE;
localcolor[1] = SKINCOLOR_WHITE;
break;
}
}
else
{
// Hide the other items.
// Effectively lets the other roulette items
// show flicker away after you select.
localpatch[0] = localpatch[2] = kp_nodraw;
}
}
// pain and suffering defined below
if (r_splitscreen < 2) // don't change shit for THIS splitscreen.
{
fx = ITEM_X;
fy = ITEM_Y;
fflags = V_SNAPTOTOP|V_SNAPTOLEFT|V_SPLITSCREEN;
}
else // now we're having a fun game.
if (offset)
{
if (stplyr == &players[displayplayers[0]] || stplyr == &players[displayplayers[2]]) // If we are P1 or P3...
{
@ -1231,35 +1252,91 @@ static void K_drawKartItem(void)
fflags = V_SNAPTORIGHT|V_SNAPTOTOP|V_SPLITSCREEN;
flipamount = true;
}
}
if (localcolor != SKINCOLOR_NONE)
colmap = R_GetTranslationColormap(colormode, localcolor, GTC_CACHE);
rouletteSpace = ROULETTE_SPACING_SPLITSCREEN;
rouletteOffset = FixedMul(rouletteOffset, FixedDiv(ROULETTE_SPACING_SPLITSCREEN, ROULETTE_SPACING));
rouletteCrop.x = 16;
rouletteCrop.y = 15;
}
else
{
fx = ITEM_X;
fy = ITEM_Y;
fflags = V_SNAPTOTOP|V_SNAPTOLEFT|V_SPLITSCREEN;
}
V_DrawScaledPatch(fx, fy, V_HUDTRANS|V_SLIDEIN|fflags, localbg);
//V_SetClipRect((fx + 10) << FRACBITS, (fy + 10) << FRACBITS, 30 << FRACBITS, 30 << FRACBITS, V_HUDTRANS|V_SLIDEIN|fflags);
// Need to draw these in a particular order, for sorting.
V_SetClipRect(
(fx + rouletteCrop.x) << FRACBITS, (fy + rouletteCrop.y) << FRACBITS,
rouletteSpace, rouletteSpace,
V_SLIDEIN|fflags
);
// Then, the numbers:
if (stplyr->itemamount >= numberdisplaymin && !stplyr->itemroulette)
V_DrawFixedPatch(
fx<<FRACBITS, (fy<<FRACBITS) + rouletteOffset + rouletteSpace,
FRACUNIT, V_HUDTRANS|V_SLIDEIN|fflags,
localpatch[0], (localcolor[0] ? R_GetTranslationColormap(colormode[0], localcolor[0], GTC_CACHE) : NULL)
);
V_DrawFixedPatch(
fx<<FRACBITS, (fy<<FRACBITS) + rouletteOffset - rouletteSpace,
FRACUNIT, V_HUDTRANS|V_SLIDEIN|fflags,
localpatch[2], (localcolor[2] ? R_GetTranslationColormap(colormode[2], localcolor[2], GTC_CACHE) : NULL)
);
if (stplyr->itemRoulette.active == true)
{
V_DrawScaledPatch(fx + (flipamount ? 48 : 0), fy, V_HUDTRANS|V_SLIDEIN|fflags|(flipamount ? V_FLIP : 0), kp_itemmulsticker[offset]); // flip this graphic for p2 and p4 in split and shift it.
V_DrawFixedPatch(fx<<FRACBITS, fy<<FRACBITS, FRACUNIT, V_HUDTRANS|V_SLIDEIN|fflags, localpatch, colmap);
if (offset)
if (flipamount) // reminder that this is for 3/4p's right end of the screen.
V_DrawString(fx+2, fy+31, V_ALLOWLOWERCASE|V_HUDTRANS|V_SLIDEIN|fflags, va("x%d", stplyr->itemamount));
else
V_DrawString(fx+24, fy+31, V_ALLOWLOWERCASE|V_HUDTRANS|V_SLIDEIN|fflags, va("x%d", stplyr->itemamount));
else
{
V_DrawScaledPatch(fy+28, fy+41, V_HUDTRANS|V_SLIDEIN|fflags, kp_itemx);
V_DrawKartString(fx+38, fy+36, V_HUDTRANS|V_SLIDEIN|fflags, va("%d", stplyr->itemamount));
}
// Draw the item underneath the box.
V_DrawFixedPatch(
fx<<FRACBITS, (fy<<FRACBITS) + rouletteOffset,
FRACUNIT, V_HUDTRANS|V_SLIDEIN|fflags,
localpatch[1], (localcolor[1] ? R_GetTranslationColormap(colormode[1], localcolor[1], GTC_CACHE) : NULL)
);
V_ClearClipRect();
}
else
V_DrawFixedPatch(fx<<FRACBITS, fy<<FRACBITS, FRACUNIT, V_HUDTRANS|V_SLIDEIN|fflags, localpatch, colmap);
{
// Draw the item above the box.
V_ClearClipRect();
//V_ClearClipRect();
if (stplyr->itemamount >= numberdisplaymin && stplyr->itemRoulette.active == false)
{
// Then, the numbers:
V_DrawScaledPatch(
fx + (flipamount ? 48 : 0), fy,
V_HUDTRANS|V_SLIDEIN|fflags|(flipamount ? V_FLIP : 0),
kp_itemmulsticker[offset]
); // flip this graphic for p2 and p4 in split and shift it.
V_DrawFixedPatch(
fx<<FRACBITS, (fy<<FRACBITS) + rouletteOffset,
FRACUNIT, V_HUDTRANS|V_SLIDEIN|fflags,
localpatch[1], (localcolor[1] ? R_GetTranslationColormap(colormode[1], localcolor[1], GTC_CACHE) : NULL)
);
if (offset)
{
if (flipamount) // reminder that this is for 3/4p's right end of the screen.
V_DrawString(fx+2, fy+31, V_ALLOWLOWERCASE|V_HUDTRANS|V_SLIDEIN|fflags, va("x%d", stplyr->itemamount));
else
V_DrawString(fx+24, fy+31, V_ALLOWLOWERCASE|V_HUDTRANS|V_SLIDEIN|fflags, va("x%d", stplyr->itemamount));
}
else
{
V_DrawScaledPatch(fy+28, fy+41, V_HUDTRANS|V_SLIDEIN|fflags, kp_itemx);
V_DrawKartString(fx+38, fy+36, V_HUDTRANS|V_SLIDEIN|fflags, va("%d", stplyr->itemamount));
}
}
else
{
V_DrawFixedPatch(
fx<<FRACBITS, (fy<<FRACBITS) + rouletteOffset,
FRACUNIT, V_HUDTRANS|V_SLIDEIN|fflags,
localpatch[1], (localcolor[1] ? R_GetTranslationColormap(colormode[1], localcolor[1], GTC_CACHE) : NULL)
);
}
}
// Extensible meter, currently only used for rocket sneaker...
if (itembar)
@ -4772,7 +4849,7 @@ K_drawMiniPing (void)
static void K_drawDistributionDebugger(void)
{
patch_t *items[NUMKARTRESULTS] = {
patch_t *patches[NUMKARTRESULTS] = {
kp_sadface[1],
kp_sneaker[1],
kp_rocketsneaker[1],
@ -4804,86 +4881,67 @@ static void K_drawDistributionDebugger(void)
kp_orbinaut[4],
kp_jawz[1]
};
UINT8 useodds = 0;
UINT8 pingame = 0, bestbumper = 0;
UINT32 pdis = 0;
INT32 i;
INT32 x = -9, y = -9;
itemroulette_t rouletteData = {0};
const fixed_t scale = (FRACUNIT >> 1);
const fixed_t space = 24 * scale;
const fixed_t pad = 9 * scale;
fixed_t x = -pad;
fixed_t y = -pad;
size_t i;
if (stplyr != &players[displayplayers[0]]) // only for p1
return;
if (K_ForcedSPB(stplyr) == true)
{
V_DrawScaledPatch(x, y, V_SNAPTOTOP, items[KITEM_SPB]);
V_DrawThinString(x+11, y+31, V_ALLOWLOWERCASE|V_SNAPTOTOP, "EX");
return;
}
// The only code duplication from the Kart, just to avoid the actual item function from calculating pingame twice
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator)
continue;
pingame++;
if (players[i].bumpers > bestbumper)
bestbumper = players[i].bumpers;
}
K_FillItemRouletteData(stplyr, &rouletteData);
// lovely double loop......
for (i = 0; i < MAXPLAYERS; i++)
for (i = 0; i < rouletteData.itemListLen; i++)
{
if (playeringame[i] && !players[i].spectator
&& players[i].position == 1)
const kartitems_t item = rouletteData.itemList[i];
UINT8 amount = 1;
if (y > (BASEVIDHEIGHT << FRACBITS) - space - pad)
{
// This player is first! Yay!
pdis = stplyr->distancetofinish - players[i].distancetofinish;
break;
x += space;
y = -pad;
}
}
pdis = K_ScaleItemDistance(pdis, pingame);
if (stplyr->bot && stplyr->botvars.rival)
{
// Rival has better odds :)
pdis = (15 * pdis) / 14;
}
useodds = K_FindUseodds(stplyr, 0, pdis, bestbumper);
for (i = 1; i < NUMKARTRESULTS; i++)
{
INT32 itemodds = K_KartGetItemOdds(
useodds, i,
stplyr->distancetofinish,
0,
stplyr->bot, (stplyr->bot && stplyr->botvars.rival)
);
INT32 amount = 1;
if (itemodds <= 0)
continue;
V_DrawScaledPatch(x, y, V_SNAPTOTOP, items[i]);
V_DrawThinString(x+11, y+31, V_SNAPTOTOP, va("%d", itemodds));
V_DrawFixedPatch(x, y, scale, V_SNAPTOTOP, patches[item], NULL);
// Display amount for multi-items
amount = K_ItemResultToAmount(i);
amount = K_ItemResultToAmount(item);
if (amount > 1)
{
V_DrawString(x+24, y+31, V_ALLOWLOWERCASE|V_SNAPTOTOP, va("x%d", amount));
V_DrawStringScaled(
x + (18 * scale),
y + (23 * scale),
scale, FRACUNIT, FRACUNIT,
V_ALLOWLOWERCASE|V_SNAPTOTOP,
NULL, HU_FONT,
va("x%d", amount)
);
}
x += 32;
if (x >= 297)
{
x = -9;
y += 32;
}
y += space;
}
V_DrawString(0, 0, V_SNAPTOTOP, va("USEODDS %d", useodds));
V_DrawString((x >> FRACBITS) + 20, 2, V_ALLOWLOWERCASE|V_SNAPTOTOP, va("useOdds[%u]", rouletteData.useOdds));
V_DrawString((x >> FRACBITS) + 20, 10, V_ALLOWLOWERCASE|V_SNAPTOTOP, va("speed = %u", rouletteData.speed));
V_DrawString((x >> FRACBITS) + 20, 22, V_ALLOWLOWERCASE|V_SNAPTOTOP, va("baseDist = %u", rouletteData.baseDist));
V_DrawString((x >> FRACBITS) + 20, 30, V_ALLOWLOWERCASE|V_SNAPTOTOP, va("dist = %u", rouletteData.dist));
V_DrawString((x >> FRACBITS) + 20, 42, V_ALLOWLOWERCASE|V_SNAPTOTOP, va("firstDist = %u", rouletteData.firstDist));
V_DrawString((x >> FRACBITS) + 20, 50, V_ALLOWLOWERCASE|V_SNAPTOTOP, va("secondDist = %u", rouletteData.secondDist));
V_DrawString((x >> FRACBITS) + 20, 58, V_ALLOWLOWERCASE|V_SNAPTOTOP, va("secondToFirst = %u", rouletteData.secondToFirst));
#ifndef ITEM_LIST_SIZE
Z_Free(rouletteData.itemList);
#endif
}
static void K_DrawWaypointDebugger(void)

File diff suppressed because it is too large Load diff

View file

@ -50,14 +50,6 @@ void K_ReduceVFX(mobj_t *mo, player_t *owner);
boolean K_IsPlayerLosing(player_t *player);
fixed_t K_GetKartGameSpeedScalar(SINT8 value);
extern consvar_t *KartItemCVars[NUMKARTRESULTS-1];
UINT8 K_FindUseodds(player_t *player, fixed_t mashed, UINT32 pdis, UINT8 bestbumper);
fixed_t K_ItemOddsScale(UINT8 numPlayers);
UINT32 K_ScaleItemDistance(UINT32 distance, UINT8 numPlayers);
INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, UINT32 ourDist, fixed_t mashed, boolean bot, boolean rival);
INT32 K_GetRollingRouletteItem(player_t *player);
boolean K_ForcedSPB(player_t *player);
INT32 K_GetShieldFromItem(INT32 item);
SINT8 K_ItemResultToType(SINT8 getitem);
UINT8 K_ItemResultToAmount(SINT8 getitem);
@ -107,7 +99,6 @@ void K_DestroyBumpers(player_t *player, UINT8 amount);
void K_TakeBumpersFromPlayer(player_t *player, player_t *victim, UINT8 amount);
void K_MineFlashScreen(mobj_t *source);
void K_SpawnMineExplosion(mobj_t *source, UINT8 color, tic_t delay);
void K_SpawnBrolyKi(mobj_t *source, tic_t duration);
void K_RunFinishLineBeam(void);
UINT16 K_DriftSparkColor(player_t *player, INT32 charge);
void K_SpawnBoostTrail(player_t *player);

View file

@ -3455,7 +3455,7 @@ void M_DrawItemToggles(void)
continue;
}
cv = KartItemCVars[currentMenu->menuitems[thisitem].mvar1-1];
cv = &cv_items[currentMenu->menuitems[thisitem].mvar1-1];
translucent = (cv->value ? 0 : V_TRANSLUCENT);
drawnum = K_ItemResultToAmount(currentMenu->menuitems[thisitem].mvar1);
@ -3502,7 +3502,7 @@ void M_DrawItemToggles(void)
}
else
{
cv = KartItemCVars[currentMenu->menuitems[itemOn].mvar1-1];
cv = &cv_items[currentMenu->menuitems[itemOn].mvar1-1];
translucent = (cv->value ? 0 : V_TRANSLUCENT);
drawnum = K_ItemResultToAmount(currentMenu->menuitems[itemOn].mvar1);

View file

@ -5632,12 +5632,12 @@ void M_HandleItemToggles(INT32 choice)
else
if (currentMenu->menuitems[itemOn].mvar1 == 0)
{
INT32 v = cv_sneaker.value;
INT32 v = cv_items[0].value;
S_StartSound(NULL, sfx_s1b4);
for (i = 0; i < NUMKARTRESULTS-1; i++)
{
if (KartItemCVars[i]->value == v)
CV_AddValue(KartItemCVars[i], 1);
if (cv_items[i].value == v)
CV_AddValue(&cv_items[i], 1);
}
}
else
@ -5650,7 +5650,7 @@ void M_HandleItemToggles(INT32 choice)
{
S_StartSound(NULL, sfx_s1ba);
}
CV_AddValue(KartItemCVars[currentMenu->menuitems[itemOn].mvar1-1], 1);
CV_AddValue(&cv_items[currentMenu->menuitems[itemOn].mvar1-1], 1);
}
}

View file

@ -54,4 +54,8 @@ void Obj_DuelBombReverse(mobj_t *bomb);
void Obj_DuelBombTouch(mobj_t *bomb, mobj_t *toucher);
void Obj_DuelBombInit(mobj_t *bomb);
/* Broly Ki */
mobj_t *Obj_SpawnBrolyKi(mobj_t *source, tic_t duration);
void Obj_BrolyKiThink(mobj_t *ki);
#endif/*k_objects_H*/

1332
src/k_roulette.c Normal file

File diff suppressed because it is too large Load diff

169
src/k_roulette.h Normal file
View file

@ -0,0 +1,169 @@
// DR. ROBOTNIK'S RING RACERS
//-----------------------------------------------------------------------------
// Copyright (C) 2022 by Kart Krew
// Copyright (C) 2022 by Sally "TehRealSalt" Cochenour
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file k_roulette.h
/// \brief Item roulette code.
#ifndef __K_ROULETTE_H__
#define __K_ROULETTE_H__
#include "doomtype.h"
#include "d_player.h"
#define ROULETTE_SPACING (36 << FRACBITS)
#define ROULETTE_SPACING_SPLITSCREEN (16 << FRACBITS)
/*--------------------------------------------------
boolean K_ItemEnabled(kartitems_t item);
Determines whenever or not an item should
be enabled. Accounts for situations where
rules should not be able to be changed.
Input Arguments:-
item - The item to check.
Return:-
true if the item is enabled, otherwise false.
--------------------------------------------------*/
boolean K_ItemEnabled(kartitems_t item);
/*--------------------------------------------------
boolean K_ItemSingularity(kartitems_t item);
Determines whenever or not this item should
be using special cases to prevent more than
one existing at a time.
Input Arguments:-
item - The item to check.
Return:-
true to use the special rules, otherwise false.
--------------------------------------------------*/
boolean K_ItemSingularity(kartitems_t item);
/*--------------------------------------------------
INT32 K_KartGetItemOdds(const player_t *player, itemroulette_t *const roulette, UINT8 pos, kartitems_t item);
Gets the frequency an item should show up in
an item bracket, and adjusted for special
factors (such as Frantic Items).
Input Arguments:-
player - The player we intend to give the item to later.
Can be NULL for generic use.
roulette - The roulette data that we intend to
insert this item into.
pos - The item bracket we are in.
item - The item to give.
Return:-
The number of items we want to insert
into the roulette.
--------------------------------------------------*/
INT32 K_KartGetItemOdds(const player_t *player, itemroulette_t *const roulette, UINT8 pos, kartitems_t item);
/*--------------------------------------------------
void K_FillItemRouletteData(const player_t *player, itemroulette_t *const roulette);
Fills out the item roulette struct when it is
initially created. This function needs to be
HUD-safe for the item debugger, so the player
cannot be modified at this stage.
Input Arguments:-
player - The player this roulette data is for.
Can be NULL for generic use.
roulette - The roulette data struct to fill out.
Return:-
N/A
--------------------------------------------------*/
void K_FillItemRouletteData(const player_t *player, itemroulette_t *const roulette);
/*--------------------------------------------------
void K_StartItemRoulette(player_t *const player);
Starts the item roulette sequence for a player.
This stage can only be used by gameplay, thus
this handles gameplay modifications as well.
Input Arguments:-
player - The player to start the item roulette for.
Return:-
N/A
--------------------------------------------------*/
void K_StartItemRoulette(player_t *const player);
/*--------------------------------------------------
void K_StartEggmanRoulette(player_t *const player);
Starts the Eggman Mark roulette sequence for
a player. Looks identical to a regular item
roulette, but gives you the Eggman explosion
countdown instead when confirming it.
Input Arguments:-
player - The player to start the Eggman roulette for.
Return:-
N/A
--------------------------------------------------*/
void K_StartEggmanRoulette(player_t *const player);
/*--------------------------------------------------
fixed_t K_GetRouletteOffset(itemroulette_t *const roulette, fixed_t renderDelta);
Gets the Y offset, for use in the roulette HUD.
A separate function since it is used both by the
HUD itself, as well as when confirming an item.
Input Arguments:-
roulette - The roulette we are drawing for.
renderDelta - Fractional tic delta, when used for HUD.
Return:-
The Y offset when drawing the item.
--------------------------------------------------*/
fixed_t K_GetRouletteOffset(itemroulette_t *const roulette, fixed_t renderDelta);
/*--------------------------------------------------
void K_KartItemRoulette(player_t *const player, ticcmd_t *cmd);
Handles ticking a player's item roulette,
and player input for stopping it.
Input Arguments:-
player - The player to run the item roulette for.
cmd - The player's controls.
Return:-
N/A
--------------------------------------------------*/
void K_KartItemRoulette(player_t *const player, ticcmd_t *cmd);
#endif // __K_ROULETTE_H__

View file

@ -304,10 +304,10 @@ static int player_get(lua_State *L)
lua_pushinteger(L, plr->tripwirePass);
else if (fastcmp(field,"tripwireLeniency"))
lua_pushinteger(L, plr->tripwireLeniency);
/*
else if (fastcmp(field,"itemroulette"))
lua_pushinteger(L, plr->itemroulette);
else if (fastcmp(field,"roulettetype"))
lua_pushinteger(L, plr->roulettetype);
*/
else if (fastcmp(field,"itemtype"))
lua_pushinteger(L, plr->itemtype);
else if (fastcmp(field,"itemamount"))
@ -680,10 +680,10 @@ static int player_set(lua_State *L)
plr->tripwirePass = luaL_checkinteger(L, 3);
else if (fastcmp(field,"tripwireLeniency"))
plr->tripwireLeniency = luaL_checkinteger(L, 3);
/*
else if (fastcmp(field,"itemroulette"))
plr->itemroulette = luaL_checkinteger(L, 3);
else if (fastcmp(field,"roulettetype"))
plr->roulettetype = luaL_checkinteger(L, 3);
*/
else if (fastcmp(field,"itemtype"))
plr->itemtype = luaL_checkinteger(L, 3);
else if (fastcmp(field,"itemamount"))

View file

@ -1 +1,12 @@
target_sourcefile(c)
target_sources(SRB2SDL2 PRIVATE
hyudoro.c
gardentop.c
shrink.c
item-debris.c
spb.c
manta-ring.c
orbinaut.c
jawz.c
duel-bomb.c
broly.c
)

View file

@ -1,9 +0,0 @@
hyudoro.c
gardentop.c
shrink.c
item-debris.c
spb.c
manta-ring.c
orbinaut.c
jawz.c
duel-bomb.c

72
src/objects/broly.c Normal file
View file

@ -0,0 +1,72 @@
#include "../doomdef.h"
#include "../info.h"
#include "../k_kart.h"
#include "../k_objects.h"
#include "../m_easing.h"
#include "../p_local.h"
#include "../s_sound.h"
// TODO: generic function
static void P_InstaScale(mobj_t *thing, fixed_t scale)
{
P_SetScale(thing, scale);
thing->destscale = scale;
}
/* An object may not be visible on the same tic:
1) that it spawned
2) that it cycles to the next state */
#define BUFFER_TICS (2)
#define broly_duration(o) ((o)->extravalue1)
#define broly_maxscale(o) ((o)->extravalue2)
static inline fixed_t
get_unit_linear (const mobj_t *x)
{
const tic_t t = (x->tics - BUFFER_TICS);
return t * FRACUNIT / broly_duration(x);
}
mobj_t *
Obj_SpawnBrolyKi
( mobj_t * source,
tic_t duration)
{
mobj_t *x = P_SpawnMobjFromMobj(
source, 0, 0, 0, MT_BROLY);
if (duration == 0)
{
return x;
}
// Shrink into center of source object.
x->z = (source->z + source->height / 2);
x->colorized = true;
x->color = source->color;
x->hitlag = 0; // do not copy source hitlag
broly_maxscale(x) = 64 * mapobjectscale;
broly_duration(x) = duration;
x->tics = (duration + BUFFER_TICS);
K_ReduceVFX(x, NULL);
S_StartSound(x, sfx_cdfm74);
return x;
}
void
Obj_BrolyKiThink (mobj_t *x)
{
const fixed_t
t = get_unit_linear(x),
n = Easing_OutSine(t, 0, broly_maxscale(x));
P_InstaScale(x, n);
}

View file

@ -34,6 +34,7 @@
#include "k_respawn.h"
#include "k_collide.h"
#include "k_objects.h"
#include "k_roulette.h"
#ifdef HW3SOUND
#include "hardware/hw3sound.h"
@ -13043,9 +13044,13 @@ void A_ItemPop(mobj_t *actor)
Obj_SpawnItemDebrisEffects(actor, actor->target);
if (locvar1 == 1)
{
P_GivePlayerSpheres(actor->target->player, actor->extravalue1);
}
else if (locvar1 == 0)
actor->target->player->itemroulette = 1;
{
K_StartItemRoulette(actor->target->player);
}
// Here at mapload in battle?
if ((gametyperules & GTR_BUMPERS) && (actor->flags2 & MF2_BOSSNOTRAP))
@ -13186,7 +13191,7 @@ void A_LandMineExplode(mobj_t *actor)
expl->momz = ((i+1)*actor->scale*5/2)*P_MobjFlip(expl);
}
K_SpawnBrolyKi(actor, delay);
Obj_SpawnBrolyKi(actor, delay);
}
void A_BallhogExplode(mobj_t *actor)

View file

@ -38,6 +38,7 @@
#include "k_respawn.h"
#include "p_spec.h"
#include "k_objects.h"
#include "k_roulette.h"
// CTF player names
#define CTFTEAMCODE(pl) pl->ctfteam ? (pl->ctfteam == 1 ? "\x85" : "\x84") : ""
@ -130,7 +131,7 @@ boolean P_CanPickupItem(player_t *player, UINT8 weapon)
return false;
// Already have fake
if (player->roulettetype == 2
if ((player->itemRoulette.active && player->itemRoulette.eggman) == true
|| player->eggmanexplode)
return false;
}
@ -143,7 +144,7 @@ boolean P_CanPickupItem(player_t *player, UINT8 weapon)
return false;
// Item slot already taken up
if (player->itemroulette
if (player->itemRoulette.active == true
|| (weapon != 3 && player->itemamount)
|| (player->pflags & PF_ITEMOUT))
return false;
@ -411,8 +412,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (special->fuse || !P_CanPickupItem(player, 1) || ((gametyperules & GTR_BUMPERS) && player->bumpers <= 0))
return;
player->itemroulette = 1;
player->roulettetype = 1;
K_StartItemRoulette(player);
// Karma fireworks
for (i = 0; i < 5; i++)
@ -1450,8 +1450,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
}
player->karthud[khud_itemblink] = TICRATE;
player->karthud[khud_itemblinkmode] = 0;
player->itemroulette = 0;
player->roulettetype = 0;
player->itemRoulette.active = false;
if (P_IsDisplayPlayer(player))
S_StartSound(NULL, sfx_itrolf);
}

View file

@ -406,7 +406,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
K_TumbleInterrupt(object->player);
P_ResetPlayer(object->player);
object->player->springstars = max(vertispeed, horizspeed) / FRACUNIT / 2;
object->player->springstars = max(abs(vertispeed), horizspeed) / FRACUNIT / 2;
object->player->springcolor = starcolor;
// Less friction when hitting springs

View file

@ -6137,7 +6137,7 @@ static void P_MobjSceneryThink(mobj_t *mobj)
break;
// see also K_drawKartItem in k_hud.c
case MT_PLAYERARROW:
case MT_PLAYERARROW: // FIXME: Delete this object, attach to name tags instead.
if (mobj->target && mobj->target->health
&& mobj->target->player && !mobj->target->player->spectator
&& mobj->target->health && mobj->target->player->playerstate != PST_DEAD
@ -6191,7 +6191,7 @@ static void P_MobjSceneryThink(mobj_t *mobj)
}
// Do this in an easy way
if (mobj->target->player->itemroulette)
if (mobj->target->player->itemRoulette.active)
{
mobj->tracer->color = mobj->target->player->skincolor;
mobj->tracer->colorized = true;
@ -6207,11 +6207,11 @@ static void P_MobjSceneryThink(mobj_t *mobj)
const INT32 numberdisplaymin = ((mobj->target->player->itemtype == KITEM_ORBINAUT) ? 5 : 2);
// Set it to use the correct states for its condition
if (mobj->target->player->itemroulette)
if (mobj->target->player->itemRoulette.active)
{
P_SetMobjState(mobj, S_PLAYERARROW_BOX);
mobj->tracer->sprite = SPR_ITEM;
mobj->tracer->frame = K_GetRollingRouletteItem(mobj->target->player) | FF_FULLBRIGHT;
mobj->tracer->frame = 1 | FF_FULLBRIGHT;
mobj->tracer->renderflags &= ~RF_DONTDRAW;
}
else if (mobj->target->player->stealingtimer < 0)
@ -6517,6 +6517,9 @@ static void P_MobjSceneryThink(mobj_t *mobj)
case MT_DRIFTELECTRICSPARK:
mobj->renderflags ^= RF_DONTDRAW;
break;
case MT_BROLY:
Obj_BrolyKiThink(mobj);
break;
case MT_VWREF:
case MT_VWREB:
{

View file

@ -96,7 +96,7 @@ static void P_NetArchivePlayers(void)
{
INT32 i, j;
UINT16 flags;
// size_t q;
size_t q;
WRITEUINT32(save_p, ARCHIVEBLOCK_PLAYERS);
@ -310,9 +310,6 @@ static void P_NetArchivePlayers(void)
WRITEUINT8(save_p, players[i].tripwirePass);
WRITEUINT16(save_p, players[i].tripwireLeniency);
WRITEUINT16(save_p, players[i].itemroulette);
WRITEUINT8(save_p, players[i].roulettetype);
WRITESINT8(save_p, players[i].itemtype);
WRITEUINT8(save_p, players[i].itemamount);
WRITESINT8(save_p, players[i].throwdir);
@ -410,6 +407,50 @@ static void P_NetArchivePlayers(void)
WRITEUINT32(save_p, players[i].botvars.itemconfirm);
WRITESINT8(save_p, players[i].botvars.turnconfirm);
WRITEUINT32(save_p, players[i].botvars.spindashconfirm);
// itemroulette_t
WRITEUINT8(save_p, players[i].itemRoulette.active);
#ifdef ITEM_LIST_SIZE
WRITEUINT32(save_p, players[i].itemRoulette.itemListLen);
for (q = 0; q < ITEM_LIST_SIZE; q++)
{
if (q >= players[i].itemRoulette.itemListLen)
{
WRITESINT8(save_p, KITEM_NONE);
}
else
{
WRITESINT8(save_p, players[i].itemRoulette.itemList[q]);
}
}
#else
if (players[i].itemRoulette.itemList == NULL)
{
WRITEUINT32(save_p, 0);
WRITEUINT32(save_p, 0);
}
else
{
WRITEUINT32(save_p, players[i].itemRoulette.itemListCap);
WRITEUINT32(save_p, players[i].itemRoulette.itemListLen);
for (q = 0; q < players[i].itemRoulette.itemListLen; q++)
{
WRITESINT8(save_p, players[i].itemRoulette.itemList[q]);
}
}
#endif
WRITEUINT8(save_p, players[i].itemRoulette.useOdds);
WRITEUINT32(save_p, players[i].itemRoulette.dist);
WRITEUINT32(save_p, players[i].itemRoulette.index);
WRITEUINT8(save_p, players[i].itemRoulette.sound);
WRITEUINT32(save_p, players[i].itemRoulette.speed);
WRITEUINT32(save_p, players[i].itemRoulette.tics);
WRITEUINT32(save_p, players[i].itemRoulette.elapsed);
WRITEUINT8(save_p, players[i].itemRoulette.eggman);
}
}
@ -417,6 +458,7 @@ static void P_NetUnArchivePlayers(void)
{
INT32 i, j;
UINT16 flags;
size_t q;
if (READUINT32(save_p) != ARCHIVEBLOCK_PLAYERS)
I_Error("Bad $$$.sav at archive block Players");
@ -612,9 +654,6 @@ static void P_NetUnArchivePlayers(void)
players[i].tripwirePass = READUINT8(save_p);
players[i].tripwireLeniency = READUINT16(save_p);
players[i].itemroulette = READUINT16(save_p);
players[i].roulettetype = READUINT8(save_p);
players[i].itemtype = READSINT8(save_p);
players[i].itemamount = READUINT8(save_p);
players[i].throwdir = READSINT8(save_p);
@ -713,6 +752,61 @@ static void P_NetUnArchivePlayers(void)
players[i].botvars.turnconfirm = READSINT8(save_p);
players[i].botvars.spindashconfirm = READUINT32(save_p);
// itemroulette_t
players[i].itemRoulette.active = (boolean)READUINT8(save_p);
#ifdef ITEM_LIST_SIZE
players[i].itemRoulette.itemListLen = (size_t)READUINT32(save_p);
for (q = 0; q < ITEM_LIST_SIZE; q++)
{
players[i].itemRoulette.itemList[q] = READSINT8(save_p);
}
#else
players[i].itemRoulette.itemListCap = (size_t)READUINT32(save_p);
players[i].itemRoulette.itemListLen = (size_t)READUINT32(save_p);
if (players[i].itemRoulette.itemListCap > 0)
{
if (players[i].itemRoulette.itemList == NULL)
{
players[i].itemRoulette.itemList = Z_Calloc(
sizeof(SINT8) * players[i].itemRoulette.itemListCap,
PU_STATIC,
&players[i].itemRoulette.itemList
);
}
else
{
players[i].itemRoulette.itemList = Z_Realloc(
players[i].itemRoulette.itemList,
sizeof(SINT8) * players[i].itemRoulette.itemListCap,
PU_STATIC,
&players[i].itemRoulette.itemList
);
}
if (players[i].itemRoulette.itemList == NULL)
{
I_Error("Not enough memory for item roulette list\n");
}
for (q = 0; q < players[i].itemRoulette.itemListLen; q++)
{
players[i].itemRoulette.itemList[q] = READSINT8(save_p);
}
}
#endif
players[i].itemRoulette.useOdds = READUINT8(save_p);
players[i].itemRoulette.dist = READUINT32(save_p);
players[i].itemRoulette.index = (size_t)READUINT32(save_p);
players[i].itemRoulette.sound = READUINT8(save_p);
players[i].itemRoulette.speed = (tic_t)READUINT32(save_p);
players[i].itemRoulette.tics = (tic_t)READUINT32(save_p);
players[i].itemRoulette.elapsed = (tic_t)READUINT32(save_p);
players[i].itemRoulette.eggman = (boolean)READUINT8(save_p);
//players[i].viewheight = P_GetPlayerViewHeight(players[i]); // scale cannot be factored in at this point
}
}

View file

@ -6837,6 +6837,7 @@ static void P_InitLevelSettings(void)
memset(&quake,0,sizeof(struct quake));
// song credit init
Z_Free(cursongcredit.text);
memset(&cursongcredit,0,sizeof(struct cursongcredit));
cursongcredit.trans = NUMTRANSMAPS;

View file

@ -1476,16 +1476,32 @@ ReadMusicDefFields
textline = value;
/* based ignored lumps */
if (!stricmp(stoken, "usage")) {
#if 0 // Ignore for now
STRBUFCPY(def->usage, textline);
#endif
} else if (!stricmp(stoken, "source")) {
STRBUFCPY(def->source, textline);
} else if (!stricmp(stoken, "volume")) {
if (!stricmp(stoken, "title"))
{
Z_Free(def->title);
def->title = Z_StrDup(textline);
}
else if (!stricmp(stoken, "author"))
{
Z_Free(def->author);
def->author = Z_StrDup(textline);
}
else if (!stricmp(stoken, "source"))
{
Z_Free(def->source);
def->source = Z_StrDup(textline);
}
else if (!stricmp(stoken, "originalcomposers"))
{
Z_Free(def->composers);
def->composers = Z_StrDup(textline);
}
else if (!stricmp(stoken, "volume"))
{
def->volume = atoi(textline);
} else {
}
else
{
MusicDefError(CONS_WARNING,
"Unknown field '%s'.",
stoken, lumpnum, line);
@ -1608,14 +1624,53 @@ void S_ShowMusicCredit(void)
{
if (!stricmp(def->name, music_name))
{
char credittext[128] = "";
char *work = NULL;
size_t len = 128, worklen;
if (!def->title)
{
return;
}
work = va("\x1F %s", def->title);
worklen = strlen(work);
if (worklen <= len)
{
strncat(credittext, work, len);
len -= worklen;
#define MUSICCREDITAPPEND(field)\
if (field)\
{\
work = va(" - %s", field);\
worklen = strlen(work);\
if (worklen <= len)\
{\
strncat(credittext, work, len);\
len -= worklen;\
}\
}
MUSICCREDITAPPEND(def->author);
MUSICCREDITAPPEND(def->source);
#undef MUSICCREDITAPPEND
}
if (credittext[0] == '\0')
return;
cursongcredit.def = def;
Z_Free(cursongcredit.text);
cursongcredit.text = Z_StrDup(credittext);
cursongcredit.anim = 5*TICRATE;
cursongcredit.x = cursongcredit.old_x =0;
cursongcredit.x = cursongcredit.old_x = 0;
cursongcredit.trans = NUMTRANSMAPS;
return;
}
else
def = def->next;
def = def->next;
}
}

View file

@ -173,8 +173,10 @@ boolean S_SpeedMusic(float speed);
struct musicdef_t
{
char name[7];
//char usage[256];
char source[256];
char *title;
char *author;
char *source;
char *composers;
int volume;
musicdef_t *next;
};
@ -182,6 +184,7 @@ struct musicdef_t
extern struct cursongcredit
{
musicdef_t *def;
char *text;
UINT16 anim;
UINT8 trans;
fixed_t x;

View file

@ -1,12 +1,17 @@
# Declare SDL2 interface sources
target_sources(SRB2SDL2 PRIVATE mixer_sound.c)
target_sourcefile(c)
target_sources(SRB2SDL2 PRIVATE ogl_sdl.c)
target_sources(SRB2SDL2 PRIVATE i_threads.c)
target_sources(SRB2SDL2 PRIVATE
mixer_sound.c
ogl_sdl.c
i_threads.c
i_net.c
i_system.c
i_main.c
i_video.c
dosstr.c
endtxt.c
hwsym_sdl.c
)
if(${SRB2_USEASM})
set_source_files_properties(${SRB2_ASM_SOURCES} PROPERTIES LANGUAGE C)

View file

@ -1,7 +0,0 @@
i_net.c
i_system.c
i_main.c
i_video.c
dosstr.c
endtxt.c
hwsym_sdl.c

3
src/tests/CMakeLists.txt Normal file
View file

@ -0,0 +1,3 @@
target_sources(srb2tests PRIVATE
boolcompat.cpp
)

8
src/tests/boolcompat.cpp Normal file
View file

@ -0,0 +1,8 @@
#include <catch2/catch_test_macros.hpp>
#include "../doomtype.h"
TEST_CASE("C++ bool is convertible to doomtype.h boolean") {
REQUIRE(static_cast<boolean>(true) == 1);
REQUIRE(static_cast<boolean>(false) == 0);
}

View file

@ -37,6 +37,7 @@ TYPEDEF (discordRequest_t);
TYPEDEF (respawnvars_t);
TYPEDEF (botvars_t);
TYPEDEF (skybox_t);
TYPEDEF (itemroulette_t);
TYPEDEF (player_t);
// d_clisrv.h