From 0156db0dc1ca225a9e035721e53d53f33cfcb881 Mon Sep 17 00:00:00 2001 From: Eidolon Date: Wed, 6 Mar 2024 22:35:02 -0600 Subject: [PATCH 01/40] Add optional CRT screen effect --- src/cvars.cpp | 1 + src/hwr2/blit_rect.cpp | 174 +++++++++++++++++++++++++++++++---- src/hwr2/blit_rect.hpp | 13 +++ src/hwr2/hardware_state.hpp | 1 + src/i_video_common.cpp | 17 +++- src/menus/options-video-1.c | 3 + src/rhi/gl2/gl2_rhi.cpp | 17 +++- src/rhi/rhi.cpp | 12 +++ src/rhi/rhi.hpp | 12 ++- src/screen.h | 1 + src/sdl/rhi_gl2_platform.cpp | 2 + 11 files changed, 228 insertions(+), 25 deletions(-) diff --git a/src/cvars.cpp b/src/cvars.cpp index 495305827..594b04563 100644 --- a/src/cvars.cpp +++ b/src/cvars.cpp @@ -430,6 +430,7 @@ consvar_t cv_scr_depth = Player("scr_depth", "16 bits").values({{8, "8 bits"}, { //added : 03-02-98: default screen mode, as loaded/saved in config consvar_t cv_scr_width = Player("scr_width", "640").values(CV_Unsigned); consvar_t cv_scr_height = Player("scr_height", "400").values(CV_Unsigned); +consvar_t cv_scr_effect = Player("scr_effect", "Nearest").values({{0, "Nearest"}, {1, "SalCRT"}}).save(); consvar_t cv_scr_scale = Player("scr_scale", "1.0").floating_point(); consvar_t cv_scr_x = Player("scr_x", "0.0").floating_point(); diff --git a/src/hwr2/blit_rect.cpp b/src/hwr2/blit_rect.cpp index 77c620875..772e8a90e 100644 --- a/src/hwr2/blit_rect.cpp +++ b/src/hwr2/blit_rect.cpp @@ -51,7 +51,22 @@ static const PipelineDesc kUnshadedPipelineDescription = { FaceWinding::kCounterClockwise, {0.f, 0.f, 0.f, 1.f}}; -BlitRectPass::BlitRectPass() = default; +/// @brief Pipeline used for CRT special blit +static const PipelineDesc kCrtPipelineDescription = { + PipelineProgram::kCrt, + {{{sizeof(BlitVertex)}}, {{VertexAttributeName::kPosition, 0, 0}, {VertexAttributeName::kTexCoord0, 0, 12}}}, + {{{UniformName::kProjection}, {{UniformName::kModelView, UniformName::kTexCoord0Transform, UniformName::kSampler0Size}}}}, + {{// RGB/A texture + SamplerName::kSampler0, SamplerName::kSampler1}}, + std::nullopt, + {std::nullopt, {true, true, true, true}}, + PrimitiveType::kTriangles, + CullMode::kNone, + FaceWinding::kCounterClockwise, + {0.f, 0.f, 0.f, 1.f}}; + +BlitRectPass::BlitRectPass() : BlitRectPass(BlitRectPass::BlitMode::kNearest) {} +BlitRectPass::BlitRectPass(BlitRectPass::BlitMode blit_mode) : blit_mode_(blit_mode) {} BlitRectPass::~BlitRectPass() = default; void BlitRectPass::draw(Rhi& rhi, Handle ctx) @@ -65,7 +80,18 @@ void BlitRectPass::prepass(Rhi& rhi) { if (!pipeline_) { - pipeline_ = rhi.create_pipeline(kUnshadedPipelineDescription); + switch (blit_mode_) + { + case BlitRectPass::BlitMode::kNearest: + pipeline_ = rhi.create_pipeline(kUnshadedPipelineDescription); + break; + case BlitRectPass::BlitMode::kCrt: + pipeline_ = rhi.create_pipeline(kCrtPipelineDescription); + break; + default: + std::terminate(); + } + } if (!quad_vbo_) @@ -79,6 +105,20 @@ void BlitRectPass::prepass(Rhi& rhi) quad_ibo_ = rhi.create_buffer({sizeof(kIndices), BufferType::kIndexBuffer, BufferUsage::kImmutable}); quad_ibo_needs_upload_ = true; } + + if (blit_mode_ == BlitRectPass::BlitMode::kCrt && !dot_pattern_) + { + dot_pattern_ = rhi.create_texture({ + rhi::TextureFormat::kRGBA, + 12, + 4, + rhi::TextureWrapMode::kRepeat, + rhi::TextureWrapMode::kRepeat, + rhi::TextureFilterMode::kLinear, + rhi::TextureFilterMode::kLinear + }); + dot_pattern_needs_upload_ = true; + } } void BlitRectPass::transfer(Rhi& rhi, Handle ctx) @@ -95,6 +135,67 @@ void BlitRectPass::transfer(Rhi& rhi, Handle ctx) quad_ibo_needs_upload_ = false; } + if (dot_pattern_needs_upload_ && dot_pattern_) + { + // Listen. I'm a *very* particular kind of lazy. + // If I'm being honest, I just don't want to have to embed a .png in the pk3s and deal with that. + static const uint8_t kDotPattern[] = { + 255, 0, 0, 255, + 0, 0, 0, 255, + 0, 255, 0, 255, + 0, 0, 0, 255, + 0, 0, 255, 255, + 0, 0, 0, 255, + 255, 0, 0, 255, + 0, 0, 0, 255, + 0, 255, 0, 255, + 0, 0, 0, 255, + 0, 0, 255, 255, + 0, 0, 0, 255, + + 255, 0, 0, 255, + 0, 0, 0, 255, + 0, 255, 0, 255, + 0, 0, 0, 255, + 0, 0, 255, 255, + 0, 0, 0, 255, + 0, 0, 0, 255, + 0, 0, 0, 255, + 0, 0, 0, 255, + 0, 0, 0, 255, + 0, 0, 0, 255, + 0, 0, 0, 255, + + 255, 0, 0, 255, + 0, 0, 0, 255, + 0, 255, 0, 255, + 0, 0, 0, 255, + 0, 0, 255, 255, + 0, 0, 0, 255, + 255, 0, 0, 255, + 0, 0, 0, 255, + 0, 255, 0, 255, + 0, 0, 0, 255, + 0, 0, 255, 255, + 0, 0, 0, 255, + + 0, 0, 0, 255, + 0, 0, 0, 255, + 0, 0, 0, 255, + 0, 0, 0, 255, + 0, 0, 0, 255, + 0, 0, 0, 255, + 255, 0, 0, 255, + 0, 0, 0, 255, + 0, 255, 0, 255, + 0, 0, 0, 255, + 0, 0, 255, 255, + 0, 0, 0, 255, + }; + rhi.update_texture(ctx, dot_pattern_, {0, 0, 12, 4}, PixelFormat::kRGBA8, tcb::as_bytes(tcb::span(kDotPattern))); + dot_pattern_needs_upload_ = false; + } + float aspect = 1.0; float output_aspect = 1.0; if (output_correct_aspect_) @@ -104,6 +205,8 @@ void BlitRectPass::transfer(Rhi& rhi, Handle ctx) } bool taller = aspect > output_aspect; + rhi::TextureDetails texture_details = rhi.get_texture_details(texture_); + std::array g1_uniforms = {{ // Projection glm::scale( @@ -112,26 +215,57 @@ void BlitRectPass::transfer(Rhi& rhi, Handle ctx) ) }}; - std::array g2_uniforms = { - // ModelView - glm::scale( - glm::identity(), - glm::vec3(taller ? 2.f : 2.f * aspect, taller ? 2.f * (1.f / aspect) : 2.f, 1.f) - ), - // Texcoord0 Transform - glm::mat3( - glm::vec3(1.f, 0.f, 0.f), - glm::vec3(0.f, output_flip_ ? -1.f : 1.f, 0.f), - glm::vec3(0.f, output_flip_ ? 1.f : 0.f, 1.f) - ) - }; - uniform_sets_[0] = rhi.create_uniform_set(ctx, {g1_uniforms}); - uniform_sets_[1] = rhi.create_uniform_set(ctx, {g2_uniforms}); - std::array vbs = {{{0, quad_vbo_}}}; - std::array tbs = {{{rhi::SamplerName::kSampler0, texture_}}}; - binding_set_ = rhi.create_binding_set(ctx, pipeline_, {vbs, tbs}); + switch (blit_mode_) + { + case BlitRectPass::BlitMode::kCrt: + { + std::array g2_uniforms = { + // ModelView + glm::scale( + glm::identity(), + glm::vec3(taller ? 2.f : 2.f * aspect, taller ? 2.f * (1.f / aspect) : 2.f, 1.f) + ), + // Texcoord0 Transform + glm::mat3( + glm::vec3(1.f, 0.f, 0.f), + glm::vec3(0.f, output_flip_ ? -1.f : 1.f, 0.f), + glm::vec3(0.f, output_flip_ ? 1.f : 0.f, 1.f) + ), + // Sampler 0 Size + glm::vec2(texture_details.width, texture_details.height) + }; + uniform_sets_[1] = rhi.create_uniform_set(ctx, {g2_uniforms}); + + std::array vbs = {{{0, quad_vbo_}}}; + std::array tbs = {{{rhi::SamplerName::kSampler0, texture_}, {rhi::SamplerName::kSampler1, dot_pattern_}}}; + binding_set_ = rhi.create_binding_set(ctx, pipeline_, {vbs, tbs}); + break; + } + default: + { + std::array g2_uniforms = { + // ModelView + glm::scale( + glm::identity(), + glm::vec3(taller ? 2.f : 2.f * aspect, taller ? 2.f * (1.f / aspect) : 2.f, 1.f) + ), + // Texcoord0 Transform + glm::mat3( + glm::vec3(1.f, 0.f, 0.f), + glm::vec3(0.f, output_flip_ ? -1.f : 1.f, 0.f), + glm::vec3(0.f, output_flip_ ? 1.f : 0.f, 1.f) + ) + }; + uniform_sets_[1] = rhi.create_uniform_set(ctx, {g2_uniforms}); + + std::array vbs = {{{0, quad_vbo_}}}; + std::array tbs = {{{rhi::SamplerName::kSampler0, texture_}}}; + binding_set_ = rhi.create_binding_set(ctx, pipeline_, {vbs, tbs}); + break; + } + } } void BlitRectPass::graphics(Rhi& rhi, Handle ctx) diff --git a/src/hwr2/blit_rect.hpp b/src/hwr2/blit_rect.hpp index f2acd9887..3aff33261 100644 --- a/src/hwr2/blit_rect.hpp +++ b/src/hwr2/blit_rect.hpp @@ -21,6 +21,14 @@ namespace srb2::hwr2 /// @brief A render pass which blits a rect using a source texture or textures. class BlitRectPass { +public: + enum class BlitMode + { + kNearest, + kCrt, + }; + +private: rhi::Handle pipeline_; rhi::Handle texture_; uint32_t texture_width_ = 0; @@ -33,15 +41,20 @@ class BlitRectPass rhi::Handle quad_ibo_; std::array, 2> uniform_sets_; rhi::Handle binding_set_; + BlitMode blit_mode_; + rhi::Handle dot_pattern_; bool quad_vbo_needs_upload_ = false; bool quad_ibo_needs_upload_ = false; + bool dot_pattern_needs_upload_ = false; void prepass(rhi::Rhi& rhi); void transfer(rhi::Rhi& rhi, rhi::Handle ctx); void graphics(rhi::Rhi& rhi, rhi::Handle ctx); public: + + explicit BlitRectPass(BlitMode blit_mode); BlitRectPass(); ~BlitRectPass(); diff --git a/src/hwr2/hardware_state.hpp b/src/hwr2/hardware_state.hpp index 86849f60c..d32f54d4f 100644 --- a/src/hwr2/hardware_state.hpp +++ b/src/hwr2/hardware_state.hpp @@ -38,6 +38,7 @@ struct HardwareState std::unique_ptr blit_postimg_screens; std::unique_ptr wipe; std::unique_ptr blit_rect; + std::unique_ptr crt_blit_rect; std::unique_ptr screen_capture; std::unique_ptr backbuffer; WipeFrames wipe_frames; diff --git a/src/i_video_common.cpp b/src/i_video_common.cpp index 84241491a..5f02430eb 100644 --- a/src/i_video_common.cpp +++ b/src/i_video_common.cpp @@ -82,7 +82,8 @@ static void reset_hardware_state(Rhi* rhi) g_hw_state.software_screen_renderer = std::make_unique(); g_hw_state.blit_postimg_screens = std::make_unique(g_hw_state.palette_manager.get()); g_hw_state.wipe = std::make_unique(); - g_hw_state.blit_rect = std::make_unique(); + g_hw_state.blit_rect = std::make_unique(BlitRectPass::BlitMode::kNearest); + g_hw_state.crt_blit_rect = std::make_unique(BlitRectPass::BlitMode::kCrt); g_hw_state.screen_capture = std::make_unique(); g_hw_state.backbuffer = std::make_unique(); g_hw_state.wipe_frames = {}; @@ -294,13 +295,25 @@ void I_FinishUpdate(void) float y = (vid.realheight - h) * (0.5f + (FixedToFloat(cv_scr_y.value) * 0.5f)); g_hw_state.blit_rect->set_output(x, y, w, h, true, true); + g_hw_state.crt_blit_rect->set_output(x, y, w, h, true, true); } else { g_hw_state.blit_rect->set_output(0, 0, vid.realwidth, vid.realheight, true, true); + g_hw_state.crt_blit_rect->set_output(0, 0, vid.realwidth, vid.realheight, true, true); } g_hw_state.blit_rect->set_texture(g_hw_state.backbuffer->color(), static_cast(vid.width), static_cast(vid.height)); - g_hw_state.blit_rect->draw(*rhi, ctx); + g_hw_state.crt_blit_rect->set_texture(g_hw_state.backbuffer->color(), static_cast(vid.width), static_cast(vid.height)); + + switch (cv_scr_effect.value) + { + case 1: + g_hw_state.crt_blit_rect->draw(*rhi, ctx); + break; + default: + g_hw_state.blit_rect->draw(*rhi, ctx); + break; + } rhi->end_render_pass(ctx); rhi->end_graphics(ctx); diff --git a/src/menus/options-video-1.c b/src/menus/options-video-1.c index a1e1dcecc..b4d2bb0f9 100644 --- a/src/menus/options-video-1.c +++ b/src/menus/options-video-1.c @@ -27,6 +27,9 @@ menuitem_t OPTIONS_Video[] = {IT_STRING | IT_CVAR, "FPS Cap", "Handles the frame rate of the game (35 to match game logic)", NULL, {.cvar = &cv_fpscap}, 0, 0}, + {IT_STRING | IT_CVAR, "Screen Effect", "Uses a special effect when displaying the game.", + NULL, {.cvar = &cv_scr_effect}, 0, 0}, + {IT_NOTHING|IT_SPACE, NULL, NULL, NULL, {NULL}, 0, 0}, diff --git a/src/rhi/gl2/gl2_rhi.cpp b/src/rhi/gl2/gl2_rhi.cpp index 27d882ecc..6568c422f 100644 --- a/src/rhi/gl2/gl2_rhi.cpp +++ b/src/rhi/gl2/gl2_rhi.cpp @@ -127,6 +127,19 @@ constexpr GLenum map_texture_wrap(rhi::TextureWrapMode wrap) return GL_REPEAT; case rhi::TextureWrapMode::kMirroredRepeat: return GL_MIRRORED_REPEAT; + default: + return GL_REPEAT; + } +} + +constexpr GLenum map_texture_filter(rhi::TextureFilterMode filter) +{ + switch (filter) + { + case rhi::TextureFilterMode::kNearest: + return GL_NEAREST; + case rhi::TextureFilterMode::kLinear: + return GL_LINEAR; default: return GL_NEAREST; } @@ -595,9 +608,9 @@ rhi::Handle Gl2Rhi::create_texture(const rhi::TextureDesc& desc) gl_->BindTexture(GL_TEXTURE_2D, name); - gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, map_texture_filter(desc.min)); GL_ASSERT; - gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, map_texture_filter(desc.mag)); GL_ASSERT; gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, map_texture_wrap(desc.u_wrap)); GL_ASSERT; diff --git a/src/rhi/rhi.cpp b/src/rhi/rhi.cpp index 76668af83..7e9cb725a 100644 --- a/src/rhi/rhi.cpp +++ b/src/rhi/rhi.cpp @@ -67,6 +67,16 @@ const ProgramRequirements srb2::rhi::kProgramRequirementsPostimg = { ProgramSamplerRequirements {{{SamplerName::kSampler0, true}, {SamplerName::kSampler1, false}}} }; +const ProgramRequirements srb2::rhi::kProgramRequirementsCrt = { + ProgramVertexInputRequirements { + {ProgramVertexInput {VertexAttributeName::kPosition, VertexAttributeFormat::kFloat3, true}, + ProgramVertexInput {VertexAttributeName::kTexCoord0, VertexAttributeFormat::kFloat2, false}, + ProgramVertexInput {VertexAttributeName::kColor, VertexAttributeFormat::kFloat4, false}}}, + ProgramUniformRequirements { + {{{{UniformName::kProjection, true}}}, + {{{UniformName::kModelView, true}, {UniformName::kTexCoord0Transform, true}, {UniformName::kSampler0Size, true}}}}}, + ProgramSamplerRequirements {{{SamplerName::kSampler0, true}, {SamplerName::kSampler1, true}}}}; + const ProgramRequirements& rhi::program_requirements_for_program(PipelineProgram program) noexcept { switch (program) @@ -79,6 +89,8 @@ const ProgramRequirements& rhi::program_requirements_for_program(PipelineProgram return kProgramRequirementsPostprocessWipe; case PipelineProgram::kPostimg: return kProgramRequirementsPostimg; + case PipelineProgram::kCrt: + return kProgramRequirementsCrt; default: std::terminate(); } diff --git a/src/rhi/rhi.hpp b/src/rhi/rhi.hpp index c094cf990..27142e3ed 100644 --- a/src/rhi/rhi.hpp +++ b/src/rhi/rhi.hpp @@ -172,7 +172,8 @@ enum class PipelineProgram kUnshaded, kUnshadedPaletted, kPostprocessWipe, - kPostimg + kPostimg, + kCrt }; enum class BufferType @@ -285,6 +286,7 @@ extern const ProgramRequirements kProgramRequirementsUnshaded; extern const ProgramRequirements kProgramRequirementsUnshadedPaletted; extern const ProgramRequirements kProgramRequirementsPostprocessWipe; extern const ProgramRequirements kProgramRequirementsPostimg; +extern const ProgramRequirements kProgramRequirementsCrt; const ProgramRequirements& program_requirements_for_program(PipelineProgram program) noexcept; @@ -480,6 +482,12 @@ enum class TextureWrapMode kClamp }; +enum class TextureFilterMode +{ + kNearest, + kLinear +}; + struct TextureDesc { TextureFormat format; @@ -487,6 +495,8 @@ struct TextureDesc uint32_t height; TextureWrapMode u_wrap; TextureWrapMode v_wrap; + TextureFilterMode mag; + TextureFilterMode min; }; struct BufferDesc diff --git a/src/screen.h b/src/screen.h index cbfe01724..ee8f4a204 100644 --- a/src/screen.h +++ b/src/screen.h @@ -135,6 +135,7 @@ extern INT32 scr_bpp; extern UINT8 *scr_borderpatch; // patch used to fill the view borders extern consvar_t cv_scr_width, cv_scr_height, cv_scr_depth, cv_renderview, cv_renderer, cv_renderhitbox, cv_fullscreen; +extern consvar_t cv_scr_effect; extern consvar_t cv_vhseffect, cv_shittyscreen; extern consvar_t cv_parallelsoftware; diff --git a/src/sdl/rhi_gl2_platform.cpp b/src/sdl/rhi_gl2_platform.cpp index bc6e0d2c1..03833dd7f 100644 --- a/src/sdl/rhi_gl2_platform.cpp +++ b/src/sdl/rhi_gl2_platform.cpp @@ -44,6 +44,8 @@ static constexpr const char* pipeline_lump_slug(rhi::PipelineProgram program) return "postprocesswipe"; case rhi::PipelineProgram::kPostimg: return "postimg"; + case rhi::PipelineProgram::kCrt: + return "crt"; default: return ""; } From adf58933b3f61b7382fa384dabd2075907d2f973 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 7 Mar 2024 00:49:50 -0800 Subject: [PATCH 02/40] Do not run Overtime ACS outside of GTR_OVERTIME or during Prisons --- src/p_tick.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/p_tick.c b/src/p_tick.c index 3e1e2bb1c..9f0b33da7 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -1081,7 +1081,8 @@ void P_Ticker(boolean run) ACS_RunPositionScript(); } - if (timelimitintics > 0 && leveltime == (timelimitintics + starttime + 1)) + if ((gametyperules & GTR_OVERTIME) && !battleprisons && + timelimitintics > 0 && leveltime == (timelimitintics + starttime + 1)) { ACS_RunOvertimeScript(); } From c09f55059bd4576d3277e227a4efa58ba7d3de75 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 7 Mar 2024 02:43:09 -0800 Subject: [PATCH 03/40] GP Prisons: use regular player starts, not Battle starts --- src/g_game.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index 18605d9fa..4a4d25f1a 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2879,7 +2879,7 @@ mapthing_t *G_FindMapStart(INT32 playernum) // -- DM/Tag/CTF-spectator/etc -- // Order: DM->CTF->Race - else if (gametyperules & GTR_BATTLESTARTS) + else if ((gametyperules & GTR_BATTLESTARTS) && !battleprisons) spawnpoint = G_FindBattleStartOrFallback(playernum); // -- Other game modes -- From d4d2196c7367074442b3abaaa26d8303326fccf0 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 7 Mar 2024 03:05:44 -0800 Subject: [PATCH 04/40] GP bonus round: do not spawn duel mode items TWICE Level load ordering's a bitch, I explain in the code comments. --- src/k_kart.c | 10 ++++------ src/k_kart.h | 2 -- src/p_mobj.c | 10 ++++++++-- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 3804235c5..5cb6235c9 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -125,11 +125,6 @@ void K_TimerReset(void) g_pointlimit = 0; } -boolean K_ShouldSpawnDuelItems(void) -{ - return (inDuel == true || (grandprixinfo.gp && grandprixinfo.eventmode == GPEVENT_BONUS)); -} - static void K_SpawnItemCapsules(void) { mapthing_t *mt = mapthings; @@ -281,7 +276,10 @@ void K_TimerInit(void) timelimitintics = K_TimeLimitForGametype(); g_pointlimit = K_PointLimitForGametype(); - if (K_ShouldSpawnDuelItems()) + // K_TimerInit is called after all mapthings are spawned, + // so they didn't know if it's supposed to be a duel + // (inDuel is always false before K_TimerInit is called). + if (inDuel) { K_SpawnDuelOnlyItems(); } diff --git a/src/k_kart.h b/src/k_kart.h index 3224e1256..ec4fe9fa1 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -233,8 +233,6 @@ void K_KartEbrakeVisuals(player_t *p); void K_HandleDirectionalInfluence(player_t *player); fixed_t K_DefaultPlayerRadius(player_t *player); -boolean K_ShouldSpawnDuelItems(void); - // sound stuff for lua void K_PlayAttackTaunt(mobj_t *source); void K_PlayBoostTaunt(mobj_t *source); diff --git a/src/p_mobj.c b/src/p_mobj.c index ce279a0d4..497275b93 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -12486,12 +12486,18 @@ static boolean P_AllowMobjSpawn(mapthing_t* mthing, mobjtype_t i) break; } - if (!K_ShouldSpawnDuelItems()) + // This duel check is tricky. + // At map load, inDuel is always false, because + // K_TimerInit is called afterward. K_TimerInit will then + // spawn all the duel mode objects itself, which ends up + // calling this function again. + // So that's why this check is even here. + if (inDuel == false && (grandprixinfo.gp == false || grandprixinfo.eventmode != GPEVENT_BONUS)) { if (K_IsDuelItem(i) == true && K_DuelItemAlwaysSpawns(mthing) == false) { - // Only spawns in Duels. + // Only spawns in Duels or GP bonus rounds. return false; } } From 5607e8e3934899393870ebcceb1f9e84651a840b Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 7 Mar 2024 09:08:15 -0800 Subject: [PATCH 05/40] Menus: reset options menu header position from shortcuts in Match Race and Host menus - Match Race, Y button - Host, Gameplay Options and Server Options --- src/menus/options-1.c | 5 +++++ src/menus/play-local-race-difficulty.c | 2 ++ 2 files changed, 7 insertions(+) diff --git a/src/menus/options-1.c b/src/menus/options-1.c index d369e1084..34d91e4e1 100644 --- a/src/menus/options-1.c +++ b/src/menus/options-1.c @@ -212,6 +212,11 @@ static void M_OptionsMenuGoto(menu_t *assignment) { assignment->prevMenu = currentMenu; M_SetupNextMenu(assignment, false); + if (currentMenu != &OPTIONS_MainDef) + { + optionsmenu.ticker = 0; + M_OptionsTick(); + } } void M_VideoOptions(INT32 choice) diff --git a/src/menus/play-local-race-difficulty.c b/src/menus/play-local-race-difficulty.c index 26feabfd1..e8874c8e3 100644 --- a/src/menus/play-local-race-difficulty.c +++ b/src/menus/play-local-race-difficulty.c @@ -52,6 +52,8 @@ static void tick_routine(void) { case drace_mritems: M_SetupNextMenu(&OPTIONS_GameplayItemsDef, false); + optionsmenu.ticker = 0; + M_OptionsTick(); break; case drace_encore: From 38811b2e4c827fafc2c8e56ec92f9540a2f3dbe3 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 7 Mar 2024 09:09:12 -0800 Subject: [PATCH 06/40] Menus/Host: fix Gameplay Options and Server Options showing wrong header - Previously could say VIDEO OPTIONS etc in those menus, when accessed from Host menu shortcut --- src/menus/options-1.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/menus/options-1.c b/src/menus/options-1.c index 34d91e4e1..d11f3f709 100644 --- a/src/menus/options-1.c +++ b/src/menus/options-1.c @@ -237,12 +237,14 @@ void M_GameplayOptions(INT32 choice) { (void)choice; M_OptionsMenuGoto(&OPTIONS_GameplayDef); + OPTIONS_MainDef.lastOn = mopt_gameplay; } void M_ServerOptions(INT32 choice) { (void)choice; M_OptionsMenuGoto(&OPTIONS_ServerDef); + OPTIONS_MainDef.lastOn = mopt_server; } boolean M_OptionsInputs(INT32 ch) From ba50685c6e2744b516090ea6961c516fd2620e6d Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 7 Mar 2024 09:36:49 -0800 Subject: [PATCH 07/40] Menus/Map Select: split map names so only 1 word goes on the bottom This is the minimum requirement for release, just to stop Mega Collision Chaos from going off the screen. - 2 words - 1 word on top - 1 word below - 3 words - 2 words on top - 1 word below --- src/k_menudraw.c | 37 ++++++++++++------------------------- 1 file changed, 12 insertions(+), 25 deletions(-) diff --git a/src/k_menudraw.c b/src/k_menudraw.c index 666add657..825cce437 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -3338,38 +3338,25 @@ static void M_DrawHighLowLevelTitle(INT16 x, INT16 y, INT16 map) } else { - boolean donewithone = false; - char *ttlsource = mapheaderinfo[map]->menuttl[0] ? mapheaderinfo[map]->menuttl : mapheaderinfo[map]->lvlttl; - for (i = 0; i < 22; i++) + // If there are 2 or more words: + // - Last word goes on word2 + // - Everything else on word1 + char *p = strrchr(ttlsource, ' '); + if (p) { - if (!ttlsource[i]) - break; - - if (ttlsource[i] == ' ') - { - if (!donewithone) - { - donewithone = true; - continue; - } - } - - if (donewithone) - { - word2[word2len] = ttlsource[i]; - word2len++; - } - else - { - word1[word1len] = ttlsource[i]; - word1len++; - } + word2len = strlen(p + 1); + memcpy(word2, p + 1, word2len); } + else + p = ttlsource + strlen(ttlsource); + + word1len = p - ttlsource; + memcpy(word1, ttlsource, word1len); } if (!mapheaderinfo[map]->menuttl[0] && mapheaderinfo[map]->actnum) From c1cb76128c315a03a7213f62c8dab04358ee1096 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 7 Mar 2024 09:46:04 -0800 Subject: [PATCH 08/40] HUD: fix delay graphic offset on tab rankings This shifts it down in the bottom right too but I actually think it looks better! --- src/hu_stuff.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 61d925aba..798e386f9 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2253,8 +2253,6 @@ void HU_drawPing(fixed_t x, fixed_t y, UINT32 lag, UINT32 pl, INT32 flags, boole boolean drawlocal = (offline && cv_mindelay.value && lag <= (tic_t)cv_mindelay.value); fixed_t x2, y2; - y = y - 10*FRACUNIT; // Making space for connection quality, sorry. - if (!server && lag <= (tic_t)cv_mindelay.value) { lag = cv_mindelay.value; From 26c72f42997b8bca668f78fb567644b5e429c78c Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 7 Mar 2024 10:19:27 -0800 Subject: [PATCH 09/40] Replays: draw missing HUD - Notably brings back tab display and cecho messages --- src/d_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index d720639a4..9d1b25edb 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -687,7 +687,7 @@ static bool D_Display(void) } } - if (Playing()) + if (Playing() || demo.playback) { HU_Drawer(); } From 2d3961701411f59e3366ecd570e93aec5ccce302 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 7 Mar 2024 11:23:58 -0800 Subject: [PATCH 10/40] HUD: redesign VIEWPOINT text - 1P - "-Watching-" in thin font - Player name in free play font - 2P - Player name in free play font, transparent - 4P - Unchanged (player name in thin font, transparent) --- src/st_stuff.c | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/src/st_stuff.c b/src/st_stuff.c index 65f048b7c..0b3c1a490 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -1279,20 +1279,30 @@ static void ST_overlayDrawer(void) { if (!demo.attract && !P_IsLocalPlayer(stplyr) && !camera[viewnum].freecam) { - if (!r_splitscreen) + if (r_splitscreen <= 1) { - V_DrawCenteredString((BASEVIDWIDTH/2), BASEVIDHEIGHT-40, V_HUDTRANSHALF, M_GetText("VIEWPOINT:")); - V_DrawCenteredString((BASEVIDWIDTH/2), BASEVIDHEIGHT-32, V_HUDTRANSHALF, player_names[stplyr-players]); - } - else if (r_splitscreen == 1) - { - char name[MAXPLAYERNAME+12]; + INT32 flags = V_SNAPTOBOTTOM | V_SPLITSCREEN | V_HUDTRANS; + INT32 x = BASEVIDWIDTH/2; + INT32 y = (BASEVIDHEIGHT / (r_splitscreen + 1)) - 34; + INT32 width = 50; - INT32 y = (viewnum == 0) ? 4 : BASEVIDHEIGHT/2-12; - sprintf(name, "VIEWPOINT: %s", player_names[stplyr-players]); - V_DrawRightAlignedThinString(BASEVIDWIDTH-40, y, V_HUDTRANSHALF|V_SNAPTOTOP|V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_SPLITSCREEN, name); + if (r_splitscreen) + { + flags = (flags & ~V_ALPHAMASK) | V_HUDTRANSHALF; + y += 4; + } + else + { + V_DrawFill(x - width/2, y + 6, width, 2, flags | 31); + V_DrawCenteredThinString(x, y, flags | V_ORANGEMAP, "Watching"); + } + + const char *text = player_names[stplyr-players]; + fixed_t textwidth = V_StringScaledWidth(FRACUNIT, FRACUNIT, FRACUNIT, flags, KART_FONT, text); + V_DrawStringScaled(x*FRACUNIT - textwidth/2, (y+10)*FRACUNIT, + FRACUNIT, FRACUNIT, FRACUNIT, flags, NULL, KART_FONT, text); } - else if (r_splitscreen) + else { V_DrawCenteredThinString((vid.width/vid.dupx)/4, BASEVIDHEIGHT/2 - 12, V_HUDTRANSHALF|V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_SPLITSCREEN, player_names[stplyr-players]); } From d07291690d0d3c197c54443179a4a9f1866b5dea Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 7 Mar 2024 12:09:43 -0800 Subject: [PATCH 11/40] HUD: display "Finish" and "Best Lap" times underneath timer when watching Time Attack replays - Replace replay tab screen --- src/hu_stuff.c | 42 ------------------------------------------ src/k_hud.cpp | 40 ++++++++++++++++++++++++++++++++++------ 2 files changed, 34 insertions(+), 48 deletions(-) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 798e386f9..d2761852a 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -1958,43 +1958,6 @@ static void HU_DrawTitlecardCEcho(size_t num) UINT32 hu_demotime; UINT32 hu_demolap; -static void HU_DrawDemoInfo(void) -{ - if (!multiplayer)/* netreplay */ - { - V_DrawCenteredString((BASEVIDWIDTH/2), BASEVIDHEIGHT-40, 0, M_GetText("Replay:")); - V_DrawCenteredString((BASEVIDWIDTH/2), BASEVIDHEIGHT-32, 0, player_names[0]); - } - else - { - V_DrawRightAlignedThinString(BASEVIDWIDTH-2, BASEVIDHEIGHT-10, 0, demo.titlename); - } - - if (modeattacking & ATTACKING_TIME) - { - V_DrawRightAlignedString((BASEVIDWIDTH/2)-4, BASEVIDHEIGHT-24, V_YELLOWMAP|V_MONOSPACE, "BEST TIME:"); - if (hu_demotime != UINT32_MAX) - V_DrawString((BASEVIDWIDTH/2)+4, BASEVIDHEIGHT-24, V_MONOSPACE, va("%i'%02i\"%02i", - G_TicsToMinutes(hu_demotime,true), - G_TicsToSeconds(hu_demotime), - G_TicsToCentiseconds(hu_demotime))); - else - V_DrawString((BASEVIDWIDTH/2)+4, BASEVIDHEIGHT-24, V_MONOSPACE, "--'--\"--"); - } - - if (modeattacking & ATTACKING_LAP) - { - V_DrawRightAlignedString((BASEVIDWIDTH/2)-4, BASEVIDHEIGHT-16, V_YELLOWMAP|V_MONOSPACE, "BEST LAP:"); - if (hu_demolap != UINT32_MAX) - V_DrawString((BASEVIDWIDTH/2)+4, BASEVIDHEIGHT-16, V_MONOSPACE, va("%i'%02i\"%02i", - G_TicsToMinutes(hu_demolap,true), - G_TicsToSeconds(hu_demolap), - G_TicsToCentiseconds(hu_demolap))); - else - V_DrawString((BASEVIDWIDTH/2)+4, BASEVIDHEIGHT-16, V_MONOSPACE, "--'--\"--"); - } -} - // // Song credits @@ -2068,11 +2031,6 @@ void HU_Drawer(void) } LUA_HUD_DrawList(luahuddrawlist_scores); } - - if (demo.playback) - { - HU_DrawDemoInfo(); - } } if (cv_vhseffect.value && (paused || (demo.playback && cv_playbackspeed.value > 1))) diff --git a/src/k_hud.cpp b/src/k_hud.cpp index 04b0041b3..7ed6d593a 100644 --- a/src/k_hud.cpp +++ b/src/k_hud.cpp @@ -6005,13 +6005,41 @@ void K_drawKartHUD(void) bool ta = modeattacking && !demo.playback; INT32 flags = V_HUDTRANS|V_SLIDEIN|V_SNAPTOTOP|V_SNAPTORIGHT; K_drawKartTimestamp(stplyr->realtime, TIME_X, TIME_Y + (ta ? 2 : 0), flags, 0); - if (ta) + if (modeattacking) { - using srb2::Draw; - Draw(BASEVIDWIDTH - 19, 2) - .flags(flags | V_YELLOWMAP) - .align(Draw::Align::kRight) - .text("\xBE Restart"); + if (ta) + { + using srb2::Draw; + Draw(BASEVIDWIDTH - 19, 2) + .flags(flags | V_YELLOWMAP) + .align(Draw::Align::kRight) + .text("\xBE Restart"); + } + else + { + using srb2::Draw; + Draw row = Draw(BASEVIDWIDTH - 20, TIME_Y + 18).flags(flags).align(Draw::Align::kRight); + auto insert = [&](const char *label, UINT32 tics) + { + Draw::TextElement text = + tics != UINT32_MAX ? + Draw::TextElement( + "{}'{}\"{}", + G_TicsToMinutes(tics, true), + G_TicsToSeconds(tics), + G_TicsToCentiseconds(tics) + ) : + Draw::TextElement("--'--\"--"); + text.font(Draw::Font::kZVote); + row.x(-text.width()).flags(V_ORANGEMAP).text(label); + row.y(1).text(text); + row = row.y(10); + }; + if (modeattacking & ATTACKING_TIME) + insert("Finish: ", hu_demotime); + if (modeattacking & ATTACKING_LAP) + insert("Best Lap: ", hu_demolap); + } } } From f066f10e8f927a97e3f76d8f145c91e7a55933e2 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 7 Mar 2024 15:25:32 -0800 Subject: [PATCH 12/40] Menus: less padding after drawer closer --- src/k_menudraw.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/k_menudraw.c b/src/k_menudraw.c index 825cce437..c1d8340c4 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -4532,9 +4532,12 @@ box_found: } /* FALLTHRU */ case IT_NOTHING: - case IT_DYBIGSPACE: y += SMALLLINEHEIGHT; break; + + case IT_DYBIGSPACE: + y += SMALLLINEHEIGHT/2; + break; #if 0 case IT_BIGSLIDER: M_DrawThermo(x, y, currentMenu->menuitems[i].itemaction.cvar); From bc9c778bb54062fbad291eac8413d03aeffde1e3 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 7 Mar 2024 15:26:59 -0800 Subject: [PATCH 13/40] Menus/Video Options: fix "Set Resolution..." submenu not having the arrow --- src/k_menu.h | 1 - src/menus/options-video-1.c | 4 ++-- src/menus/options-video-modes.c | 10 ++++------ 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/k_menu.h b/src/k_menu.h index c39984a37..479d9495e 100644 --- a/src/k_menu.h +++ b/src/k_menu.h @@ -1104,7 +1104,6 @@ void M_ProfileTryController(INT32 choice); void M_ProfileControlsConfirm(INT32 choice); // video modes menu (resolution) -void M_VideoModeMenu(INT32 choice); void M_HandleVideoModes(INT32 ch); // data stuff diff --git a/src/menus/options-video-1.c b/src/menus/options-video-1.c index a1e1dcecc..e233ee195 100644 --- a/src/menus/options-video-1.c +++ b/src/menus/options-video-1.c @@ -10,8 +10,8 @@ menuitem_t OPTIONS_Video[] = { - {IT_STRING | IT_CALL, "Set Resolution...", "Change the screen resolution for the game.", - NULL, {.routine = M_VideoModeMenu}, 0, 0}, + {IT_STRING | IT_SUBMENU, "Set Resolution...", "Change the screen resolution for the game.", + NULL, {.submenu = &OPTIONS_VideoModesDef}, 0, 0}, {IT_NOTHING|IT_SPACE, NULL, NULL, NULL, {NULL}, 0, 0}, diff --git a/src/menus/options-video-modes.c b/src/menus/options-video-modes.c index a7648b7d6..ee360491c 100644 --- a/src/menus/options-video-modes.c +++ b/src/menus/options-video-modes.c @@ -12,6 +12,8 @@ menuitem_t OPTIONS_VideoModes[] = { }; +static void M_VideoModeMenu(void); + menu_t OPTIONS_VideoModesDef = { sizeof (OPTIONS_VideoModes) / sizeof (menuitem_t), &OPTIONS_VideoDef, @@ -25,20 +27,18 @@ menu_t OPTIONS_VideoModesDef = { M_DrawVideoModes, M_DrawOptionsCogs, M_OptionsTick, - NULL, + M_VideoModeMenu, NULL, NULL, }; // setup video mode menu -void M_VideoModeMenu(INT32 choice) +static void M_VideoModeMenu(void) { INT32 i, j, vdup, nummodes; UINT32 width, height; const char *desc; - (void)choice; - memset(optionsmenu.modedescs, 0, sizeof(optionsmenu.modedescs)); #if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL) @@ -100,8 +100,6 @@ void M_VideoModeMenu(INT32 choice) } optionsmenu.vidm_column_size = (optionsmenu.vidm_nummodes+2) / 3; - - M_SetupNextMenu(&OPTIONS_VideoModesDef, false); } // special menuitem key handler for video mode list From fe71c489468ecf808af4c90660f8e41440c91668 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 7 Mar 2024 15:27:22 -0800 Subject: [PATCH 14/40] Legacy GL: models on by default --- src/cvars.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cvars.cpp b/src/cvars.cpp index 7d6aad888..e729567ee 100644 --- a/src/cvars.cpp +++ b/src/cvars.cpp @@ -1367,7 +1367,7 @@ consvar_t cv_mute = UnsavedNetVar("mute", "Off").on_off().onchange(Mute_OnChange consvar_t cv_glmodellighting = OpenGL("gr_modellighting", "Off").on_off(); #endif - consvar_t cv_glmodels = OpenGL("gr_models", "Off").on_off(); + consvar_t cv_glmodels = OpenGL("gr_models", "On").on_off(); consvar_t cv_glshearing = OpenGL("gr_shearing", "Off").values({{0, "Off"}, {1, "On"}, {2, "Third-person"}}); consvar_t cv_glskydome = OpenGL("gr_skydome", "On").on_off(); consvar_t cv_glsolvetjoin = OpenGL("gr_solvetjoin", "On").on_off().dont_save(); From 1e578a177950c11eac4fb3c91493a1d95da46cc5 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 7 Mar 2024 15:31:58 -0800 Subject: [PATCH 15/40] Menus/Options: reorganize and rename - Tried to make verbiage consistent in tooltips - Move advanced video options into submenu - Remove console chat option - Move some really technical options from Data to submenu --- src/cvars.cpp | 4 +- src/k_menu.h | 27 +++++++---- src/menus/CMakeLists.txt | 5 +- src/menus/options-1.c | 18 +++---- src/menus/options-data-1.c | 13 ++--- src/menus/options-data-advanced-1.c | 41 ++++++++++++++++ ...addons.c => options-data-advanced-addon.c} | 13 ++--- src/menus/options-data-screenshots.c | 8 ++-- src/menus/options-gameplay-1.c | 12 ++--- src/menus/options-hud-1.c | 16 +++---- src/menus/options-hud-online.c | 4 +- src/menus/options-profiles-edit-1.c | 6 +-- src/menus/options-server-1.c | 28 +++++------ src/menus/options-server-advanced.c | 6 +-- src/menus/options-sound.cpp | 10 ++-- src/menus/options-video-1.c | 47 +++---------------- ...ns-video-gl.c => options-video-advanced.c} | 24 ++++++++-- src/menus/play-online-host.c | 4 +- 18 files changed, 154 insertions(+), 132 deletions(-) create mode 100644 src/menus/options-data-advanced-1.c rename src/menus/{options-data-addons.c => options-data-advanced-addon.c} (81%) rename src/menus/{options-video-gl.c => options-video-advanced.c} (72%) diff --git a/src/cvars.cpp b/src/cvars.cpp index e729567ee..798d9e1f8 100644 --- a/src/cvars.cpp +++ b/src/cvars.cpp @@ -540,7 +540,7 @@ consvar_t cv_netdemosize = Server("netdemo_size", "6").values(CV_Natural); void NetTimeout_OnChange(void); consvar_t cv_nettimeout = Server("nettimeout", "210").min_max(TICRATE/7, 60*TICRATE).onchange(NetTimeout_OnChange); -consvar_t cv_pause = NetVar("pausepermission", "Server").values({{0, "Server"}, {1, "All"}}); +consvar_t cv_pause = NetVar("pausepermission", "Server Admins").values({{0, "Server Admins"}, {1, "Everyone"}}); consvar_t cv_pingmeasurement = Server("pingmeasurement", "Frames").values({{0, "Frames"}, {1, "Milliseconds"}}); consvar_t cv_playbackspeed = Server("playbackspeed", "1").min_max(1, 10).dont_save(); @@ -1326,7 +1326,7 @@ consvar_t cv_chattime = Player("chattime", "8").min_max(5, 999); consvar_t cv_chatwidth = Player("chatwidth", "150").min_max(64, 150); // old shit console chat. (mostly exists for stuff like terminal, not because I cared if anyone liked the old chat.) -consvar_t cv_consolechat = Player("chatmode", "Window").values({{0, "Window"}, {1, "Console"}, {2, "Window (Hidden)"}}); +consvar_t cv_consolechat = Player("chatmode", "Yes").values({{0, "Yes"}, {2, "No"}}); consvar_t cv_gamestochat = Player("gamestochat", "0").values(CV_Unsigned); diff --git a/src/k_menu.h b/src/k_menu.h index 479d9495e..a9348442d 100644 --- a/src/k_menu.h +++ b/src/k_menu.h @@ -353,11 +353,10 @@ typedef enum typedef enum { dopt_screenshot = 0, - dopt_addon, + dopt_advanced, dopt_spacer1, dopt_replay, dopt_rprecord, - dopt_rpsync, dopt_rpsize, #ifdef HAVE_DISCORDRPC dopt_discord, @@ -370,6 +369,14 @@ typedef enum dopt_erase, } dopt_e; +typedef enum +{ + daopt_addon = 0, + daopt_spacer1, + daopt_replay, + daopt_replaycons, +} daopt_e; + extern menuitem_t OPTIONS_Profiles[]; extern menu_t OPTIONS_ProfilesDef; @@ -404,10 +411,8 @@ extern menu_t OPTIONS_VideoDef; extern menuitem_t OPTIONS_VideoModes[]; extern menu_t OPTIONS_VideoModesDef; -#ifdef HWRENDER -extern menuitem_t OPTIONS_VideoOGL[]; -extern menu_t OPTIONS_VideoOGLDef; -#endif +extern menuitem_t OPTIONS_VideoAdvanced[]; +extern menu_t OPTIONS_VideoAdvancedDef; extern menuitem_t OPTIONS_Sound[]; extern menu_t OPTIONS_SoundDef; @@ -420,7 +425,8 @@ extern menu_t OPTIONS_HUDOnlineDef; typedef enum { - gopt_gamespeed = 0, + gopt_spacer0 = 0, + gopt_gamespeed, gopt_baselapcount, gopt_frantic, gopt_encore, @@ -451,8 +457,11 @@ extern menu_t OPTIONS_DataDef; extern menuitem_t OPTIONS_DataScreenshot[]; extern menu_t OPTIONS_DataScreenshotDef; -extern menuitem_t OPTIONS_DataAddon[]; -extern menu_t OPTIONS_DataAddonDef; +extern menuitem_t OPTIONS_DataAdvanced[]; +extern menu_t OPTIONS_DataAdvancedDef; + +extern menuitem_t OPTIONS_DataAdvancedAddon[]; +extern menu_t OPTIONS_DataAdvancedAddonDef; extern menuitem_t OPTIONS_DataErase[]; extern menu_t OPTIONS_DataEraseDef; diff --git a/src/menus/CMakeLists.txt b/src/menus/CMakeLists.txt index 728d29303..be72a4996 100644 --- a/src/menus/CMakeLists.txt +++ b/src/menus/CMakeLists.txt @@ -10,7 +10,8 @@ target_sources(SRB2SDL2 PRIVATE main-profile-select.c options-1.c options-data-1.c - options-data-addons.c + options-data-advanced-1.c + options-data-advanced-addon.c options-data-erase-1.c options-data-erase-profile.c options-data-screenshots.c @@ -26,7 +27,7 @@ target_sources(SRB2SDL2 PRIVATE options-server-advanced.c options-sound.cpp options-video-1.c - options-video-gl.c + options-video-advanced.c options-video-modes.c play-1.c play-char-select.c diff --git a/src/menus/options-1.c b/src/menus/options-1.c index d11f3f709..a4b60feba 100644 --- a/src/menus/options-1.c +++ b/src/menus/options-1.c @@ -11,25 +11,25 @@ menuitem_t OPTIONS_Main[] = { - {IT_STRING | IT_CALL, "Profile Setup", "Remap keys & buttons to your likings.", + {IT_STRING | IT_CALL, "Profile Setup", "Remap keys & buttons.", NULL, {.routine = M_ProfileSelectInit}, 0, 0}, - {IT_STRING | IT_CALL, "Video Options", "Change video settings such as the resolution.", + {IT_STRING | IT_CALL, "Video Options", "Change the resolution.", NULL, {.routine = M_VideoOptions}, 0, 0}, - {IT_STRING | IT_CALL, "Sound Options", "Adjust various sound settings such as the volume.", + {IT_STRING | IT_CALL, "Sound Options", "Adjust the volume.", NULL, {.routine = M_SoundOptions}, 0, 0}, - {IT_STRING | IT_SUBMENU, "HUD Options", "Options related to the Heads-Up Display.", + {IT_STRING | IT_SUBMENU, "HUD Options", "Tweak the Heads-Up Display.", NULL, {.submenu = &OPTIONS_HUDDef}, 0, 0}, - {IT_STRING | IT_CALL, "Gameplay Options", "Change various game related options", + {IT_STRING | IT_CALL, "Gameplay Options", "Modify game mechanics.", NULL, {.routine = M_GameplayOptions}, 0, 0}, - {IT_STRING | IT_CALL, "Server Options", "Change various specific options for your game server.", + {IT_STRING | IT_CALL, "Server Options", "Update server settings.", NULL, {.routine = M_ServerOptions}, 0, 0}, - {IT_STRING | IT_SUBMENU, "Data Options", "Miscellaneous data options such as the screenshot format.", + {IT_STRING | IT_SUBMENU, "Data Options", "Video recording, file saving, Discord status.", NULL, {.submenu = &OPTIONS_DataDef}, 0, 0}, #ifdef TODONEWMANUAL @@ -96,9 +96,9 @@ void M_InitOptions(INT32 choice) (M_SecretUnlocked(SECRET_ENCORE, false) ? (IT_STRING | IT_CVAR) : IT_DISABLED); } - OPTIONS_DataDef.menuitems[dopt_addon].status = (M_SecretUnlocked(SECRET_ADDONS, true) + OPTIONS_DataAdvancedDef.menuitems[daopt_addon].status = (M_SecretUnlocked(SECRET_ADDONS, true) ? (IT_STRING | IT_SUBMENU) - : (IT_TRANSTEXT2 | IT_SPACE)); + : (IT_NOTHING | IT_SPACE)); OPTIONS_DataDef.menuitems[dopt_erase].status = (gamestate == GS_MENU ? (IT_STRING | IT_SUBMENU) : (IT_TRANSTEXT2 | IT_SPACE)); diff --git a/src/menus/options-data-1.c b/src/menus/options-data-1.c index fd7f830d6..af6e7829d 100644 --- a/src/menus/options-data-1.c +++ b/src/menus/options-data-1.c @@ -10,11 +10,11 @@ extern consvar_t cv_netdemosize; menuitem_t OPTIONS_Data[] = { - {IT_STRING | IT_SUBMENU, "Video Recording...", "Set options relative to screenshot and movie capture.", + {IT_STRING | IT_SUBMENU, "Video Recording...", "Options for recording clips.", NULL, {.submenu = &OPTIONS_DataScreenshotDef}, 0, 0}, - {IT_STRING | IT_SUBMENU, "Addons...", "Set options relative to the addons menu.", - NULL, {.submenu = &OPTIONS_DataAddonDef}, 0, 0}, + {IT_STRING | IT_SUBMENU, "Advanced...", "Technical settings that you probably don't want to change.", + NULL, {.submenu = &OPTIONS_DataAdvancedDef}, 0, 0}, {IT_SPACE | IT_NOTHING, NULL, NULL, NULL, {NULL}, 0, 0}, @@ -22,12 +22,9 @@ menuitem_t OPTIONS_Data[] = {IT_HEADER, "Replays...", NULL, NULL, {NULL}, 0, 0}, - {IT_STRING | IT_CVAR, "Record Replays", "Select when to save replays.", + {IT_STRING | IT_CVAR, "Record Replays", "How the save prompt should appear.", NULL, {.cvar = &cv_recordmultiplayerdemos}, 0, 0}, - {IT_STRING | IT_CVAR, "Net Consistency Quality", "For filesize, how often do we write position data in online replays?", - NULL, {.cvar = &cv_netdemosyncquality}, 0, 0}, - {IT_STRING | IT_CVAR, "Buffer Size (MB)", "Lets replays last longer with more players. Uses more RAM.", NULL, {.cvar = &cv_netdemosize}, 0, 0}, @@ -51,7 +48,7 @@ menuitem_t OPTIONS_Data[] = {IT_SPACE | IT_DYBIGSPACE, NULL, NULL, NULL, {NULL}, 0, 0}, - {IT_STRING | IT_SUBMENU, "\x85""Erase Data...", "Erase specific data. Be careful, what's deleted is gone forever!", + {IT_STRING | IT_SUBMENU, "\x85""Erase Data...", "Erase save data. Be careful, what's deleted is gone forever!", NULL, {.submenu = &OPTIONS_DataEraseDef}, 0, 0}, }; diff --git a/src/menus/options-data-advanced-1.c b/src/menus/options-data-advanced-1.c new file mode 100644 index 000000000..4edc26ae9 --- /dev/null +++ b/src/menus/options-data-advanced-1.c @@ -0,0 +1,41 @@ +/// \file menus/options-data-advanced.c +/// \brief Advanced Data Options + +#include "../k_menu.h" +#include "../filesrch.h" // addons cvars + +// advanced data options menu -- see daopt_e +menuitem_t OPTIONS_DataAdvanced[] = +{ + + {IT_STRING | IT_SUBMENU, "Addons...", NULL, + NULL, {.submenu = &OPTIONS_DataAdvancedAddonDef}, 0, 0}, + + {IT_NOTHING | IT_SPACE, NULL, NULL, + NULL, {NULL}, 0, 0}, + + {IT_HEADER, "Replays (Advanced)...", NULL, + NULL, {NULL}, 0, 0}, + + {IT_STRING | IT_CVAR, "Net Consistency Quality", "For filesize, how often do we write position data in online replays?", + NULL, {.cvar = &cv_netdemosyncquality}, 0, 0}, + +}; + +menu_t OPTIONS_DataAdvancedDef = { + sizeof (OPTIONS_DataAdvanced) / sizeof (menuitem_t), + &OPTIONS_DataDef, + 0, + OPTIONS_DataAdvanced, + 48, 80, + SKINCOLOR_BLUEBERRY, 0, + MBF_DRAWBGWHILEPLAYING, + NULL, + 2, 5, + M_DrawGenericOptions, + M_DrawOptionsCogs, + M_OptionsTick, + NULL, + NULL, + NULL, +}; diff --git a/src/menus/options-data-addons.c b/src/menus/options-data-advanced-addon.c similarity index 81% rename from src/menus/options-data-addons.c rename to src/menus/options-data-advanced-addon.c index 53a9ebac4..159fe6061 100644 --- a/src/menus/options-data-addons.c +++ b/src/menus/options-data-advanced-addon.c @@ -1,10 +1,7 @@ -/// \file menus/options-data-addons.c -/// \brief Addon Options - #include "../k_menu.h" #include "../filesrch.h" // addons cvars -menuitem_t OPTIONS_DataAddon[] = +menuitem_t OPTIONS_DataAdvancedAddon[] = { {IT_HEADER, "Addon List", NULL, @@ -27,11 +24,11 @@ menuitem_t OPTIONS_DataAddon[] = }; -menu_t OPTIONS_DataAddonDef = { - sizeof (OPTIONS_DataAddon) / sizeof (menuitem_t), - &OPTIONS_DataDef, +menu_t OPTIONS_DataAdvancedAddonDef = { + sizeof (OPTIONS_DataAdvancedAddon) / sizeof (menuitem_t), + &OPTIONS_DataAdvancedDef, 0, - OPTIONS_DataAddon, + OPTIONS_DataAdvancedAddon, 48, 80, SKINCOLOR_BLUEBERRY, 0, MBF_DRAWBGWHILEPLAYING, diff --git a/src/menus/options-data-screenshots.c b/src/menus/options-data-screenshots.c index ec84cebac..515b25505 100644 --- a/src/menus/options-data-screenshots.c +++ b/src/menus/options-data-screenshots.c @@ -10,7 +10,7 @@ menuitem_t OPTIONS_DataScreenshot[] = { #ifdef SRB2_CONFIG_ENABLE_WEBM_MOVIES - {IT_HEADER, "Movie Recording (F9)", NULL, + {IT_HEADER, "WebM Recording (F9)", NULL, NULL, {NULL}, 0, 0}, {IT_STRING | IT_CVAR, "Max. Duration (s)", "Automatically stop recording after this much time.", @@ -28,10 +28,10 @@ menuitem_t OPTIONS_DataScreenshot[] = {IT_SPACE | IT_NOTHING, NULL, NULL, NULL, {NULL}, 0, 0}, - {IT_STRING | IT_CVAR, "Resolution", "Video resolution", + {IT_STRING | IT_CVAR, "Resolution", "Video resolution.", NULL, {.cvar = &cv_movie_resolution}, 0, 0}, - {IT_STRING | IT_CVAR, "Max. FPS", "Video framerate", + {IT_STRING | IT_CVAR, "Max. FPS", "Video framerate.", NULL, {.cvar = &cv_movie_fps}, 0, 0}, {IT_STRING | IT_CVAR, "Record Audio", "Record audio.", @@ -41,7 +41,7 @@ menuitem_t OPTIONS_DataScreenshot[] = {IT_HEADER, "Lossless Recording (F10)", NULL, NULL, {NULL}, 0, 0}, - {IT_STRING | IT_CVAR, "Recording Format", "What file format will lossless recordings use?", + {IT_STRING | IT_CVAR, "Recording Format", "Which file format will lossless recordings use?", NULL, {.cvar = &cv_lossless_recorder}, 0, 0}, }; diff --git a/src/menus/options-gameplay-1.c b/src/menus/options-gameplay-1.c index e6fb71750..38aeb4925 100644 --- a/src/menus/options-gameplay-1.c +++ b/src/menus/options-gameplay-1.c @@ -10,16 +10,16 @@ menuitem_t OPTIONS_Gameplay[] = {IT_HEADER, "Race...", NULL, NULL, {NULL}, 0, 0}, - {IT_STRING | IT_CVAR, "Game Speed", "Change Game Speed for the next map.", + {IT_STRING | IT_CVAR, "Game Speed", "Gear for the next map.", NULL, {.cvar = &cv_kartspeed}, 0, 0}, - {IT_STRING | IT_CVAR, "Base Lap Count", "Change how many laps must be completed per race.", + {IT_STRING | IT_CVAR, "Base Lap Count", "How many laps must be completed per race.", NULL, {.cvar = &cv_numlaps}, 0, 0}, {IT_STRING | IT_CVAR, "Frantic Items", "Make item odds crazier with more powerful items!", NULL, {.cvar = &cv_kartfrantic}, 0, 0}, - {IT_STRING | IT_CVAR, "Encore Mode", "Forces Encore Mode on for the next map.", + {IT_STRING | IT_CVAR, "Encore Mode", "Play in Encore Mode next map.", NULL, {.cvar = &cv_kartencore}, 0, 0}, {IT_STRING | IT_CVAR, "Exit Countdown", "How long players have to finish after 1st place finishes.", @@ -29,20 +29,20 @@ menuitem_t OPTIONS_Gameplay[] = {IT_HEADER, "Battle...", NULL, NULL, {NULL}, 0, 0}, - {IT_STRING | IT_CVAR, "Time Limit", "Change the time limit for Battle rounds.", + {IT_STRING | IT_CVAR, "Time Limit", "Time limit for Battle rounds.", NULL, {.cvar = &cv_timelimit}, 0, 0}, {IT_STRING | IT_CVAR, "Point Limit", "How many strikes it takes to win a Battle.", NULL, {.cvar = &cv_pointlimit}, 0, 0}, - {IT_STRING | IT_CVAR, "Starting Bumpers", "Change how many bumpers player start with in Battle.", + {IT_STRING | IT_CVAR, "Starting Bumpers", "How many bumpers players start with in Battle.", NULL, {.cvar = &cv_kartbumpers}, 0, 0}, {IT_SPACE | IT_DYBIGSPACE, NULL, NULL, NULL, {NULL}, 0, 0}, - {IT_STRING | IT_SUBMENU, "Random Item Toggles...", "Change which items to enable for your games.", + {IT_STRING | IT_SUBMENU, "Random Item Toggles...", "Which items appear in your games.", NULL, {.submenu = &OPTIONS_GameplayItemsDef}, 0, 0}, }; diff --git a/src/menus/options-hud-1.c b/src/menus/options-hud-1.c index 34c494955..3b7809937 100644 --- a/src/menus/options-hud-1.c +++ b/src/menus/options-hud-1.c @@ -8,35 +8,31 @@ menuitem_t OPTIONS_HUD[] = { - {IT_STRING | IT_CVAR, "Show HUD (F3)", "Toggles HUD display. Great for taking screenshots!", + {IT_STRING | IT_CVAR, "Show HUD (F3)", "Toggles the Heads-Up display. Great for taking screenshots!", NULL, {.cvar = &cv_showhud}, 0, 0}, {IT_SPACE | IT_NOTHING, NULL, NULL, NULL, {NULL}, 0, 0}, - {IT_STRING | IT_CVAR, "Speedometer", "Choose to what speed unit to display or toggle off the speedometer.", + {IT_STRING | IT_CVAR, "Speedometer", "Choose which speed unit to display on the speedometer.", NULL, {.cvar = &cv_kartspeedometer}, 0, 0}, {IT_SPACE | IT_NOTHING, NULL, NULL, NULL, {NULL}, 0, 0}, -/* -- Nah, console isn't even bound by default, if you know how to use it you can change the size there - {IT_STRING | IT_CVAR, "Console Text Size", "Size of the text within the console.", - NULL, {.cvar = &cv_constextsize}, 0, 0},*/ - - {IT_STRING | IT_CVAR, "Show FPS", "Displays the game framerate at the lower right corner of the screen.", + {IT_STRING | IT_CVAR, "Show FPS", "Displays the framerate in the lower right corner of the screen.", NULL, {.cvar = &cv_ticrate}, 0, 0}, - {IT_STRING | IT_CVAR, "Show Input Delay", "Displays your input delay at the lower right corner of the screen.", + {IT_STRING | IT_CVAR, "Show Input Delay", "Displays your input delay in the lower right corner of the screen.", NULL, {.cvar = &cv_showping}, 0, 0}, - {IT_STRING | IT_CVAR, "Show \"FOCUS LOST\"", "Displays \"FOCUS LOST\" when the game window isn't the active window.", + {IT_STRING | IT_CVAR, "Show \"FOCUS LOST\"", "Displays \"FOCUS LOST\" when the game cannot accept inputs.", NULL, {.cvar = &cv_showfocuslost}, 0, 0}, {IT_SPACE | IT_NOTHING, NULL, NULL, NULL, {NULL}, 0, 0}, - {IT_STRING | IT_SUBMENU, "Online Chat Options...", "HUD options related to the online chat box.", + {IT_STRING | IT_SUBMENU, "Online Chat Options...", "Visual options for the online chat box.", NULL, {.submenu = &OPTIONS_HUDOnlineDef}, 0, 0}, }; diff --git a/src/menus/options-hud-online.c b/src/menus/options-hud-online.c index b7449d28d..4eda3528e 100644 --- a/src/menus/options-hud-online.c +++ b/src/menus/options-hud-online.c @@ -7,7 +7,7 @@ menuitem_t OPTIONS_HUDOnline[] = { - {IT_STRING | IT_CVAR, "Chat Mode", "Choose whether to display chat in its own window or the console.", + {IT_STRING | IT_CVAR, "Show Chat", "Show chat by default or keep it hidden until you open it.", NULL, {.cvar = &cv_consolechat}, 0, 0}, {IT_SPACE | IT_NOTHING, NULL, NULL, @@ -28,7 +28,7 @@ menuitem_t OPTIONS_HUDOnline[] = {IT_STRING | IT_CVAR, "Message Fadeout Time (s)", "How long chat messages stay displayed with the chat closed.", NULL, {.cvar = &cv_chattime}, 0, 0}, - {IT_STRING | IT_CVAR, "Message Tint", "Shows the tint for new chat messages when the box is closed.", + {IT_STRING | IT_CVAR, "Message Fadeout Tint", "Shows the tint for new chat messages when the box is closed.", NULL, {.cvar = &cv_chatbacktint}, 0, 0}, }; diff --git a/src/menus/options-profiles-edit-1.c b/src/menus/options-profiles-edit-1.c index 65eca8819..ef6a7212c 100644 --- a/src/menus/options-profiles-edit-1.c +++ b/src/menus/options-profiles-edit-1.c @@ -12,16 +12,16 @@ menuitem_t OPTIONS_EditProfile[] = { {IT_STRING | IT_CVAR | IT_CV_STRING, "Profile ID", "6-character long name to identify this Profile.", NULL, {.cvar = &cv_dummyprofilename}, 0, 41}, - {IT_STRING | IT_CALL, "Controls", "Select the button mappings for this Profile.", + {IT_STRING | IT_CALL, "Controls", "Change the button mappings.", NULL, {.routine = M_ProfileDeviceSelect}, 0, 71}, {IT_STRING | IT_SUBMENU, "Accessibility", "Acccessibility and quality of life options.", NULL, {.submenu = &OPTIONS_ProfileAccessibilityDef}, 0, 91}, - {IT_STRING | IT_CALL, "Character", "Default character and color for this Profile.", + {IT_STRING | IT_CALL, "Character", "Default character and color.", NULL, {.routine = M_CharacterSelect}, 0, 111}, - {IT_STRING | IT_CVAR | IT_CV_STRING, "Player Tag", "Name displayed online when using this Profile.", + {IT_STRING | IT_CVAR | IT_CV_STRING, "Player Tag", "Name displayed online and in replays.", NULL, {.cvar = &cv_dummyprofileplayername}, 0, 141}, {IT_STRING | IT_CALL, "Confirm", "Confirm changes.", diff --git a/src/menus/options-server-1.c b/src/menus/options-server-1.c index 1a83b6af1..507e304bd 100644 --- a/src/menus/options-server-1.c +++ b/src/menus/options-server-1.c @@ -9,13 +9,13 @@ menuitem_t OPTIONS_Server[] = {IT_HEADER, "Advertising...", NULL, NULL, {NULL}, 0, 0}, - {IT_STRING | IT_CVAR | IT_CV_STRING, "Server Name", "Change the name of your server.", + {IT_STRING | IT_CVAR | IT_CV_STRING, "Server Name", "Name of your server.", NULL, {.cvar = &cv_servername}, 0, 0}, - {IT_STRING | IT_CVAR | IT_CV_STRING, "Server Contact", "Where you should be contacted for Master Server moderation.", + {IT_STRING | IT_CVAR | IT_CV_STRING, "Server Contact", "How you should be contacted for Master Server moderation.", NULL, {.cvar = &cv_server_contact}, 0, 0}, - {IT_STRING | IT_CVAR, "Advertise", "Display your game in the Server Browser for other players.", + {IT_STRING | IT_CVAR, "Advertise", "Display your server in the Browser for other players to join.", NULL, {.cvar = &cv_advertise}, 0, 0}, @@ -28,49 +28,49 @@ menuitem_t OPTIONS_Server[] = {IT_STRING | IT_CVAR, "Maximum Connections", "How many players & spectators can connect to the server.", NULL, {.cvar = &cv_maxconnections}, 0, 0}, - {IT_STRING | IT_CVAR, "CPU Difficulty", "Bots can fill unused slots. How strong should they be?", + {IT_STRING | IT_CVAR, "CPU Level", "Bots can fill unused slots. How strong should they be?", NULL, {.cvar = &cv_kartbot}, 0, 0}, - {IT_STRING | IT_CVAR, "Use PWR.LV", "Set whether players should be rated on their performance.", + {IT_STRING | IT_CVAR, "Use PWR.LV", "Should players should be rated on their performance?", NULL, {.cvar = &cv_kartusepwrlv}, 0, 0}, {IT_HEADER, "Progression...", NULL, NULL, {NULL}, 0, 0}, - {IT_STRING | IT_CVAR, "Intermission", "Set how long to stay on the result screen.", + {IT_STRING | IT_CVAR, "Intermission", "How long to stay on the result screen.", NULL, {.cvar = &cv_inttime}, 0, 0}, - {IT_STRING | IT_CVAR, "Map Progression", "Set how the next map is chosen.", + {IT_STRING | IT_CVAR, "Map Progression", "How the next map is chosen.", NULL, {.cvar = &cv_advancemap}, 0, 0}, - {IT_STRING | IT_CVAR, "Vote Timer", "Set how long players have to vote.", + {IT_STRING | IT_CVAR, "Vote Timer", "How long players have to vote.", NULL, {.cvar = &cv_votetime}, 0, 0}, {IT_HEADER, "Permissions...", NULL, NULL, {NULL}, 0, 0}, - {IT_STRING | IT_CVAR, "Allow Joining", "Sets whether players can connect to your server.", + {IT_STRING | IT_CVAR, "Allow Joining", "Let players connect to your server.", NULL, {.cvar = &cv_allownewplayer}, 0, 0}, - {IT_STRING | IT_CVAR, "Allow Downloads", "Allows joiners to download missing files from you.", + {IT_STRING | IT_CVAR, "Allow Downloads", "Let players download missing files from your server.", NULL, {.cvar = &cv_downloading}, 0, 0}, - {IT_STRING | IT_CVAR, "Pause Permissions", "Sets who can pause the game.", + {IT_STRING | IT_CVAR, "Pause Permissions", "Who is allowed to pause the game?", NULL, {.cvar = &cv_pause}, 0, 0}, {IT_HEADER, "Chat...", NULL, NULL, {NULL}, 0, 0}, - {IT_STRING | IT_CVAR, "Mute Chat", "Prevents non-admins from sending chat messages.", + {IT_STRING | IT_CVAR, "Mute Chat", "Prevent everyone but admins from sending chat messages.", NULL, {.cvar = &cv_mute}, 0, 0}, - {IT_STRING | IT_CVAR, "Chat Spam Protection", "Prevents too many message from a single player.", + {IT_STRING | IT_CVAR, "Chat Spam Protection", "Prevent too many message from a single player.", NULL, {.cvar = &cv_chatspamprotection}, 0, 0}, - {IT_HEADER, "Advanced...", NULL, + {IT_SPACE | IT_DYBIGSPACE, NULL, NULL, NULL, {NULL}, 0, 0}, {IT_STRING | IT_SUBMENU, "Advanced...", "Advanced options. Be careful when messing with these!", diff --git a/src/menus/options-server-advanced.c b/src/menus/options-server-advanced.c index 77f0052d4..35da6a003 100644 --- a/src/menus/options-server-advanced.c +++ b/src/menus/options-server-advanced.c @@ -38,7 +38,7 @@ menuitem_t OPTIONS_ServerAdvanced[] = {IT_HEADER, "Addon Downloading", NULL, NULL, {NULL}, 0, 0}, - {IT_STRING | IT_CVAR, "Max File Transfer", "Maximum size of the files that can be downloaded from joining clients. (KB)", + {IT_STRING | IT_CVAR, "Max File Transfer", "Maximum size of each file that joining players may download. (KB)", NULL, {.cvar = &cv_maxsend}, 0, 0}, {IT_STRING | IT_CVAR, "File Transfer Speed", "File transfer packet rate. Larger values send more data.", @@ -48,13 +48,13 @@ menuitem_t OPTIONS_ServerAdvanced[] = {IT_HEADER, "Logging", NULL, NULL, {NULL}, 0, 0}, - {IT_STRING | IT_CVAR, "Log Joiner IPs", "Shows the IP of connecting players.", + {IT_STRING | IT_CVAR, "Log Joiner IPs", "Shows the IP address of connecting players as they join.", NULL, {.cvar = &cv_showjoinaddress}, 0, 0}, {IT_STRING | IT_CVAR, "Log Resynch", "Shows which players need resynchronization.", NULL, {.cvar = &cv_blamecfail}, 0, 0}, - {IT_STRING | IT_CVAR, "Log Transfers", "Shows when clients are downloading files from you.", + {IT_STRING | IT_CVAR, "Log Transfers", "Shows when players are downloading files from you.", NULL, {.cvar = &cv_noticedownload}, 0, 0}, }; diff --git a/src/menus/options-sound.cpp b/src/menus/options-sound.cpp index e5d0eeff6..716ee5752 100644 --- a/src/menus/options-sound.cpp +++ b/src/menus/options-sound.cpp @@ -220,22 +220,22 @@ boolean input_routine(INT32) menuitem_t OPTIONS_Sound[] = { - {IT_STRING | IT_ARROWS | IT_CV_SLIDER, "Volume", "Adjust the volume of game audio.", + {IT_STRING | IT_ARROWS | IT_CV_SLIDER, "Volume", "Loudness of all game audio.", NULL, {.routine = slider_routine}, 0, Slider::kMasterVolume}, - {IT_STRING | IT_ARROWS | IT_CV_SLIDER, "SFX Volume", "Adjust the volume of sound effects.", + {IT_STRING | IT_ARROWS | IT_CV_SLIDER, "SFX Volume", "Loudness of sound effects.", NULL, {.routine = slider_routine}, 0, Slider::kSfxVolume}, - {IT_STRING | IT_ARROWS | IT_CV_SLIDER, "Music Volume", "Adjust the volume of music playback.", + {IT_STRING | IT_ARROWS | IT_CV_SLIDER, "Music Volume", "Loudness of music.", NULL, {.routine = slider_routine}, 0, Slider::kMusicVolume}, {IT_SPACE | IT_NOTHING, NULL, NULL, NULL, {NULL}, 0, 0}, - {IT_STRING | IT_CVAR, "Chat Notifications", "Set when to play notification sounds when chat messages are received.", + {IT_STRING | IT_CVAR, "Chat Notifications", "Play a sound effect when chat messages appear.", NULL, {.cvar = &cv_chatnotifications}, 0, 0}, - {IT_STRING | IT_CVAR, "Character Voices", "Set how often to play character voices in game.", + {IT_STRING | IT_CVAR, "Character Voices", "How often to play character voices in a race.", NULL, {.cvar = &cv_kartvoices}, 0, 0}, {IT_SPACE | IT_NOTHING, NULL, NULL, diff --git a/src/menus/options-video-1.c b/src/menus/options-video-1.c index e233ee195..9c0d20a12 100644 --- a/src/menus/options-video-1.c +++ b/src/menus/options-video-1.c @@ -2,7 +2,6 @@ /// \brief Video Options #include "../k_menu.h" -#include "../r_main.h" // cv_skybox #include "../v_video.h" // cv_globalgamma #include "../r_fps.h" // fps cvars @@ -10,65 +9,31 @@ menuitem_t OPTIONS_Video[] = { - {IT_STRING | IT_SUBMENU, "Set Resolution...", "Change the screen resolution for the game.", + {IT_STRING | IT_SUBMENU, "Resolution...", "Change the aspect ratio and image quality.", NULL, {.submenu = &OPTIONS_VideoModesDef}, 0, 0}, {IT_NOTHING|IT_SPACE, NULL, NULL, NULL, {NULL}, 0, 0}, #if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL) - {IT_STRING | IT_CVAR, "Fullscreen", "Set whether you want to use fullscreen or windowed mode.", + {IT_STRING | IT_CVAR, "Fullscreen", "Play on the big screen or in a small window.", NULL, {.cvar = &cv_fullscreen}, 0, 0}, #endif - {IT_STRING | IT_CVAR, "Vertical Sync", "Works with your screen to reduce image tearing and judder.", + {IT_STRING | IT_CVAR, "V-Sync", "Reduce image tearing and judder.", NULL, {.cvar = &cv_vidwait}, 0, 0}, - {IT_STRING | IT_CVAR, "FPS Cap", "Handles the frame rate of the game (35 to match game logic)", + {IT_STRING | IT_CVAR, "FPS Cap", "Limit the frame rate. Higher values may consume more CPU usage.", NULL, {.cvar = &cv_fpscap}, 0, 0}, {IT_NOTHING|IT_SPACE, NULL, NULL, NULL, {NULL}, 0, 0}, -#if 0 // See Profiles/Accessibility - {IT_STRING | IT_CVAR, "Screen Tilting", "The view rotatation on inclines can be disabled to reduce motion sickness.", - NULL, {.cvar = &cv_tilting}, 0, 0}, - - {IT_STRING | IT_CVAR, "Reduce Visual Effects", "If on, some less-important particle cues will be hidden.", - NULL, {.cvar = &cv_reducevfx}, 0, 0}, -#endif - - /* - {IT_STRING | IT_CVAR | IT_CV_SLIDER, "Gamma", "Adjusts the overall brightness of the game.", - NULL, {.cvar = &cv_globalgamma}, 0, 0}, - {IT_NOTHING|IT_SPACE, NULL, NULL, NULL, {NULL}, 0, 0}, - */ - - {IT_HEADER, "Advanced...", NULL, - NULL, {NULL}, 0, 0}, - - {IT_STRING | IT_CVAR, "Draw Distance", "How far objects can be drawn. A tradeoff between performance & visibility.", - NULL, {.cvar = &cv_drawdist}, 0, 0}, - - {IT_STRING | IT_CVAR, "Weather Draw Distance", "Affects how far weather visuals can be drawn. Lower values improve performance.", - NULL, {.cvar = &cv_drawdist_precip}, 0, 0}, - - {IT_STRING | IT_CVAR, "Enable Skyboxes", "Turning this off may improve performance, but reduces courses' background details.", - NULL, {.cvar = &cv_skybox}, 0, 0}, - - {IT_STRING | IT_CVAR, "Parallel Software", "Uses multiple CPU cores for the software renderer if available, for a FPS boost.", - NULL, {.cvar = &cv_parallelsoftware}, 0, 0}, - -#ifdef HWRENDER - {IT_NOTHING|IT_SPACE, NULL, NULL, - NULL, {NULL}, 0, 0}, - - {IT_STRING | IT_SUBMENU, "Hardware Options...", "For usage and configuration of the OpenGL renderer.", - NULL, {.submenu = &OPTIONS_VideoOGLDef}, 0, 0}, -#endif + {IT_STRING | IT_SUBMENU, "Advanced...", "Advanced performance options and experimental rendering features.", + NULL, {.submenu = &OPTIONS_VideoAdvancedDef}, 0, 0}, }; diff --git a/src/menus/options-video-gl.c b/src/menus/options-video-advanced.c similarity index 72% rename from src/menus/options-video-gl.c rename to src/menus/options-video-advanced.c index 4c63601d1..e5b941ccf 100644 --- a/src/menus/options-video-gl.c +++ b/src/menus/options-video-advanced.c @@ -2,10 +2,26 @@ /// \brief OpenGL Options #include "../k_menu.h" +#include "../r_main.h" // cv_skybox #include "../hardware/hw_main.h" // gl consvars -menuitem_t OPTIONS_VideoOGL[] = +menuitem_t OPTIONS_VideoAdvanced[] = { + {IT_HEADER, "Performance...", NULL, + NULL, {NULL}, 0, 0}, + + {IT_STRING | IT_CVAR, "Draw Distance", "How far objects can be drawn. A tradeoff between performance & visibility.", + NULL, {.cvar = &cv_drawdist}, 0, 0}, + + {IT_STRING | IT_CVAR, "Weather Draw Distance", "Affects how far weather visuals can be drawn. Lower values improve performance.", + NULL, {.cvar = &cv_drawdist_precip}, 0, 0}, + + {IT_STRING | IT_CVAR, "Enable Skyboxes", "Turning this off may improve performance, but reduces courses' background details.", + NULL, {.cvar = &cv_skybox}, 0, 0}, + + {IT_STRING | IT_CVAR, "Parallel Software", "Uses multiple CPU cores for the software renderer if available, for a FPS boost.", + NULL, {.cvar = &cv_parallelsoftware}, 0, 0}, + {IT_HEADER, "Rendering Backend...", "Watch people get confused anyway!!", NULL, {NULL}, 0, 0}, @@ -67,11 +83,11 @@ menuitem_t OPTIONS_VideoOGL[] = NULL, {.cvar = &cv_glshearing}, 0, 0}, }; -menu_t OPTIONS_VideoOGLDef = { - sizeof (OPTIONS_VideoOGL) / sizeof (menuitem_t), +menu_t OPTIONS_VideoAdvancedDef = { + sizeof (OPTIONS_VideoAdvanced) / sizeof (menuitem_t), &OPTIONS_VideoDef, 0, - OPTIONS_VideoOGL, + OPTIONS_VideoAdvanced, 48, 80, SKINCOLOR_PLAGUE, 0, MBF_DRAWBGWHILEPLAYING, diff --git a/src/menus/play-online-host.c b/src/menus/play-online-host.c index 3c6f344d6..02613ef54 100644 --- a/src/menus/play-online-host.c +++ b/src/menus/play-online-host.c @@ -41,10 +41,10 @@ menuitem_t PLAY_MP_Host[] = {IT_STRING | IT_ARROWS, "Gametype", "Choose the type of play on your serer.", NULL, {.routine = M_HandleHostMenuGametype}, 0, 0}, - {IT_STRING2 | IT_CALL, "Gameplay Options...", "Adjust settings pertaining to gameplay.", + {IT_STRING2 | IT_CALL, "Gameplay Options...", "Modify game mechanics.", NULL, {.routine = M_GameplayOptions}, 0, 0}, - {IT_STRING2 | IT_CALL, "Server Options...", "Adjust settings pertaining to online play.", + {IT_STRING2 | IT_CALL, "Server Options...", "Update server settings.", NULL, {.routine = M_ServerOptions}, 0, 0}, {IT_STRING | IT_CALL, "Map Select", "Go on and select a level!", From fc215e0572589eabb2d087bc975ce8e17f37bce9 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 7 Mar 2024 16:16:01 -0800 Subject: [PATCH 16/40] Add hardcoded F11 key to toggle fullscreen --- src/k_menufunc.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/k_menufunc.c b/src/k_menufunc.c index 881b9b044..de474ae23 100644 --- a/src/k_menufunc.c +++ b/src/k_menufunc.c @@ -275,6 +275,14 @@ static boolean M_GamestateCanOpenMenu(void) // boolean M_Responder(event_t *ev) { + if (ev->type == ev_keydown && ev->data1 == KEY_F11 && !ev->data2) + { + // F11 can always be used to toggle fullscreen, it's + // a safe key. + CV_AddValue(&cv_fullscreen, 1); + return true; + } + if (dedicated || (demo.playback && demo.attract) || M_GamestateCanOpenMenu() == false) From d44c2f5c58c273a800fe9fdfc3403bdb54cab372 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 7 Mar 2024 16:35:18 -0800 Subject: [PATCH 17/40] Add back F3 key to toggle HUD --- src/k_menufunc.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/k_menufunc.c b/src/k_menufunc.c index de474ae23..17353ce2a 100644 --- a/src/k_menufunc.c +++ b/src/k_menufunc.c @@ -275,12 +275,23 @@ static boolean M_GamestateCanOpenMenu(void) // boolean M_Responder(event_t *ev) { - if (ev->type == ev_keydown && ev->data1 == KEY_F11 && !ev->data2) + if (ev->type == ev_keydown && !ev->data2) { - // F11 can always be used to toggle fullscreen, it's - // a safe key. - CV_AddValue(&cv_fullscreen, 1); - return true; + extern consvar_t cv_showhud; + switch (ev->data1) + { + case KEY_F3: // Toggle HUD + // I am lazy so this button is also + // hardcoded. + CV_SetValue(&cv_showhud, !cv_showhud.value); + return true; + + case KEY_F11: // Fullscreen + // F11 can always be used to toggle + // fullscreen, it's a safe key. + CV_AddValue(&cv_fullscreen, 1); + return true; + } } if (dedicated From f29dce316107e52c6923235f581b9e34f9d5ae94 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Thu, 7 Mar 2024 19:16:02 -0700 Subject: [PATCH 18/40] Options: tyop fixes --- src/menus/options-server-1.c | 2 +- src/menus/options-server-advanced.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/menus/options-server-1.c b/src/menus/options-server-1.c index 507e304bd..7feab84b2 100644 --- a/src/menus/options-server-1.c +++ b/src/menus/options-server-1.c @@ -67,7 +67,7 @@ menuitem_t OPTIONS_Server[] = {IT_STRING | IT_CVAR, "Mute Chat", "Prevent everyone but admins from sending chat messages.", NULL, {.cvar = &cv_mute}, 0, 0}, - {IT_STRING | IT_CVAR, "Chat Spam Protection", "Prevent too many message from a single player.", + {IT_STRING | IT_CVAR, "Chat Spam Protection", "Prevent too many messages from a single player.", NULL, {.cvar = &cv_chatspamprotection}, 0, 0}, {IT_SPACE | IT_DYBIGSPACE, NULL, NULL, diff --git a/src/menus/options-server-advanced.c b/src/menus/options-server-advanced.c index 35da6a003..6c9a04a52 100644 --- a/src/menus/options-server-advanced.c +++ b/src/menus/options-server-advanced.c @@ -28,7 +28,7 @@ menuitem_t OPTIONS_ServerAdvanced[] = {IT_STRING | IT_CVAR, "Ping Timeout (s)", "Players must be above the ping limit for this long before being kicked.", NULL, {.cvar = &cv_pingtimeout}, 0, 0}, - {IT_STRING | IT_CVAR, "Connection Timeout (tics)", "Players not giving any netowrk activity for this long are kicked.", + {IT_STRING | IT_CVAR, "Connection Timeout (tics)", "Players not giving any network activity for this long are kicked.", NULL, {.cvar = &cv_nettimeout}, 0, 0}, {IT_STRING | IT_CVAR, "Join Timeout (tics)", "Players taking too long to join are kicked.", From 2492fa0013959e1719b52db371a10635f53ab1ff Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Thu, 7 Mar 2024 19:16:41 -0700 Subject: [PATCH 19/40] Save Legacy GL anisotropic filtering --- src/cvars.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cvars.cpp b/src/cvars.cpp index 798d9e1f8..417eefa08 100644 --- a/src/cvars.cpp +++ b/src/cvars.cpp @@ -1347,7 +1347,7 @@ consvar_t cv_mute = UnsavedNetVar("mute", "Off").on_off().onchange(Mute_OnChange extern CV_PossibleValue_t glanisotropicmode_cons_t[]; void CV_glanisotropic_OnChange(void); - consvar_t cv_glanisotropicmode = OpenGL("gr_anisotropicmode", "1").values(glanisotropicmode_cons_t).onchange(CV_glanisotropic_OnChange).dont_save(); + consvar_t cv_glanisotropicmode = OpenGL("gr_anisotropicmode", "1").values(glanisotropicmode_cons_t).onchange(CV_glanisotropic_OnChange); consvar_t cv_glbatching = OpenGL("gr_batching", "On").on_off().dont_save(); From 7391094ef2bbaae33b34cfe6fd22c5d7fd05da98 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Thu, 7 Mar 2024 19:55:33 -0700 Subject: [PATCH 20/40] Minor timeout/delaylimit presentation fixes --- src/cvars.cpp | 2 +- src/k_menufunc.c | 2 -- src/menus/options-server-advanced.c | 4 ++-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/cvars.cpp b/src/cvars.cpp index 417eefa08..46d27e5d8 100644 --- a/src/cvars.cpp +++ b/src/cvars.cpp @@ -531,7 +531,7 @@ consvar_t cv_masterserver_token = Server("masterserver_token", ""); void MasterClient_Ticker(void); consvar_t cv_masterserver_update_rate = Server("masterserver_update_rate", "15").min_max(2, 60).onchange_noinit(MasterClient_Ticker); -consvar_t cv_maxping = Server("maxdelay", "20").values(CV_Unsigned); +consvar_t cv_maxping = Server("maxdelay", "20").min_max(0, 30); consvar_t cv_menujam = Server("menujam", "menu").values({{0, "menu"}, {1, "menu2"}, {2, "menu3"}}); consvar_t cv_menujam_update = Server("menujam_update", "Off").on_off(); consvar_t cv_netdemosyncquality = Server("netdemo_syncquality", "1").min_max(1, 35); diff --git a/src/k_menufunc.c b/src/k_menufunc.c index 881b9b044..d402d7d9b 100644 --- a/src/k_menufunc.c +++ b/src/k_menufunc.c @@ -176,8 +176,6 @@ void M_ChangeCvarDirect(INT32 choice, consvar_t *cv) choice *= (TICRATE/7); else if (cv == &cv_maxsend) choice *= 512; - else if (cv == &cv_maxping) - choice *= 50; CV_AddValue(cv, choice); } diff --git a/src/menus/options-server-advanced.c b/src/menus/options-server-advanced.c index 6c9a04a52..7488e2d33 100644 --- a/src/menus/options-server-advanced.c +++ b/src/menus/options-server-advanced.c @@ -22,10 +22,10 @@ menuitem_t OPTIONS_ServerAdvanced[] = {IT_STRING | IT_CVAR, "Resynch. Attempts", "How many times to attempt sending data to desynchronized players.", NULL, {.cvar = &cv_resynchattempts}, 0, 0}, - {IT_STRING | IT_CVAR, "Ping Limit (ms)", "Players above the ping limit will get kicked from the server.", + {IT_STRING | IT_CVAR, "Delay Limit (tics)", "Players above the delay limit will get kicked from the server.", NULL, {.cvar = &cv_maxping}, 0, 0}, - {IT_STRING | IT_CVAR, "Ping Timeout (s)", "Players must be above the ping limit for this long before being kicked.", + {IT_STRING | IT_CVAR, "Delay Timeout (seconds)", "Players must be above the delay limit for this long before being kicked.", NULL, {.cvar = &cv_pingtimeout}, 0, 0}, {IT_STRING | IT_CVAR, "Connection Timeout (tics)", "Players not giving any network activity for this long are kicked.", From e7c8f7044a3c257bf4533753327ed6148ea2e093 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Thu, 7 Mar 2024 20:43:47 -0700 Subject: [PATCH 21/40] Cancel ballhog charge when hit --- src/k_kart.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/k_kart.c b/src/k_kart.c index 5cb6235c9..97a6bef56 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -9048,6 +9048,9 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->spinouttimer || player->tumbleBounces) { + if (player->ballhogcharge) + player->ballhogcharge = 0; + if (player->progressivethrust < MAXCOMBOTIME) player->progressivethrust++; if (player->incontrol > 0) From 9a2550469008e4e320c6367da12395084d238fc5 Mon Sep 17 00:00:00 2001 From: SteelT Date: Thu, 7 Mar 2024 22:37:39 -0500 Subject: [PATCH 22/40] Use button prompts on the connect screen Closes KartKrew/Kart#470 --- src/d_clisrv.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index dbc95e065..1beef9bd4 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -679,7 +679,7 @@ static inline void CL_DrawConnectionStatus(void) // Draw bottom box M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-24-8, 32, 1); - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-24, V_YELLOWMAP, "Press (B) to abort"); + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-24, V_YELLOWMAP, "Press \xAB or \xAD to abort"); for (i = 0; i < 16; ++i) V_DrawFill((BASEVIDWIDTH/2-128) + (i * 16), BASEVIDHEIGHT-24, 16, 8, palstart + ((animtime - i) & 15)); @@ -752,7 +752,7 @@ static inline void CL_DrawConnectionStatus(void) INT32 checkednum = 0; INT32 i; - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-24, V_YELLOWMAP, "Press (B) to abort"); + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-24, V_YELLOWMAP, "Press \xAB or \xAD to abort"); //ima just count files here for (i = 0; i < fileneedednum; i++) @@ -774,7 +774,7 @@ static inline void CL_DrawConnectionStatus(void) INT32 loadcompletednum = 0; INT32 i; - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-24, V_YELLOWMAP, "Press (B) to abort"); + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-24, V_YELLOWMAP, "Press \xAB or \xAD to abort"); //ima just count files here for (i = 0; i < fileneedednum; i++) @@ -801,7 +801,7 @@ static inline void CL_DrawConnectionStatus(void) // Draw the bottom box. M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-58-8, 32, 1); - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-58-14, V_YELLOWMAP, "Press (B) to abort"); + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-58-14, V_YELLOWMAP, "Press \xAB or \xAD to abort"); Net_GetNetStat(); dldlength = (INT32)((file->currentsize/(double)file->totalsize) * 256); @@ -867,7 +867,7 @@ static inline void CL_DrawConnectionStatus(void) //Draw bottom box M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-24-8, 32, 1); - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-24, V_YELLOWMAP, "Press (B) to abort"); + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-24, V_YELLOWMAP, "Press \xAB or \xAD to abort"); for (i = 0; i < 16; ++i) V_DrawFill((BASEVIDWIDTH/2-128) + (i * 16), BASEVIDHEIGHT-24, 16, 8, palstart + ((animtime - i) & 15)); @@ -5943,7 +5943,7 @@ static void SV_Maketic(void) for (i = 0; i < MAXPLAYERS; i++) { packetloss[i][maketic%PACKETMEASUREWINDOW] = false; - + if (!playeringame[i]) continue; From 123477dac978188dc2621cafbe3a5bf799565262 Mon Sep 17 00:00:00 2001 From: Eidolon Date: Thu, 7 Mar 2024 22:03:36 -0600 Subject: [PATCH 23/40] Add Sharp Bilinear mode, make default --- src/cvars.cpp | 2 +- src/hwr2/blit_rect.cpp | 41 ++++++++++++++++++++++++++++++++++++ src/hwr2/blit_rect.hpp | 1 + src/hwr2/hardware_state.hpp | 1 + src/i_video_common.cpp | 10 +++++++++ src/rhi/gl2/gl2_rhi.cpp | 28 ++++++++++++++++++++++++ src/rhi/gl2/gl2_rhi.hpp | 8 +++++++ src/rhi/rhi.cpp | 12 +++++++++++ src/rhi/rhi.hpp | 12 ++++++++++- src/sdl/rhi_gl2_platform.cpp | 2 ++ 10 files changed, 115 insertions(+), 2 deletions(-) diff --git a/src/cvars.cpp b/src/cvars.cpp index 594b04563..11a2b9378 100644 --- a/src/cvars.cpp +++ b/src/cvars.cpp @@ -430,7 +430,7 @@ consvar_t cv_scr_depth = Player("scr_depth", "16 bits").values({{8, "8 bits"}, { //added : 03-02-98: default screen mode, as loaded/saved in config consvar_t cv_scr_width = Player("scr_width", "640").values(CV_Unsigned); consvar_t cv_scr_height = Player("scr_height", "400").values(CV_Unsigned); -consvar_t cv_scr_effect = Player("scr_effect", "Nearest").values({{0, "Nearest"}, {1, "SalCRT"}}).save(); +consvar_t cv_scr_effect = Player("scr_effect", "Sharp Bilinear").values({{0, "Nearest"}, {1, "Sharp Bilinear"}, {2, "SalCRT"}}).save(); consvar_t cv_scr_scale = Player("scr_scale", "1.0").floating_point(); consvar_t cv_scr_x = Player("scr_x", "0.0").floating_point(); diff --git a/src/hwr2/blit_rect.cpp b/src/hwr2/blit_rect.cpp index 772e8a90e..41290604c 100644 --- a/src/hwr2/blit_rect.cpp +++ b/src/hwr2/blit_rect.cpp @@ -51,6 +51,20 @@ static const PipelineDesc kUnshadedPipelineDescription = { FaceWinding::kCounterClockwise, {0.f, 0.f, 0.f, 1.f}}; +/// @brief Pipeline used for sharp bilinear special blit. +static const PipelineDesc kSharpBilinearPipelineDescription = { + PipelineProgram::kSharpBilinear, + {{{sizeof(BlitVertex)}}, {{VertexAttributeName::kPosition, 0, 0}, {VertexAttributeName::kTexCoord0, 0, 12}}}, + {{{UniformName::kProjection}, {{UniformName::kModelView, UniformName::kTexCoord0Transform, UniformName::kSampler0Size}}}}, + {{// RGB/A texture + SamplerName::kSampler0}}, + std::nullopt, + {std::nullopt, {true, true, true, true}}, + PrimitiveType::kTriangles, + CullMode::kNone, + FaceWinding::kCounterClockwise, + {0.f, 0.f, 0.f, 1.f}}; + /// @brief Pipeline used for CRT special blit static const PipelineDesc kCrtPipelineDescription = { PipelineProgram::kCrt, @@ -85,6 +99,9 @@ void BlitRectPass::prepass(Rhi& rhi) case BlitRectPass::BlitMode::kNearest: pipeline_ = rhi.create_pipeline(kUnshadedPipelineDescription); break; + case BlitRectPass::BlitMode::kSharpBilinear: + pipeline_ = rhi.create_pipeline(kSharpBilinearPipelineDescription); + break; case BlitRectPass::BlitMode::kCrt: pipeline_ = rhi.create_pipeline(kCrtPipelineDescription); break; @@ -243,6 +260,30 @@ void BlitRectPass::transfer(Rhi& rhi, Handle ctx) binding_set_ = rhi.create_binding_set(ctx, pipeline_, {vbs, tbs}); break; } + case BlitRectPass::BlitMode::kSharpBilinear: + { + std::array g2_uniforms = { + // ModelView + glm::scale( + glm::identity(), + glm::vec3(taller ? 2.f : 2.f * aspect, taller ? 2.f * (1.f / aspect) : 2.f, 1.f) + ), + // Texcoord0 Transform + glm::mat3( + glm::vec3(1.f, 0.f, 0.f), + glm::vec3(0.f, output_flip_ ? -1.f : 1.f, 0.f), + glm::vec3(0.f, output_flip_ ? 1.f : 0.f, 1.f) + ), + // Sampler0 size + glm::vec2(texture_details.width, texture_details.height) + }; + uniform_sets_[1] = rhi.create_uniform_set(ctx, {g2_uniforms}); + + std::array vbs = {{{0, quad_vbo_}}}; + std::array tbs = {{{rhi::SamplerName::kSampler0, texture_}}}; + binding_set_ = rhi.create_binding_set(ctx, pipeline_, {vbs, tbs}); + break; + } default: { std::array g2_uniforms = { diff --git a/src/hwr2/blit_rect.hpp b/src/hwr2/blit_rect.hpp index 3aff33261..ba256e6ee 100644 --- a/src/hwr2/blit_rect.hpp +++ b/src/hwr2/blit_rect.hpp @@ -25,6 +25,7 @@ public: enum class BlitMode { kNearest, + kSharpBilinear, kCrt, }; diff --git a/src/hwr2/hardware_state.hpp b/src/hwr2/hardware_state.hpp index d32f54d4f..fa8871f0e 100644 --- a/src/hwr2/hardware_state.hpp +++ b/src/hwr2/hardware_state.hpp @@ -38,6 +38,7 @@ struct HardwareState std::unique_ptr blit_postimg_screens; std::unique_ptr wipe; std::unique_ptr blit_rect; + std::unique_ptr sharp_bilinear_blit_rect; std::unique_ptr crt_blit_rect; std::unique_ptr screen_capture; std::unique_ptr backbuffer; diff --git a/src/i_video_common.cpp b/src/i_video_common.cpp index 5f02430eb..5ed0cb7aa 100644 --- a/src/i_video_common.cpp +++ b/src/i_video_common.cpp @@ -83,6 +83,7 @@ static void reset_hardware_state(Rhi* rhi) g_hw_state.blit_postimg_screens = std::make_unique(g_hw_state.palette_manager.get()); g_hw_state.wipe = std::make_unique(); g_hw_state.blit_rect = std::make_unique(BlitRectPass::BlitMode::kNearest); + g_hw_state.sharp_bilinear_blit_rect = std::make_unique(BlitRectPass::BlitMode::kSharpBilinear); g_hw_state.crt_blit_rect = std::make_unique(BlitRectPass::BlitMode::kCrt); g_hw_state.screen_capture = std::make_unique(); g_hw_state.backbuffer = std::make_unique(); @@ -295,22 +296,31 @@ void I_FinishUpdate(void) float y = (vid.realheight - h) * (0.5f + (FixedToFloat(cv_scr_y.value) * 0.5f)); g_hw_state.blit_rect->set_output(x, y, w, h, true, true); + g_hw_state.sharp_bilinear_blit_rect->set_output(x, y, w, h, true, true); g_hw_state.crt_blit_rect->set_output(x, y, w, h, true, true); } else { g_hw_state.blit_rect->set_output(0, 0, vid.realwidth, vid.realheight, true, true); + g_hw_state.sharp_bilinear_blit_rect->set_output(0, 0, vid.realwidth, vid.realheight, true, true); g_hw_state.crt_blit_rect->set_output(0, 0, vid.realwidth, vid.realheight, true, true); } g_hw_state.blit_rect->set_texture(g_hw_state.backbuffer->color(), static_cast(vid.width), static_cast(vid.height)); + g_hw_state.sharp_bilinear_blit_rect->set_texture(g_hw_state.backbuffer->color(), static_cast(vid.width), static_cast(vid.height)); g_hw_state.crt_blit_rect->set_texture(g_hw_state.backbuffer->color(), static_cast(vid.width), static_cast(vid.height)); switch (cv_scr_effect.value) { case 1: + rhi->update_texture_settings(ctx, g_hw_state.backbuffer->color(), TextureWrapMode::kClamp, TextureWrapMode::kClamp, TextureFilterMode::kLinear, TextureFilterMode::kLinear); + g_hw_state.sharp_bilinear_blit_rect->draw(*rhi, ctx); + break; + case 2: + rhi->update_texture_settings(ctx, g_hw_state.backbuffer->color(), TextureWrapMode::kClamp, TextureWrapMode::kClamp, TextureFilterMode::kNearest, TextureFilterMode::kNearest); g_hw_state.crt_blit_rect->draw(*rhi, ctx); break; default: + rhi->update_texture_settings(ctx, g_hw_state.backbuffer->color(), TextureWrapMode::kClamp, TextureWrapMode::kClamp, TextureFilterMode::kNearest, TextureFilterMode::kNearest); g_hw_state.blit_rect->draw(*rhi, ctx); break; } diff --git a/src/rhi/gl2/gl2_rhi.cpp b/src/rhi/gl2/gl2_rhi.cpp index 6568c422f..b73da22a9 100644 --- a/src/rhi/gl2/gl2_rhi.cpp +++ b/src/rhi/gl2/gl2_rhi.cpp @@ -685,6 +685,34 @@ void Gl2Rhi::update_texture( GL_ASSERT; } +void Gl2Rhi::update_texture_settings( + Handle ctx, + Handle texture, + TextureWrapMode u_wrap, + TextureWrapMode v_wrap, + TextureFilterMode min, + TextureFilterMode mag +) +{ + SRB2_ASSERT(graphics_context_active_ == true); + + SRB2_ASSERT(texture_slab_.is_valid(texture) == true); + auto& t = texture_slab_[texture]; + + gl_->ActiveTexture(GL_TEXTURE0); + GL_ASSERT; + gl_->BindTexture(GL_TEXTURE_2D, t.texture); + GL_ASSERT; + gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, map_texture_wrap(u_wrap)); + GL_ASSERT; + gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, map_texture_wrap(v_wrap)); + GL_ASSERT; + gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, map_texture_filter(min)); + GL_ASSERT; + gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, map_texture_filter(mag)); + GL_ASSERT; +} + rhi::Handle Gl2Rhi::create_buffer(const rhi::BufferDesc& desc) { GLenum target = map_buffer_type(desc.type); diff --git a/src/rhi/gl2/gl2_rhi.hpp b/src/rhi/gl2/gl2_rhi.hpp index f530d49d9..5dc54cc7a 100644 --- a/src/rhi/gl2/gl2_rhi.hpp +++ b/src/rhi/gl2/gl2_rhi.hpp @@ -198,6 +198,14 @@ public: srb2::rhi::PixelFormat data_format, tcb::span data ) override; + virtual void update_texture_settings( + Handle ctx, + Handle texture, + TextureWrapMode u_wrap, + TextureWrapMode v_wrap, + TextureFilterMode min, + TextureFilterMode mag + ) override; virtual Handle create_uniform_set(Handle ctx, const CreateUniformSetInfo& info) override; virtual Handle diff --git a/src/rhi/rhi.cpp b/src/rhi/rhi.cpp index 7e9cb725a..6813122bb 100644 --- a/src/rhi/rhi.cpp +++ b/src/rhi/rhi.cpp @@ -67,6 +67,16 @@ const ProgramRequirements srb2::rhi::kProgramRequirementsPostimg = { ProgramSamplerRequirements {{{SamplerName::kSampler0, true}, {SamplerName::kSampler1, false}}} }; +const ProgramRequirements srb2::rhi::kProgramRequirementsSharpBilinear = { + ProgramVertexInputRequirements { + {ProgramVertexInput {VertexAttributeName::kPosition, VertexAttributeFormat::kFloat3, true}, + ProgramVertexInput {VertexAttributeName::kTexCoord0, VertexAttributeFormat::kFloat2, false}, + ProgramVertexInput {VertexAttributeName::kColor, VertexAttributeFormat::kFloat4, false}}}, + ProgramUniformRequirements { + {{{{UniformName::kProjection, true}}}, + {{{UniformName::kModelView, true}, {UniformName::kTexCoord0Transform, true}, {UniformName::kSampler0Size, true}}}}}, + ProgramSamplerRequirements {{{SamplerName::kSampler0, true}}}}; + const ProgramRequirements srb2::rhi::kProgramRequirementsCrt = { ProgramVertexInputRequirements { {ProgramVertexInput {VertexAttributeName::kPosition, VertexAttributeFormat::kFloat3, true}, @@ -89,6 +99,8 @@ const ProgramRequirements& rhi::program_requirements_for_program(PipelineProgram return kProgramRequirementsPostprocessWipe; case PipelineProgram::kPostimg: return kProgramRequirementsPostimg; + case PipelineProgram::kSharpBilinear: + return kProgramRequirementsSharpBilinear; case PipelineProgram::kCrt: return kProgramRequirementsCrt; default: diff --git a/src/rhi/rhi.hpp b/src/rhi/rhi.hpp index 27142e3ed..2b42a6cca 100644 --- a/src/rhi/rhi.hpp +++ b/src/rhi/rhi.hpp @@ -173,6 +173,7 @@ enum class PipelineProgram kUnshadedPaletted, kPostprocessWipe, kPostimg, + kSharpBilinear, kCrt }; @@ -286,6 +287,7 @@ extern const ProgramRequirements kProgramRequirementsUnshaded; extern const ProgramRequirements kProgramRequirementsUnshadedPaletted; extern const ProgramRequirements kProgramRequirementsPostprocessWipe; extern const ProgramRequirements kProgramRequirementsPostimg; +extern const ProgramRequirements kProgramRequirementsSharpBilinear; extern const ProgramRequirements kProgramRequirementsCrt; const ProgramRequirements& program_requirements_for_program(PipelineProgram program) noexcept; @@ -495,8 +497,8 @@ struct TextureDesc uint32_t height; TextureWrapMode u_wrap; TextureWrapMode v_wrap; - TextureFilterMode mag; TextureFilterMode min; + TextureFilterMode mag; }; struct BufferDesc @@ -628,6 +630,14 @@ struct Rhi srb2::rhi::PixelFormat data_format, tcb::span data ) = 0; + virtual void update_texture_settings( + Handle ctx, + Handle texture, + TextureWrapMode u_wrap, + TextureWrapMode v_wrap, + TextureFilterMode min, + TextureFilterMode mag + ) = 0; virtual Handle create_uniform_set(Handle ctx, const CreateUniformSetInfo& info) = 0; virtual Handle create_binding_set(Handle ctx, Handle pipeline, const CreateBindingSetInfo& info) = 0; diff --git a/src/sdl/rhi_gl2_platform.cpp b/src/sdl/rhi_gl2_platform.cpp index 03833dd7f..47e6203ff 100644 --- a/src/sdl/rhi_gl2_platform.cpp +++ b/src/sdl/rhi_gl2_platform.cpp @@ -44,6 +44,8 @@ static constexpr const char* pipeline_lump_slug(rhi::PipelineProgram program) return "postprocesswipe"; case rhi::PipelineProgram::kPostimg: return "postimg"; + case rhi::PipelineProgram::kSharpBilinear: + return "sharpbilinear"; case rhi::PipelineProgram::kCrt: return "crt"; default: From 2e0fb999b380f741e770234f43d545283984c7d1 Mon Sep 17 00:00:00 2001 From: Eidolon Date: Thu, 7 Mar 2024 23:25:47 -0600 Subject: [PATCH 24/40] Use bilinear filtering for CRT shader --- src/i_video_common.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i_video_common.cpp b/src/i_video_common.cpp index 5ed0cb7aa..f357fb178 100644 --- a/src/i_video_common.cpp +++ b/src/i_video_common.cpp @@ -316,7 +316,7 @@ void I_FinishUpdate(void) g_hw_state.sharp_bilinear_blit_rect->draw(*rhi, ctx); break; case 2: - rhi->update_texture_settings(ctx, g_hw_state.backbuffer->color(), TextureWrapMode::kClamp, TextureWrapMode::kClamp, TextureFilterMode::kNearest, TextureFilterMode::kNearest); + rhi->update_texture_settings(ctx, g_hw_state.backbuffer->color(), TextureWrapMode::kClamp, TextureWrapMode::kClamp, TextureFilterMode::kLinear, TextureFilterMode::kLinear); g_hw_state.crt_blit_rect->draw(*rhi, ctx); break; default: From 9eeb583670c5a87bf66884e020ce004953c3df30 Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 8 Mar 2024 00:24:41 -0800 Subject: [PATCH 25/40] Menus: fix multi-line message box text not fitting in the box --- src/k_menudraw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_menudraw.c b/src/k_menudraw.c index 666add657..9099279e8 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -918,7 +918,7 @@ void M_DrawMenuMessage(void) } V_DrawString((BASEVIDWIDTH - V_StringWidth(string, 0))/2, y, 0, string); - y += 9; + y += 8; } } From 7305afa5ea94dffcdd5e71eb0533c59cb4fc8f3e Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 8 Mar 2024 04:52:03 -0800 Subject: [PATCH 26/40] D_ProcessEvents: fix old input events repeating themselves when pressing Y button in Time Attack --- src/d_main.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index 9d1b25edb..3eafa8c67 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -272,9 +272,19 @@ void D_ProcessEvents(boolean callresponders) boolean eaten; G_ResetAllDeviceResponding(); - for (; eventtail != eventhead; eventtail = (eventtail+1) & (MAXEVENTS-1)) + + // Save these in local variables because eventtail != + // eventhead was evaluating true when they were equal, + // but only when using the Y button to restart a Time + // Attack?? + INT32 tail = eventtail; + INT32 head = eventhead; + + eventtail = eventhead; + + for (; tail != head; tail = (tail+1) & (MAXEVENTS-1)) { - ev = &events[eventtail]; + ev = &events[tail]; HandleGamepadDeviceEvents(ev); From 36a1fd15f3012134f13ee4208678e63207dc695c Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 8 Mar 2024 08:19:07 -0800 Subject: [PATCH 27/40] Audience: scale jump height to map scale, not audience scale --- src/objects/audience.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/objects/audience.c b/src/objects/audience.c index b5814ae16..9558dfe9f 100644 --- a/src/objects/audience.c +++ b/src/objects/audience.c @@ -123,11 +123,11 @@ Obj_AudienceInit // The following is derived from the default bobamp if (mobj->type != MT_EMBLEM && !(mobj->flags & MF_NOGRAVITY) && followers[followerpick].bobamp < 4*FRACUNIT) { - audience_bobamp(mobj) = 4*mobj->scale; + audience_bobamp(mobj) = 4*mapobjectscale; } else { - audience_bobamp(mobj) = FixedMul(mobj->scale, followers[followerpick].bobamp); + audience_bobamp(mobj) = FixedMul(mapobjectscale, followers[followerpick].bobamp); } } From a06bfea4eb75967d8f01d7ace4d2674aa0edd69a Mon Sep 17 00:00:00 2001 From: Eidolon Date: Fri, 8 Mar 2024 14:26:46 -0600 Subject: [PATCH 28/40] Fix interpolation of ring debt indicator --- src/k_kart.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/k_kart.c b/src/k_kart.c index 97a6bef56..85c8978c8 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -8435,6 +8435,10 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) mobj_t *debtflag = P_SpawnMobj(player->mo->x + player->mo->momx, player->mo->y + player->mo->momy, player->mo->z + P_GetMobjZMovement(player->mo) + player->mo->height + (24*player->mo->scale), MT_THOK); + debtflag->old_x = player->mo->old_x; + debtflag->old_y = player->mo->old_y; + debtflag->old_z = player->mo->old_z + P_GetMobjZMovement(player->mo) + player->mo->height + (24*player->mo->scale); + P_SetMobjState(debtflag, S_RINGDEBT); P_SetScale(debtflag, (debtflag->destscale = player->mo->scale)); From 19418ff1a63b9d80632205c4d7788c4d4822dcd2 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 7 Mar 2024 00:23:12 -0800 Subject: [PATCH 29/40] Power-ups: play loud Gunstar pickup sound --- src/k_powerup.cpp | 2 +- src/sounds.c | 1 + src/sounds.h | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/k_powerup.cpp b/src/k_powerup.cpp index 8bc504cbc..e4827a230 100644 --- a/src/k_powerup.cpp +++ b/src/k_powerup.cpp @@ -54,7 +54,7 @@ void K_GivePowerUp(player_t* player, kartitems_t powerup, tic_t time) Obj_SpawnPowerUpAura(player); } - S_StartSound(NULL, sfx_gsha7); + S_StartSound(NULL, sfx_gsha7l); player->flashing = 2*TICRATE; K_AddHitLag(player->mo, BATTLE_POWERUP_VFX_TIME, false); player->powerupVFXTimer = BATTLE_POWERUP_VFX_TIME; diff --git a/src/sounds.c b/src/sounds.c index ffe57da83..d1e4a7f65 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -1420,6 +1420,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"gsha5", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"gsha6", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"gsha7", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"gsha7l",false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"gsha8", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"gsha9", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"gshaa", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, diff --git a/src/sounds.h b/src/sounds.h index 4a7c0bfc7..86f012c11 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -1496,6 +1496,7 @@ typedef enum sfx_gsha5, sfx_gsha6, sfx_gsha7, + sfx_gsha7l, sfx_gsha8, sfx_gsha9, sfx_gshaa, From f7d396d150b3f0ec5162a425adecdc33760c32be Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 7 Mar 2024 00:33:43 -0800 Subject: [PATCH 30/40] Power-ups: spawn spinning power-up icon on player - Spins for 40 tics, speeds up over duration - Starts wide stretched, ends thin and tall - Additive, fades into translucency --- src/deh_tables.c | 1 + src/info.c | 27 +++++++++++++ src/info.h | 1 + src/k_objects.h | 4 ++ src/k_powerup.cpp | 1 + src/objects/CMakeLists.txt | 1 + src/objects/powerup-spinner.cpp | 70 +++++++++++++++++++++++++++++++++ src/p_mobj.c | 5 +++ 8 files changed, 110 insertions(+) create mode 100644 src/objects/powerup-spinner.cpp diff --git a/src/deh_tables.c b/src/deh_tables.c index 5bd5700f9..513a50c46 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -3455,6 +3455,7 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t "MT_RANDOMITEM", "MT_SPHEREBOX", "MT_FLOATINGITEM", + "MT_GOTPOWERUP", "MT_ITEMCAPSULE", "MT_ITEMCAPSULE_PART", "MT_MONITOR", diff --git a/src/info.c b/src/info.c index 6aa10a510..d48a3debd 100644 --- a/src/info.c +++ b/src/info.c @@ -13188,6 +13188,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_GOTPOWERUP + -1, // doomednum + S_ITEMICON, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // 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_itpick, // deathsound + 0, // speed + 48*FRACUNIT, // radius + 64*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SCENERY|MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOSQUISH|MF_DONTENCOREMAP, // flags + S_NULL // raisestate + }, + { // MT_ITEMCAPSULE 2010, // doomednum S_ITEMCAPSULE, // spawnstate diff --git a/src/info.h b/src/info.h index 3b26cfefc..442581ac8 100644 --- a/src/info.h +++ b/src/info.h @@ -4475,6 +4475,7 @@ typedef enum mobj_type MT_RANDOMITEM, MT_SPHEREBOX, MT_FLOATINGITEM, + MT_GOTPOWERUP, MT_ITEMCAPSULE, MT_ITEMCAPSULE_PART, MT_MONITOR, diff --git a/src/k_objects.h b/src/k_objects.h index 93e6692d0..ee1a24290 100644 --- a/src/k_objects.h +++ b/src/k_objects.h @@ -398,6 +398,10 @@ void Obj_TalkPointInit(mobj_t* mo); void Obj_TalkPointThink(mobj_t* mo); void Obj_TalkPointOrbThink(mobj_t* mo); +/* Power-up Spinner */ +void Obj_SpawnPowerUpSpinner(mobj_t *source, INT32 powerup, tic_t duration); +void Obj_TickPowerUpSpinner(mobj_t *mobj); + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/k_powerup.cpp b/src/k_powerup.cpp index e4827a230..da40ca68f 100644 --- a/src/k_powerup.cpp +++ b/src/k_powerup.cpp @@ -58,6 +58,7 @@ void K_GivePowerUp(player_t* player, kartitems_t powerup, tic_t time) player->flashing = 2*TICRATE; K_AddHitLag(player->mo, BATTLE_POWERUP_VFX_TIME, false); player->powerupVFXTimer = BATTLE_POWERUP_VFX_TIME; + Obj_SpawnPowerUpSpinner(player->mo, powerup, BATTLE_POWERUP_VFX_TIME); g_darkness.start = leveltime; g_darkness.end = leveltime + BATTLE_POWERUP_VFX_TIME + DARKNESS_FADE_TIME; diff --git a/src/objects/CMakeLists.txt b/src/objects/CMakeLists.txt index fce16395a..0dde3da9f 100644 --- a/src/objects/CMakeLists.txt +++ b/src/objects/CMakeLists.txt @@ -54,6 +54,7 @@ target_sources(SRB2SDL2 PRIVATE waterfall-particle.c sealed-star.c talk-point.cpp + powerup-spinner.cpp ) add_subdirectory(versus) diff --git a/src/objects/powerup-spinner.cpp b/src/objects/powerup-spinner.cpp new file mode 100644 index 000000000..d709b1a0e --- /dev/null +++ b/src/objects/powerup-spinner.cpp @@ -0,0 +1,70 @@ +// DR. ROBOTNIK'S RING RACERS +//----------------------------------------------------------------------------- +// Copyright (C) 2024 by James Robert Roman +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- + +#include + +#include "objects.hpp" + +#include "../m_easing.h" +#include "../m_fixed.h" +#include "../tables.h" + +using namespace srb2::objects; + +namespace +{ + +struct Spinner : Mobj +{ + static constexpr int kDuration = 40; + + void extravalue1() = delete; + INT32 powerup() const { return mobj_t::extravalue1; } + void powerup(INT32 n) { mobj_t::extravalue1 = n; } + + void extravalue2() = delete; + INT32 duration() const { return mobj_t::extravalue2; } + void duration(INT32 n) { mobj_t::extravalue2 = n; } + + static void spawn(Mobj* source, INT32 powerup, tic_t duration) + { + Spinner* x = Mobj::spawn(source->pos(), MT_GOTPOWERUP); + K_UpdateMobjItemOverlay(x, powerup, 1); + x->frame |= FF_PAPERSPRITE | FF_ADD; + x->fuse = duration; + x->powerup(powerup); + x->duration(duration); + } + + void think() + { + fixed_t f = FRACUNIT - std::clamp(fuse, 0, duration()) * FRACUNIT / std::max(duration(), 1); + + angle += Easing_InQuad(f, ANGLE_11hh, ANGLE_45); + renderflags = (renderflags & ~RF_TRANSMASK) | (Easing_Linear(f, 0, 9) << RF_TRANSSHIFT); + spritescale({Easing_Linear(f, 4*FRACUNIT, FRACUNIT/4), Easing_Linear(f, FRACUNIT, 6*FRACUNIT)}); + + if (--fuse <= 0) + { + remove(); + } + } +}; + +}; // namespace + +void Obj_SpawnPowerUpSpinner(mobj_t *source, INT32 powerup, tic_t duration) +{ + Spinner::spawn(static_cast(source), powerup, duration); +} + +void Obj_TickPowerUpSpinner(mobj_t *mobj) +{ + static_cast(mobj)->think(); +} diff --git a/src/p_mobj.c b/src/p_mobj.c index 497275b93..488193e3a 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6596,6 +6596,11 @@ static void P_MobjSceneryThink(mobj_t *mobj) Obj_SSGobletMobjThink(mobj); return; } + case MT_GOTPOWERUP: + { + Obj_TickPowerUpSpinner(mobj); + return; + } default: if (mobj->fuse) { // Scenery object fuse! Very basic! From 549865ce2d17bc3fce00a2d5d50432a0d8563097 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 7 Mar 2024 00:35:02 -0800 Subject: [PATCH 31/40] Power-ups: delay voice clips by 10 tics --- src/k_powerup.cpp | 6 ------ src/objects/powerup-spinner.cpp | 27 +++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/k_powerup.cpp b/src/k_powerup.cpp index da40ca68f..9e8203c12 100644 --- a/src/k_powerup.cpp +++ b/src/k_powerup.cpp @@ -66,33 +66,28 @@ void K_GivePowerUp(player_t* player, kartitems_t powerup, tic_t time) switch (powerup) { case POWERUP_SMONITOR: - S_StartSound(NULL, sfx_bpwrua); K_AddMessageForPlayer(player, "Got S MONITOR!", true, false); K_DoInvincibility(player, player->invincibilitytimer + time); player->powerup.superTimer += time; break; case POWERUP_BARRIER: - S_StartSound(NULL, sfx_bpwrub); K_AddMessageForPlayer(player, "Got MEGA BARRIER!", true, false); player->powerup.barrierTimer += time; Obj_SpawnMegaBarrier(player); break; case POWERUP_BUMPER: - S_StartSound(NULL, sfx_bpwruc); K_AddMessageForPlayer(player, "Got BUMPER RESTOCK!", true, false); K_GiveBumpersToPlayer(player, nullptr, 5); break; case POWERUP_BADGE: - S_StartSound(NULL, sfx_bpwrud); K_AddMessageForPlayer(player, "Got RHYTHM BADGE!", true, false); player->powerup.rhythmBadgeTimer += time; break; case POWERUP_SUPERFLICKY: - S_StartSound(NULL, sfx_bpwrue); K_AddMessageForPlayer(player, "Got SUPER FLICKY!", true, false); if (K_PowerUpRemaining(player, POWERUP_SUPERFLICKY)) { @@ -105,7 +100,6 @@ void K_GivePowerUp(player_t* player, kartitems_t powerup, tic_t time) break; case POWERUP_POINTS: - S_StartSound(NULL, sfx_bpwruf); K_AddMessageForPlayer(player, "Got 6 POINTS!", true, false); K_GivePointsToPlayer(player, nullptr, 6); diff --git a/src/objects/powerup-spinner.cpp b/src/objects/powerup-spinner.cpp index d709b1a0e..248a95b69 100644 --- a/src/objects/powerup-spinner.cpp +++ b/src/objects/powerup-spinner.cpp @@ -46,6 +46,11 @@ struct Spinner : Mobj { fixed_t f = FRACUNIT - std::clamp(fuse, 0, duration()) * FRACUNIT / std::max(duration(), 1); + if (fuse == duration() - 20) + { + S_StartSound(nullptr, sound()); + } + angle += Easing_InQuad(f, ANGLE_11hh, ANGLE_45); renderflags = (renderflags & ~RF_TRANSMASK) | (Easing_Linear(f, 0, 9) << RF_TRANSSHIFT); spritescale({Easing_Linear(f, 4*FRACUNIT, FRACUNIT/4), Easing_Linear(f, FRACUNIT, 6*FRACUNIT)}); @@ -55,6 +60,28 @@ struct Spinner : Mobj remove(); } } + +private: + sfxenum_t sound() const + { + switch (powerup()) + { + case POWERUP_SMONITOR: + return sfx_bpwrua; + case POWERUP_BARRIER: + return sfx_bpwrub; + case POWERUP_BUMPER: + return sfx_bpwruc; + case POWERUP_BADGE: + return sfx_bpwrud; + case POWERUP_SUPERFLICKY: + return sfx_bpwrue; + case POWERUP_POINTS: + return sfx_bpwruf; + default: + return sfx_thok; + } + } }; }; // namespace From 0707c9e5ec07d775caa1a7a2d497a2be4bf6dc70 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 7 Mar 2024 00:37:06 -0800 Subject: [PATCH 32/40] Add g_musicfade, generic system to fade out the level music for a brief period --- src/doomstat.h | 6 ++++++ src/g_game.c | 1 + src/k_kart.c | 1 + src/p_saveg.c | 10 ++++++++++ src/p_tick.c | 17 +++++++++++++++++ src/typedef.h | 1 + 6 files changed, 36 insertions(+) diff --git a/src/doomstat.h b/src/doomstat.h index c74dda7ac..ce0782cd9 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -811,6 +811,12 @@ extern struct darkness_t fixed_t value[MAXSPLITSCREENPLAYERS]; } g_darkness; +extern struct musicfade_t +{ + tic_t start, end, fade; + boolean ticked; +} g_musicfade; + #define DEFAULT_GRAVITY (4*FRACUNIT/5) extern fixed_t gravity; extern fixed_t mapobjectscale; diff --git a/src/g_game.c b/src/g_game.c index 4a4d25f1a..5d181a536 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -279,6 +279,7 @@ tic_t racecountdown, exitcountdown, musiccountdown; // for racing exitcondition_t g_exit; darkness_t g_darkness; +musicfade_t g_musicfade; fixed_t gravity; fixed_t mapobjectscale; diff --git a/src/k_kart.c b/src/k_kart.c index 97a6bef56..d3f5f757a 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -118,6 +118,7 @@ void K_TimerReset(void) { starttime = introtime = 0; memset(&g_darkness, 0, sizeof g_darkness); + memset(&g_musicfade, 0, sizeof g_musicfade); numbulbs = 1; inDuel = rainbowstartavailable = false; linecrossed = 0; diff --git a/src/p_saveg.c b/src/p_saveg.c index b89ee4412..8a1956ba4 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -6567,6 +6567,11 @@ static void P_NetArchiveMisc(savebuffer_t *save, boolean resending) WRITEUINT32(save->p, g_darkness.start); WRITEUINT32(save->p, g_darkness.end); + WRITEUINT32(save->p, g_musicfade.start); + WRITEUINT32(save->p, g_musicfade.end); + WRITEUINT32(save->p, g_musicfade.fade); + WRITEUINT8(save->p, g_musicfade.ticked); + WRITEUINT16(save->p, numchallengedestructibles); // Is it paused? @@ -6753,6 +6758,11 @@ static boolean P_NetUnArchiveMisc(savebuffer_t *save, boolean reloading) g_darkness.start = READUINT32(save->p); g_darkness.end = READUINT32(save->p); + g_musicfade.start = READUINT32(save->p); + g_musicfade.end = READUINT32(save->p); + g_musicfade.fade = READUINT32(save->p); + g_musicfade.ticked = READUINT8(save->p); + numchallengedestructibles = READUINT16(save->p); // Is it paused? diff --git a/src/p_tick.c b/src/p_tick.c index 9f0b33da7..bc78f291a 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -808,6 +808,22 @@ static void P_TickDarkness(void) } } +static void P_TickMusicFade(void) +{ + if (leveltime >= g_musicfade.start && leveltime <= g_musicfade.end) + { + INT32 half = (g_musicfade.end - g_musicfade.start) / 2; + INT32 fade = max(1, g_musicfade.fade); + INT32 mid = half - fade; + INT32 t = abs((INT32)leveltime - (INT32)(g_musicfade.start + half)); + Music_LevelVolume((max(t, mid) - mid) * 100 / fade); + } + else if (!g_musicfade.ticked) + Music_LevelVolume(100); + + g_musicfade.ticked = true; +} + // // P_Ticker // @@ -1102,6 +1118,7 @@ void P_Ticker(boolean run) racecountdown--; P_TickDarkness(); + P_TickMusicFade(); if (exitcountdown >= 1) { diff --git a/src/typedef.h b/src/typedef.h index e866a22a9..ac9bbff5f 100644 --- a/src/typedef.h +++ b/src/typedef.h @@ -143,6 +143,7 @@ TYPEDEF (cupheader_t); TYPEDEF (unloaded_cupheader_t); TYPEDEF (exitcondition_t); TYPEDEF (darkness_t); +TYPEDEF (musicfade_t); // font.h TYPEDEF (font_t); From 215446f42ad0ca44124db5048b7ae8cd56329e30 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 7 Mar 2024 00:37:41 -0800 Subject: [PATCH 33/40] Power-ups: fade out level music while voice clip is playing --- src/k_powerup.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/k_powerup.cpp b/src/k_powerup.cpp index 9e8203c12..90cec3f4e 100644 --- a/src/k_powerup.cpp +++ b/src/k_powerup.cpp @@ -63,6 +63,11 @@ void K_GivePowerUp(player_t* player, kartitems_t powerup, tic_t time) g_darkness.start = leveltime; g_darkness.end = leveltime + BATTLE_POWERUP_VFX_TIME + DARKNESS_FADE_TIME; + g_musicfade.start = leveltime; + g_musicfade.end = g_musicfade.start + 90; + g_musicfade.fade = 20; + g_musicfade.ticked = false; + switch (powerup) { case POWERUP_SMONITOR: From e4f5e3c78e31c8e906ef906a6093231e02af0348 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 7 Mar 2024 02:25:33 -0800 Subject: [PATCH 34/40] P_CheckBumpers: do not end round with 1 player - Fixes round ending instantly when warping to Battle with 1 human player and at least 1 other bot loaded --- src/k_battle.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/k_battle.c b/src/k_battle.c index d08fcee2c..ffd370ee2 100644 --- a/src/k_battle.c +++ b/src/k_battle.c @@ -175,7 +175,8 @@ void K_CheckBumpers(void) { // If every other player is eliminated, the // last player standing wins by default. - K_EndBattleRound(kingofthehill != -1 ? &players[kingofthehill] : NULL); + if (numingame > 1) + K_EndBattleRound(kingofthehill != -1 ? &players[kingofthehill] : NULL); return; } From a7979e973e689fc846bd86a510790ce92d4cd5db Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 7 Mar 2024 02:27:19 -0800 Subject: [PATCH 35/40] Battle: cap lasers at player's last known floorz - Do not use camera_t.floorz - Fixes lasers bobbing up and down sometimes --- src/k_battle.c | 4 ++-- src/p_local.h | 4 ++++ src/p_user.c | 5 +++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/k_battle.c b/src/k_battle.c index ffd370ee2..5d284bb77 100644 --- a/src/k_battle.c +++ b/src/k_battle.c @@ -654,12 +654,12 @@ static void K_SpawnOvertimeLaser(fixed_t x, fixed_t y, fixed_t scale) if (player->mo->eflags & MFE_VERTICALFLIP) { zpos = cam->z + player->mo->height; - zpos = min(zpos + heightPadding, cam->ceilingz); + zpos = min(zpos + heightPadding, cam->centerceilingz); } else { zpos = cam->z; - zpos = max(zpos - heightPadding, cam->floorz); + zpos = max(zpos - heightPadding, cam->centerfloorz); } flip = P_MobjFlip(player->mo); diff --git a/src/p_local.h b/src/p_local.h index f36337615..c9e1860c1 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -112,6 +112,10 @@ struct camera_t fixed_t floorz; fixed_t ceilingz; + // From the player + fixed_t centerfloorz; + fixed_t centerceilingz; + // For movement checking. fixed_t radius; fixed_t height; diff --git a/src/p_user.c b/src/p_user.c index 1fdafd4aa..de8c4234e 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -3053,6 +3053,8 @@ void P_ResetCamera(player_t *player, camera_t *thiscam) thiscam->x = x; thiscam->y = y; thiscam->z = z; + thiscam->centerfloorz = player->mo->floorz; + thiscam->centerceilingz = player->mo->ceilingz; thiscam->angle = player->mo->angle; thiscam->aiming = 0; @@ -3570,6 +3572,9 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall R_ResetViewInterpolation(num + 1); } + thiscam->centerfloorz = mo->floorz; + thiscam->centerceilingz = mo->ceilingz; + return (x == thiscam->x && y == thiscam->y && z == thiscam->z && angle == thiscam->aiming); } From d35edcac9c6b5b37010c2be16de18fdc3905b6ef Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 7 Mar 2024 03:15:56 -0800 Subject: [PATCH 36/40] Invinc, Grow: fade with in-level music volume Fade S-Monitor music with voice clip --- src/music.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/music.cpp b/src/music.cpp index 953f20071..7205c2535 100644 --- a/src/music.cpp +++ b/src/music.cpp @@ -71,6 +71,7 @@ void Music_Init(void) tune.song = "kgrow"; tune.priority = 20; tune.resume_fade_in = 200; + tune.use_level_volume = true; } { @@ -78,6 +79,7 @@ void Music_Init(void) tune.song = "kinvnc"; tune.priority = 21; + tune.use_level_volume = true; } { From 79177f6aff46cf19c4884c1452f1ca695cc0ad9c Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 7 Mar 2024 07:22:13 -0800 Subject: [PATCH 37/40] Power-ups: fix HUD not sliding away on tally --- src/hud/powerup.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/hud/powerup.cpp b/src/hud/powerup.cpp index 5861791be..449236099 100644 --- a/src/hud/powerup.cpp +++ b/src/hud/powerup.cpp @@ -1,3 +1,12 @@ +// DR. ROBOTNIK'S RING RACERS +//----------------------------------------------------------------------------- +// Copyright (C) 2023-2024 by Kart Krew. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- + #include #include @@ -81,7 +90,7 @@ void K_drawKartPowerUps(void) { auto make_drawer = [](int x, int y, Draw::Font font) -> Draw { - return Draw(x, y).font(font).align(Draw::Align::kRight); + return Draw(x, y).font(font).align(Draw::Align::kRight).flags(V_SLIDEIN); }; const int viewnum = R_GetViewNumber(); From 80a65cd61ffe2679501925f5da9b109f6b18fc82 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 7 Mar 2024 07:44:32 -0800 Subject: [PATCH 38/40] Do not Guard-Break player in power-up collect animation --- src/k_kart.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index d3f5f757a..32c72b807 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1016,7 +1016,8 @@ boolean K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2) K_SpawnBumpForObjs(mobj1, mobj2); - if (mobj1->type == MT_PLAYER && mobj2->type == MT_PLAYER) + if (mobj1->type == MT_PLAYER && mobj2->type == MT_PLAYER + && !mobj1->player->powerupVFXTimer && !mobj2->player->powerupVFXTimer) { boolean guard1 = K_PlayerGuard(mobj1->player); boolean guard2 = K_PlayerGuard(mobj2->player); From 54240ac96b2c746405cc52d2888022f2d2ea1516 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 7 Mar 2024 07:46:26 -0800 Subject: [PATCH 39/40] Power-ups: always give player consistent hitlag on collect, even if they are near MAXHITLAGTICS --- src/k_powerup.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_powerup.cpp b/src/k_powerup.cpp index 90cec3f4e..b2f7c720e 100644 --- a/src/k_powerup.cpp +++ b/src/k_powerup.cpp @@ -56,7 +56,7 @@ void K_GivePowerUp(player_t* player, kartitems_t powerup, tic_t time) S_StartSound(NULL, sfx_gsha7l); player->flashing = 2*TICRATE; - K_AddHitLag(player->mo, BATTLE_POWERUP_VFX_TIME, false); + player->mo->hitlag += BATTLE_POWERUP_VFX_TIME; player->powerupVFXTimer = BATTLE_POWERUP_VFX_TIME; Obj_SpawnPowerUpSpinner(player->mo, powerup, BATTLE_POWERUP_VFX_TIME); From 6993f12dff9634bc35caa1562865c780159b8143 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 7 Mar 2024 00:40:24 -0800 Subject: [PATCH 40/40] Power-ups: dropped power-ups always have at least 15 seconds --- src/k_battle.h | 1 + src/k_powerup.cpp | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/k_battle.h b/src/k_battle.h index f1310e4d1..7806894e5 100644 --- a/src/k_battle.h +++ b/src/k_battle.h @@ -11,6 +11,7 @@ extern "C" { #define BATTLE_SPAWN_INTERVAL (4*TICRATE) #define BATTLE_DESPAWN_TIME (15*TICRATE) #define BATTLE_POWERUP_TIME (30*TICRATE) +#define BATTLE_POWERUP_DROPPED_TIME (15*TICRATE) #define BATTLE_UFO_TIME (20*TICRATE) extern struct battleovertime diff --git a/src/k_powerup.cpp b/src/k_powerup.cpp index b2f7c720e..5472eec34 100644 --- a/src/k_powerup.cpp +++ b/src/k_powerup.cpp @@ -2,6 +2,7 @@ #include +#include "k_battle.h" #include "k_kart.h" #include "k_objects.h" #include "k_powerup.h" @@ -127,7 +128,7 @@ void K_DropPowerUps(player_t* player) if (remaining) { - K_DropPaperItem(player, powerup, remaining); + K_DropPaperItem(player, powerup, std::max(remaining, BATTLE_POWERUP_DROPPED_TIME)); callback(); } };