mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-12-23 16:32:36 +00:00
Merge branch 'master' of https://git.do.srb2.org/KartKrew/Kart into spraycans
This commit is contained in:
commit
f7635c4399
54 changed files with 1006 additions and 600 deletions
|
|
@ -88,7 +88,7 @@ if(SRB2_CONFIG_ENABLE_TESTS)
|
|||
# https://github.com/catchorg/Catch2
|
||||
CPMAddPackage(
|
||||
NAME Catch2
|
||||
VERSION 3.1.1
|
||||
VERSION 3.4.0
|
||||
GITHUB_REPOSITORY catchorg/Catch2
|
||||
OPTIONS
|
||||
"CATCH_INSTALL_DOCS OFF"
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@
|
|||
#include "../k_podium.h"
|
||||
#include "../k_bot.h"
|
||||
#include "../z_zone.h"
|
||||
#include "../music.h"
|
||||
|
||||
#include "call-funcs.hpp"
|
||||
|
||||
|
|
@ -1802,6 +1803,7 @@ bool CallFunc_MapWarp(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Wor
|
|||
if (argV[1] == 0)
|
||||
skipstats = 1;
|
||||
|
||||
G_BeginLevelExit();
|
||||
exitcountdown = 1;
|
||||
|
||||
if (server)
|
||||
|
|
@ -1856,6 +1858,91 @@ bool CallFunc_AddBot(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word
|
|||
return false;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
bool CallFunc_StopLevelExit(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||
|
||||
Halts the level exit if it's happening.
|
||||
--------------------------------------------------*/
|
||||
bool CallFunc_StopLevelExit(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||
{
|
||||
(void)argV;
|
||||
(void)argC;
|
||||
|
||||
exitcountdown = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
bool CallFunc_ExitLevel(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||
|
||||
Exits the level.
|
||||
--------------------------------------------------*/
|
||||
bool CallFunc_ExitLevel(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||
{
|
||||
(void)argV;
|
||||
(void)argC;
|
||||
|
||||
if (exitcountdown == 1)
|
||||
{
|
||||
// An exit is already in progress.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (argC >= 1)
|
||||
{
|
||||
skipstats = (argV[0] == 0);
|
||||
}
|
||||
|
||||
G_BeginLevelExit();
|
||||
exitcountdown = 1;
|
||||
|
||||
if (server)
|
||||
SendNetXCmd(XD_EXITLEVEL, NULL, 0);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
bool CallFunc_MusicPlay(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||
|
||||
Play a tune. If it's already playing, restart from the
|
||||
beginning.
|
||||
--------------------------------------------------*/
|
||||
bool CallFunc_MusicPlay(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||
{
|
||||
ACSVM::MapScope *map = thread->scopeMap;
|
||||
|
||||
Music_Play(map->getString(argV[0])->str);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
bool CallFunc_MusicStopAll(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||
|
||||
Stop every tune that is currently playing.
|
||||
--------------------------------------------------*/
|
||||
bool CallFunc_MusicStopAll(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||
{
|
||||
Music_StopAll();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
bool CallFunc_MusicRemap(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||
|
||||
Change the actual song lump that a tune will play.
|
||||
--------------------------------------------------*/
|
||||
bool CallFunc_MusicRemap(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||
{
|
||||
ACSVM::MapScope *map = thread->scopeMap;
|
||||
|
||||
Music_Remap(map->getString(argV[0])->str, map->getString(argV[1])->str);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
bool CallFunc_Get/SetLineProperty(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||
|
||||
|
|
|
|||
|
|
@ -87,6 +87,11 @@ bool CallFunc_SetLineRenderStyle(ACSVM::Thread *thread, const ACSVM::Word *argV,
|
|||
|
||||
bool CallFunc_MapWarp(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
||||
bool CallFunc_AddBot(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
||||
bool CallFunc_StopLevelExit(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
||||
bool CallFunc_ExitLevel(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
||||
bool CallFunc_MusicPlay(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
||||
bool CallFunc_MusicStopAll(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
||||
bool CallFunc_MusicRemap(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
||||
|
||||
bool CallFunc_GetLineProperty(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
||||
bool CallFunc_SetLineProperty(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
||||
|
|
|
|||
|
|
@ -171,6 +171,11 @@ Environment::Environment()
|
|||
addFuncDataACS0( 503, addCallFunc(CallFunc_SetLineRenderStyle));
|
||||
addFuncDataACS0( 504, addCallFunc(CallFunc_MapWarp));
|
||||
addFuncDataACS0( 505, addCallFunc(CallFunc_AddBot));
|
||||
addFuncDataACS0( 506, addCallFunc(CallFunc_StopLevelExit));
|
||||
addFuncDataACS0( 507, addCallFunc(CallFunc_ExitLevel));
|
||||
addFuncDataACS0( 508, addCallFunc(CallFunc_MusicPlay));
|
||||
addFuncDataACS0( 509, addCallFunc(CallFunc_MusicStopAll));
|
||||
addFuncDataACS0( 510, addCallFunc(CallFunc_MusicRemap));
|
||||
}
|
||||
|
||||
ACSVM::Thread *Environment::allocThread()
|
||||
|
|
|
|||
|
|
@ -315,6 +315,22 @@ void ACS_RunEmeraldScript(mobj_t *mo)
|
|||
map->scriptStartType(ACS_ST_EMERALD, scriptInfo);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void ACS_RunGameOverScript(void)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
void ACS_RunGameOverScript(void)
|
||||
{
|
||||
Environment *env = &ACSEnv;
|
||||
|
||||
ACSVM::GlobalScope *const global = env->getGlobalScope(0);
|
||||
ACSVM::HubScope *const hub = global->getHubScope(0);
|
||||
ACSVM::MapScope *const map = hub->getMapScope(0);
|
||||
|
||||
map->scriptStartType(ACS_ST_GAMEOVER, {});
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void ACS_Tick(void)
|
||||
|
||||
|
|
|
|||
|
|
@ -179,6 +179,17 @@ void ACS_RunCatcherScript(mobj_t *mo);
|
|||
void ACS_RunEmeraldScript(mobj_t *mo);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
void ACS_RunGameOverScript(void);
|
||||
|
||||
Runs the map's special scripts for exiting
|
||||
the level, due to a losing condition and
|
||||
without any extra lives to retry.
|
||||
--------------------------------------------------*/
|
||||
|
||||
void ACS_RunGameOverScript(void);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
void ACS_Tick(void);
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ enum acs_scriptType_e
|
|||
ACS_ST_OVERTIME = 7, // OVERTIME: Runs when Overtime starts in timed game modes.
|
||||
ACS_ST_UFO = 8, // UFO: Runs when the UFO Catcher is destroyed in a Special Stage.
|
||||
ACS_ST_EMERALD = 9, // EMERALD: Runs when the Chaos Emerald is collected in a Special Stage.
|
||||
ACS_ST_GAMEOVER = 10, // GAMEOVER: Runs when the level ends due to a losing condition and no player has an extra life.
|
||||
};
|
||||
|
||||
//
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
* Last updated 2020 / 08 / 30 - Kart v1.3 - patch.kart
|
||||
*/
|
||||
|
||||
#define ASSET_HASH_MAIN_KART "00000000000000000000000000000000"
|
||||
#define ASSET_HASH_BIOS_PK3 "00000000000000000000000000000000"
|
||||
#define ASSET_HASH_GFX_PK3 "00000000000000000000000000000000"
|
||||
#define ASSET_HASH_TEXTURES_GENERAL_PK3 "00000000000000000000000000000000"
|
||||
#define ASSET_HASH_TEXTURES_SEGA_PK3 "00000000000000000000000000000000"
|
||||
|
|
|
|||
|
|
@ -561,6 +561,21 @@ void D_ResetTiccmds(void)
|
|||
D_Clearticcmd(textcmds[i]->tic);
|
||||
}
|
||||
|
||||
void D_ResetTiccmdAngle(UINT8 ss, angle_t angle)
|
||||
{
|
||||
INT32 i;
|
||||
|
||||
for (i = 0; i < MAXGENTLEMENDELAY; ++i)
|
||||
{
|
||||
localcmds[ss][i].angle = angle >> TICCMD_REDUCE;
|
||||
}
|
||||
}
|
||||
|
||||
ticcmd_t *D_LocalTiccmd(UINT8 ss)
|
||||
{
|
||||
return &localcmds[ss][0];
|
||||
}
|
||||
|
||||
void SendKick(UINT8 playernum, UINT8 msg)
|
||||
{
|
||||
UINT8 buf[2];
|
||||
|
|
|
|||
|
|
@ -615,7 +615,10 @@ extern UINT8 playerconsole[MAXPLAYERS];
|
|||
|
||||
INT32 D_NumPlayers(void);
|
||||
boolean D_IsPlayerHumanAndGaming(INT32 player_number);
|
||||
|
||||
void D_ResetTiccmds(void);
|
||||
void D_ResetTiccmdAngle(UINT8 ss, angle_t angle);
|
||||
ticcmd_t *D_LocalTiccmd(UINT8 ss);
|
||||
|
||||
tic_t GetLag(INT32 node);
|
||||
UINT8 GetFreeXCmdSize(UINT8 playerid);
|
||||
|
|
|
|||
11
src/d_main.c
11
src/d_main.c
|
|
@ -886,11 +886,14 @@ void D_SRB2Loop(void)
|
|||
{
|
||||
rendertimefrac = FRACUNIT;
|
||||
}
|
||||
|
||||
rendertimefrac_unpaused = g_time.timefrac;
|
||||
}
|
||||
else
|
||||
{
|
||||
renderdeltatics = realtics * FRACUNIT;
|
||||
rendertimefrac = FRACUNIT;
|
||||
rendertimefrac_unpaused = FRACUNIT;
|
||||
}
|
||||
|
||||
if (interp || doDisplay)
|
||||
|
|
@ -1096,7 +1099,7 @@ static void ChangeDirForUrlHandler(void)
|
|||
|
||||
static boolean AddIWAD(void)
|
||||
{
|
||||
char * path = va(pandf,srb2path,"main.kart");
|
||||
char * path = va(pandf,srb2path,"bios.pk3");
|
||||
|
||||
if (FIL_ReadFileOK(path))
|
||||
{
|
||||
|
|
@ -1114,7 +1117,7 @@ static void IdentifyVersion(void)
|
|||
const char *srb2waddir = NULL;
|
||||
|
||||
#if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL)
|
||||
// change to the directory where 'main.kart' is found
|
||||
// change to the directory where 'bios.pk3' is found
|
||||
srb2waddir = I_LocateWad();
|
||||
#endif
|
||||
|
||||
|
|
@ -1134,7 +1137,7 @@ static void IdentifyVersion(void)
|
|||
// Load the IWAD
|
||||
if (! AddIWAD())
|
||||
{
|
||||
I_Error("MAIN.KART not found! Expected in %s\n", srb2waddir);
|
||||
I_Error("\"bios.pk3\" not found! Expected in %s\n", srb2waddir);
|
||||
}
|
||||
|
||||
// will be overwritten in case of -cdrom or unix/win home
|
||||
|
|
@ -1478,7 +1481,7 @@ void D_SRB2Main(void)
|
|||
#endif
|
||||
// Check MD5s of autoloaded files
|
||||
// Note: Do not add any files that ignore MD5!
|
||||
W_VerifyFileMD5(mainwads, ASSET_HASH_MAIN_KART); // main.kart
|
||||
W_VerifyFileMD5(mainwads, ASSET_HASH_BIOS_PK3); // bios.pk3
|
||||
mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_GFX_PK3); // gfx.pk3
|
||||
mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_TEXTURES_GENERAL_PK3); // textures_general.pk3
|
||||
mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_TEXTURES_SEGA_PK3); // textures_segazones.pk3
|
||||
|
|
|
|||
|
|
@ -3690,11 +3690,14 @@ static void Command_Pause(void)
|
|||
CONS_Printf(M_GetText("You can't pause here.\n"));
|
||||
return;
|
||||
}
|
||||
// TODO: this would make a great debug feature for release
|
||||
#ifndef DEVELOP
|
||||
else if (modeattacking) // in time attack, pausing restarts the map
|
||||
{
|
||||
//M_ModeAttackRetry(0); // directly call from m_menu;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
SendNetXCmd(XD_PAUSE, &buf, 2);
|
||||
}
|
||||
|
|
@ -3715,8 +3718,11 @@ static void Got_Pause(UINT8 **cp, INT32 playernum)
|
|||
return;
|
||||
}
|
||||
|
||||
// TODO: this would make a great debug feature for release
|
||||
#ifndef DEVELOP
|
||||
if (modeattacking && !demo.playback)
|
||||
return;
|
||||
#endif
|
||||
|
||||
paused = READUINT8(*cp);
|
||||
dedicatedpause = READUINT8(*cp);
|
||||
|
|
@ -5770,7 +5776,7 @@ static void Got_ExitLevelcmd(UINT8 **cp, INT32 playernum)
|
|||
if (G_GamestateUsesExitLevel() == false)
|
||||
return;
|
||||
|
||||
G_ExitLevel();
|
||||
G_FinishExitLevel();
|
||||
}
|
||||
|
||||
static void Got_SetupVotecmd(UINT8 **cp, INT32 playernum)
|
||||
|
|
|
|||
|
|
@ -1426,7 +1426,7 @@ void PT_FileFragment(void)
|
|||
filename = va("%s", file->filename);
|
||||
nameonly(filename);
|
||||
|
||||
if (!strcmp(filename, "main.kart")
|
||||
if (!strcmp(filename, "bios.pk3")
|
||||
|| !strcmp(filename, "gfx.pk3")
|
||||
|| !strcmp(filename, "textures.pk3")
|
||||
|| !strcmp(filename, "textures_general.pk3")
|
||||
|
|
|
|||
|
|
@ -504,6 +504,7 @@ struct player_t
|
|||
fixed_t deltaviewheight;
|
||||
// bounded/scaled total momentum.
|
||||
fixed_t bob;
|
||||
fixed_t cameraOffset;
|
||||
|
||||
skybox_t skybox;
|
||||
|
||||
|
|
|
|||
|
|
@ -1211,6 +1211,8 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi
|
|||
"S_EMERALDSPARK6",
|
||||
"S_EMERALDSPARK7",
|
||||
|
||||
"S_EMERALDFLARE1",
|
||||
|
||||
// Emerald hunt shards
|
||||
"S_SHRD1",
|
||||
"S_SHRD2",
|
||||
|
|
@ -4793,6 +4795,7 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t
|
|||
"MT_SPRAYCAN",
|
||||
"MT_EMERALD",
|
||||
"MT_EMERALDSPARK",
|
||||
"MT_EMERALDFLARE",
|
||||
"MT_EMERHUNT", // Emerald Hunt
|
||||
"MT_EMERALDSPAWN", // Emerald spawner w/ delay
|
||||
|
||||
|
|
|
|||
|
|
@ -767,8 +767,15 @@ extern UINT8 maxXtraLife; // Max extra lives from rings
|
|||
|
||||
extern mobj_t *hunt1, *hunt2, *hunt3; // Emerald hunt locations
|
||||
|
||||
struct exitcondition_t
|
||||
{
|
||||
boolean losing;
|
||||
boolean retry;
|
||||
};
|
||||
|
||||
// For racing
|
||||
extern tic_t racecountdown, exitcountdown, musiccountdown;
|
||||
extern exitcondition_t g_exit;
|
||||
|
||||
#define DEFAULT_GRAVITY (4*FRACUNIT/5)
|
||||
extern fixed_t gravity;
|
||||
|
|
|
|||
|
|
@ -206,9 +206,17 @@ class TiccmdBuilder
|
|||
return true;
|
||||
}
|
||||
|
||||
void toggle_freecam_input()
|
||||
{
|
||||
if (M_MenuButtonPressed(forplayer(), MBT_C))
|
||||
{
|
||||
P_ToggleDemoCamera();
|
||||
}
|
||||
}
|
||||
|
||||
bool director_input()
|
||||
{
|
||||
if (G_IsPartyLocal(displayplayers[forplayer()]) == true)
|
||||
if (demo.freecam || G_IsPartyLocal(displayplayers[forplayer()]) == true)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -239,12 +247,14 @@ class TiccmdBuilder
|
|||
}
|
||||
}
|
||||
|
||||
toggle_freecam_input();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spectator_analog_input()
|
||||
{
|
||||
if (!player()->spectator && !objectplacing)
|
||||
if (!player()->spectator && !objectplacing && !demo.freecam)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -261,7 +271,7 @@ class TiccmdBuilder
|
|||
|
||||
if (G_PlayerInputDown(forplayer(), gc_lookback, 0))
|
||||
{
|
||||
cmd->aiming -= joystickvector.yaxis;
|
||||
cmd->aiming -= (joystickvector.yaxis * KART_FULLTURN) / JOYAXISRANGE;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -361,10 +371,28 @@ public:
|
|||
explicit TiccmdBuilder(ticcmd_t* cmd_, INT32 realtics_, UINT8 ssplayer_) :
|
||||
cmd(cmd_), realtics(realtics_), ssplayer(ssplayer_), viewnum(G_PartyPosition(g_localplayers[forplayer()]))
|
||||
{
|
||||
*cmd = {}; // blank ticcmd
|
||||
|
||||
if (demo.playback)
|
||||
auto regular_input = [this]
|
||||
{
|
||||
analog_input();
|
||||
common_button_input();
|
||||
};
|
||||
|
||||
if (demo.playback || demo.freecam || player()->spectator)
|
||||
{
|
||||
// freecam is controllable even while paused
|
||||
|
||||
*cmd = {};
|
||||
|
||||
if (!typing_input() && !director_input())
|
||||
{
|
||||
regular_input();
|
||||
|
||||
if (demo.freecam)
|
||||
{
|
||||
toggle_freecam_input();
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -373,6 +401,8 @@ public:
|
|||
return;
|
||||
}
|
||||
|
||||
*cmd = {}; // blank ticcmd
|
||||
|
||||
if (gamestate == GS_LEVEL && player()->playerstate == PST_REBORN)
|
||||
{
|
||||
return;
|
||||
|
|
@ -391,8 +421,7 @@ public:
|
|||
|
||||
if (!overlay)
|
||||
{
|
||||
analog_input();
|
||||
common_button_input();
|
||||
regular_input();
|
||||
}
|
||||
|
||||
cmd->angle = localangle[viewnum] >> TICCMD_REDUCE;
|
||||
|
|
|
|||
|
|
@ -4127,12 +4127,6 @@ void G_StopDemo(void)
|
|||
singletics = false;
|
||||
|
||||
demo.freecam = false;
|
||||
// reset democam shit too:
|
||||
democam.cam = NULL;
|
||||
democam.soundmobj = NULL;
|
||||
democam.localangle = 0;
|
||||
democam.localaiming = 0;
|
||||
democam.keyboardlook = false;
|
||||
|
||||
Z_Free(demo.skinlist);
|
||||
demo.skinlist = NULL;
|
||||
|
|
@ -4167,7 +4161,7 @@ boolean G_CheckDemoStatus(void)
|
|||
I_Quit();
|
||||
|
||||
if (multiplayer && !demo.title)
|
||||
G_ExitLevel();
|
||||
G_FinishExitLevel();
|
||||
else
|
||||
{
|
||||
G_StopDemo();
|
||||
|
|
|
|||
220
src/g_game.c
220
src/g_game.c
|
|
@ -76,6 +76,10 @@
|
|||
#include "discord.h"
|
||||
#endif
|
||||
|
||||
#ifdef HWRENDER
|
||||
#include "hardware/hw_main.h" // for cv_glshearing
|
||||
#endif
|
||||
|
||||
gameaction_t gameaction;
|
||||
gamestate_t gamestate = GS_NULL;
|
||||
UINT8 ultimatemode = false;
|
||||
|
|
@ -272,6 +276,7 @@ mobj_t *hunt2;
|
|||
mobj_t *hunt3;
|
||||
|
||||
tic_t racecountdown, exitcountdown, musiccountdown; // for racing
|
||||
exitcondition_t g_exit;
|
||||
|
||||
fixed_t gravity;
|
||||
fixed_t mapobjectscale;
|
||||
|
|
@ -803,9 +808,7 @@ const char *G_BuildMapName(INT32 map)
|
|||
*/
|
||||
INT32 G_MapNumber(const char * name)
|
||||
{
|
||||
#ifdef NEXTMAPINSOC
|
||||
if (strncasecmp("NEXTMAP_", name, 8) != 0)
|
||||
#endif
|
||||
{
|
||||
INT32 map;
|
||||
UINT32 hash = quickncasehash(name, MAXMAPLUMPNAME);
|
||||
|
|
@ -824,7 +827,6 @@ INT32 G_MapNumber(const char * name)
|
|||
return NEXTMAP_INVALID;
|
||||
}
|
||||
|
||||
#ifdef NEXTMAPINSOC
|
||||
name += 8;
|
||||
|
||||
if (strcasecmp("EVALUATION", name) == 0)
|
||||
|
|
@ -833,9 +835,10 @@ INT32 G_MapNumber(const char * name)
|
|||
return NEXTMAP_CREDITS;
|
||||
if (strcasecmp("CEREMONY", name) == 0)
|
||||
return NEXTMAP_CEREMONY;
|
||||
//if (strcasecmp("TITLE", name) == 0)
|
||||
if (strcasecmp("TITLE", name) == 0)
|
||||
return NEXTMAP_TITLE;
|
||||
#endif
|
||||
|
||||
return NEXTMAP_INVALID;
|
||||
}
|
||||
|
||||
/** Clips the console player's mouse aiming to the current view.
|
||||
|
|
@ -863,7 +866,7 @@ INT16 G_SoftwareClipAimingPitch(INT32 *aiming)
|
|||
INT32 limitangle;
|
||||
|
||||
// note: the current software mode implementation doesn't have true perspective
|
||||
limitangle = ANGLE_90 - ANG10; // Some viewing fun, but not too far down...
|
||||
limitangle = ANGLE_45; // Some viewing fun, but not too far down...
|
||||
|
||||
if (*aiming > limitangle)
|
||||
*aiming = limitangle;
|
||||
|
|
@ -873,6 +876,31 @@ INT16 G_SoftwareClipAimingPitch(INT32 *aiming)
|
|||
return (INT16)((*aiming)>>16);
|
||||
}
|
||||
|
||||
void G_FinalClipAimingPitch(INT32 *aiming, player_t *player, boolean skybox)
|
||||
{
|
||||
#ifndef HWRENDER
|
||||
(void)player;
|
||||
(void)skybox;
|
||||
#endif
|
||||
|
||||
// clip it in the case we are looking a hardware 90 degrees full aiming
|
||||
// (lmps, network and use F12...)
|
||||
if (rendermode == render_soft
|
||||
#ifdef HWRENDER
|
||||
|| (rendermode == render_opengl
|
||||
&& (cv_glshearing.value == 1
|
||||
|| (cv_glshearing.value == 2 && R_IsViewpointThirdPerson(player, skybox))))
|
||||
#endif
|
||||
)
|
||||
{
|
||||
G_SoftwareClipAimingPitch(aiming);
|
||||
}
|
||||
else
|
||||
{
|
||||
G_ClipAimingPitch(aiming);
|
||||
}
|
||||
}
|
||||
|
||||
static INT32 G_GetValueFromControlTable(INT32 deviceID, INT32 deadzone, INT32 *controltable)
|
||||
{
|
||||
INT32 i, failret = NO_BINDS_REACHABLE;
|
||||
|
|
@ -1257,6 +1285,7 @@ void G_StartTitleCard(void)
|
|||
ST_startTitleCard();
|
||||
|
||||
// play the sound
|
||||
if (gamestate != GS_CEREMONY)
|
||||
{
|
||||
sfxenum_t kstart = sfx_kstart;
|
||||
if (K_CheckBossIntro() == true)
|
||||
|
|
@ -2900,95 +2929,116 @@ void G_AddPlayer(INT32 playernum)
|
|||
demo_extradata[playernum] |= DXD_JOINDATA|DXD_PLAYSTATE|DXD_COLOR|DXD_NAME|DXD_SKIN|DXD_FOLLOWER; // Set everything
|
||||
}
|
||||
|
||||
void G_ExitLevel(void)
|
||||
void G_BeginLevelExit(void)
|
||||
{
|
||||
g_exit.losing = true;
|
||||
g_exit.retry = false;
|
||||
|
||||
if (grandprixinfo.gp == true)
|
||||
{
|
||||
UINT8 i;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i] && !players[i].spectator)
|
||||
{
|
||||
K_PlayerFinishGrandPrix(&players[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!G_GametypeUsesLives() || skipstats != 0)
|
||||
{
|
||||
g_exit.losing = false; // never force a retry
|
||||
}
|
||||
else if (specialstageinfo.valid == true || (gametyperules & GTR_BOSS))
|
||||
{
|
||||
UINT8 i;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i] && !players[i].spectator && !players[i].bot)
|
||||
{
|
||||
if (!K_IsPlayerLosing(&players[i]))
|
||||
{
|
||||
g_exit.losing = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (grandprixinfo.gp == true && grandprixinfo.eventmode == GPEVENT_NONE)
|
||||
{
|
||||
g_exit.losing = (grandprixinfo.wonround != true);
|
||||
}
|
||||
|
||||
if (g_exit.losing)
|
||||
{
|
||||
// You didn't win...
|
||||
|
||||
UINT8 i;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i] && !players[i].spectator && !players[i].bot)
|
||||
{
|
||||
if (players[i].lives > 0)
|
||||
{
|
||||
g_exit.retry = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (g_exit.losing && specialstageinfo.valid)
|
||||
{
|
||||
exitcountdown = TICRATE;
|
||||
}
|
||||
else
|
||||
{
|
||||
exitcountdown = raceexittime+1;
|
||||
}
|
||||
|
||||
if (g_exit.losing)
|
||||
{
|
||||
if (!g_exit.retry)
|
||||
{
|
||||
ACS_RunGameOverScript();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void G_FinishExitLevel(void)
|
||||
{
|
||||
G_ResetAllDeviceRumbles();
|
||||
|
||||
if (gamestate == GS_LEVEL)
|
||||
{
|
||||
UINT8 i;
|
||||
boolean doretry = false;
|
||||
|
||||
if (grandprixinfo.gp == true)
|
||||
if (g_exit.retry)
|
||||
{
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i] && !players[i].spectator)
|
||||
{
|
||||
K_PlayerFinishGrandPrix(&players[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!G_GametypeUsesLives() || skipstats != 0)
|
||||
; // never force a retry
|
||||
else if (specialstageinfo.valid == true || (gametyperules & GTR_BOSS))
|
||||
{
|
||||
doretry = true;
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i] && !players[i].spectator && !players[i].bot)
|
||||
{
|
||||
if (!K_IsPlayerLosing(&players[i]))
|
||||
{
|
||||
doretry = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (grandprixinfo.gp == true && grandprixinfo.eventmode == GPEVENT_NONE)
|
||||
{
|
||||
doretry = (grandprixinfo.wonround != true);
|
||||
}
|
||||
|
||||
if (doretry)
|
||||
{
|
||||
// You didn't win...
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i] && !players[i].spectator && !players[i].bot)
|
||||
{
|
||||
if (players[i].lives > 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (i == MAXPLAYERS)
|
||||
{
|
||||
// GAME OVER, try again from the start!
|
||||
if (grandprixinfo.gp == true
|
||||
&& grandprixinfo.eventmode == GPEVENT_SPECIAL)
|
||||
{
|
||||
// We were in a Special Stage.
|
||||
// We can still progress to the podium when we game over here.
|
||||
doretry = false;
|
||||
}
|
||||
else if (netgame)
|
||||
{
|
||||
; // Restart cup here whenever we do Online GP
|
||||
}
|
||||
else
|
||||
{
|
||||
// Back to the menu with you.
|
||||
G_HandleSaveLevel(true);
|
||||
D_QuitNetGame();
|
||||
CL_Reset();
|
||||
D_ClearState();
|
||||
M_StartControlPanel();
|
||||
}
|
||||
}
|
||||
else
|
||||
// Restart cup here whenever we do Online GP
|
||||
if (!netgame)
|
||||
{
|
||||
// We have lives, just redo this one course.
|
||||
G_SetRetryFlag();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (g_exit.losing)
|
||||
{
|
||||
// We were in a Special Stage.
|
||||
// We can still progress to the podium when we game over here.
|
||||
const boolean special = grandprixinfo.gp == true && grandprixinfo.eventmode == GPEVENT_SPECIAL;
|
||||
|
||||
if (doretry == true)
|
||||
if (!netgame && !special)
|
||||
{
|
||||
// Back to the menu with you.
|
||||
G_HandleSaveLevel(true);
|
||||
D_QuitNetGame();
|
||||
CL_Reset();
|
||||
D_ClearState();
|
||||
M_StartControlPanel();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -3291,6 +3341,10 @@ boolean G_GametypeHasTeams(void)
|
|||
//
|
||||
boolean G_GametypeHasSpectators(void)
|
||||
{
|
||||
// TODO: this would make a great debug feature for release
|
||||
#ifdef DEVELOP
|
||||
return true;
|
||||
#endif
|
||||
return (netgame || (multiplayer && demo.netgame));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -126,6 +126,7 @@ ticcmd_t *G_MoveTiccmd(ticcmd_t* dest, const ticcmd_t* src, const size_t n);
|
|||
// clip the console player aiming to the view
|
||||
INT32 G_ClipAimingPitch(INT32 *aiming);
|
||||
INT16 G_SoftwareClipAimingPitch(INT32 *aiming);
|
||||
void G_FinalClipAimingPitch(INT32 *aiming, player_t *player, boolean skybox);
|
||||
|
||||
extern angle_t localangle[MAXSPLITSCREENPLAYERS];
|
||||
extern INT32 localaiming[MAXSPLITSCREENPLAYERS]; // should be an angle_t but signed
|
||||
|
|
@ -205,7 +206,8 @@ boolean G_GametypeUsesLives(void);
|
|||
boolean G_GametypeHasTeams(void);
|
||||
boolean G_GametypeHasSpectators(void);
|
||||
INT16 G_SometimesGetDifferentEncore(void);
|
||||
void G_ExitLevel(void);
|
||||
void G_BeginLevelExit(void);
|
||||
void G_FinishExitLevel(void);
|
||||
void G_NextLevel(void);
|
||||
void G_GetNextMap(void);
|
||||
void G_Continue(void);
|
||||
|
|
|
|||
|
|
@ -310,7 +310,7 @@ static FUINT HWR_CalcSlopeLight(FUINT lightnum, pslope_t *slope, const sector_t
|
|||
{
|
||||
INT16 finallight = lightnum;
|
||||
|
||||
if (slope != NULL && P_ApplyLightOffsetFine(lightnum, sector))
|
||||
if (slope != NULL && sector != NULL && P_ApplyLightOffsetFine(lightnum, sector))
|
||||
{
|
||||
finallight += slope->hwLightOffset;
|
||||
|
||||
|
|
@ -4773,7 +4773,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
|
|||
if (spriterotangle != 0
|
||||
&& !(splat && !(thing->renderflags & RF_NOSPLATROLLANGLE)))
|
||||
{
|
||||
rollangle = R_GetRollAngle(vflip
|
||||
rollangle = R_GetRollAngle(papersprite == vflip
|
||||
? spriterotangle : InvAngle(spriterotangle));
|
||||
rotsprite = Patch_GetRotatedSprite(sprframe, (thing->frame & FF_FRAMEMASK), rot, flip, false, sprinfo, rollangle);
|
||||
|
||||
|
|
|
|||
29
src/info.c
29
src/info.c
|
|
@ -1881,6 +1881,8 @@ state_t states[NUMSTATES] =
|
|||
{SPR_ESPK, FF_FULLBRIGHT|5, 3, {NULL}, 0, 0, S_EMERALDSPARK7}, // S_EMERALDSPARK6
|
||||
{SPR_ESPK, FF_FULLBRIGHT|6, 3, {NULL}, 0, 0, S_NULL}, // S_EMERALDSPARK7
|
||||
|
||||
{SPR_LENS, FF_FULLBRIGHT|FF_ADD|FF_TRANS10|FF_ANIMATE|11, 8, {NULL}, 7, 1, S_GAINAX_MID2}, // S_EMERALDFLARE1
|
||||
|
||||
// Emerald hunt shards
|
||||
{SPR_SHRD, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SHRD1
|
||||
{SPR_SHRD, 1, -1, {NULL}, 0, 0, S_NULL}, // S_SHRD2
|
||||
|
|
@ -8345,6 +8347,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_EMERALDFLARE
|
||||
-1, // doomednum
|
||||
S_INVISIBLE, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
8, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
0, // painchance
|
||||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
0, // speed
|
||||
8*FRACUNIT, // radius
|
||||
8*FRACUNIT, // height
|
||||
0, // display offset
|
||||
16, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_EMERHUNT
|
||||
320, // doomednum
|
||||
S_SHRD1, // spawnstate
|
||||
|
|
|
|||
|
|
@ -2365,6 +2365,8 @@ typedef enum state
|
|||
S_EMERALDSPARK6,
|
||||
S_EMERALDSPARK7,
|
||||
|
||||
S_EMERALDFLARE1,
|
||||
|
||||
// Emerald hunt shards
|
||||
S_SHRD1,
|
||||
S_SHRD2,
|
||||
|
|
@ -5982,6 +5984,7 @@ typedef enum mobj_type
|
|||
MT_SPRAYCAN,
|
||||
MT_EMERALD,
|
||||
MT_EMERALDSPARK,
|
||||
MT_EMERALDFLARE,
|
||||
MT_EMERHUNT, // Emerald Hunt
|
||||
MT_EMERALDSPAWN, // Emerald spawner w/ delay
|
||||
|
||||
|
|
|
|||
|
|
@ -127,7 +127,10 @@ void K_CheckBumpers(void)
|
|||
{
|
||||
if (nobumpers > 0 && nobumpers >= numingame)
|
||||
{
|
||||
// TODO: this would make a great debug feature for release
|
||||
#ifndef DEVELOP
|
||||
P_DoAllPlayersExit(PF_NOCONTEST, false);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -275,8 +278,7 @@ void K_DropEmeraldsFromPlayer(player_t *player, UINT32 emeraldType)
|
|||
|
||||
if ((player->emeralds & emeraldFlag) && (emeraldFlag & emeraldType))
|
||||
{
|
||||
mobj_t *emerald = K_SpawnChaosEmerald(player->mo->x, player->mo->y, player->mo->z, player->mo->angle - ANGLE_90, flip, emeraldFlag);
|
||||
P_SetTarget(&emerald->target, player->mo);
|
||||
K_SpawnChaosEmerald(player->mo->x, player->mo->y, player->mo->z, player->mo->angle - ANGLE_90, flip, emeraldFlag);
|
||||
|
||||
player->emeralds &= ~emeraldFlag;
|
||||
break; // Drop only one emerald. Emerald wins are hard enough!
|
||||
|
|
|
|||
|
|
@ -844,6 +844,12 @@ boolean K_CanChangeRules(boolean allowdemos)
|
|||
--------------------------------------------------*/
|
||||
void K_PlayerFinishGrandPrix(player_t *player)
|
||||
{
|
||||
if (grandprixinfo.wonround == true)
|
||||
{
|
||||
// This was already completed.
|
||||
return;
|
||||
}
|
||||
|
||||
if (player->exiting == false)
|
||||
{
|
||||
// You did not finish
|
||||
|
|
|
|||
15
src/k_hud.c
15
src/k_hud.c
|
|
@ -5169,7 +5169,8 @@ static void K_DrawDirectorButton(INT32 idx, const char *label, patch_t *kp[2], I
|
|||
|
||||
static void K_drawDirectorHUD(void)
|
||||
{
|
||||
const INT32 p = G_PartyMember(consoleplayer, R_GetViewNumber());
|
||||
const UINT8 viewnum = R_GetViewNumber();
|
||||
const INT32 p = viewnum < G_PartySize(consoleplayer) ? G_PartyMember(consoleplayer, viewnum) : -1;
|
||||
const char *itemtxt = "Join";
|
||||
UINT8 offs = 0;
|
||||
|
||||
|
|
@ -5192,12 +5193,15 @@ static void K_drawDirectorHUD(void)
|
|||
offs = 2;
|
||||
}
|
||||
|
||||
K_DrawDirectorButton(offs + 1, "Freecam", kp_button_c[0], 0);
|
||||
|
||||
if (p == -1 || !playeringame[p] || players[p].spectator == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
K_DrawDirectorButton(offs + 1, "Director", kp_button_r,
|
||||
// TODO: this is too close to the screen bottom
|
||||
K_DrawDirectorButton(offs + 2, "Director", kp_button_r,
|
||||
(directorinfo.active ? V_YELLOWMAP : 0));
|
||||
|
||||
if (players[p].flashing)
|
||||
|
|
@ -5643,6 +5647,11 @@ void K_drawKartHUD(void)
|
|||
if (stplyr->karthud[khud_trickcool])
|
||||
K_drawTrickCool();
|
||||
|
||||
if (freecam)
|
||||
{
|
||||
K_DrawDirectorButton(3, "Freecam", kp_button_c[0], 0);
|
||||
}
|
||||
|
||||
if (modeattacking || freecam) // everything after here is MP and debug only
|
||||
return;
|
||||
|
||||
|
|
@ -5659,7 +5668,7 @@ void K_drawKartHUD(void)
|
|||
|
||||
K_drawKartPowerUps();
|
||||
|
||||
if (G_IsPartyLocal(displayplayers[viewnum]) == false && !demo.playback)
|
||||
if (G_IsPartyLocal(displayplayers[viewnum]) == false)
|
||||
{
|
||||
K_drawDirectorHUD();
|
||||
}
|
||||
|
|
|
|||
27
src/k_kart.c
27
src/k_kart.c
|
|
@ -7794,6 +7794,8 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
|
|||
player->mo->spritexoffset = 0;
|
||||
player->mo->spriteyoffset = 0;
|
||||
|
||||
player->cameraOffset = 0;
|
||||
|
||||
if (player->curshield == KSHIELD_TOP)
|
||||
{
|
||||
mobj_t *top = K_GetGardenTop(player);
|
||||
|
|
@ -7814,6 +7816,21 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
|
|||
}
|
||||
}
|
||||
|
||||
if (!P_MobjWasRemoved(player->whip) && (player->whip->flags2 & MF2_AMBUSH))
|
||||
{
|
||||
// Linear acceleration and deceleration to a peak.
|
||||
// There is a constant total time to complete but the
|
||||
// acceleration and deceleration times can be made
|
||||
// asymmetrical.
|
||||
const fixed_t hop = 24 * mapobjectscale;
|
||||
const INT32 duration = 12;
|
||||
const INT32 mid = (duration / 2) - 1;
|
||||
const INT32 t = (duration - mid) - player->whip->fuse;
|
||||
|
||||
player->cameraOffset = hop - (abs(t * hop) / (t < 0 ? mid : duration - mid));
|
||||
player->mo->sprzoff += player->cameraOffset;
|
||||
}
|
||||
|
||||
K_UpdateOffroad(player);
|
||||
K_UpdateDraft(player);
|
||||
K_UpdateEngineSounds(player); // Thanks, VAda!
|
||||
|
|
@ -10943,9 +10960,13 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
|
|||
P_SetTarget(&whip->target, player->mo);
|
||||
K_MatchGenericExtraFlags(whip, player->mo);
|
||||
P_SpawnFakeShadow(whip, 20);
|
||||
whip->fuse = 12; // Changing instawhip animation duration? Look here
|
||||
player->flashing = max(player->flashing, 12);
|
||||
player->mo->momz += 4*mapobjectscale;
|
||||
whip->fuse = INSTAWHIP_DURATION;
|
||||
player->flashing = max(player->flashing, INSTAWHIP_DURATION);
|
||||
|
||||
if (P_IsObjectOnGround(player->mo))
|
||||
{
|
||||
whip->flags2 |= MF2_AMBUSH;
|
||||
}
|
||||
|
||||
if (!K_PowerUpRemaining(player, POWERUP_BADGE))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ Make sure this matches the actual number of states
|
|||
#define GROW_PHYSICS_SCALE (3*FRACUNIT/2)
|
||||
#define SHRINK_PHYSICS_SCALE (3*FRACUNIT/4)
|
||||
|
||||
#define INSTAWHIP_DURATION (12)
|
||||
#define INSTAWHIP_COOLDOWN (TICRATE*2)
|
||||
#define INSTAWHIP_STARTOFRACE (255)
|
||||
#define INSTAWHIP_STARTOFBATTLE (1)
|
||||
|
|
|
|||
|
|
@ -816,7 +816,13 @@ void M_Drawer(void)
|
|||
// draw pause pic
|
||||
if (paused && !demo.playback && (menuactive || cv_showhud.value))
|
||||
{
|
||||
M_DrawPausedText(0);
|
||||
// Don't cover the Stereo player!
|
||||
boolean stereo_open = menuactive && currentMenu == &MISC_SoundTestDef;
|
||||
|
||||
if (stereo_open == false)
|
||||
{
|
||||
M_DrawPausedText(0);
|
||||
}
|
||||
}
|
||||
|
||||
// focus lost notification goes on top of everything, even the former everything
|
||||
|
|
@ -5048,7 +5054,7 @@ void M_DrawAddons(void)
|
|||
|
||||
m = numwadfiles-(mainwads+musicwads+1);
|
||||
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, y+4, (majormods ? highlightflags : V_TRANSLUCENT), va("%ld ADD-ON%s LOADED", (long)m, (m == 1) ? "" : "S")); //+2 for music, sounds, +1 for main.kart
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, y+4, (majormods ? highlightflags : V_TRANSLUCENT), va("%ld ADD-ON%s LOADED", (long)m, (m == 1) ? "" : "S")); //+2 for music, sounds, +1 for bios.pk3
|
||||
}
|
||||
|
||||
#undef addonsseperation
|
||||
|
|
|
|||
|
|
@ -207,6 +207,9 @@ void Obj_SneakerPanelCollide(mobj_t *pad, mobj_t *mo);
|
|||
/* Emerald */
|
||||
void Obj_SpawnEmeraldSparks(mobj_t *source);
|
||||
void Obj_EmeraldThink(mobj_t *emerald);
|
||||
void Obj_EmeraldFlareThink(mobj_t *flare);
|
||||
void Obj_BeginEmeraldOrbit(mobj_t *emerald, mobj_t *target, fixed_t radius, INT32 revolution_time, tic_t fuse);
|
||||
void Obj_GiveEmerald(mobj_t *emerald);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
|
|
|
|||
|
|
@ -2869,7 +2869,8 @@ static int lib_gExitLevel(lua_State *L)
|
|||
// Moved this bit to G_SetCustomExitVars
|
||||
if (n >= 1) // Don't run the reset to defaults option
|
||||
lib_gSetCustomExitVars(L);
|
||||
G_ExitLevel();
|
||||
G_BeginLevelExit();
|
||||
G_FinishExitLevel();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -236,20 +236,7 @@ void M_PlaybackToggleFreecam(INT32 choice)
|
|||
splitscreen = 0;
|
||||
R_ExecuteSetViewSize();
|
||||
|
||||
P_InitCameraCmd(); // init camera controls
|
||||
if (!demo.freecam) // toggle on
|
||||
{
|
||||
demo.freecam = true;
|
||||
democam.cam = &camera[0]; // this is rather useful
|
||||
}
|
||||
else // toggle off
|
||||
{
|
||||
demo.freecam = false;
|
||||
// reset democam vars:
|
||||
democam.cam = NULL;
|
||||
//democam.turnheld = false;
|
||||
democam.keyboardlook = false; // reset only these. localangle / aiming gets set before the cam does anything anyway
|
||||
}
|
||||
P_ToggleDemoCamera();
|
||||
}
|
||||
|
||||
void M_PlaybackQuit(INT32 choice)
|
||||
|
|
|
|||
|
|
@ -1,10 +1,25 @@
|
|||
#include "../k_battle.h"
|
||||
#include "../k_objects.h"
|
||||
#include "../k_specialstage.h"
|
||||
#include "../info.h"
|
||||
#include "../m_random.h"
|
||||
#include "../p_local.h"
|
||||
#include "../r_main.h"
|
||||
#include "../s_sound.h"
|
||||
#include "../tables.h"
|
||||
|
||||
#define emerald_type(o) ((o)->extravalue1)
|
||||
#define emerald_anim_start(o) ((o)->movedir)
|
||||
#define emerald_revolution_time(o) ((o)->threshold)
|
||||
#define emerald_start_radius(o) ((o)->movecount)
|
||||
#define emerald_target_radius(o) ((o)->extravalue2)
|
||||
#define emerald_z_shift(o) ((o)->reactiontime)
|
||||
#define emerald_scale_rate(o) ((o)->movefactor)
|
||||
|
||||
// Think of this like EMERALD_SPEED_UP / EMERALD_SPEED_UP_RATE
|
||||
#define EMERALD_SPEED_UP (1) // speed up by this much...
|
||||
#define EMERALD_SPEED_UP_RATE (1) // ...every N tics
|
||||
|
||||
void Obj_SpawnEmeraldSparks(mobj_t *mobj)
|
||||
{
|
||||
if (leveltime % 3 != 0)
|
||||
|
|
@ -25,31 +40,95 @@ void Obj_SpawnEmeraldSparks(mobj_t *mobj)
|
|||
sparkle->sprzoff = mobj->sprzoff;
|
||||
}
|
||||
|
||||
static INT32 get_elapsed(mobj_t *emerald)
|
||||
{
|
||||
return leveltime - min((tic_t)emerald_anim_start(emerald), leveltime);
|
||||
}
|
||||
|
||||
static INT32 get_revolve_time(mobj_t *emerald)
|
||||
{
|
||||
return max(1, emerald_revolution_time(emerald));
|
||||
}
|
||||
|
||||
static fixed_t get_suck_factor(mobj_t *emerald)
|
||||
{
|
||||
const INT32 suck_time = get_revolve_time(emerald) * 2;
|
||||
|
||||
return (min(get_elapsed(emerald), suck_time) * FRACUNIT) / suck_time;
|
||||
}
|
||||
|
||||
static fixed_t get_current_radius(mobj_t *emerald)
|
||||
{
|
||||
fixed_t s = emerald_start_radius(emerald);
|
||||
fixed_t t = emerald_target_radius(emerald);
|
||||
|
||||
return s + FixedMul(t - s, get_suck_factor(emerald));
|
||||
}
|
||||
|
||||
static fixed_t get_bob(mobj_t *emerald)
|
||||
{
|
||||
// With a fuse, the emerald experiences "speed up" and the
|
||||
// scale also shrinks. All of these these effects caused
|
||||
// the bob phase shift to look disproportioned.
|
||||
angle_t phase = emerald->fuse ? 0 : get_elapsed(emerald) * ((ANGLE_MAX / get_revolve_time(emerald)) / 2);
|
||||
|
||||
return FixedMul(30 * mapobjectscale, FSIN(emerald->angle + phase));
|
||||
}
|
||||
|
||||
static fixed_t center_of(mobj_t *mobj)
|
||||
{
|
||||
return mobj->z + (mobj->height / 2);
|
||||
}
|
||||
|
||||
static fixed_t get_target_z(mobj_t *emerald)
|
||||
{
|
||||
fixed_t shift = FixedMul(emerald_z_shift(emerald), FRACUNIT - get_suck_factor(emerald));
|
||||
|
||||
return center_of(emerald->target) + get_bob(emerald) + shift;
|
||||
}
|
||||
|
||||
static void speed_up(mobj_t *emerald)
|
||||
{
|
||||
// Revolution time shouldn't decrease below zero.
|
||||
if (emerald_revolution_time(emerald) <= EMERALD_SPEED_UP)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (get_elapsed(emerald) % EMERALD_SPEED_UP_RATE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Decrease the fuse proportionally to the revolution time.
|
||||
const fixed_t ratio = (emerald->fuse * FRACUNIT) / emerald_revolution_time(emerald);
|
||||
|
||||
emerald_revolution_time(emerald) -= EMERALD_SPEED_UP;
|
||||
|
||||
emerald->fuse = max(1, (emerald_revolution_time(emerald) * ratio) / FRACUNIT);
|
||||
}
|
||||
|
||||
static void Obj_EmeraldOrbitPlayer(mobj_t *emerald)
|
||||
{
|
||||
const int kOrbitTics = 64;
|
||||
const int kPhaseTics = 128;
|
||||
|
||||
const fixed_t orbit_radius = 100 * mapobjectscale;
|
||||
const fixed_t orbit_height = 30 * mapobjectscale;
|
||||
|
||||
mobj_t *targ = emerald->target;
|
||||
|
||||
angle_t a = emerald->angle;
|
||||
|
||||
fixed_t x = FixedMul(orbit_radius, FCOS(a));
|
||||
fixed_t y = FixedMul(orbit_radius, FSIN(a));
|
||||
|
||||
angle_t phase = (ANGLE_MAX / kPhaseTics) * (leveltime % kPhaseTics);
|
||||
fixed_t r = get_current_radius(emerald);
|
||||
fixed_t x = FixedMul(r, FCOS(emerald->angle));
|
||||
fixed_t y = FixedMul(r, FSIN(emerald->angle));
|
||||
|
||||
P_MoveOrigin(
|
||||
emerald,
|
||||
targ->x + x,
|
||||
targ->y + y,
|
||||
targ->z + targ->height + FixedMul(orbit_height, FSIN(a + phase))
|
||||
emerald->target->x + x,
|
||||
emerald->target->y + y,
|
||||
get_target_z(emerald)
|
||||
);
|
||||
|
||||
emerald->angle += ANGLE_MAX / kOrbitTics;
|
||||
emerald->angle += ANGLE_MAX / get_revolve_time(emerald);
|
||||
|
||||
if (emerald->fuse > 0)
|
||||
{
|
||||
speed_up(emerald);
|
||||
|
||||
P_InstaScale(emerald, emerald->fuse * emerald_scale_rate(emerald));
|
||||
}
|
||||
}
|
||||
|
||||
void Obj_EmeraldThink(mobj_t *emerald)
|
||||
|
|
@ -84,3 +163,156 @@ void Obj_EmeraldThink(mobj_t *emerald)
|
|||
|
||||
K_BattleOvertimeKiller(emerald);
|
||||
}
|
||||
|
||||
static mobj_t *spawn_glow(mobj_t *flare)
|
||||
{
|
||||
mobj_t *targ = flare->target;
|
||||
mobj_t *x = P_SpawnGhostMobj(targ);
|
||||
|
||||
x->old_x = targ->old_x;
|
||||
x->old_y = targ->old_y;
|
||||
x->old_z = targ->old_z;
|
||||
|
||||
x->fuse = 2; // this actually does last one tic
|
||||
x->extravalue1 = 1;
|
||||
x->extravalue2 = 0;
|
||||
|
||||
x->renderflags = RF_ADD | RF_ALWAYSONTOP;
|
||||
|
||||
// FIXME: linkdraw doesn't work consistently, so I drew it on top of everyting (and through walls)
|
||||
#if 0
|
||||
P_SetTarget(&x->tracer, targ);
|
||||
x->flags2 |= MF2_LINKDRAW;
|
||||
x->dispoffset = 1000;
|
||||
#endif
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
static mobj_t *spawn_glow_colorize(mobj_t *flare)
|
||||
{
|
||||
mobj_t *x = spawn_glow(flare);
|
||||
|
||||
x->color = flare->color;
|
||||
x->colorized = true;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
void Obj_EmeraldFlareThink(mobj_t *flare)
|
||||
{
|
||||
const INT32 kExtraTics = 3;
|
||||
const INT32 flare_tics = states[S_EMERALDFLARE1].tics + kExtraTics;
|
||||
|
||||
if (P_MobjWasRemoved(flare->target))
|
||||
{
|
||||
P_RemoveMobj(flare);
|
||||
return;
|
||||
}
|
||||
|
||||
// Target is assumed to be the emerald in orbit. When
|
||||
// emerald fuse runs out, it shall update player's emerald
|
||||
// flags. Time the flare animation so it ends with the
|
||||
// emerald fuse.
|
||||
if (!flare->fuse && flare->target->fuse > flare_tics)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (flare->state == &states[S_INVISIBLE])
|
||||
{
|
||||
// In special stages, just follow the emerald.
|
||||
if (specialstageinfo.valid == false)
|
||||
{
|
||||
// Update target to player. We don't need to track
|
||||
// the emerald anymore.
|
||||
P_SetTarget(&flare->target, flare->target->target);
|
||||
|
||||
if (P_MobjWasRemoved(flare->target))
|
||||
{
|
||||
P_RemoveMobj(flare);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
P_SetMobjState(flare, S_EMERALDFLARE1);
|
||||
flare->fuse = flare_tics;
|
||||
}
|
||||
|
||||
// Focus on center of player.
|
||||
P_SetOrigin(flare, flare->target->x, flare->target->y, center_of(flare->target));
|
||||
|
||||
if (leveltime & 1)
|
||||
{
|
||||
// Stacked for more exposure
|
||||
spawn_glow_colorize(flare);
|
||||
spawn_glow(flare);
|
||||
spawn_glow(flare);
|
||||
}
|
||||
}
|
||||
|
||||
static void spawn_lens_flare(mobj_t *emerald)
|
||||
{
|
||||
mobj_t *flare = P_SpawnMobjFromMobj(emerald, 0, 0, 0, MT_EMERALDFLARE);
|
||||
|
||||
P_SetTarget(&flare->target, emerald);
|
||||
P_InstaScale(flare, emerald->target->scale);
|
||||
|
||||
flare->color = emerald->color;
|
||||
flare->colorized = true;
|
||||
|
||||
flare->renderflags |= RF_ALWAYSONTOP;
|
||||
|
||||
// FIXME: linkdraw doesn't work consistently, so I drew it on top of everyting (and through walls)
|
||||
#if 0
|
||||
P_SetTarget(&flare->tracer, emerald->target);
|
||||
flare->flags2 |= MF2_LINKDRAW;
|
||||
flare->dispoffset = 1000;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Obj_BeginEmeraldOrbit(mobj_t *emerald, mobj_t *target, fixed_t radius, INT32 revolution_time, tic_t fuse)
|
||||
{
|
||||
P_SetTarget(&emerald->target, target);
|
||||
|
||||
emerald_anim_start(emerald) = leveltime;
|
||||
emerald_revolution_time(emerald) = revolution_time;
|
||||
|
||||
emerald_start_radius(emerald) = R_PointToDist2(target->x, target->y, emerald->x, emerald->y);
|
||||
emerald_target_radius(emerald) = radius;
|
||||
|
||||
emerald->fuse = fuse;
|
||||
|
||||
if (fuse)
|
||||
{
|
||||
emerald_scale_rate(emerald) = emerald->scale / fuse;
|
||||
}
|
||||
|
||||
emerald->angle = R_PointToAngle2(target->x, target->y, emerald->x, emerald->y);
|
||||
emerald_z_shift(emerald) = emerald->z - get_target_z(emerald);
|
||||
|
||||
emerald->flags |= MF_NOGRAVITY | MF_NOCLIP | MF_NOCLIPTHING | MF_NOCLIPHEIGHT;
|
||||
emerald->shadowscale = 0;
|
||||
|
||||
spawn_lens_flare(emerald);
|
||||
}
|
||||
|
||||
void Obj_GiveEmerald(mobj_t *emerald)
|
||||
{
|
||||
if (P_MobjWasRemoved(emerald->target))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
player_t *player = emerald->target->player;
|
||||
|
||||
if (!player)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
player->emeralds |= emerald_type(emerald);
|
||||
K_CheckEmeralds(player);
|
||||
|
||||
S_StartSound(emerald->target, emerald->info->deathsound);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,8 @@ void Obj_InstaWhipThink (mobj_t *whip)
|
|||
// Visuals
|
||||
whip->renderflags |= RF_NOSPLATBILLBOARD|RF_FULLBRIGHT;
|
||||
|
||||
if (whip->renderflags & RF_DONTDRAW)
|
||||
// This is opposite of player flashing tics
|
||||
if (leveltime & 1)
|
||||
whip->renderflags &= ~RF_DONTDRAW;
|
||||
else
|
||||
whip->renderflags |= RF_DONTDRAW;
|
||||
|
|
|
|||
|
|
@ -789,11 +789,7 @@ void Obj_CreateShrinkPohbees(player_t *owner)
|
|||
pohbees[j].start = GetPohbeeStart(player->nextwaypoint);
|
||||
pohbees[j].end = endWaypoint;
|
||||
pohbees[j].lasers = 1;
|
||||
|
||||
if (player->position == 1)
|
||||
{
|
||||
pohbees[j].first = true;
|
||||
}
|
||||
pohbees[j].first = (player->position == 1);
|
||||
|
||||
numPohbees++;
|
||||
}
|
||||
|
|
@ -801,6 +797,7 @@ void Obj_CreateShrinkPohbees(player_t *owner)
|
|||
|
||||
for (i = 0; i < numPohbees; i++)
|
||||
{
|
||||
// omg pobby hi!!!
|
||||
CreatePohbee(owner, pohbees[i].start, pohbees[i].end, pohbees[i].lasers);
|
||||
|
||||
if (pohbees[i].first == true)
|
||||
|
|
|
|||
|
|
@ -883,7 +883,7 @@ boolean Obj_UFOEmeraldCollect(mobj_t *ufo, mobj_t *toucher)
|
|||
const int kScaleTics = 16;
|
||||
|
||||
// Emerald will now orbit the player
|
||||
P_SetTarget(&emerald->target, toucher);
|
||||
Obj_BeginEmeraldOrbit(emerald, toucher, 100 * mapobjectscale, 64, 0);
|
||||
|
||||
// Scale down because the emerald is huge
|
||||
// Super Emerald needs to be scaled down further
|
||||
|
|
|
|||
|
|
@ -464,9 +464,14 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
if (toucher->hitlag > 0)
|
||||
return;
|
||||
|
||||
player->emeralds |= special->extravalue1;
|
||||
K_CheckEmeralds(player);
|
||||
break;
|
||||
// Emerald will now orbit the player
|
||||
|
||||
{
|
||||
const tic_t orbit = 2*TICRATE;
|
||||
Obj_BeginEmeraldOrbit(special, toucher, toucher->radius, orbit, orbit * 20);
|
||||
}
|
||||
|
||||
return;
|
||||
case MT_SPECIAL_UFO:
|
||||
if (Obj_UFOEmeraldCollect(special, toucher) == false)
|
||||
{
|
||||
|
|
@ -2031,7 +2036,15 @@ static boolean P_KillPlayer(player_t *player, mobj_t *inflictor, mobj_t *source,
|
|||
|
||||
if (!player->exiting && (specialstageinfo.valid == true || modeattacking & ATTACKING_SPB))
|
||||
{
|
||||
// TODO: this would make a great debug feature for release
|
||||
#ifdef DEVELOP
|
||||
if (type != DMG_SPECTATOR)
|
||||
{
|
||||
P_DoPlayerExit(player, PF_NOCONTEST);
|
||||
}
|
||||
#else
|
||||
P_DoPlayerExit(player, PF_NOCONTEST);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (player->exiting)
|
||||
|
|
|
|||
|
|
@ -126,6 +126,9 @@ struct camera_t
|
|||
// SRB2Kart: camera pitches on slopes
|
||||
angle_t pitch;
|
||||
|
||||
// Freecam: aiming needs to be reset after switching from chasecam
|
||||
boolean reset_aiming;
|
||||
|
||||
// Interpolation data
|
||||
fixed_t old_x, old_y, old_z;
|
||||
angle_t old_angle, old_aiming;
|
||||
|
|
@ -134,13 +137,7 @@ struct camera_t
|
|||
// demo freecam or something before i commit die
|
||||
struct demofreecam_s {
|
||||
|
||||
camera_t *cam; // this is useful when the game is paused, notably
|
||||
mobj_t *soundmobj; // mobj to play sound from, used in s_sound
|
||||
|
||||
angle_t localangle; // keeps track of the cam angle for cmds
|
||||
angle_t localaiming; // ditto with aiming
|
||||
boolean turnheld; // holding turn button for gradual turn speed
|
||||
boolean keyboardlook; // keyboard look
|
||||
UINT8 button_a_held; // A button was held since entering from menu, so don't move camera
|
||||
};
|
||||
|
||||
extern struct demofreecam_s democam;
|
||||
|
|
@ -159,7 +156,7 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam);
|
|||
void P_SlideCameraMove(camera_t *thiscam);
|
||||
void P_DemoCameraMovement(camera_t *cam);
|
||||
boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcalled);
|
||||
void P_InitCameraCmd(void);
|
||||
void P_ToggleDemoCamera(void);
|
||||
|
||||
boolean P_PlayerInPain(player_t *player);
|
||||
void P_ResetPlayer(player_t *player);
|
||||
|
|
|
|||
37
src/p_mobj.c
37
src/p_mobj.c
|
|
@ -7550,6 +7550,14 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
|||
case MT_EMERALD:
|
||||
Obj_EmeraldThink(mobj);
|
||||
|
||||
if (P_MobjWasRemoved(mobj))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case MT_EMERALDFLARE:
|
||||
Obj_EmeraldFlareThink(mobj);
|
||||
|
||||
if (P_MobjWasRemoved(mobj))
|
||||
{
|
||||
return false;
|
||||
|
|
@ -9824,6 +9832,12 @@ static boolean P_FuseThink(mobj_t *mobj)
|
|||
|
||||
break;
|
||||
}
|
||||
case MT_EMERALD:
|
||||
{
|
||||
Obj_GiveEmerald(mobj);
|
||||
P_RemoveMobj(mobj);
|
||||
return false;
|
||||
}
|
||||
case MT_PLAYER:
|
||||
break; // don't remove
|
||||
default:
|
||||
|
|
@ -11840,7 +11854,10 @@ void P_SpawnPlayer(INT32 playernum)
|
|||
}
|
||||
else // Otherwise, never spectator.
|
||||
{
|
||||
// TODO: this would make a great debug feature for release
|
||||
#ifndef DEVELOP
|
||||
p->spectator = false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -11968,6 +11985,15 @@ void P_SpawnPlayer(INT32 playernum)
|
|||
{
|
||||
K_ToggleDirector(players[consoleplayer].spectator && pcount > 0);
|
||||
}
|
||||
|
||||
// TODO: handle splitscreen
|
||||
// Spectators can switch to freecam. This should be
|
||||
// disabled when they enter the race, or when the level
|
||||
// changes.
|
||||
if (playernum == consoleplayer && !demo.playback)
|
||||
{
|
||||
demo.freecam = false;
|
||||
}
|
||||
}
|
||||
|
||||
void P_AfterPlayerSpawn(INT32 playernum)
|
||||
|
|
@ -12001,12 +12027,15 @@ void P_AfterPlayerSpawn(INT32 playernum)
|
|||
|
||||
p->drawangle = mobj->angle;
|
||||
|
||||
for (i = 0; i <= r_splitscreen; i++)
|
||||
if (p->spectator == false)
|
||||
{
|
||||
if (camera[i].chase)
|
||||
for (i = 0; i <= r_splitscreen; i++)
|
||||
{
|
||||
if (displayplayers[i] == playernum)
|
||||
P_ResetCamera(p, &camera[i]);
|
||||
if (camera[i].chase)
|
||||
{
|
||||
if (displayplayers[i] == playernum)
|
||||
P_ResetCamera(p, &camera[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5735,6 +5735,10 @@ static void P_NetArchiveMisc(savebuffer_t *save, boolean resending)
|
|||
WRITEUINT32(save->p, racecountdown);
|
||||
WRITEUINT32(save->p, exitcountdown);
|
||||
|
||||
// exitcondition_t
|
||||
WRITEUINT8(save->p, g_exit.losing);
|
||||
WRITEUINT8(save->p, g_exit.retry);
|
||||
|
||||
WRITEFIXED(save->p, gravity);
|
||||
WRITEFIXED(save->p, mapobjectscale);
|
||||
|
||||
|
|
@ -5910,6 +5914,10 @@ static boolean P_NetUnArchiveMisc(savebuffer_t *save, boolean reloading)
|
|||
racecountdown = READUINT32(save->p);
|
||||
exitcountdown = READUINT32(save->p);
|
||||
|
||||
// exitcondition_t
|
||||
g_exit.losing = READUINT8(save->p);
|
||||
g_exit.retry = READUINT8(save->p);
|
||||
|
||||
gravity = READFIXED(save->p);
|
||||
mapobjectscale = READFIXED(save->p);
|
||||
|
||||
|
|
|
|||
|
|
@ -1220,46 +1220,6 @@ static void P_LoadSidedefs(UINT8 *data)
|
|||
sd->toptexture = sd->midtexture = sd->bottomtexture = 0;
|
||||
break;
|
||||
|
||||
case 413: // Change music
|
||||
{
|
||||
if (!isfrontside)
|
||||
break;
|
||||
|
||||
char process[8+1];
|
||||
|
||||
sd->toptexture = sd->midtexture = sd->bottomtexture = 0;
|
||||
if (msd->bottomtexture[0] != '-' || msd->bottomtexture[1] != '\0')
|
||||
{
|
||||
M_Memcpy(process,msd->bottomtexture,8);
|
||||
process[8] = '\0';
|
||||
sd->bottomtexture = get_number(process);
|
||||
}
|
||||
|
||||
if (!(msd->midtexture[0] == '-' && msd->midtexture[1] == '\0') || msd->midtexture[1] != '\0')
|
||||
{
|
||||
M_Memcpy(process,msd->midtexture,8);
|
||||
process[8] = '\0';
|
||||
sd->midtexture = get_number(process);
|
||||
}
|
||||
|
||||
if (msd->toptexture[0] != '-' && msd->toptexture[1] != '\0')
|
||||
{
|
||||
sd->line->stringargs[0] = Z_Malloc(7, PU_LEVEL, NULL);
|
||||
M_Memcpy(process,msd->toptexture,8);
|
||||
process[8] = '\0';
|
||||
|
||||
// If they type in O_ or D_ and their music name, just shrug,
|
||||
// then copy the rest instead.
|
||||
if ((process[0] == 'O' || process[0] == 'D') && process[7])
|
||||
M_Memcpy(sd->line->stringargs[0], process+2, 6);
|
||||
else // Assume it's a proper music name.
|
||||
M_Memcpy(sd->line->stringargs[0], process, 6);
|
||||
sd->line->stringargs[0][6] = '\0';
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 414: // Play SFX
|
||||
{
|
||||
sd->toptexture = sd->midtexture = sd->bottomtexture = 0;
|
||||
|
|
@ -5586,28 +5546,6 @@ static void P_ConvertBinaryLinedefTypes(void)
|
|||
lines[i].args[3] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS;
|
||||
lines[i].args[4] = lines[i].frontsector->ceilingheight >> FRACBITS;
|
||||
break;
|
||||
case 413: //Change music
|
||||
if (lines[i].flags & ML_NOCLIMB)
|
||||
lines[i].args[1] |= TMM_ALLPLAYERS;
|
||||
if (lines[i].flags & ML_SKEWTD)
|
||||
lines[i].args[1] |= TMM_OFFSET;
|
||||
if (lines[i].flags & ML_NOSKEW)
|
||||
lines[i].args[1] |= TMM_FADE;
|
||||
if (lines[i].flags & ML_BLOCKPLAYERS)
|
||||
lines[i].args[1] |= TMM_NORELOAD;
|
||||
if (lines[i].flags & ML_NOTBOUNCY)
|
||||
lines[i].args[1] |= TMM_FORCERESET;
|
||||
if (lines[i].flags & ML_MIDSOLID)
|
||||
lines[i].args[1] |= TMM_NOLOOP;
|
||||
if (lines[i].flags & ML_MIDPEG)
|
||||
lines[i].args[1] |= TMM_NOCREDIT;
|
||||
lines[i].args[2] = sides[lines[i].sidenum[0]].midtexture;
|
||||
lines[i].args[3] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS;
|
||||
lines[i].args[4] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS;
|
||||
lines[i].args[5] = (lines[i].sidenum[1] != 0xffff) ? sides[lines[i].sidenum[1]].textureoffset >> FRACBITS : 0;
|
||||
lines[i].args[6] = (lines[i].sidenum[1] != 0xffff) ? sides[lines[i].sidenum[1]].rowoffset >> FRACBITS : -1;
|
||||
lines[i].args[7] = sides[lines[i].sidenum[0]].bottomtexture;
|
||||
break;
|
||||
case 414: //Play sound effect
|
||||
lines[i].args[3] = tag;
|
||||
if (tag != 0)
|
||||
|
|
@ -7524,6 +7462,9 @@ static void P_InitLevelSettings(void)
|
|||
racecountdown = exitcountdown = musiccountdown = exitfadestarted = 0;
|
||||
curlap = bestlap = 0; // SRB2Kart
|
||||
|
||||
g_exit.losing = false;
|
||||
g_exit.retry = false;
|
||||
|
||||
// Gamespeed and frantic items
|
||||
gamespeed = KARTSPEED_EASY;
|
||||
franticitems = false;
|
||||
|
|
@ -7754,6 +7695,8 @@ static void P_SetupCamera(UINT8 pnum, camera_t *cam)
|
|||
cam->subsector = R_PointInSubsector(cam->x, cam->y); // make sure camera has a subsector set -- Monster Iestyn (12/11/18)
|
||||
}
|
||||
}
|
||||
|
||||
cam->chase = false; // tell camera to reset its position next tic
|
||||
}
|
||||
|
||||
static void P_InitCamera(void)
|
||||
|
|
@ -8165,7 +8108,6 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
|
|||
if (K_PodiumSequence())
|
||||
{
|
||||
// mapmusrng is set by local player position in K_ResetCeremony
|
||||
P_ResetLevelMusic();
|
||||
P_LoadLevelMusic();
|
||||
}
|
||||
else if (gamestate == GS_LEVEL)
|
||||
|
|
|
|||
82
src/p_spec.c
82
src/p_spec.c
|
|
@ -2886,88 +2886,6 @@ boolean P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, cha
|
|||
}
|
||||
break;
|
||||
|
||||
case 413: // Change music
|
||||
// FIXME: port to new music system
|
||||
#if 0
|
||||
// console player only unless TMM_ALLPLAYERS is set
|
||||
if ((args[1] & TMM_ALLPLAYERS) || (mo && mo->player && P_IsLocalPlayer(mo->player)) || titlemapinaction)
|
||||
{
|
||||
boolean musicsame = (!stringargs[0] || !stringargs[0][0] || !strnicmp(stringargs[0], S_MusicName(), 7));
|
||||
UINT16 tracknum = (UINT16)max(args[7], 0);
|
||||
INT32 position = (INT32)max(args[2], 0);
|
||||
UINT32 prefadems = (UINT32)max(args[3], 0);
|
||||
UINT32 postfadems = (UINT32)max(args[4], 0);
|
||||
UINT8 fadetarget = (UINT8)max(args[5], 0);
|
||||
INT16 fadesource = (INT16)max(args[6], -1);
|
||||
|
||||
// Seek offset from current song position
|
||||
if (args[1] & TMM_OFFSET)
|
||||
{
|
||||
// adjust for loop point if subtracting
|
||||
if (position < 0 && S_GetMusicLength() &&
|
||||
S_GetMusicPosition() > S_GetMusicLoopPoint() &&
|
||||
S_GetMusicPosition() + position < S_GetMusicLoopPoint())
|
||||
position = max(S_GetMusicLength() - (S_GetMusicLoopPoint() - (S_GetMusicPosition() + position)), 0);
|
||||
else
|
||||
position = max(S_GetMusicPosition() + position, 0);
|
||||
}
|
||||
|
||||
// Fade current music to target volume (if music won't be changed)
|
||||
if ((args[1] & TMM_FADE) && fadetarget && musicsame)
|
||||
{
|
||||
// 0 fadesource means fade from current volume.
|
||||
// meaning that we can't specify volume 0 as the source volume -- this starts at 1.
|
||||
if (!fadesource)
|
||||
fadesource = -1;
|
||||
|
||||
if (!postfadems)
|
||||
S_SetInternalMusicVolume(fadetarget);
|
||||
else
|
||||
S_FadeMusicFromVolume(fadetarget, fadesource, postfadems);
|
||||
|
||||
if (position)
|
||||
S_SetMusicPosition(position);
|
||||
}
|
||||
// Change the music and apply position/fade operations
|
||||
else
|
||||
{
|
||||
if (!stringargs[0])
|
||||
break;
|
||||
|
||||
strncpy(mapmusname, stringargs[0], 7);
|
||||
mapmusname[6] = 0;
|
||||
|
||||
mapmusflags = tracknum & MUSIC_TRACKMASK;
|
||||
if (!(args[1] & TMM_NORELOAD))
|
||||
mapmusflags |= MUSIC_RELOADRESET;
|
||||
if (args[1] & TMM_FORCERESET)
|
||||
mapmusflags |= MUSIC_FORCERESET;
|
||||
|
||||
mapmusposition = position;
|
||||
mapmusresume = 0;
|
||||
|
||||
S_ChangeMusicEx(mapmusname, mapmusflags, !(args[1] & TMM_NOLOOP), position,
|
||||
!(args[1] & TMM_FADE) ? prefadems : 0,
|
||||
!(args[1] & TMM_FADE) ? postfadems : 0);
|
||||
|
||||
if (!(args[1] & TMM_NOCREDIT))
|
||||
S_ShowMusicCredit();
|
||||
|
||||
if ((args[1] & TMM_FADE) && fadetarget)
|
||||
{
|
||||
if (!postfadems)
|
||||
S_SetInternalMusicVolume(fadetarget);
|
||||
else
|
||||
S_FadeMusicFromVolume(fadetarget, fadesource, postfadems);
|
||||
}
|
||||
}
|
||||
|
||||
// Except, you can use the TMM_NORELOAD flag to change this behavior.
|
||||
// if (mapmusflags & MUSIC_RELOADRESET) then it will reset the music in G_PlayerReborn.
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 414: // Play SFX
|
||||
P_PlaySFX(stringargs[0] ? get_number(stringargs[0]) : sfx_None, mo, callsec, args[3], args[1], args[2]);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -729,8 +729,8 @@ void P_Ticker(boolean run)
|
|||
timeinmap = (timeinmap-1) & ~3;
|
||||
G_PreviewRewind(leveltime);
|
||||
}
|
||||
else if (demo.freecam && democam.cam) // special case: allow freecam to MOVE during pause!
|
||||
P_DemoCameraMovement(democam.cam);
|
||||
else
|
||||
P_RunChaseCameras(); // special case: allow freecam to MOVE during pause!
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
336
src/p_user.c
336
src/p_user.c
|
|
@ -1082,6 +1082,15 @@ boolean P_IsDisplayPlayer(player_t *player)
|
|||
return false;
|
||||
}
|
||||
|
||||
// Freecam still techically has a player in
|
||||
// displayplayers. But since the camera is detached, it
|
||||
// would be weird if sounds were heard from that player's
|
||||
// perspective.
|
||||
if (demo.freecam)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0; i <= r_splitscreen; i++) // DON'T skip P1
|
||||
{
|
||||
if (player == &players[displayplayers[i]])
|
||||
|
|
@ -1309,19 +1318,12 @@ void P_DoPlayerExit(player_t *player, pflags_t flags)
|
|||
|
||||
if (P_CheckRacers() && !exitcountdown)
|
||||
{
|
||||
if (specialout == true)
|
||||
{
|
||||
exitcountdown = TICRATE;
|
||||
}
|
||||
else
|
||||
{
|
||||
exitcountdown = raceexittime+1;
|
||||
}
|
||||
G_BeginLevelExit();
|
||||
}
|
||||
}
|
||||
else if (!exitcountdown) // All other gametypes
|
||||
{
|
||||
exitcountdown = raceexittime+1;
|
||||
G_BeginLevelExit();
|
||||
}
|
||||
|
||||
if (grandprixinfo.gp == true && player->bot == false && losing == false)
|
||||
|
|
@ -2350,45 +2352,6 @@ static void P_UpdatePlayerAngle(player_t *player)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_SpectatorMovement
|
||||
//
|
||||
// Control for spectators in multiplayer
|
||||
//
|
||||
static void P_SpectatorMovement(player_t *player)
|
||||
{
|
||||
ticcmd_t *cmd = &player->cmd;
|
||||
|
||||
P_UpdatePlayerAngle(player);
|
||||
|
||||
ticruned++;
|
||||
if (!(cmd->flags & TICCMD_RECEIVED))
|
||||
ticmiss++;
|
||||
|
||||
if (cmd->buttons & BT_ACCELERATE)
|
||||
player->mo->z += 32*mapobjectscale;
|
||||
else if (cmd->buttons & BT_BRAKE)
|
||||
player->mo->z -= 32*mapobjectscale;
|
||||
|
||||
if (!(player->mo->flags & MF_NOCLIPHEIGHT))
|
||||
{
|
||||
if (player->mo->z > player->mo->ceilingz - player->mo->height)
|
||||
player->mo->z = player->mo->ceilingz - player->mo->height;
|
||||
if (player->mo->z < player->mo->floorz)
|
||||
player->mo->z = player->mo->floorz;
|
||||
}
|
||||
|
||||
player->mo->momx = player->mo->momy = player->mo->momz = 0;
|
||||
if (cmd->forwardmove != 0)
|
||||
{
|
||||
P_Thrust(player->mo, player->mo->angle, cmd->forwardmove*mapobjectscale);
|
||||
|
||||
// Quake-style flying spectators :D
|
||||
player->mo->momz += FixedMul(cmd->forwardmove*mapobjectscale, AIMINGTOSLOPE(player->aiming));
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// P_MovePlayer
|
||||
void P_MovePlayer(player_t *player)
|
||||
|
|
@ -2415,7 +2378,6 @@ void P_MovePlayer(player_t *player)
|
|||
if (player->spectator)
|
||||
{
|
||||
player->mo->eflags &= ~MFE_VERTICALFLIP; // deflip...
|
||||
P_SpectatorMovement(player);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -2970,184 +2932,87 @@ fixed_t t_cam_dist[MAXSPLITSCREENPLAYERS] = {-42,-42,-42,-42};
|
|||
fixed_t t_cam_height[MAXSPLITSCREENPLAYERS] = {-42,-42,-42,-42};
|
||||
fixed_t t_cam_rotate[MAXSPLITSCREENPLAYERS] = {-42,-42,-42,-42};
|
||||
|
||||
// Heavily simplified version of G_BuildTicCmd that only takes the local first player's control input and converts it to readable ticcmd_t
|
||||
// we then throw that ticcmd garbage in the camera and make it move
|
||||
// TODO: please just use the normal ticcmd function somehow
|
||||
|
||||
static ticcmd_t cameracmd;
|
||||
|
||||
struct demofreecam_s democam;
|
||||
|
||||
// called by m_menu to reinit cam input every time it's toggled
|
||||
void P_InitCameraCmd(void)
|
||||
{
|
||||
memset(&cameracmd, 0, sizeof(ticcmd_t)); // initialize cmd
|
||||
}
|
||||
|
||||
static ticcmd_t *P_CameraCmd(camera_t *cam)
|
||||
{
|
||||
/*
|
||||
INT32 forward, axis; //i
|
||||
// these ones used for multiple conditions
|
||||
boolean turnleft, turnright, mouseaiming;
|
||||
boolean invertmouse, lookaxis, usejoystick, kbl;
|
||||
INT32 player_invert;
|
||||
INT32 screen_invert;
|
||||
*/
|
||||
ticcmd_t *cmd = &cameracmd;
|
||||
|
||||
(void)cam;
|
||||
|
||||
if (!demo.playback)
|
||||
return cmd; // empty cmd, no.
|
||||
|
||||
/*
|
||||
kbl = democam.keyboardlook;
|
||||
|
||||
G_CopyTiccmd(cmd, I_BaseTiccmd(), 1); // empty, or external driver
|
||||
|
||||
mouseaiming = true;
|
||||
invertmouse = cv_invertmouse.value;
|
||||
lookaxis = cv_lookaxis[0].value;
|
||||
|
||||
usejoystick = true;
|
||||
turnright = PlayerInputDown(1, gc_turnright);
|
||||
turnleft = PlayerInputDown(1, gc_turnleft);
|
||||
|
||||
axis = PlayerJoyAxis(1, AXISTURN);
|
||||
|
||||
if (encoremode)
|
||||
{
|
||||
turnright ^= turnleft; // swap these using three XORs
|
||||
turnleft ^= turnright;
|
||||
turnright ^= turnleft;
|
||||
axis = -axis;
|
||||
}
|
||||
|
||||
if (axis != 0)
|
||||
{
|
||||
turnright = turnright || (axis > 0);
|
||||
turnleft = turnleft || (axis < 0);
|
||||
}
|
||||
forward = 0;
|
||||
|
||||
cmd->turning = 0;
|
||||
|
||||
// let movement keys cancel each other out
|
||||
if (turnright && !(turnleft))
|
||||
{
|
||||
cmd->turning -= KART_FULLTURN;
|
||||
}
|
||||
else if (turnleft && !(turnright))
|
||||
{
|
||||
cmd->turning += KART_FULLTURN;
|
||||
}
|
||||
|
||||
cmd->turning -= (mousex * 8) * (encoremode ? -1 : 1);
|
||||
|
||||
axis = PlayerJoyAxis(1, AXISMOVE);
|
||||
if (PlayerInputDown(1, gc_a) || (usejoystick && axis > 0))
|
||||
cmd->buttons |= BT_ACCELERATE;
|
||||
axis = PlayerJoyAxis(1, AXISBRAKE);
|
||||
if (PlayerInputDown(1, gc_brake) || (usejoystick && axis > 0))
|
||||
cmd->buttons |= BT_BRAKE;
|
||||
axis = PlayerJoyAxis(1, AXISAIM);
|
||||
if (PlayerInputDown(1, gc_aimforward) || (usejoystick && axis < 0))
|
||||
forward += MAXPLMOVE;
|
||||
if (PlayerInputDown(1, gc_aimbackward) || (usejoystick && axis > 0))
|
||||
forward -= MAXPLMOVE;
|
||||
|
||||
// fire with any button/key
|
||||
axis = PlayerJoyAxis(1, AXISFIRE);
|
||||
if (PlayerInputDown(1, gc_fire) || (usejoystick && axis > 0))
|
||||
cmd->buttons |= BT_ATTACK;
|
||||
|
||||
// spectator aiming shit, ahhhh...
|
||||
player_invert = invertmouse ? -1 : 1;
|
||||
screen_invert = 1; // nope
|
||||
|
||||
// mouse look stuff (mouse look is not the same as mouse aim)
|
||||
kbl = false;
|
||||
|
||||
// looking up/down
|
||||
cmd->aiming += (mlooky<<19)*player_invert*screen_invert;
|
||||
|
||||
axis = PlayerJoyAxis(1, AXISLOOK);
|
||||
|
||||
// spring back if not using keyboard neither mouselookin'
|
||||
if (!kbl && !lookaxis && !mouseaiming)
|
||||
cmd->aiming = 0;
|
||||
|
||||
if (PlayerInputDown(1, gc_lookup) || (axis < 0))
|
||||
{
|
||||
cmd->aiming += KB_LOOKSPEED * screen_invert;
|
||||
kbl = true;
|
||||
}
|
||||
else if (PlayerInputDown(1, gc_lookdown) || (axis > 0))
|
||||
{
|
||||
cmd->aiming -= KB_LOOKSPEED * screen_invert;
|
||||
kbl = true;
|
||||
}
|
||||
|
||||
if (PlayerInputDown(1, gc_centerview)) // No need to put a spectator limit on this one though :V
|
||||
cmd->aiming = 0;
|
||||
|
||||
cmd->forwardmove += (SINT8)forward;
|
||||
|
||||
if (cmd->forwardmove > MAXPLMOVE)
|
||||
cmd->forwardmove = MAXPLMOVE;
|
||||
else if (cmd->forwardmove < -MAXPLMOVE)
|
||||
cmd->forwardmove = -MAXPLMOVE;
|
||||
|
||||
if (cmd->turning > KART_FULLTURN)
|
||||
cmd->turning = KART_FULLTURN;
|
||||
else if (cmd->turning < -KART_FULLTURN)
|
||||
cmd->turning = -KART_FULLTURN;
|
||||
|
||||
democam.keyboardlook = kbl;
|
||||
*/
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
||||
void P_DemoCameraMovement(camera_t *cam)
|
||||
{
|
||||
ticcmd_t *cmd;
|
||||
angle_t thrustangle;
|
||||
mobj_t *awayviewmobj_hack;
|
||||
player_t *lastp;
|
||||
|
||||
// update democam stuff with what we got here:
|
||||
democam.cam = cam;
|
||||
democam.localangle = cam->angle;
|
||||
democam.localaiming = cam->aiming;
|
||||
boolean moving = false;
|
||||
|
||||
// first off we need to get button input
|
||||
cmd = P_CameraCmd(cam);
|
||||
cmd = D_LocalTiccmd(0);
|
||||
|
||||
if (cmd->aiming != 0)
|
||||
{
|
||||
cam->aiming += cmd->aiming << TICCMD_REDUCE;
|
||||
|
||||
cam->reset_aiming = false;
|
||||
}
|
||||
|
||||
cam->aiming += cmd->aiming << TICCMD_REDUCE;
|
||||
cam->angle += cmd->turning << TICCMD_REDUCE;
|
||||
|
||||
democam.localangle += cmd->turning << TICCMD_REDUCE;
|
||||
democam.localaiming += cmd->aiming << TICCMD_REDUCE;
|
||||
|
||||
cam->aiming = G_ClipAimingPitch((INT32 *)&cam->aiming);
|
||||
democam.localaiming = G_ClipAimingPitch((INT32 *)&democam.localaiming);
|
||||
|
||||
// camera movement:
|
||||
if (cmd->buttons & BT_ACCELERATE)
|
||||
cam->z += 32*mapobjectscale;
|
||||
else if (cmd->buttons & BT_BRAKE)
|
||||
cam->z -= 32*mapobjectscale;
|
||||
if (!democam.button_a_held)
|
||||
{
|
||||
if (cmd->buttons & BT_ACCELERATE)
|
||||
{
|
||||
cam->z += 32*mapobjectscale;
|
||||
moving = true;
|
||||
}
|
||||
else if (cmd->buttons & BT_BRAKE)
|
||||
{
|
||||
cam->z -= 32*mapobjectscale;
|
||||
moving = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(cmd->buttons & (BT_ACCELERATE | BT_DRIFT)) && democam.button_a_held)
|
||||
{
|
||||
democam.button_a_held--;
|
||||
}
|
||||
|
||||
// if you hold item, you will lock on to displayplayer. (The last player you were ""f12-ing"")
|
||||
if (cmd->buttons & BT_ATTACK)
|
||||
if (demo.freecam && cmd->buttons & BT_ATTACK)
|
||||
{
|
||||
lastp = &players[displayplayers[0]]; // Fun fact, I was trying displayplayers[0]->mo as if it was Lua like an absolute idiot.
|
||||
cam->angle = R_PointToAngle2(cam->x, cam->y, lastp->mo->x, lastp->mo->y);
|
||||
cam->aiming = R_PointToAngle2(0, cam->z, R_PointToDist2(cam->x, cam->y, lastp->mo->x, lastp->mo->y), lastp->mo->z + lastp->mo->scale*128*P_MobjFlip(lastp->mo)); // This is still unholy. Aim a bit above their heads.
|
||||
|
||||
cam->reset_aiming = false;
|
||||
}
|
||||
|
||||
if (cmd->forwardmove != 0)
|
||||
{
|
||||
moving = true;
|
||||
}
|
||||
|
||||
// After switching to democam, the vertical angle of
|
||||
// chasecam is inherited. This is intentional because it
|
||||
// creates a smooth transition. However, moving
|
||||
// forward/back will have a slope. So, as long as democam
|
||||
// controls haven't been used to alter the vertical angle,
|
||||
// slowly reset it to flat.
|
||||
if ((cam->reset_aiming && moving) || ((cmd->buttons & BT_DRIFT) && !democam.button_a_held))
|
||||
{
|
||||
INT32 aiming = cam->aiming;
|
||||
INT32 smooth = FixedMul(ANGLE_11hh / 4, FCOS(cam->aiming));
|
||||
|
||||
if (abs(smooth) < abs(aiming))
|
||||
{
|
||||
cam->aiming -= smooth * intsign(aiming);
|
||||
}
|
||||
else
|
||||
{
|
||||
cam->aiming = 0;
|
||||
cam->reset_aiming = false; // completely smoothed out
|
||||
}
|
||||
}
|
||||
|
||||
G_FinalClipAimingPitch((INT32 *)&cam->aiming, NULL, false);
|
||||
|
||||
cam->momx = cam->momy = cam->momz = 0;
|
||||
|
||||
if (cmd->forwardmove != 0)
|
||||
|
|
@ -3156,25 +3021,35 @@ void P_DemoCameraMovement(camera_t *cam)
|
|||
|
||||
cam->x += FixedMul(cmd->forwardmove*mapobjectscale, FINECOSINE(thrustangle));
|
||||
cam->y += FixedMul(cmd->forwardmove*mapobjectscale, FINESINE(thrustangle));
|
||||
cam->z += FixedMul(cmd->forwardmove*mapobjectscale, AIMINGTOSLOPE(cam->aiming));
|
||||
|
||||
if (!cam->reset_aiming)
|
||||
{
|
||||
cam->z += FixedMul(cmd->forwardmove*mapobjectscale, AIMINGTOSLOPE(cam->aiming));
|
||||
}
|
||||
// momentums are useless here, directly add to the coordinates
|
||||
|
||||
// this.......... doesn't actually check for floors and walls and whatnot but the function to do that is a pure mess so fuck that.
|
||||
// besides freecam going inside walls sounds pretty cool on paper.
|
||||
}
|
||||
|
||||
// awayviewmobj hack; this is to prevent us from hearing sounds from the player's perspective
|
||||
|
||||
awayviewmobj_hack = P_SpawnMobj(cam->x, cam->y, cam->z, MT_THOK);
|
||||
awayviewmobj_hack->tics = 2;
|
||||
awayviewmobj_hack->renderflags |= RF_DONTDRAW;
|
||||
|
||||
democam.soundmobj = awayviewmobj_hack;
|
||||
|
||||
// update subsector to avoid crashes;
|
||||
cam->subsector = R_PointInSubsector(cam->x, cam->y);
|
||||
}
|
||||
|
||||
void P_ToggleDemoCamera(void)
|
||||
{
|
||||
if (!demo.freecam) // toggle on
|
||||
{
|
||||
demo.freecam = true;
|
||||
democam.button_a_held = 2;
|
||||
camera[0].reset_aiming = true;
|
||||
}
|
||||
else // toggle off
|
||||
{
|
||||
demo.freecam = false;
|
||||
}
|
||||
}
|
||||
|
||||
void P_ResetCamera(player_t *player, camera_t *thiscam)
|
||||
{
|
||||
tic_t tries = 0;
|
||||
|
|
@ -3211,6 +3086,8 @@ void P_ResetCamera(player_t *player, camera_t *thiscam)
|
|||
thiscam->radius = 20*FRACUNIT;
|
||||
thiscam->height = 16*FRACUNIT;
|
||||
|
||||
thiscam->reset_aiming = true;
|
||||
|
||||
while (!P_MoveChaseCamera(player,thiscam,true) && ++tries < 2*TICRATE);
|
||||
}
|
||||
|
||||
|
|
@ -3239,8 +3116,6 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
|
|||
thiscam->old_angle = thiscam->angle;
|
||||
thiscam->old_aiming = thiscam->aiming;
|
||||
|
||||
democam.soundmobj = NULL; // reset this each frame, we don't want the game crashing for stupid reasons now do we
|
||||
|
||||
// We probably shouldn't move the camera if there is no player or player mobj somehow
|
||||
if (!player || !player->mo)
|
||||
return true;
|
||||
|
|
@ -3249,12 +3124,15 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
|
|||
if (thiscam->subsector == NULL || thiscam->subsector->sector == NULL)
|
||||
return true;
|
||||
|
||||
if (demo.freecam)
|
||||
if (demo.freecam || player->spectator)
|
||||
{
|
||||
P_DemoCameraMovement(thiscam);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (paused || P_AutoPause())
|
||||
return true;
|
||||
|
||||
playerScale = FixedDiv(player->mo->scale, mapobjectscale);
|
||||
scaleDiff = playerScale - FRACUNIT;
|
||||
|
||||
|
|
@ -3542,6 +3420,8 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
|
|||
z = mo->z + pviewheight + distz;
|
||||
}
|
||||
|
||||
z += player->cameraOffset;
|
||||
|
||||
// point viewed by the camera
|
||||
// this point is just 64 unit forward the player
|
||||
dist = 64*cameraScale;
|
||||
|
|
@ -3586,13 +3466,13 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
|
|||
|
||||
if (mo->eflags & MFE_VERTICALFLIP)
|
||||
{
|
||||
angle = R_PointToAngle2(0, thiscam->z + thiscam->height, dist, mo->z + mo->height - player->mo->height);
|
||||
angle = R_PointToAngle2(0, thiscam->z + thiscam->height, dist, mo->z + mo->height - player->mo->height + player->cameraOffset);
|
||||
if (thiscam->pitch < ANGLE_180 && thiscam->pitch > angle)
|
||||
angle += (thiscam->pitch - angle)/2;
|
||||
}
|
||||
else
|
||||
{
|
||||
angle = R_PointToAngle2(0, thiscam->z, dist, mo->z + player->mo->height);
|
||||
angle = R_PointToAngle2(0, thiscam->z, dist, mo->z + player->mo->height + player->cameraOffset);
|
||||
if (thiscam->pitch >= ANGLE_180 && thiscam->pitch < angle)
|
||||
angle -= (angle - thiscam->pitch)/2;
|
||||
}
|
||||
|
|
@ -3890,7 +3770,7 @@ void P_DoTimeOver(player_t *player)
|
|||
|
||||
if (!exitcountdown)
|
||||
{
|
||||
exitcountdown = raceexittime;
|
||||
G_BeginLevelExit();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4802,6 +4682,22 @@ void P_ForceLocalAngle(player_t *player, angle_t angle)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// jartha: OK, I don't really know how ticcmds work. The
|
||||
// specific problem I'm trying to fix is that, on level
|
||||
// load, the player angle gets reset. But the ticcmds
|
||||
// copied in afterward don't match this angle, and they
|
||||
// influence the player steering.
|
||||
for (i = 0; i <= splitscreen; i++)
|
||||
{
|
||||
if (player == &players[g_localplayers[i]])
|
||||
{
|
||||
D_ResetTiccmdAngle(i, angle);
|
||||
localsteering[i] = angle;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean P_PlayerFullbright(player_t *player)
|
||||
|
|
|
|||
21
src/r_fps.c
21
src/r_fps.c
|
|
@ -22,9 +22,6 @@
|
|||
#include "r_state.h"
|
||||
#include "z_zone.h"
|
||||
#include "console.h" // con_startup_loadprogress
|
||||
#ifdef HWRENDER
|
||||
#include "hardware/hw_main.h" // for cv_glshearing
|
||||
#endif
|
||||
|
||||
static CV_PossibleValue_t fpscap_cons_t[] = {
|
||||
#ifdef DEVELOP
|
||||
|
|
@ -117,23 +114,7 @@ static vector3_t *R_LerpVector3(const vector3_t *from, const vector3_t *to, fixe
|
|||
// 18/08/18: (No it's actually 16*viewheight, thanks Jimita for finding this out)
|
||||
static void R_SetupFreelook(player_t *player, boolean skybox)
|
||||
{
|
||||
#ifndef HWRENDER
|
||||
(void)player;
|
||||
(void)skybox;
|
||||
#endif
|
||||
|
||||
// clip it in the case we are looking a hardware 90 degrees full aiming
|
||||
// (lmps, network and use F12...)
|
||||
if (rendermode == render_soft
|
||||
#ifdef HWRENDER
|
||||
|| (rendermode == render_opengl
|
||||
&& (cv_glshearing.value == 1
|
||||
|| (cv_glshearing.value == 2 && R_IsViewpointThirdPerson(player, skybox))))
|
||||
#endif
|
||||
)
|
||||
{
|
||||
G_SoftwareClipAimingPitch((INT32 *)&aimingangle);
|
||||
}
|
||||
G_FinalClipAimingPitch((INT32 *)&aimingangle, player, skybox);
|
||||
|
||||
centeryfrac = (viewheight/2)<<FRACBITS;
|
||||
|
||||
|
|
|
|||
21
src/r_main.c
21
src/r_main.c
|
|
@ -81,6 +81,7 @@ mobj_t *r_viewmobj;
|
|||
int r_splitscreen;
|
||||
|
||||
fixed_t rendertimefrac;
|
||||
fixed_t rendertimefrac_unpaused;
|
||||
fixed_t renderdeltatics;
|
||||
boolean renderisnewtic;
|
||||
|
||||
|
|
@ -978,7 +979,7 @@ angle_t R_ViewRollAngle(const player_t *player)
|
|||
|
||||
if (cv_tilting.value)
|
||||
{
|
||||
if (!player->spectator)
|
||||
if (!player->spectator && !demo.freecam)
|
||||
{
|
||||
roll += player->tilt;
|
||||
}
|
||||
|
|
@ -1227,7 +1228,7 @@ R_SetupCommonFrame
|
|||
else
|
||||
newview->sector = R_PointInSubsector(newview->x, newview->y)->sector;
|
||||
|
||||
R_InterpolateView(rendertimefrac);
|
||||
R_InterpolateView(rendertimefrac_unpaused);
|
||||
}
|
||||
|
||||
static void R_SetupAimingFrame(int s)
|
||||
|
|
@ -1265,8 +1266,12 @@ void R_SetupFrame(int s)
|
|||
|
||||
R_SetViewContext(VIEWCONTEXT_PLAYER1 + s);
|
||||
|
||||
if (player->spectator) // no spectator chasecam
|
||||
chasecam = false; // force chasecam off
|
||||
if (player->spectator)
|
||||
{
|
||||
// Free flying spectator uses demo freecam. This
|
||||
// requires chasecam to be enabled.
|
||||
chasecam = true;
|
||||
}
|
||||
|
||||
if (chasecam && (thiscam && !thiscam->chase))
|
||||
{
|
||||
|
|
@ -1292,7 +1297,7 @@ void R_SetupFrame(int s)
|
|||
|
||||
R_SetupCommonFrame(player, r_viewmobj->subsector);
|
||||
}
|
||||
else if (!player->spectator && chasecam)
|
||||
else if (chasecam)
|
||||
// use outside cam view
|
||||
{
|
||||
r_viewmobj = NULL;
|
||||
|
|
@ -1430,10 +1435,8 @@ boolean R_ViewpointHasChasecam(player_t *player)
|
|||
}
|
||||
}
|
||||
|
||||
if (player->playerstate == PST_DEAD || gamestate == GS_TITLESCREEN)
|
||||
if (player->playerstate == PST_DEAD || gamestate == GS_TITLESCREEN || player->spectator)
|
||||
chasecam = true; // force chasecam on
|
||||
else if (player->spectator) // no spectator chasecam
|
||||
chasecam = false; // force chasecam off
|
||||
|
||||
return chasecam;
|
||||
}
|
||||
|
|
@ -1446,7 +1449,7 @@ boolean R_IsViewpointThirdPerson(player_t *player, boolean skybox)
|
|||
if (player->awayview.tics || skybox)
|
||||
return chasecam;
|
||||
// use outside cam view
|
||||
else if (!player->spectator && chasecam)
|
||||
else if (chasecam)
|
||||
return true;
|
||||
|
||||
// use the player's eyes view
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@ extern size_t validcount, linecount, loopcount, framecount;
|
|||
|
||||
// The fraction of a tic being drawn (for interpolation between two tics)
|
||||
extern fixed_t rendertimefrac;
|
||||
// Same as rendertimefrac but not suspended when the game is paused
|
||||
extern fixed_t rendertimefrac_unpaused;
|
||||
// Evaluated delta tics for this frame (how many tics since the last frame)
|
||||
extern fixed_t renderdeltatics;
|
||||
// The current render is a new logical tic
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ INT32 R_ThingLightLevel(mobj_t* thing)
|
|||
|
||||
if (player)
|
||||
{
|
||||
if (player->instaShieldCooldown && (player->rings <= 0) && (leveltime & 1))
|
||||
if (player->instaShieldCooldown && !player->whip && (player->rings <= 0) && (leveltime & 1))
|
||||
{
|
||||
// Darken on every other frame of instawhip cooldown
|
||||
lightlevel -= 128;
|
||||
|
|
|
|||
|
|
@ -540,11 +540,6 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (i == 0 && democam.soundmobj)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (player->awayview.tics)
|
||||
{
|
||||
listenmobj[i] = player->awayview.mobj;
|
||||
|
|
@ -554,7 +549,7 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume)
|
|||
listenmobj[i] = player->mo;
|
||||
}
|
||||
|
||||
if (origin && origin == listenmobj[i])
|
||||
if (origin && origin == listenmobj[i] && !demo.freecam)
|
||||
{
|
||||
itsUs = true;
|
||||
}
|
||||
|
|
@ -827,11 +822,6 @@ void S_UpdateSounds(void)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (i == 0 && democam.soundmobj)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (player->awayview.tics)
|
||||
{
|
||||
listenmobj[i] = player->awayview.mobj;
|
||||
|
|
@ -898,12 +888,15 @@ void S_UpdateSounds(void)
|
|||
{
|
||||
boolean itsUs = false;
|
||||
|
||||
for (i = r_splitscreen; i >= 0; i--)
|
||||
if (!demo.freecam)
|
||||
{
|
||||
if (c->origin != listenmobj[i])
|
||||
continue;
|
||||
for (i = r_splitscreen; i >= 0; i--)
|
||||
{
|
||||
if (c->origin != listenmobj[i])
|
||||
continue;
|
||||
|
||||
itsUs = true;
|
||||
itsUs = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (itsUs == false)
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T);
|
|||
#define UNIXBACKTRACE
|
||||
#endif
|
||||
|
||||
// Locations for searching for main.kart
|
||||
// Locations for searching for bios.pk3
|
||||
#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON)
|
||||
#define DEFAULTWADLOCATION1 "/usr/local/share/games/RingRacers"
|
||||
#define DEFAULTWADLOCATION2 "/usr/local/games/RingRacers"
|
||||
|
|
@ -150,7 +150,7 @@ typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T);
|
|||
|
||||
/** \brief WAD file to look for
|
||||
*/
|
||||
#define WADKEYWORD "main.kart"
|
||||
#define WADKEYWORD "bios.pk3"
|
||||
/** \brief holds wad path
|
||||
*/
|
||||
static char returnWadPath[256];
|
||||
|
|
@ -2104,7 +2104,7 @@ static void pathonly(char *s)
|
|||
}
|
||||
}
|
||||
|
||||
/** \brief search for main.kart in the given path
|
||||
/** \brief search for bios.pk3 in the given path
|
||||
|
||||
\param searchDir starting path
|
||||
|
||||
|
|
@ -2128,9 +2128,9 @@ static const char *searchWad(const char *searchDir)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/** \brief go through all possible paths and look for main.kart
|
||||
/** \brief go through all possible paths and look for bios.pk3
|
||||
|
||||
\return path to main.kart if any
|
||||
\return path to bios.pk3 if any
|
||||
|
||||
*/
|
||||
static const char *locateWad(void)
|
||||
|
|
@ -2260,7 +2260,7 @@ const char *I_LocateWad(void)
|
|||
|
||||
if (waddir)
|
||||
{
|
||||
// change to the directory where we found main.kart
|
||||
// change to the directory where we found bios.pk3
|
||||
#if defined (_WIN32)
|
||||
SetCurrentDirectoryA(waddir);
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ void __set_fpscr(long); // in libgcc / kernel's startup.s?
|
|||
#define O_BINARY 0
|
||||
#endif
|
||||
|
||||
// Locations for searching the main.kart
|
||||
// Locations for searching the bios.pk3
|
||||
#ifdef _arch_dreamcast
|
||||
#define DEFAULTWADLOCATION1 "/cd"
|
||||
#define DEFAULTWADLOCATION2 "/pc"
|
||||
|
|
@ -217,7 +217,7 @@ void __set_fpscr(long); // in libgcc / kernel's startup.s?
|
|||
|
||||
/** \brief WAD file to look for
|
||||
*/
|
||||
#define WADKEYWORD "main.kart"
|
||||
#define WADKEYWORD "bios.pk3"
|
||||
/** \brief holds wad path
|
||||
*/
|
||||
static char returnWadPath[256];
|
||||
|
|
@ -3436,7 +3436,7 @@ static void pathonly(char *s)
|
|||
}
|
||||
}
|
||||
|
||||
/** \brief search for main.kart in the given path
|
||||
/** \brief search for bios.pk3 in the given path
|
||||
|
||||
\param searchDir starting path
|
||||
|
||||
|
|
@ -3460,9 +3460,9 @@ static const char *searchWad(const char *searchDir)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/** \brief go through all possible paths and look for main.kart
|
||||
/** \brief go through all possible paths and look for bios.pk3
|
||||
|
||||
\return path to main.kart if any
|
||||
\return path to bios.pk3 if any
|
||||
*/
|
||||
static const char *locateWad(void)
|
||||
{
|
||||
|
|
@ -3579,7 +3579,7 @@ const char *I_LocateWad(void)
|
|||
|
||||
if (waddir)
|
||||
{
|
||||
// change to the directory where we found main.kart
|
||||
// change to the directory where we found bios.pk3
|
||||
#if (defined (_WIN32) && !defined (_WIN32_WCE)) && !defined (_XBOX)
|
||||
SetCurrentDirectoryA(waddir);
|
||||
#elif !defined (_WIN32_WCE) && !defined (_PS3)
|
||||
|
|
|
|||
|
|
@ -1171,7 +1171,7 @@ static void ST_overlayDrawer(void)
|
|||
{
|
||||
if (cv_showviewpointtext.value)
|
||||
{
|
||||
if (!demo.title && !P_IsLocalPlayer(stplyr))
|
||||
if (!demo.title && !P_IsLocalPlayer(stplyr) && !demo.freecam)
|
||||
{
|
||||
if (!r_splitscreen)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -134,6 +134,7 @@ TYPEDEF (unloaded_mapheader_t);
|
|||
TYPEDEF (tolinfo_t);
|
||||
TYPEDEF (cupheader_t);
|
||||
TYPEDEF (unloaded_cupheader_t);
|
||||
TYPEDEF (exitcondition_t);
|
||||
|
||||
// font.h
|
||||
TYPEDEF (font_t);
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ static patch_t *widebgpatch = NULL;
|
|||
static patch_t *bgtile = NULL; // SPECTILE/SRB2BACK
|
||||
static patch_t *interpic = NULL; // custom picture defined in map header
|
||||
|
||||
#define INFINITE_TIMER (INT16_MAX) // just some arbitrarily large value that won't easily overflow
|
||||
static INT32 timer;
|
||||
static INT32 powertype = PWRLV_DISABLED;
|
||||
|
||||
|
|
@ -86,6 +87,16 @@ intertype_t intertype = int_none;
|
|||
|
||||
static huddrawlist_h luahuddrawlist_intermission;
|
||||
|
||||
static boolean Y_CanSkipIntermission(void)
|
||||
{
|
||||
if (!netgame)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void Y_UnloadData(void);
|
||||
|
||||
//
|
||||
|
|
@ -1533,6 +1544,17 @@ finalcounter:
|
|||
}
|
||||
}
|
||||
|
||||
if (Y_CanSkipIntermission())
|
||||
{
|
||||
K_drawButton(
|
||||
2*FRACUNIT,
|
||||
(BASEVIDHEIGHT - 16)*FRACUNIT,
|
||||
0,
|
||||
kp_button_a[1],
|
||||
M_MenuConfirmHeld(0)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
const INT32 tickDown = (timer + 1)/TICRATE;
|
||||
|
||||
|
|
@ -1578,6 +1600,46 @@ void Y_Ticker(void)
|
|||
|
||||
LUA_HOOK(IntermissionThinker);
|
||||
|
||||
if (Y_CanSkipIntermission())
|
||||
{
|
||||
if (M_MenuConfirmPressed(0))
|
||||
{
|
||||
// If there is a roundqueue, make time for it.
|
||||
// Else, end instantly on button press.
|
||||
// Actually, give it a slight delay, so the "kaching" sound isn't cut off.
|
||||
const tic_t end = roundqueue.size != 0 ? 3*TICRATE : TICRATE;
|
||||
|
||||
if (intertic == -1) // card flip hasn't started
|
||||
{
|
||||
if (sorttic != -1)
|
||||
{
|
||||
intertic = sorttic;
|
||||
}
|
||||
else
|
||||
{
|
||||
intertic = 0;
|
||||
timer = end;
|
||||
}
|
||||
}
|
||||
else if (timer >= INFINITE_TIMER && intertic >= sorttic + 16) // card done flipping
|
||||
{
|
||||
const INT32 kaching = sorttic + 16 + (2*TICRATE);
|
||||
|
||||
if (intertic < kaching)
|
||||
{
|
||||
intertic = kaching; // kaching immediately
|
||||
}
|
||||
|
||||
timer = end;
|
||||
}
|
||||
}
|
||||
|
||||
if (intertic == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
intertic++;
|
||||
|
||||
// Team scramble code for team match and CTF.
|
||||
|
|
@ -1590,7 +1652,7 @@ void Y_Ticker(void)
|
|||
P_DoTeamscrambling();
|
||||
}*/
|
||||
|
||||
if ((timer && !--timer)
|
||||
if ((timer < INFINITE_TIMER && --timer <= 0)
|
||||
|| (intertic == endtic))
|
||||
{
|
||||
Y_EndIntermission();
|
||||
|
|
@ -1665,6 +1727,12 @@ void Y_Ticker(void)
|
|||
r++;
|
||||
data.jitter[data.num[q]] = 1;
|
||||
|
||||
// Player can skip the tally, kaching!
|
||||
if (Y_CanSkipIntermission() && timer < INFINITE_TIMER)
|
||||
{
|
||||
data.increase[data.num[q]] = 0;
|
||||
}
|
||||
|
||||
if (powertype != PWRLV_DISABLED)
|
||||
{
|
||||
// Power Levels
|
||||
|
|
@ -1815,6 +1883,21 @@ void Y_StartIntermission(void)
|
|||
sorttic = max((timer/2) - 2*TICRATE, 2*TICRATE);
|
||||
}
|
||||
|
||||
// TODO: code's a mess, I'm just making it extra clear
|
||||
// that this piece of code is supposed to take priority
|
||||
// over the above. :)
|
||||
if (Y_CanSkipIntermission())
|
||||
{
|
||||
timer = INFINITE_TIMER; // doesn't count down
|
||||
|
||||
if (sorttic != -1)
|
||||
{
|
||||
// Will start immediately, but must be triggered.
|
||||
// Needs to be TICRATE to bypass a condition in Y_Ticker.
|
||||
sorttic = TICRATE;
|
||||
}
|
||||
}
|
||||
|
||||
// We couldn't display the intermission even if we wanted to.
|
||||
// But we still need to give the players their score bonuses, dummy.
|
||||
//if (dedicated) return;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue