mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Merge branch 'master' of https://git.do.srb2.org/KartKrew/Kart into seeecret-colors
This commit is contained in:
commit
4344221252
65 changed files with 2915 additions and 1130 deletions
|
|
@ -146,6 +146,7 @@ add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32
|
|||
k_serverstats.c
|
||||
k_zvote.c
|
||||
k_mapuser.c
|
||||
k_powerup.cpp
|
||||
)
|
||||
|
||||
if(SRB2_CONFIG_ENABLE_WEBM_MOVIES)
|
||||
|
|
|
|||
|
|
@ -3255,7 +3255,11 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
|
|||
{
|
||||
// Running the callback here would mean a very dumb infinite loop.
|
||||
// We'll manually handle this here by changing the msg type.
|
||||
msg = KICK_MSG_VOTE_KICK;
|
||||
if (msg != KICK_MSG_BANNED && msg != KICK_MSG_CUSTOM_BAN)
|
||||
{
|
||||
// of course, don't take the teeth out of a ban
|
||||
msg = KICK_MSG_VOTE_KICK;
|
||||
}
|
||||
K_MidVoteFinalize(FRACUNIT); // Vote succeeded, so the delay is normal.
|
||||
}
|
||||
else
|
||||
|
|
|
|||
11
src/d_main.c
11
src/d_main.c
|
|
@ -464,22 +464,12 @@ static void D_Display(void)
|
|||
}
|
||||
break;
|
||||
|
||||
case GS_ENDING:
|
||||
F_EndingDrawer();
|
||||
HU_Erase();
|
||||
HU_Drawer();
|
||||
break;
|
||||
|
||||
case GS_CUTSCENE:
|
||||
F_CutsceneDrawer();
|
||||
HU_Erase();
|
||||
HU_Drawer();
|
||||
break;
|
||||
|
||||
case GS_GAMEEND:
|
||||
F_GameEndDrawer();
|
||||
break;
|
||||
|
||||
case GS_EVALUATION:
|
||||
F_GameEvaluationDrawer();
|
||||
HU_Erase();
|
||||
|
|
@ -980,7 +970,6 @@ void D_ClearState(void)
|
|||
SplitScreen_OnChange();
|
||||
|
||||
cht_debug = 0;
|
||||
emeralds = 0;
|
||||
memset(&luabanks, 0, sizeof(luabanks));
|
||||
|
||||
// In case someone exits out at the same time they start a time attack run,
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@
|
|||
#include "k_vote.h"
|
||||
#include "k_zvote.h"
|
||||
#include "k_bot.h"
|
||||
#include "k_powerup.h"
|
||||
|
||||
#ifdef SRB2_CONFIG_ENABLE_WEBM_MOVIES
|
||||
#include "m_avrecorder.h"
|
||||
|
|
@ -433,6 +434,8 @@ consvar_t cv_kartbot = CVAR_INIT ("bots", "0", CV_NETVAR, kartbot_cons_t, NULL);
|
|||
|
||||
consvar_t cv_karteliminatelast = CVAR_INIT ("eliminatelast", "Yes", CV_NETVAR|CV_CALL, CV_YesNo, KartEliminateLast_OnChange);
|
||||
|
||||
consvar_t cv_thunderdome = CVAR_INIT ("thunderdome", "Off", CV_NETVAR, CV_OnOff, NULL);
|
||||
|
||||
consvar_t cv_kartusepwrlv = CVAR_INIT ("usepwrlv", "Yes", CV_NETVAR, CV_YesNo, NULL);
|
||||
|
||||
static CV_PossibleValue_t kartdebugitem_cons_t[] =
|
||||
|
|
@ -440,6 +443,11 @@ static CV_PossibleValue_t kartdebugitem_cons_t[] =
|
|||
#define FOREACH( name, n ) { n, #name }
|
||||
KART_ITEM_ITERATOR,
|
||||
#undef FOREACH
|
||||
{POWERUP_SMONITOR, "SMonitor"},
|
||||
{POWERUP_BARRIER, "Barrier"},
|
||||
{POWERUP_BUMPER, "Bumper"},
|
||||
{POWERUP_BADGE, "Badge"},
|
||||
{POWERUP_SUPERFLICKY, "SuperFlicky"},
|
||||
{0}
|
||||
};
|
||||
consvar_t cv_kartdebugitem = CVAR_INIT ("debugitem", "None", CV_NETVAR|CV_CHEAT, kartdebugitem_cons_t, NULL);
|
||||
|
|
@ -2070,6 +2078,11 @@ void D_Cheat(INT32 playernum, INT32 cheat, ...)
|
|||
COPY(WRITEUINT8, unsigned int);
|
||||
break;
|
||||
|
||||
case CHEAT_GIVEPOWERUP:
|
||||
COPY(WRITEUINT8, unsigned int);
|
||||
COPY(WRITEUINT16, unsigned int);
|
||||
break;
|
||||
|
||||
case CHEAT_SCORE:
|
||||
COPY(WRITEUINT32, UINT32);
|
||||
break;
|
||||
|
|
@ -5644,6 +5657,22 @@ static void Command_Mapmd5_f(void)
|
|||
CONS_Printf(M_GetText("You must be in a level to use this.\n"));
|
||||
}
|
||||
|
||||
boolean G_GamestateUsesExitLevel(void)
|
||||
{
|
||||
if (demo.playback)
|
||||
return false;
|
||||
|
||||
switch (gamestate)
|
||||
{
|
||||
case GS_LEVEL:
|
||||
case GS_CREDITS:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static void Command_ExitLevel_f(void)
|
||||
{
|
||||
if (!(server || (IsPlayerAdmin(consoleplayer))))
|
||||
|
|
@ -5654,7 +5683,7 @@ static void Command_ExitLevel_f(void)
|
|||
{
|
||||
CONS_Printf(M_GetText("This cannot be used without cheats enabled.\n"));
|
||||
}
|
||||
else if (( gamestate != GS_LEVEL && gamestate != GS_CREDITS ) || demo.playback)
|
||||
else if (G_GamestateUsesExitLevel() == false)
|
||||
{
|
||||
CONS_Printf(M_GetText("You must be in a level to use this.\n"));
|
||||
}
|
||||
|
|
@ -5680,6 +5709,9 @@ static void Got_ExitLevelcmd(UINT8 **cp, INT32 playernum)
|
|||
return;
|
||||
}
|
||||
|
||||
if (G_GamestateUsesExitLevel() == false)
|
||||
return;
|
||||
|
||||
G_ExitLevel();
|
||||
}
|
||||
|
||||
|
|
@ -6110,6 +6142,20 @@ static void Got_Cheat(UINT8 **cp, INT32 playernum)
|
|||
break;
|
||||
}
|
||||
|
||||
case CHEAT_GIVEPOWERUP: {
|
||||
UINT8 powerup = READUINT8(*cp);
|
||||
UINT16 time = READUINT16(*cp);
|
||||
|
||||
// FIXME: we should have actual KITEM_ name array
|
||||
const char *powerupname = cv_kartdebugitem.PossibleValue[
|
||||
1 + NUMKARTITEMS + (powerup - FIRSTPOWERUP)].strvalue;
|
||||
|
||||
K_GivePowerUp(player, powerup, time);
|
||||
|
||||
CV_CheaterWarning(playernum, va("give powerup %s %d tics", powerupname, time));
|
||||
break;
|
||||
}
|
||||
|
||||
case CHEAT_SCORE: {
|
||||
UINT32 score = READUINT32(*cp);
|
||||
|
||||
|
|
@ -6252,7 +6298,6 @@ void Command_ExitGame_f(void)
|
|||
SplitScreen_OnChange();
|
||||
|
||||
cht_debug = 0;
|
||||
emeralds = 0;
|
||||
memset(&luabanks, 0, sizeof(luabanks));
|
||||
|
||||
if (dirmenu)
|
||||
|
|
@ -6417,7 +6462,18 @@ static void Command_KartGiveItem_f(void)
|
|||
}
|
||||
}
|
||||
|
||||
if (item < NUMKARTITEMS)
|
||||
if (item >= FIRSTPOWERUP)
|
||||
{
|
||||
INT32 amt;
|
||||
|
||||
if (ac > 2)
|
||||
amt = atoi(COM_Argv(2));
|
||||
else
|
||||
amt = BATTLE_POWERUP_TIME;
|
||||
|
||||
D_Cheat(consoleplayer, CHEAT_GIVEPOWERUP, item, amt);
|
||||
}
|
||||
else if (item < NUMKARTITEMS)
|
||||
{
|
||||
INT32 amt;
|
||||
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ extern consvar_t cv_kartspeedometer;
|
|||
extern consvar_t cv_kartvoices;
|
||||
extern consvar_t cv_kartbot;
|
||||
extern consvar_t cv_karteliminatelast;
|
||||
extern consvar_t cv_thunderdome;
|
||||
extern consvar_t cv_kartusepwrlv;
|
||||
|
||||
extern consvar_t cv_votetime;
|
||||
|
|
@ -241,6 +242,7 @@ void WeaponPref_Parse(UINT8 **cp, INT32 playernum);
|
|||
void D_SendPlayerConfig(UINT8 n);
|
||||
void Command_ExitGame_f(void);
|
||||
void Command_Retry_f(void);
|
||||
boolean G_GamestateUsesExitLevel(void);
|
||||
void D_GameTypeChanged(INT32 lastgametype); // not a real _OnChange function anymore
|
||||
void D_MapChange(UINT16 pmapnum, INT32 pgametype, boolean pencoremode, boolean presetplayers, INT32 pdelay, boolean pskipprecutscene, boolean pforcespecialstage);
|
||||
void D_SetupVote(void);
|
||||
|
|
|
|||
|
|
@ -179,7 +179,16 @@ typedef enum
|
|||
KRITEM_DUALJAWZ,
|
||||
KRITEM_TRIPLEGACHABOM,
|
||||
|
||||
NUMKARTRESULTS
|
||||
NUMKARTRESULTS,
|
||||
|
||||
// Power-ups exist in the same enum as items so it's easy
|
||||
// for paper items to be reused for them.
|
||||
FIRSTPOWERUP,
|
||||
POWERUP_SMONITOR = FIRSTPOWERUP,
|
||||
POWERUP_BARRIER,
|
||||
POWERUP_BUMPER,
|
||||
POWERUP_BADGE,
|
||||
POWERUP_SUPERFLICKY,
|
||||
} kartitems_t;
|
||||
|
||||
typedef enum
|
||||
|
|
@ -192,6 +201,17 @@ typedef enum
|
|||
NUMKARTSHIELDS
|
||||
} kartshields_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
KSM_BAR,
|
||||
KSM_DOUBLEBAR,
|
||||
KSM_TRIPLEBAR,
|
||||
KSM_RING,
|
||||
KSM_SEVEN,
|
||||
KSM_JACKPOT,
|
||||
KSM__MAX,
|
||||
} kartslotmachine_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
KSPIN_THRUST = (1<<0),
|
||||
|
|
@ -410,6 +430,7 @@ struct itemroulette_t
|
|||
tic_t elapsed;
|
||||
|
||||
boolean eggman;
|
||||
boolean ringbox;
|
||||
};
|
||||
|
||||
// enum for bot item priorities
|
||||
|
|
@ -439,6 +460,11 @@ typedef struct {
|
|||
boolean flip;
|
||||
} sonicloopvars_t;
|
||||
|
||||
// player_t struct for power-ups
|
||||
struct powerupvars_t {
|
||||
mobj_t *flickyController;
|
||||
};
|
||||
|
||||
// player_t struct for all alternative viewpoint variables
|
||||
struct altview_t
|
||||
{
|
||||
|
|
@ -756,6 +782,7 @@ struct player_t
|
|||
mobj_t *sliptideZipIndicator;
|
||||
mobj_t *whip;
|
||||
mobj_t *hand;
|
||||
mobj_t *flickyAttacker;
|
||||
|
||||
UINT8 instaShieldCooldown;
|
||||
UINT8 guardCooldown;
|
||||
|
|
@ -767,6 +794,9 @@ struct player_t
|
|||
|
||||
boolean markedfordeath;
|
||||
|
||||
UINT8 ringboxdelay; // Delay until Ring Box auto-activates
|
||||
UINT8 ringboxaward; // Where did we stop?
|
||||
|
||||
fixed_t outrun; // Milky Way road effect
|
||||
|
||||
uint8_t public_key[PUBKEYLENGTH];
|
||||
|
|
@ -777,6 +807,7 @@ struct player_t
|
|||
|
||||
sonicloopvars_t loop;
|
||||
roundconditions_t roundconditions;
|
||||
powerupvars_t powerup;
|
||||
};
|
||||
|
||||
// WARNING FOR ANYONE ABOUT TO ADD SOMETHING TO THE PLAYER STRUCT, G_PlayerReborn WANTS YOU TO SUFFER
|
||||
|
|
|
|||
|
|
@ -2395,7 +2395,7 @@ void readunlockable(MYFILE *f, INT32 num)
|
|||
Z_Free(s);
|
||||
}
|
||||
|
||||
static void readcondition(UINT8 set, UINT32 id, char *word2)
|
||||
static void readcondition(UINT16 set, UINT32 id, char *word2)
|
||||
{
|
||||
INT32 i;
|
||||
char *params[5]; // condition, requirement, extra info, extra info, stringvar
|
||||
|
|
@ -2585,6 +2585,7 @@ static void readcondition(UINT8 set, UINT32 id, char *word2)
|
|||
}
|
||||
}
|
||||
else if ((offset=0) || fastcmp(params[0], "ADDON")
|
||||
|| (++offset && fastcmp(params[0], "CREDITS"))
|
||||
|| (++offset && fastcmp(params[0], "REPLAY"))
|
||||
|| (++offset && fastcmp(params[0], "CRASH")))
|
||||
{
|
||||
|
|
@ -2861,13 +2862,13 @@ static void readcondition(UINT8 set, UINT32 id, char *word2)
|
|||
M_AddRawCondition(set, (UINT8)id, ty, re, x1, x2, stringvar);
|
||||
}
|
||||
|
||||
void readconditionset(MYFILE *f, UINT8 setnum)
|
||||
void readconditionset(MYFILE *f, UINT16 setnum)
|
||||
{
|
||||
char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
|
||||
char *word = s;
|
||||
char *word2;
|
||||
char *tmp;
|
||||
UINT8 id;
|
||||
UINT16 id;
|
||||
UINT8 previd = 0;
|
||||
|
||||
M_ClearConditionSet(setnum);
|
||||
|
|
@ -2904,21 +2905,26 @@ void readconditionset(MYFILE *f, UINT8 setnum)
|
|||
|
||||
if (fastncmp(word, "CONDITION", 9))
|
||||
{
|
||||
id = (UINT8)atoi(word + 9);
|
||||
id = atoi(word + 9);
|
||||
if (id == 0)
|
||||
{
|
||||
deh_warning("Condition set %d: unknown word '%s'", setnum+1, word);
|
||||
continue;
|
||||
}
|
||||
else if (previd > id)
|
||||
if (previd > id)
|
||||
{
|
||||
// out of order conditions can cause problems, so enforce proper order
|
||||
deh_warning("Condition set %d: conditions are out of order, ignoring this line", setnum+1);
|
||||
continue;
|
||||
}
|
||||
previd = id;
|
||||
if (id > UINT8_MAX)
|
||||
{
|
||||
deh_warning("Condition set %d: too many Condition# types, ignoring this line", setnum+1);
|
||||
continue;
|
||||
}
|
||||
previd = (UINT8)id;
|
||||
|
||||
readcondition(setnum, id, word2);
|
||||
readcondition(setnum, (UINT8)id, word2);
|
||||
}
|
||||
else
|
||||
deh_warning("Condition set %d: unknown word '%s'", setnum, word);
|
||||
|
|
@ -3122,13 +3128,13 @@ void readmaincfg(MYFILE *f, boolean mainfile)
|
|||
if (creditscutscene > 128)
|
||||
creditscutscene = 128;
|
||||
}
|
||||
else if (fastcmp(word, "USEBLACKROCK"))
|
||||
else if (fastcmp(word, "USESEAL"))
|
||||
{
|
||||
useBlackRock = (UINT8)(value || word2[0] == 'T' || word2[0] == 'Y');
|
||||
useSeal = (UINT8)(value || word2[0] == 'T' || word2[0] == 'Y');
|
||||
}
|
||||
else if (fastcmp(word, "LOOPTITLE"))
|
||||
{
|
||||
looptitle = (value || word2[0] == 'T' || word2[0] == 'Y');
|
||||
looptitle = (value != 0 || word2[0] == 'T' || word2[0] == 'Y');
|
||||
titlechanged = true;
|
||||
}
|
||||
else if (fastcmp(word, "TITLEMAP"))
|
||||
|
|
@ -3139,7 +3145,7 @@ void readmaincfg(MYFILE *f, boolean mainfile)
|
|||
}
|
||||
else if (fastcmp(word, "HIDETITLEPICS") || fastcmp(word, "TITLEPICSHIDE"))
|
||||
{
|
||||
hidetitlepics = (boolean)(value || word2[0] == 'T' || word2[0] == 'Y');
|
||||
hidetitlepics = (boolean)(value != 0 || word2[0] == 'T' || word2[0] == 'Y');
|
||||
titlechanged = true;
|
||||
}
|
||||
else if (fastcmp(word, "TITLEPICSMODE"))
|
||||
|
|
@ -3367,14 +3373,6 @@ void readwipes(MYFILE *f)
|
|||
else if (fastcmp(pword, "FINAL"))
|
||||
wipeoffset = wipe_evaluation_final;
|
||||
}
|
||||
else if (fastncmp(word, "GAMEEND_", 8))
|
||||
{
|
||||
pword = word + 8;
|
||||
if (fastcmp(pword, "TOBLACK"))
|
||||
wipeoffset = wipe_gameend_toblack;
|
||||
else if (fastcmp(pword, "FINAL"))
|
||||
wipeoffset = wipe_gameend_final;
|
||||
}
|
||||
else if (fastncmp(word, "CEREMONY_", 9))
|
||||
{
|
||||
pword = word + 9;
|
||||
|
|
@ -3440,6 +3438,15 @@ static void invalidateacrosscups(UINT16 map)
|
|||
mapheaderinfo[map]->cup = NULL;
|
||||
}
|
||||
|
||||
static char *MapNameOrRemoval(char *name)
|
||||
{
|
||||
if (name[0] == '\0'
|
||||
|| (name[0] == '/' && name[1] == '\0'))
|
||||
return NULL;
|
||||
|
||||
return Z_StrDup(name);
|
||||
}
|
||||
|
||||
void readcupheader(MYFILE *f, cupheader_t *cup)
|
||||
{
|
||||
char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
|
||||
|
|
@ -3541,8 +3548,12 @@ void readcupheader(MYFILE *f, cupheader_t *cup)
|
|||
break;
|
||||
}
|
||||
|
||||
cup->levellist[CUPCACHE_BONUS + cup->numbonus] = Z_StrDup(tmp);
|
||||
cup->levellist[CUPCACHE_BONUS + cup->numbonus] = MapNameOrRemoval(tmp);
|
||||
cup->cachedlevels[CUPCACHE_BONUS + cup->numbonus] = NEXTMAP_INVALID;
|
||||
|
||||
if (cup->levellist[CUPCACHE_BONUS + cup->numbonus] == NULL)
|
||||
break;
|
||||
|
||||
cup->numbonus++;
|
||||
} while((tmp = strtok(NULL,",")) != NULL);
|
||||
}
|
||||
|
|
@ -3550,9 +3561,16 @@ void readcupheader(MYFILE *f, cupheader_t *cup)
|
|||
{
|
||||
invalidateacrosscups(cup->cachedlevels[CUPCACHE_SPECIAL]);
|
||||
Z_Free(cup->levellist[CUPCACHE_SPECIAL]);
|
||||
cup->levellist[CUPCACHE_SPECIAL] = Z_StrDup(word2);
|
||||
cup->levellist[CUPCACHE_SPECIAL] = MapNameOrRemoval(word2);
|
||||
cup->cachedlevels[CUPCACHE_SPECIAL] = NEXTMAP_INVALID;
|
||||
}
|
||||
else if (fastcmp(word, "ALTPODIUM"))
|
||||
{
|
||||
invalidateacrosscups(cup->cachedlevels[CUPCACHE_PODIUM]);
|
||||
Z_Free(cup->levellist[CUPCACHE_PODIUM]);
|
||||
cup->levellist[CUPCACHE_PODIUM] = MapNameOrRemoval(word2);
|
||||
cup->cachedlevels[CUPCACHE_PODIUM] = NEXTMAP_INVALID;
|
||||
}
|
||||
else if (fastcmp(word, "EMERALDNUM"))
|
||||
{
|
||||
if (i >= 0 && i <= 14)
|
||||
|
|
@ -3560,6 +3578,10 @@ void readcupheader(MYFILE *f, cupheader_t *cup)
|
|||
else
|
||||
deh_warning("%s Cup: invalid emerald number %d", cup->name, i);
|
||||
}
|
||||
else if (fastcmp(word, "PLAYCREDITS"))
|
||||
{
|
||||
cup->playcredits = (i != 0 || word2[0] == 'T' || word2[0] == 'Y');
|
||||
}
|
||||
else
|
||||
deh_warning("%s Cup: unknown word '%s'", cup->name, word);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ skincolornum_t get_skincolor(const char *word);
|
|||
|
||||
void readwipes(MYFILE *f);
|
||||
void readmaincfg(MYFILE *f, boolean mainfile);
|
||||
void readconditionset(MYFILE *f, UINT8 setnum);
|
||||
void readconditionset(MYFILE *f, UINT16 setnum);
|
||||
void readunlockable(MYFILE *f, INT32 num);
|
||||
void reademblemdata(MYFILE *f, INT32 num);
|
||||
void readsound(MYFILE *f, INT32 num);
|
||||
|
|
|
|||
|
|
@ -283,7 +283,6 @@ actionpointer_t actionpointers[] =
|
|||
{{A_ChangeHeight}, "A_CHANGEHEIGHT"},
|
||||
|
||||
// SRB2Kart
|
||||
{{A_ItemPop}, "A_ITEMPOP"},
|
||||
{{A_JawzExplode}, "A_JAWZEXPLODE"},
|
||||
{{A_SSMineSearch}, "A_SSMINESEARCH"},
|
||||
{{A_SSMineExplode}, "A_SSMINEEXPLODE"},
|
||||
|
|
@ -3223,7 +3222,20 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi
|
|||
"S_RANDOMITEM10",
|
||||
"S_RANDOMITEM11",
|
||||
"S_RANDOMITEM12",
|
||||
"S_DEADRANDOMITEM",
|
||||
|
||||
// Ring Box
|
||||
"S_RINGBOX1",
|
||||
"S_RINGBOX2",
|
||||
"S_RINGBOX3",
|
||||
"S_RINGBOX4",
|
||||
"S_RINGBOX5",
|
||||
"S_RINGBOX6",
|
||||
"S_RINGBOX7",
|
||||
"S_RINGBOX8",
|
||||
"S_RINGBOX9",
|
||||
"S_RINGBOX10",
|
||||
"S_RINGBOX11",
|
||||
"S_RINGBOX12",
|
||||
|
||||
// Sphere Box (for Battle)
|
||||
"S_SPHEREBOX1",
|
||||
|
|
@ -3238,7 +3250,6 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi
|
|||
"S_SPHEREBOX10",
|
||||
"S_SPHEREBOX11",
|
||||
"S_SPHEREBOX12",
|
||||
"S_DEADSPHEREBOX",
|
||||
|
||||
// Random Item Pop
|
||||
"S_RANDOMITEMPOP1",
|
||||
|
|
@ -4571,6 +4582,8 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi
|
|||
"S_GACHABOM_EXPLOSION_4",
|
||||
"S_GACHABOM_WAITING",
|
||||
"S_GACHABOM_RETURNING",
|
||||
|
||||
"S_SUPER_FLICKY",
|
||||
};
|
||||
|
||||
// RegEx to generate this from info.h: ^\tMT_([^,]+), --> \t"MT_\1",
|
||||
|
|
@ -5697,6 +5710,9 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t
|
|||
|
||||
"MT_LOOPENDPOINT",
|
||||
"MT_LOOPCENTERPOINT",
|
||||
|
||||
"MT_SUPER_FLICKY",
|
||||
"MT_SUPER_FLICKY_CONTROLLER",
|
||||
};
|
||||
|
||||
const char *const MOBJFLAG_LIST[] = {
|
||||
|
|
@ -6835,9 +6851,7 @@ struct int_const_s const INT_CONST[] = {
|
|||
{"GS_MENU",GS_MENU},
|
||||
{"GS_CREDITS",GS_CREDITS},
|
||||
{"GS_EVALUATION",GS_EVALUATION},
|
||||
{"GS_GAMEEND",GS_GAMEEND},
|
||||
{"GS_INTRO",GS_INTRO},
|
||||
{"GS_ENDING",GS_ENDING},
|
||||
{"GS_CUTSCENE",GS_CUTSCENE},
|
||||
{"GS_DEDICATEDSERVER",GS_DEDICATEDSERVER},
|
||||
{"GS_WAITINGPLAYERS",GS_WAITINGPLAYERS},
|
||||
|
|
@ -6856,6 +6870,12 @@ struct int_const_s const INT_CONST[] = {
|
|||
{"KRITEM_DUALJAWZ",KRITEM_DUALJAWZ},
|
||||
{"KRITEM_TRIPLEGACHABOM",KRITEM_TRIPLEGACHABOM},
|
||||
{"NUMKARTRESULTS",NUMKARTRESULTS},
|
||||
{"FIRSTPOWERUP",FIRSTPOWERUP},
|
||||
{"POWERUP_SMONITOR",POWERUP_SMONITOR},
|
||||
{"POWERUP_BARRIER",POWERUP_BARRIER},
|
||||
{"POWERUP_BUMPER",POWERUP_BUMPER},
|
||||
{"POWERUP_BADGE",POWERUP_BADGE},
|
||||
{"POWERUP_SUPERFLICKY",POWERUP_SUPERFLICKY},
|
||||
|
||||
// kartshields_t
|
||||
{"KSHIELD_NONE",KSHIELD_NONE},
|
||||
|
|
|
|||
|
|
@ -453,7 +453,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile)
|
|||
ignorelines(f);
|
||||
}
|
||||
else if (i > 0 && i <= MAXCONDITIONSETS)
|
||||
readconditionset(f, (UINT8)(i-1));
|
||||
readconditionset(f, (UINT16)(i-1));
|
||||
else
|
||||
{
|
||||
deh_warning("Condition set number %d out of range (1 - %d)", i, MAXCONDITIONSETS);
|
||||
|
|
|
|||
|
|
@ -383,7 +383,8 @@ struct customoption_t
|
|||
#define CUPCACHE_BONUS MAXLEVELLIST
|
||||
#define MAXBONUSLIST 2
|
||||
#define CUPCACHE_SPECIAL (CUPCACHE_BONUS+MAXBONUSLIST)
|
||||
#define CUPCACHE_MAX (CUPCACHE_SPECIAL+1)
|
||||
#define CUPCACHE_PODIUM (CUPCACHE_SPECIAL+1)
|
||||
#define CUPCACHE_MAX (CUPCACHE_PODIUM+1)
|
||||
|
||||
#define MAXCUPNAME 16 // includes \0, for cleaner savedata
|
||||
|
||||
|
|
@ -401,6 +402,9 @@ struct cupheader_t
|
|||
UINT8 numlevels; ///< Number of levels defined in levellist
|
||||
UINT8 numbonus; ///< Number of bonus stages defined
|
||||
UINT8 emeraldnum; ///< ID of Emerald to use for special stage (1-7 for Chaos Emeralds, 8-14 for Super Emeralds, 0 for no emerald)
|
||||
|
||||
boolean playcredits; ///< Play the credits?
|
||||
|
||||
cupwindata_t windata[4]; ///< Data for cup visitation
|
||||
cupheader_t *next; ///< Next cup in linked list
|
||||
};
|
||||
|
|
@ -687,8 +691,6 @@ typedef enum
|
|||
EMERALD_ALL = EMERALD_ALLCHAOS|EMERALD_ALLSUPER
|
||||
} emeraldflags_t;
|
||||
|
||||
extern UINT16 emeralds;
|
||||
|
||||
#define ALLCHAOSEMERALDS(v) ((v & EMERALD_ALLCHAOS) == EMERALD_ALLCHAOS)
|
||||
#define ALLSUPEREMERALDS(v) ((v & EMERALD_ALLSUPER) == EMERALD_ALLSUPER)
|
||||
#define ALLEMERALDS(v) ((v & EMERALD_ALL) == EMERALD_ALL)
|
||||
|
|
@ -744,7 +746,7 @@ extern INT32 flameseg;
|
|||
|
||||
extern UINT8 introtoplay;
|
||||
extern UINT8 creditscutscene;
|
||||
extern UINT8 useBlackRock;
|
||||
extern UINT8 useSeal;
|
||||
|
||||
extern UINT8 use1upSound;
|
||||
extern UINT8 maxXtraLife; // Max extra lives from rings
|
||||
|
|
|
|||
990
src/f_finale.c
990
src/f_finale.c
File diff suppressed because it is too large
Load diff
|
|
@ -33,7 +33,6 @@ boolean F_CutsceneResponder(event_t *ev);
|
|||
boolean F_CreditResponder(event_t *ev);
|
||||
|
||||
// Called by main loop.
|
||||
void F_GameEndTicker(void);
|
||||
void F_IntroTicker(void);
|
||||
void F_TitleScreenTicker(boolean run);
|
||||
void F_CutsceneTicker(void);
|
||||
|
|
@ -41,7 +40,6 @@ void F_TitleDemoTicker(void);
|
|||
void F_TextPromptTicker(void);
|
||||
|
||||
// Called by main loop.
|
||||
void F_GameEndDrawer(void);
|
||||
void F_IntroDrawer(void);
|
||||
void F_TitleScreenDrawer(void);
|
||||
void F_SkyScroll(INT32 scrollxspeed, INT32 scrollyspeed, const char *patchname);
|
||||
|
|
@ -54,9 +52,6 @@ void F_GameEvaluationDrawer(void);
|
|||
void F_StartGameEvaluation(void);
|
||||
void F_GameEvaluationTicker(void);
|
||||
|
||||
void F_EndingTicker(void);
|
||||
void F_EndingDrawer(void);
|
||||
|
||||
void F_CreditTicker(void);
|
||||
void F_CreditDrawer(void);
|
||||
|
||||
|
|
@ -173,10 +168,8 @@ enum
|
|||
wipe_menu_toblack,
|
||||
wipe_credits_toblack,
|
||||
wipe_evaluation_toblack,
|
||||
wipe_gameend_toblack,
|
||||
wipe_ceremony_toblack,
|
||||
wipe_intro_toblack,
|
||||
wipe_ending_toblack,
|
||||
wipe_cutscene_toblack,
|
||||
|
||||
// Specialized wipes
|
||||
|
|
@ -192,10 +185,8 @@ enum
|
|||
wipe_menu_final,
|
||||
wipe_credits_final,
|
||||
wipe_evaluation_final,
|
||||
wipe_gameend_final,
|
||||
wipe_ceremony_final,
|
||||
wipe_intro_final,
|
||||
wipe_ending_final,
|
||||
wipe_cutscene_final,
|
||||
|
||||
// custom intermissions
|
||||
|
|
|
|||
20
src/f_wipe.c
20
src/f_wipe.c
|
|
@ -63,10 +63,8 @@ UINT8 wipedefs[NUMWIPEDEFS] = {
|
|||
1, // wipe_menu_toblack
|
||||
99, // wipe_credits_toblack
|
||||
0, // wipe_evaluation_toblack
|
||||
0, // wipe_gameend_toblack
|
||||
0, // wipe_ceremony_toblack
|
||||
UINT8_MAX, // wipe_intro_toblack (hardcoded)
|
||||
99, // wipe_ending_toblack (hardcoded)
|
||||
99, // wipe_cutscene_toblack (hardcoded)
|
||||
|
||||
72, // wipe_encore_toinvert
|
||||
|
|
@ -80,10 +78,8 @@ UINT8 wipedefs[NUMWIPEDEFS] = {
|
|||
1, // wipe_menu_final
|
||||
99, // wipe_credits_final
|
||||
0, // wipe_evaluation_final
|
||||
0, // wipe_gameend_final
|
||||
0, // wipe_ceremony_final
|
||||
99, // wipe_intro_final (hardcoded)
|
||||
99, // wipe_ending_final (hardcoded)
|
||||
99 // wipe_cutscene_final (hardcoded)
|
||||
};
|
||||
|
||||
|
|
@ -98,10 +94,8 @@ static boolean g_wipedef_toblack[NUMWIPEDEFS] = {
|
|||
true, // wipe_menu_toblack
|
||||
true, // wipe_credits_toblack
|
||||
true, // wipe_evaluation_toblack
|
||||
true, // wipe_gameend_toblack
|
||||
true, // wipe_ceremony_toblack
|
||||
true, // wipe_intro_toblack (hardcoded)
|
||||
true, // wipe_ending_toblack (hardcoded)
|
||||
true, // wipe_cutscene_toblack (hardcoded)
|
||||
|
||||
false, // wipe_encore_toinvert
|
||||
|
|
@ -115,10 +109,8 @@ static boolean g_wipedef_toblack[NUMWIPEDEFS] = {
|
|||
true, // wipe_menu_final
|
||||
true, // wipe_credits_final
|
||||
true, // wipe_evaluation_final
|
||||
true, // wipe_gameend_final
|
||||
true, // wipe_ceremony_final
|
||||
true, // wipe_intro_final (hardcoded)
|
||||
true, // wipe_ending_final (hardcoded)
|
||||
true // wipe_cutscene_final (hardcoded)
|
||||
};
|
||||
|
||||
|
|
@ -133,10 +125,8 @@ static boolean g_wipedef_toinvert[NUMWIPEDEFS] = {
|
|||
false, // wipe_menu_toblack
|
||||
false, // wipe_credits_toblack
|
||||
false, // wipe_evaluation_toblack
|
||||
false, // wipe_gameend_toblack
|
||||
false, // wipe_ceremony_toblack
|
||||
false, // wipe_intro_toblack (hardcoded)
|
||||
false, // wipe_ending_toblack (hardcoded)
|
||||
false, // wipe_cutscene_toblack (hardcoded)
|
||||
|
||||
true, // wipe_encore_toinvert
|
||||
|
|
@ -150,10 +140,8 @@ static boolean g_wipedef_toinvert[NUMWIPEDEFS] = {
|
|||
false, // wipe_menu_final
|
||||
false, // wipe_credits_final
|
||||
false, // wipe_evaluation_final
|
||||
false, // wipe_gameend_final
|
||||
false, // wipe_ceremony_final
|
||||
false, // wipe_intro_final (hardcoded)
|
||||
false, // wipe_ending_final (hardcoded)
|
||||
false // wipe_cutscene_final (hardcoded)
|
||||
};
|
||||
|
||||
|
|
@ -168,10 +156,8 @@ static boolean g_wipedef_towhite[NUMWIPEDEFS] = {
|
|||
false, // wipe_menu_toblack
|
||||
false, // wipe_credits_toblack
|
||||
false, // wipe_evaluation_toblack
|
||||
false, // wipe_gameend_toblack
|
||||
false, // wipe_ceremony_toblack
|
||||
false, // wipe_intro_toblack (hardcoded)
|
||||
false, // wipe_ending_toblack (hardcoded)
|
||||
false, // wipe_cutscene_toblack (hardcoded)
|
||||
|
||||
false, // wipe_encore_toinvert
|
||||
|
|
@ -185,10 +171,8 @@ static boolean g_wipedef_towhite[NUMWIPEDEFS] = {
|
|||
false, // wipe_menu_final
|
||||
false, // wipe_credits_final
|
||||
false, // wipe_evaluation_final
|
||||
false, // wipe_gameend_final
|
||||
false, // wipe_ceremony_final
|
||||
false, // wipe_intro_final (hardcoded)
|
||||
false, // wipe_ending_final (hardcoded)
|
||||
false // wipe_cutscene_final (hardcoded)
|
||||
};
|
||||
|
||||
|
|
@ -203,10 +187,8 @@ static boolean g_wipedef_crossfade[NUMWIPEDEFS] = {
|
|||
false, // wipe_menu_toblack
|
||||
false, // wipe_credits_toblack
|
||||
false, // wipe_evaluation_toblack
|
||||
false, // wipe_gameend_toblack
|
||||
false, // wipe_ceremony_toblack
|
||||
false, // wipe_intro_toblack (hardcoded)
|
||||
false, // wipe_ending_toblack (hardcoded)
|
||||
false, // wipe_cutscene_toblack (hardcoded)
|
||||
|
||||
false, // wipe_encore_toinvert
|
||||
|
|
@ -220,10 +202,8 @@ static boolean g_wipedef_crossfade[NUMWIPEDEFS] = {
|
|||
true, // wipe_menu_final
|
||||
true, // wipe_credits_final
|
||||
true, // wipe_evaluation_final
|
||||
true, // wipe_gameend_final
|
||||
true, // wipe_ceremony_final
|
||||
true, // wipe_intro_final (hardcoded)
|
||||
true, // wipe_ending_final (hardcoded)
|
||||
true // wipe_cutscene_final (hardcoded)
|
||||
};
|
||||
|
||||
|
|
|
|||
90
src/g_game.c
90
src/g_game.c
|
|
@ -140,8 +140,6 @@ boolean usedCheats = false; // Set when a "cheats on" is ever used.
|
|||
UINT8 paused;
|
||||
UINT8 modeattacking = ATTACKING_NONE;
|
||||
boolean imcontinuing = false;
|
||||
boolean runemeraldmanager = false;
|
||||
UINT16 emeraldspawndelay = 60*TICRATE;
|
||||
|
||||
// menu demo things
|
||||
UINT8 numDemos = 0;
|
||||
|
|
@ -205,7 +203,6 @@ static boolean retryingmodeattack = false;
|
|||
|
||||
UINT8 stagefailed; // Used for GEMS BONUS? Also to see if you beat the stage.
|
||||
|
||||
UINT16 emeralds;
|
||||
INT32 luabanks[NUM_LUABANKS];
|
||||
|
||||
// Temporary holding place for nights data for the current map
|
||||
|
|
@ -264,7 +261,7 @@ UINT8 maxXtraLife = 2; // Max extra lives from rings
|
|||
|
||||
UINT8 introtoplay;
|
||||
UINT8 creditscutscene;
|
||||
UINT8 useBlackRock = 1;
|
||||
UINT8 useSeal = 1;
|
||||
|
||||
// Emerald locations
|
||||
mobj_t *hunt1;
|
||||
|
|
@ -1785,7 +1782,7 @@ boolean G_Responder(event_t *ev)
|
|||
return true;
|
||||
}
|
||||
}
|
||||
else if (gamestate == GS_CREDITS || gamestate == GS_ENDING) // todo: keep ending here?
|
||||
else if (gamestate == GS_CREDITS)
|
||||
{
|
||||
if (HU_Responder(ev))
|
||||
{
|
||||
|
|
@ -1813,7 +1810,17 @@ boolean G_Responder(event_t *ev)
|
|||
|
||||
if (K_CeremonyResponder(ev))
|
||||
{
|
||||
nextmap = NEXTMAP_TITLE;
|
||||
if (grandprixinfo.gp == true
|
||||
&& grandprixinfo.cup != NULL
|
||||
&& grandprixinfo.cup->playcredits == true)
|
||||
{
|
||||
nextmap = NEXTMAP_CREDITS;
|
||||
}
|
||||
else
|
||||
{
|
||||
nextmap = NEXTMAP_TITLE;
|
||||
}
|
||||
|
||||
G_EndGame();
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1822,11 +1829,6 @@ boolean G_Responder(event_t *ev)
|
|||
{
|
||||
return true;
|
||||
}
|
||||
// Demo End
|
||||
else if (gamestate == GS_GAMEEND)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (gamestate == GS_INTERMISSION || gamestate == GS_VOTING || gamestate == GS_EVALUATION)
|
||||
{
|
||||
if (HU_Responder(ev))
|
||||
|
|
@ -2322,23 +2324,12 @@ void G_Ticker(boolean run)
|
|||
F_IntroTicker();
|
||||
break;
|
||||
|
||||
case GS_ENDING:
|
||||
if (run)
|
||||
F_EndingTicker();
|
||||
HU_Ticker();
|
||||
break;
|
||||
|
||||
case GS_CUTSCENE:
|
||||
if (run)
|
||||
F_CutsceneTicker();
|
||||
HU_Ticker();
|
||||
break;
|
||||
|
||||
case GS_GAMEEND:
|
||||
if (run)
|
||||
F_GameEndTicker();
|
||||
break;
|
||||
|
||||
case GS_EVALUATION:
|
||||
if (run)
|
||||
F_GameEvaluationTicker();
|
||||
|
|
@ -3387,10 +3378,6 @@ void G_ExitLevel(void)
|
|||
|
||||
// Don't save demos immediately here! Let standings write first
|
||||
}
|
||||
else if (gamestate == GS_ENDING)
|
||||
{
|
||||
F_StartCredits();
|
||||
}
|
||||
else if (gamestate == GS_CREDITS)
|
||||
{
|
||||
F_StartGameEvaluation();
|
||||
|
|
@ -4664,6 +4651,8 @@ void G_EndGame(void)
|
|||
// Only do evaluation and credits in singleplayer contexts
|
||||
if (!netgame && grandprixinfo.gp == true)
|
||||
{
|
||||
G_HandleSaveLevel(true);
|
||||
|
||||
if (nextmap == NEXTMAP_CEREMONY) // end game with ceremony
|
||||
{
|
||||
if (K_StartCeremony() == true)
|
||||
|
|
@ -4736,7 +4725,15 @@ void G_LoadGameSettings(void)
|
|||
}
|
||||
|
||||
#define GD_VERSIONCHECK 0xBA5ED123 // Change every major version, as usual
|
||||
#define GD_VERSIONMINOR 3 // Change every format update
|
||||
#define GD_VERSIONMINOR 4 // Change every format update
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GDEVER_ADDON = 1,
|
||||
GDEVER_CREDITS = 1<<1,
|
||||
GDEVER_REPLAY = 1<<2,
|
||||
GDEVER_SPECIAL = 1<<3,
|
||||
} gdeverdone_t;
|
||||
|
||||
static const char *G_GameDataFolder(void)
|
||||
{
|
||||
|
|
@ -4860,9 +4857,21 @@ void G_LoadGameData(void)
|
|||
|
||||
gamedata->chaokeys = READUINT16(save.p);
|
||||
|
||||
gamedata->everloadedaddon = (boolean)READUINT8(save.p);
|
||||
gamedata->eversavedreplay = (boolean)READUINT8(save.p);
|
||||
gamedata->everseenspecial = (boolean)READUINT8(save.p);
|
||||
if (versionMinor >= 4)
|
||||
{
|
||||
UINT32 everflags = READUINT32(save.p);
|
||||
|
||||
gamedata->everloadedaddon = !!(everflags & GDEVER_ADDON);
|
||||
gamedata->everfinishedcredits = !!(everflags & GDEVER_CREDITS);
|
||||
gamedata->eversavedreplay = !!(everflags & GDEVER_REPLAY);
|
||||
gamedata->everseenspecial = !!(everflags & GDEVER_SPECIAL);
|
||||
}
|
||||
else
|
||||
{
|
||||
gamedata->everloadedaddon = (boolean)READUINT8(save.p);
|
||||
gamedata->eversavedreplay = (boolean)READUINT8(save.p);
|
||||
gamedata->everseenspecial = (boolean)READUINT8(save.p);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -5289,7 +5298,7 @@ void G_SaveGameData(void)
|
|||
4+4+
|
||||
(4*GDGT_MAX)+
|
||||
4+1+2+2+
|
||||
1+1+1+
|
||||
4+
|
||||
4+
|
||||
(MAXEMBLEMS+(MAXUNLOCKABLES*2)+MAXCONDITIONSETS)+
|
||||
4+2);
|
||||
|
|
@ -5426,11 +5435,22 @@ void G_SaveGameData(void)
|
|||
WRITEUINT16(save.p, gamedata->keyspending); // 2
|
||||
WRITEUINT16(save.p, gamedata->chaokeys); // 2
|
||||
|
||||
WRITEUINT8(save.p, gamedata->everloadedaddon); // 1
|
||||
WRITEUINT8(save.p, gamedata->eversavedreplay); // 1
|
||||
WRITEUINT8(save.p, gamedata->everseenspecial); // 1
|
||||
{
|
||||
UINT32 everflags = 0;
|
||||
|
||||
WRITEUINT32(save.p, quickncasehash(timeattackfolder, 64));
|
||||
if (gamedata->everloadedaddon)
|
||||
everflags |= GDEVER_ADDON;
|
||||
if (gamedata->everfinishedcredits)
|
||||
everflags |= GDEVER_CREDITS;
|
||||
if (gamedata->eversavedreplay)
|
||||
everflags |= GDEVER_REPLAY;
|
||||
if (gamedata->everseenspecial)
|
||||
everflags |= GDEVER_SPECIAL;
|
||||
|
||||
WRITEUINT32(save.p, everflags); // 4
|
||||
}
|
||||
|
||||
WRITEUINT32(save.p, quickncasehash(timeattackfolder, 64)); // 4
|
||||
|
||||
// To save space, use one bit per collected/achieved/unlocked flag
|
||||
for (i = 0; i < MAXEMBLEMS;) // MAXEMBLEMS * 1;
|
||||
|
|
|
|||
|
|
@ -35,12 +35,10 @@ typedef enum
|
|||
|
||||
GS_CREDITS, // credit sequence
|
||||
GS_EVALUATION, // Evaluation at the end of a game.
|
||||
GS_GAMEEND, // game end sequence - "did you get all those chaos emeralds?"
|
||||
GS_CEREMONY, // RR: Podium sequence
|
||||
|
||||
// Hardcoded fades or other fading methods
|
||||
GS_INTRO, // introduction
|
||||
GS_ENDING, // currently shared between bad and good endings
|
||||
GS_CUTSCENE, // custom cutscene
|
||||
|
||||
// Not fadable
|
||||
|
|
|
|||
85
src/info.c
85
src/info.c
|
|
@ -531,6 +531,7 @@ char sprnames[NUMSPRITES + 1][5] =
|
|||
//SRB2kart Sprites (sort later)
|
||||
"RNDM", // Random Item Box
|
||||
"SBOX", // Sphere Box (for Battle)
|
||||
"RBOX", // Ring Box
|
||||
"RPOP", // Random Item Box Pop
|
||||
"ITRI", // Item Box Debris
|
||||
"ITPA", // Paper item backdrop
|
||||
|
|
@ -648,6 +649,7 @@ char sprnames[NUMSPRITES + 1][5] =
|
|||
"ITMO",
|
||||
"ITMI",
|
||||
"ITMN",
|
||||
"PWRB",
|
||||
"WANT",
|
||||
|
||||
"PBOM", // player bomb
|
||||
|
|
@ -815,6 +817,8 @@ char sprnames[NUMSPRITES + 1][5] =
|
|||
"GBOM",
|
||||
"GCHX",
|
||||
|
||||
"3DFR",
|
||||
|
||||
// First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw later
|
||||
"VIEW",
|
||||
};
|
||||
|
|
@ -3895,7 +3899,19 @@ state_t states[NUMSTATES] =
|
|||
{SPR_RNDM, 18|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RANDOMITEM11}, // S_RANDOMITEM10
|
||||
{SPR_RNDM, 20|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RANDOMITEM12}, // S_RANDOMITEM11
|
||||
{SPR_RNDM, 22|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RANDOMITEM1}, // S_RANDOMITEM12
|
||||
{SPR_NULL, 0, 0, {A_ItemPop}, 0, 0, S_RANDOMITEM1}, // S_DEADRANDOMITEM
|
||||
|
||||
{SPR_RBOX, FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RINGBOX2}, // S_RINGBOX1
|
||||
{SPR_RBOX, 2|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RINGBOX3}, // S_RINGBOX2
|
||||
{SPR_RBOX, 4|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RINGBOX4}, // S_RINGBOX3
|
||||
{SPR_RBOX, 6|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RINGBOX5}, // S_RINGBOX4
|
||||
{SPR_RBOX, 8|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RINGBOX6}, // S_RINGBOX5
|
||||
{SPR_RBOX, 10|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RINGBOX7}, // S_RINGBOX6
|
||||
{SPR_RBOX, 12|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RINGBOX8}, // S_RINGBOX7
|
||||
{SPR_RBOX, 14|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RINGBOX9}, // S_RINGBOX8
|
||||
{SPR_RBOX, 16|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RINGBOX10}, // S_RINGBOX9
|
||||
{SPR_RBOX, 18|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RINGBOX11}, // S_RINGBOX10
|
||||
{SPR_RBOX, 20|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RINGBOX12}, // S_RINGBOX11
|
||||
{SPR_RBOX, 22|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RINGBOX1}, // S_RINGBOX12
|
||||
|
||||
{SPR_SBOX, FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX2}, // S_SPHEREBOX1
|
||||
{SPR_SBOX, 2|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX3}, // S_SPHEREBOX2
|
||||
|
|
@ -3909,7 +3925,6 @@ state_t states[NUMSTATES] =
|
|||
{SPR_SBOX, 18|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX11}, // S_SPHEREBOX10
|
||||
{SPR_SBOX, 20|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX12}, // S_SPHEREBOX11
|
||||
{SPR_SBOX, 22|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX1}, // S_SPHEREBOX12
|
||||
{SPR_NULL, 0, 0, {A_ItemPop}, 1, 0, S_NULL}, // S_DEADSPHEREBOX
|
||||
|
||||
{SPR_RPOP, FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_RANDOMITEMPOP2}, // S_RANDOMITEMPOP1
|
||||
{SPR_RPOP, FF_FULLBRIGHT|1, 5, {NULL}, 0, 0, S_RANDOMITEMPOP3}, // S_RANDOMITEMPOP2
|
||||
|
|
@ -5235,6 +5250,8 @@ state_t states[NUMSTATES] =
|
|||
{SPR_GCHX, 6|FF_PAPERSPRITE|FF_ANIMATE|FF_REVERSEANIM, 14, {NULL}, 6, 2, S_GACHABOM_WAITING}, // S_GACHABOM_EXPLOSION_4
|
||||
{SPR_GBOM, FF_INVERT, 8, {A_SetScale}, FRACUNIT, 0, S_GACHABOM_RETURNING}, // S_GACHABOM_WAITING
|
||||
{SPR_GBOM, FF_INVERT, -1, {A_SetScale}, FRACUNIT/2, 1, S_NULL}, // S_GACHABOM_RETURNING
|
||||
|
||||
{SPR_3DFR, 1|FF_ANIMATE, -1, {NULL}, 2, 5, S_NULL}, // S_SUPER_FLICKY
|
||||
};
|
||||
|
||||
mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
||||
|
|
@ -8117,8 +8134,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_NULL, // xdeathstate
|
||||
sfx_s3k9c, // deathsound
|
||||
0, // speed
|
||||
72*FRACUNIT, // radius
|
||||
72*FRACUNIT, // height
|
||||
80*FRACUNIT, // radius
|
||||
80*FRACUNIT, // height
|
||||
0, // display offset
|
||||
16, // mass
|
||||
0, // damage
|
||||
|
|
@ -22394,7 +22411,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
// SRB2kart MT's
|
||||
{ // MT_RANDOMITEM
|
||||
2000, // doomednum
|
||||
S_RANDOMITEM1, // spawnstate
|
||||
S_RINGBOX1, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
|
|
@ -22405,7 +22422,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_DEADRANDOMITEM, // deathstate
|
||||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_kc2e, // deathsound
|
||||
60*FRACUNIT, // speed
|
||||
|
|
@ -22432,7 +22449,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_DEADSPHEREBOX, // deathstate
|
||||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_kc2e, // deathsound
|
||||
60*FRACUNIT, // speed
|
||||
|
|
@ -29794,6 +29811,60 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
MF_NOSECTOR|MF_NOBLOCKMAP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_SUPER_FLICKY
|
||||
-1, // doomednum
|
||||
S_SUPER_FLICKY, // spawnstate
|
||||
1000, // 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_None, // deathsound
|
||||
0, // speed
|
||||
16*FRACUNIT, // radius
|
||||
32*FRACUNIT, // height
|
||||
0, // display offset
|
||||
0, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_SUPER_FLICKY_CONTROLLER
|
||||
-1, // doomednum
|
||||
S_INVISIBLE, // spawnstate
|
||||
1000, // 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_None, // deathsound
|
||||
0, // speed
|
||||
16*FRACUNIT, // radius
|
||||
32*FRACUNIT, // height
|
||||
0, // display offset
|
||||
0, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOSECTOR|MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_SCENERY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
};
|
||||
|
||||
skincolor_t skincolors[MAXSKINCOLORS] = {
|
||||
|
|
|
|||
27
src/info.h
27
src/info.h
|
|
@ -277,7 +277,6 @@ enum actionnum
|
|||
A_DRAGONWING,
|
||||
A_DRAGONSEGMENT,
|
||||
A_CHANGEHEIGHT,
|
||||
A_ITEMPOP,
|
||||
A_JAWZEXPLODE,
|
||||
A_SSMINESEARCH,
|
||||
A_SSMINEEXPLODE,
|
||||
|
|
@ -550,7 +549,6 @@ void A_ChangeHeight();
|
|||
//
|
||||
// SRB2Kart
|
||||
//
|
||||
void A_ItemPop();
|
||||
void A_JawzExplode();
|
||||
void A_SSMineSearch();
|
||||
void A_SSMineExplode();
|
||||
|
|
@ -1084,6 +1082,7 @@ typedef enum sprite
|
|||
// SRB2Kart
|
||||
SPR_RNDM, // Random Item Box
|
||||
SPR_SBOX, // Sphere Box (for Battle)
|
||||
SPR_RBOX, // Ring Box
|
||||
SPR_RPOP, // Random Item Box Pop
|
||||
SPR_ITRI, // Item Box Debris
|
||||
SPR_ITPA, // Paper item backdrop
|
||||
|
|
@ -1201,6 +1200,7 @@ typedef enum sprite
|
|||
SPR_ITMO,
|
||||
SPR_ITMI,
|
||||
SPR_ITMN,
|
||||
SPR_PWRB,
|
||||
SPR_WANT,
|
||||
|
||||
SPR_PBOM, // player bomb
|
||||
|
|
@ -1368,6 +1368,8 @@ typedef enum sprite
|
|||
SPR_GBOM,
|
||||
SPR_GCHX,
|
||||
|
||||
SPR_3DFR,
|
||||
|
||||
// First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw later
|
||||
SPR_VIEW,
|
||||
|
||||
|
|
@ -4302,7 +4304,20 @@ typedef enum state
|
|||
S_RANDOMITEM10,
|
||||
S_RANDOMITEM11,
|
||||
S_RANDOMITEM12,
|
||||
S_DEADRANDOMITEM,
|
||||
|
||||
// Ring Box
|
||||
S_RINGBOX1,
|
||||
S_RINGBOX2,
|
||||
S_RINGBOX3,
|
||||
S_RINGBOX4,
|
||||
S_RINGBOX5,
|
||||
S_RINGBOX6,
|
||||
S_RINGBOX7,
|
||||
S_RINGBOX8,
|
||||
S_RINGBOX9,
|
||||
S_RINGBOX10,
|
||||
S_RINGBOX11,
|
||||
S_RINGBOX12,
|
||||
|
||||
// Sphere Box (for Battle)
|
||||
S_SPHEREBOX1,
|
||||
|
|
@ -4317,7 +4332,6 @@ typedef enum state
|
|||
S_SPHEREBOX10,
|
||||
S_SPHEREBOX11,
|
||||
S_SPHEREBOX12,
|
||||
S_DEADSPHEREBOX,
|
||||
|
||||
// Random Item Pop
|
||||
S_RANDOMITEMPOP1,
|
||||
|
|
@ -5667,6 +5681,8 @@ typedef enum state
|
|||
S_GACHABOM_WAITING,
|
||||
S_GACHABOM_RETURNING,
|
||||
|
||||
S_SUPER_FLICKY,
|
||||
|
||||
S_FIRSTFREESLOT,
|
||||
S_LASTFREESLOT = S_FIRSTFREESLOT + NUMSTATEFREESLOTS - 1,
|
||||
NUMSTATES
|
||||
|
|
@ -6812,6 +6828,9 @@ typedef enum mobj_type
|
|||
MT_LOOPENDPOINT,
|
||||
MT_LOOPCENTERPOINT,
|
||||
|
||||
MT_SUPER_FLICKY,
|
||||
MT_SUPER_FLICKY_CONTROLLER,
|
||||
|
||||
MT_FIRSTFREESLOT,
|
||||
MT_LASTFREESLOT = MT_FIRSTFREESLOT + NUMMOBJFREESLOTS - 1,
|
||||
NUMMOBJTYPES
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ extern "C" {
|
|||
|
||||
#define BATTLE_SPAWN_INTERVAL (4*TICRATE)
|
||||
#define BATTLE_DESPAWN_TIME (15*TICRATE)
|
||||
#define BATTLE_POWERUP_TIME (20*TICRATE)
|
||||
|
||||
extern struct battleovertime
|
||||
{
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include "k_objects.h"
|
||||
#include "k_roulette.h"
|
||||
#include "k_podium.h"
|
||||
#include "k_powerup.h"
|
||||
|
||||
angle_t K_GetCollideAngle(mobj_t *t1, mobj_t *t2)
|
||||
{
|
||||
|
|
@ -888,6 +889,8 @@ boolean K_InstaWhipCollide(mobj_t *shield, mobj_t *victim)
|
|||
P_PlayerRingBurst(victimPlayer, 5);
|
||||
P_DamageMobj(victim, shield, attacker, 1, DMG_STUMBLE); // There's a special exception in P_DamageMobj for type==MT_INSTAWHIP
|
||||
|
||||
K_DropPowerUps(victimPlayer);
|
||||
|
||||
angle_t thrangle = ANGLE_180 + R_PointToAngle2(victim->x, victim->y, shield->x, shield->y);
|
||||
P_Thrust(victim, thrangle, FRACUNIT*10);
|
||||
|
||||
|
|
@ -898,6 +901,19 @@ boolean K_InstaWhipCollide(mobj_t *shield, mobj_t *victim)
|
|||
}
|
||||
return false;
|
||||
}
|
||||
else if (victim->type == MT_SUPER_FLICKY)
|
||||
{
|
||||
if (Obj_IsSuperFlickyWhippable(victim))
|
||||
{
|
||||
K_AddHitLag(victim, victimHitlag, true);
|
||||
K_AddHitLag(attacker, attackerHitlag, false);
|
||||
shield->hitlag = attacker->hitlag;
|
||||
|
||||
Obj_WhipSuperFlicky(victim);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (victim->type == MT_ORBINAUT || victim->type == MT_JAWZ || victim->type == MT_GACHABOM
|
||||
|
|
|
|||
168
src/k_hud.c
168
src/k_hud.c
|
|
@ -114,6 +114,7 @@ static patch_t *kp_wantedsplit;
|
|||
static patch_t *kp_wantedreticle;
|
||||
|
||||
static patch_t *kp_itembg[4];
|
||||
static patch_t *kp_ringbg[4];
|
||||
static patch_t *kp_itemtimer[2];
|
||||
static patch_t *kp_itemmulsticker[2];
|
||||
static patch_t *kp_itemx;
|
||||
|
|
@ -142,6 +143,12 @@ static patch_t *kp_kitchensink[2];
|
|||
static patch_t *kp_droptarget[2];
|
||||
static patch_t *kp_gardentop[2];
|
||||
static patch_t *kp_gachabom[2];
|
||||
static patch_t *kp_bar[2];
|
||||
static patch_t *kp_doublebar[2];
|
||||
static patch_t *kp_triplebar[2];
|
||||
static patch_t *kp_slotring[2];
|
||||
static patch_t *kp_seven[2];
|
||||
static patch_t *kp_jackpot[2];
|
||||
|
||||
static patch_t *kp_check[6];
|
||||
|
||||
|
|
@ -443,6 +450,9 @@ void K_LoadKartHUDGraphics(void)
|
|||
HU_UpdatePatch(&kp_itemmulsticker[0], "K_ITMUL");
|
||||
HU_UpdatePatch(&kp_itemx, "K_ITX");
|
||||
|
||||
HU_UpdatePatch(&kp_ringbg[0], "K_RBBG");
|
||||
HU_UpdatePatch(&kp_ringbg[1], "K_SBBG");
|
||||
|
||||
HU_UpdatePatch(&kp_sadface[0], "K_ITSAD");
|
||||
HU_UpdatePatch(&kp_sneaker[0], "K_ITSHOE");
|
||||
HU_UpdatePatch(&kp_rocketsneaker[0], "K_ITRSHE");
|
||||
|
|
@ -478,6 +488,12 @@ void K_LoadKartHUDGraphics(void)
|
|||
HU_UpdatePatch(&kp_droptarget[0], "K_ITDTRG");
|
||||
HU_UpdatePatch(&kp_gardentop[0], "K_ITGTOP");
|
||||
HU_UpdatePatch(&kp_gachabom[0], "K_ITGBOM");
|
||||
HU_UpdatePatch(&kp_bar[0], "K_RBBAR");
|
||||
HU_UpdatePatch(&kp_doublebar[0], "K_RBBAR2");
|
||||
HU_UpdatePatch(&kp_triplebar[0], "K_RBBAR3");
|
||||
HU_UpdatePatch(&kp_slotring[0], "K_RBRING");
|
||||
HU_UpdatePatch(&kp_seven[0], "K_RBSEV");
|
||||
HU_UpdatePatch(&kp_jackpot[0], "K_RBJACK");
|
||||
|
||||
sprintf(buffer, "FSMFGxxx");
|
||||
for (i = 0; i < 104; i++)
|
||||
|
|
@ -531,6 +547,12 @@ void K_LoadKartHUDGraphics(void)
|
|||
HU_UpdatePatch(&kp_droptarget[1], "K_ISDTRG");
|
||||
HU_UpdatePatch(&kp_gardentop[1], "K_ISGTOP");
|
||||
HU_UpdatePatch(&kp_gachabom[1], "K_ISGBOM");
|
||||
HU_UpdatePatch(&kp_bar[1], "K_SBBAR");
|
||||
HU_UpdatePatch(&kp_doublebar[1], "K_SBBAR2");
|
||||
HU_UpdatePatch(&kp_triplebar[1], "K_SBBAR3");
|
||||
HU_UpdatePatch(&kp_slotring[1], "K_SBRING");
|
||||
HU_UpdatePatch(&kp_seven[1], "K_SBSEV");
|
||||
HU_UpdatePatch(&kp_jackpot[1], "K_SBJACK");
|
||||
|
||||
sprintf(buffer, "FSMFSxxx");
|
||||
for (i = 0; i < 104; i++)
|
||||
|
|
@ -875,6 +897,23 @@ static patch_t *K_GetSmallStaticCachedItemPatch(kartitems_t item)
|
|||
return K_GetCachedItemPatch(item, offset);
|
||||
}
|
||||
|
||||
static patch_t *K_GetCachedSlotMachinePatch(INT32 item, UINT8 offset)
|
||||
{
|
||||
patch_t **kp[KSM__MAX] = {
|
||||
kp_bar,
|
||||
kp_doublebar,
|
||||
kp_triplebar,
|
||||
kp_slotring,
|
||||
kp_seven,
|
||||
kp_jackpot,
|
||||
};
|
||||
|
||||
if (item >= 0 && item < KSM__MAX)
|
||||
return kp[item][offset];
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//}
|
||||
|
||||
INT32 ITEM_X, ITEM_Y; // Item Window
|
||||
|
|
@ -1217,7 +1256,7 @@ static void K_drawKartItem(void)
|
|||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
const SINT8 indexOfs = i-1;
|
||||
const size_t index = (stplyr->itemRoulette.index + indexOfs) % stplyr->itemRoulette.itemListLen;
|
||||
const size_t index = (stplyr->itemRoulette.itemListLen + (stplyr->itemRoulette.index + indexOfs)) % stplyr->itemRoulette.itemListLen;
|
||||
|
||||
const SINT8 result = stplyr->itemRoulette.itemList[index];
|
||||
const SINT8 item = K_ItemResultToType(result);
|
||||
|
|
@ -1533,6 +1572,118 @@ static void K_drawKartItem(void)
|
|||
}
|
||||
}
|
||||
|
||||
static void K_drawKartSlotMachine(void)
|
||||
{
|
||||
// ITEM_X = BASEVIDWIDTH-50; // 270
|
||||
// ITEM_Y = 24; // 24
|
||||
|
||||
// Why write V_DrawScaledPatch calls over and over when they're all the same?
|
||||
// Set to 'no item' just in case.
|
||||
const UINT8 offset = ((r_splitscreen > 1) ? 1 : 0);
|
||||
|
||||
patch_t *localpatch[3] = { kp_nodraw, kp_nodraw, kp_nodraw };
|
||||
patch_t *localbg = offset ? kp_ringbg[1] : kp_ringbg[0];
|
||||
|
||||
// == SHITGARBAGE UNLIMITED 2: RISE OF MY ASS ==
|
||||
// FIVE LAYERS OF BULLSHIT PER-PIXEL SHOVING BECAUSE THE PATCHES HAVE DIFFERENT OFFSETS
|
||||
// IF YOU ARE HERE TO ADJUST THE RINGBOX HUD TURN OFF YOUR COMPUTER AND GO TO YOUR LOCAL PARK
|
||||
|
||||
INT32 fx = 0, fy = 0, fflags = 0; // final coords for hud and flags...
|
||||
INT32 boxoffx = 0;
|
||||
INT32 boxoffy = -6;
|
||||
INT32 vstretch = 0;
|
||||
INT32 hstretch = 3;
|
||||
INT32 splitbsx, splitbsy = 0;
|
||||
UINT16 localcolor[3] = { stplyr->skincolor };
|
||||
SINT8 colormode[3] = { TC_RAINBOW };
|
||||
|
||||
fixed_t rouletteOffset = 0;
|
||||
fixed_t rouletteSpace = SLOT_SPACING;
|
||||
vector2_t rouletteCrop = {10, 10};
|
||||
INT32 i;
|
||||
|
||||
if (stplyr->itemRoulette.itemListLen > 0)
|
||||
{
|
||||
// Init with item roulette stuff.
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
const SINT8 indexOfs = i-1;
|
||||
const size_t index = (stplyr->itemRoulette.itemListLen + (stplyr->itemRoulette.index + indexOfs)) % stplyr->itemRoulette.itemListLen;
|
||||
|
||||
const SINT8 result = stplyr->itemRoulette.itemList[index];
|
||||
|
||||
localpatch[i] = K_GetCachedSlotMachinePatch(result, offset);
|
||||
}
|
||||
}
|
||||
|
||||
if (stplyr->itemRoulette.active == true)
|
||||
{
|
||||
rouletteOffset = K_GetSlotOffset(&stplyr->itemRoulette, rendertimefrac);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!stplyr->ringboxdelay)
|
||||
return;
|
||||
}
|
||||
|
||||
// pain and suffering defined below
|
||||
if (offset)
|
||||
{
|
||||
boxoffx -= 4;
|
||||
if (stplyr == &players[displayplayers[0]] || stplyr == &players[displayplayers[2]]) // If we are P1 or P3...
|
||||
{
|
||||
fx = ITEM_X + 10;
|
||||
fy = ITEM_Y + 10;
|
||||
fflags = V_SNAPTOLEFT|V_SNAPTOTOP|V_SPLITSCREEN;
|
||||
}
|
||||
else // else, that means we're P2 or P4.
|
||||
{
|
||||
fx = ITEM2_X + 7;
|
||||
fy = ITEM2_Y + 10;
|
||||
fflags = V_SNAPTORIGHT|V_SNAPTOTOP|V_SPLITSCREEN;
|
||||
}
|
||||
|
||||
rouletteSpace = SLOT_SPACING_SPLITSCREEN;
|
||||
rouletteOffset = FixedMul(rouletteOffset, FixedDiv(SLOT_SPACING_SPLITSCREEN, SLOT_SPACING));
|
||||
rouletteCrop.x = 16;
|
||||
rouletteCrop.y = 13;
|
||||
splitbsx = -6;
|
||||
splitbsy = -6;
|
||||
boxoffy += 2;
|
||||
hstretch = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
fx = ITEM_X;
|
||||
fy = ITEM_Y;
|
||||
fflags = V_SNAPTOTOP|V_SNAPTOLEFT|V_SPLITSCREEN;
|
||||
}
|
||||
|
||||
V_DrawScaledPatch(fx, fy, V_HUDTRANS|V_SLIDEIN|fflags, localbg);
|
||||
|
||||
V_SetClipRect(
|
||||
((fx + rouletteCrop.x + boxoffx + splitbsx) << FRACBITS), ((fy + rouletteCrop.y + boxoffy - vstretch + splitbsy) << FRACBITS),
|
||||
rouletteSpace + (hstretch<<FRACBITS), rouletteSpace + (vstretch<<FRACBITS),
|
||||
V_SLIDEIN|fflags
|
||||
);
|
||||
|
||||
// item box has special layering, transparency, different sized patches, other fucked up shit
|
||||
// ring box is evenly spaced and easy
|
||||
rouletteOffset += rouletteSpace;
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
V_DrawFixedPatch(
|
||||
((fx)<<FRACBITS), ((fy)<<FRACBITS) + rouletteOffset,
|
||||
FRACUNIT, V_HUDTRANS|V_SLIDEIN|fflags,
|
||||
localpatch[i], (localcolor[i] ? R_GetTranslationColormap(colormode[i], localcolor[i], GTC_CACHE) : NULL)
|
||||
);
|
||||
|
||||
rouletteOffset -= rouletteSpace;
|
||||
}
|
||||
|
||||
V_ClearClipRect();
|
||||
}
|
||||
|
||||
void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT32 splitflags, UINT8 mode)
|
||||
{
|
||||
// TIME_X = BASEVIDWIDTH-124; // 196
|
||||
|
|
@ -4943,7 +5094,7 @@ static void K_drawDistributionDebugger(void)
|
|||
return;
|
||||
}
|
||||
|
||||
K_FillItemRouletteData(stplyr, &rouletteData);
|
||||
K_FillItemRouletteData(stplyr, &rouletteData, false);
|
||||
|
||||
for (i = 0; i < rouletteData.itemListLen; i++)
|
||||
{
|
||||
|
|
@ -5200,7 +5351,16 @@ void K_drawKartHUD(void)
|
|||
|
||||
// Draw the item window
|
||||
if (LUA_HudEnabled(hud_item) && !freecam)
|
||||
K_drawKartItem();
|
||||
{
|
||||
if (stplyr->itemRoulette.ringbox && stplyr->itemamount == 0 && stplyr->itemtype == 0)
|
||||
{
|
||||
K_drawKartSlotMachine();
|
||||
}
|
||||
else
|
||||
{
|
||||
K_drawKartItem();
|
||||
}
|
||||
}
|
||||
|
||||
if (demo.title)
|
||||
;
|
||||
|
|
@ -5280,7 +5440,7 @@ void K_drawKartHUD(void)
|
|||
{
|
||||
if (gametyperules & GTR_CIRCUIT)
|
||||
{
|
||||
if (numlaps > 1)
|
||||
if (numlaps != 1)
|
||||
{
|
||||
K_drawKartLaps();
|
||||
gametypeinfoshown = true;
|
||||
|
|
|
|||
90
src/k_kart.c
90
src/k_kart.c
|
|
@ -361,6 +361,7 @@ void K_RegisterKartStuff(void)
|
|||
CV_RegisterVar(&cv_kartvoices);
|
||||
CV_RegisterVar(&cv_kartbot);
|
||||
CV_RegisterVar(&cv_karteliminatelast);
|
||||
CV_RegisterVar(&cv_thunderdome);
|
||||
CV_RegisterVar(&cv_kartusepwrlv);
|
||||
CV_RegisterVar(&cv_votetime);
|
||||
CV_RegisterVar(&cv_botscanvote);
|
||||
|
|
@ -6532,13 +6533,26 @@ SINT8 K_GetTotallyRandomResult(UINT8 useodds)
|
|||
return i;
|
||||
}
|
||||
|
||||
mobj_t *K_CreatePaperItem(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8 flip, UINT8 type, UINT8 amount)
|
||||
mobj_t *K_CreatePaperItem(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8 flip, UINT8 type, UINT16 amount)
|
||||
{
|
||||
mobj_t *drop = P_SpawnMobj(x, y, z, MT_FLOATINGITEM);
|
||||
mobj_t *backdrop = P_SpawnMobjFromMobj(drop, 0, 0, 0, MT_OVERLAY);
|
||||
|
||||
P_SetTarget(&backdrop->target, drop);
|
||||
P_SetMobjState(backdrop, S_ITEMBACKDROP);
|
||||
// FIXME: due to linkdraw sucking major ass, I was unable
|
||||
// to make a backdrop render behind dropped power-ups
|
||||
// (which use a smaller sprite than normal items). So
|
||||
// dropped power-ups have the backdrop baked into the
|
||||
// sprite for now.
|
||||
if (type < FIRSTPOWERUP)
|
||||
{
|
||||
mobj_t *backdrop = P_SpawnMobjFromMobj(drop, 0, 0, 0, MT_OVERLAY);
|
||||
|
||||
P_SetTarget(&backdrop->target, drop);
|
||||
P_SetMobjState(backdrop, S_ITEMBACKDROP);
|
||||
|
||||
backdrop->dispoffset = 1;
|
||||
P_SetTarget(&backdrop->tracer, drop);
|
||||
backdrop->flags2 |= MF2_LINKDRAW;
|
||||
}
|
||||
|
||||
P_SetScale(drop, drop->scale>>4);
|
||||
drop->destscale = (3*drop->destscale)/2;
|
||||
|
|
@ -6587,9 +6601,6 @@ mobj_t *K_CreatePaperItem(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8
|
|||
}
|
||||
|
||||
drop->flags |= MF_NOCLIPTHING;
|
||||
backdrop->dispoffset = 1;
|
||||
P_SetTarget(&backdrop->tracer, drop);
|
||||
backdrop->flags2 |= MF2_LINKDRAW;
|
||||
|
||||
if (gametyperules & GTR_CLOSERPLAYERS)
|
||||
{
|
||||
|
|
@ -6599,20 +6610,30 @@ mobj_t *K_CreatePaperItem(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8
|
|||
return drop;
|
||||
}
|
||||
|
||||
void K_DropPaperItem(player_t *player, UINT8 itemtype, UINT16 itemamount)
|
||||
{
|
||||
if (!player->mo || P_MobjWasRemoved(player->mo))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mobj_t *drop = K_CreatePaperItem(
|
||||
player->mo->x, player->mo->y, player->mo->z + player->mo->height/2,
|
||||
player->mo->angle + ANGLE_90, P_MobjFlip(player->mo),
|
||||
itemtype, itemamount
|
||||
);
|
||||
|
||||
K_FlipFromObject(drop, player->mo);
|
||||
}
|
||||
|
||||
// For getting EXTRA hit!
|
||||
void K_DropItems(player_t *player)
|
||||
{
|
||||
K_DropHnextList(player);
|
||||
|
||||
if (player->mo && !P_MobjWasRemoved(player->mo) && player->itemamount > 0)
|
||||
if (player->itemamount > 0)
|
||||
{
|
||||
mobj_t *drop = K_CreatePaperItem(
|
||||
player->mo->x, player->mo->y, player->mo->z + player->mo->height/2,
|
||||
player->mo->angle + ANGLE_90, P_MobjFlip(player->mo),
|
||||
player->itemtype, player->itemamount
|
||||
);
|
||||
|
||||
K_FlipFromObject(drop, player->mo);
|
||||
K_DropPaperItem(player, player->itemtype, player->itemamount);
|
||||
}
|
||||
|
||||
K_StripItems(player);
|
||||
|
|
@ -8287,6 +8308,12 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
|
|||
if (player->hand && P_MobjWasRemoved(player->hand))
|
||||
P_SetTarget(&player->hand, NULL);
|
||||
|
||||
if (player->flickyAttacker && P_MobjWasRemoved(player->flickyAttacker))
|
||||
P_SetTarget(&player->flickyAttacker, NULL);
|
||||
|
||||
if (player->powerup.flickyController && P_MobjWasRemoved(player->powerup.flickyController))
|
||||
P_SetTarget(&player->powerup.flickyController, NULL);
|
||||
|
||||
if (player->spectator == false)
|
||||
{
|
||||
K_KartEbrakeVisuals(player);
|
||||
|
|
@ -10753,6 +10780,26 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
|
|||
player->pflags &= ~PF_USERINGS;
|
||||
}
|
||||
|
||||
if (player->ringboxdelay)
|
||||
{
|
||||
player->ringboxdelay--;
|
||||
if (player->ringboxdelay == 0)
|
||||
{
|
||||
// TODO
|
||||
UINT32 behind = K_GetItemRouletteDistance(player, player->itemRoulette.playing);
|
||||
UINT32 behindMulti = behind / 1000;
|
||||
behindMulti = min(behindMulti, 20);
|
||||
|
||||
UINT32 award = 5*player->ringboxaward + 10;
|
||||
if (player->ringboxaward > 2) // not a BAR
|
||||
award = 3 * award / 2;
|
||||
award = award * (behindMulti + 10) / 10;
|
||||
|
||||
K_AwardPlayerRings(player, award, true);
|
||||
player->ringboxaward = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (player && player->mo && player->mo->health > 0 && !player->spectator && !P_PlayerInPain(player) && !mapreset && leveltime > introtime)
|
||||
{
|
||||
// First, the really specific, finicky items that function without the item being directly in your item slot.
|
||||
|
|
@ -11988,8 +12035,17 @@ void K_UpdateMobjItemOverlay(mobj_t *part, SINT8 itemType, UINT8 itemCount)
|
|||
part->frame = FF_FULLBRIGHT|FF_PAPERSPRITE;
|
||||
break;
|
||||
default:
|
||||
part->sprite = SPR_ITEM;
|
||||
part->frame = FF_FULLBRIGHT|FF_PAPERSPRITE|(itemType);
|
||||
if (itemType >= FIRSTPOWERUP)
|
||||
{
|
||||
part->sprite = SPR_PWRB;
|
||||
// Not a papersprite. See K_CreatePaperItem for why.
|
||||
part->frame = FF_FULLBRIGHT|(itemType - FIRSTPOWERUP);
|
||||
}
|
||||
else
|
||||
{
|
||||
part->sprite = SPR_ITEM;
|
||||
part->frame = FF_FULLBRIGHT|FF_PAPERSPRITE|(itemType);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -150,7 +150,8 @@ void K_SpawnDriftElectricSparks(player_t *player, int color, boolean shockwave);
|
|||
void K_KartUpdatePosition(player_t *player);
|
||||
void K_UpdateAllPlayerPositions(void);
|
||||
SINT8 K_GetTotallyRandomResult(UINT8 useodds);
|
||||
mobj_t *K_CreatePaperItem(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8 flip, UINT8 type, UINT8 amount);
|
||||
mobj_t *K_CreatePaperItem(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8 flip, UINT8 type, UINT16 amount);
|
||||
void K_DropPaperItem(player_t *player, UINT8 itemtype, UINT16 itemamount);
|
||||
void K_PopPlayerShield(player_t *player);
|
||||
void K_DropItems(player_t *player);
|
||||
void K_DropRocketSneaker(player_t *player);
|
||||
|
|
|
|||
18
src/k_menu.h
18
src/k_menu.h
|
|
@ -126,6 +126,9 @@ void M_PrevMenuGametype(UINT32 forbidden);
|
|||
void M_HandleHostMenuGametype(INT32 choice);
|
||||
void M_HandlePauseMenuGametype(INT32 choice);
|
||||
|
||||
extern UINT32 menucallvote; // not midVoteType_e to prevent #include k_zvote
|
||||
void M_HandlePauseMenuCallVote(INT32 choice);
|
||||
|
||||
//
|
||||
// MENU TYPEDEFS
|
||||
//
|
||||
|
|
@ -415,6 +418,8 @@ extern menu_t EXTRAS_EggTVDef;
|
|||
extern menuitem_t PAUSE_Main[];
|
||||
extern menu_t PAUSE_MainDef;
|
||||
|
||||
extern menu_t PAUSE_KickHandlerDef;
|
||||
|
||||
// EXTRAS
|
||||
extern menuitem_t MISC_Manual[];
|
||||
extern menu_t MISC_ManualDef;
|
||||
|
|
@ -447,6 +452,8 @@ typedef enum
|
|||
#ifdef HAVE_DISCORDRPC
|
||||
mpause_discordrequests,
|
||||
#endif
|
||||
mpause_admin,
|
||||
mpause_callvote,
|
||||
|
||||
mpause_continue,
|
||||
mpause_spectate,
|
||||
|
|
@ -1052,6 +1059,7 @@ typedef enum
|
|||
extras_eggtv,
|
||||
extras_stereo,
|
||||
extras_password,
|
||||
extras_credits,
|
||||
} extras_e;
|
||||
|
||||
void M_InitExtras(INT32 choice); // init for the struct
|
||||
|
|
@ -1082,6 +1090,15 @@ void M_QuitPauseMenu(INT32 choice);
|
|||
boolean M_PauseInputs(INT32 ch);
|
||||
void M_PauseTick(void);
|
||||
|
||||
extern struct playerkickmenu_s {
|
||||
tic_t ticker;
|
||||
UINT8 player;
|
||||
UINT8 poke;
|
||||
boolean adminpowered;
|
||||
} playerkickmenu;
|
||||
|
||||
void M_KickHandler(INT32 choice);
|
||||
|
||||
extern consvar_t cv_dummymenuplayer;
|
||||
extern consvar_t cv_dummyspectator;
|
||||
|
||||
|
|
@ -1154,6 +1171,7 @@ void M_DrawMPServerBrowser(void);
|
|||
|
||||
// Pause menu:
|
||||
void M_DrawPause(void);
|
||||
void M_DrawKickHandler(void);
|
||||
|
||||
// Replay Playback
|
||||
void M_DrawPlaybackMenu(void);
|
||||
|
|
|
|||
231
src/k_menudraw.c
231
src/k_menudraw.c
|
|
@ -52,6 +52,7 @@
|
|||
#include "doomstat.h" // MAXSPLITSCREENPLAYERS
|
||||
#include "k_grandprix.h" // K_CanChangeRules
|
||||
#include "k_rank.h" // K_GetGradeColor
|
||||
#include "k_zvote.h" // K_GetMidVoteLabel
|
||||
|
||||
#include "y_inter.h" // Y_RoundQueueDrawer
|
||||
|
||||
|
|
@ -3111,7 +3112,7 @@ void M_DrawMPHost(void)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case IT_KEYHANDLER:
|
||||
case IT_ARROWS:
|
||||
{
|
||||
if (currentMenu->menuitems[i].itemaction.routine != M_HandleHostMenuGametype)
|
||||
break;
|
||||
|
|
@ -4308,11 +4309,6 @@ void M_DrawPause(void)
|
|||
INT16 arrxpos = 150 + 2*offset; // To draw the background arrow.
|
||||
|
||||
INT16 j = 0;
|
||||
char word1[MAXSTRINGLENGTH];
|
||||
INT16 word1len = 0;
|
||||
char word2[MAXSTRINGLENGTH];
|
||||
INT16 word2len = 0;
|
||||
boolean sok = false;
|
||||
|
||||
patch_t *vertbg = W_CachePatchName("M_STRIPV", PU_CACHE);
|
||||
patch_t *arrstart = W_CachePatchName("M_PTIP", PU_CACHE);
|
||||
|
|
@ -4410,54 +4406,107 @@ void M_DrawPause(void)
|
|||
}
|
||||
|
||||
// Draw the string!
|
||||
// ...but first get what we need to get.
|
||||
while (currentMenu->menuitems[itemOn].text[j] && j < MAXSTRINGLENGTH)
|
||||
{
|
||||
char c = currentMenu->menuitems[itemOn].text[j];
|
||||
|
||||
if (c == ' ' && !sok)
|
||||
{
|
||||
sok = true;
|
||||
j++;
|
||||
continue; // We don't care about this :moyai:
|
||||
}
|
||||
|
||||
if (sok)
|
||||
{
|
||||
word2[word2len] = c;
|
||||
word2len++;
|
||||
}
|
||||
else
|
||||
{
|
||||
word1[word1len] = c;
|
||||
word1len++;
|
||||
}
|
||||
|
||||
j++;
|
||||
}
|
||||
|
||||
word1[word1len] = '\0';
|
||||
word2[word2len] = '\0';
|
||||
const char *maintext = NULL;
|
||||
const char *selectabletext = NULL;
|
||||
INT32 mainflags = V_YELLOWMAP, selectableflags = 0;
|
||||
|
||||
if (itemOn == mpause_changegametype)
|
||||
{
|
||||
INT32 w = V_LSTitleLowStringWidth(gametypes[menugametype]->name, 0)/2;
|
||||
selectabletext = gametypes[menugametype]->name;
|
||||
}
|
||||
else if (itemOn == mpause_callvote)
|
||||
{
|
||||
selectabletext = K_GetMidVoteLabel(menucallvote);
|
||||
|
||||
if (word1len)
|
||||
V_DrawCenteredLSTitleHighString(220 + offset*2, 75, 0, word1);
|
||||
if (K_MinimalCheckNewMidVote(menucallvote) == false)
|
||||
{
|
||||
if (g_midVote.active == true)
|
||||
{
|
||||
maintext = "ACTIVE...";
|
||||
}
|
||||
else if (g_midVote.delay > 0)
|
||||
{
|
||||
if (g_midVote.delay != 1)
|
||||
maintext = va("%u", ((g_midVote.delay - 1) / TICRATE) + 1);
|
||||
}
|
||||
else if (K_PlayerIDAllowedInMidVote(consoleplayer) == false)
|
||||
{
|
||||
maintext = "SPECTATING";
|
||||
}
|
||||
else
|
||||
{
|
||||
maintext = "INVALID!?";
|
||||
}
|
||||
|
||||
V_DrawLSTitleLowString(220-w + offset*2, 103, V_YELLOWMAP, gametypes[menugametype]->name);
|
||||
V_DrawCharacter(220-w + offset*2 - 8 - (skullAnimCounter/5), 103+6, '\x1C' | V_YELLOWMAP, false); // left arrow
|
||||
V_DrawCharacter(220+w + offset*2 + 4 + (skullAnimCounter/5), 103+6, '\x1D' | V_YELLOWMAP, false); // right arrow
|
||||
if (maintext != NULL)
|
||||
selectableflags |= V_MODULATE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
maintext = currentMenu->menuitems[itemOn].text;
|
||||
mainflags = 0;
|
||||
}
|
||||
|
||||
if (selectabletext != NULL)
|
||||
{
|
||||
// We have a selection. Let's show the full menu text on top, and the choice below.
|
||||
|
||||
if (currentMenu->menuitems[itemOn].text)
|
||||
V_DrawCenteredLSTitleHighString(220 + offset*2, 75, selectableflags, currentMenu->menuitems[itemOn].text);
|
||||
|
||||
selectableflags |= V_YELLOWMAP;
|
||||
|
||||
INT32 w = V_LSTitleLowStringWidth(selectabletext, selectableflags)/2;
|
||||
V_DrawLSTitleLowString(220-w + offset*2, 103, selectableflags, selectabletext);
|
||||
|
||||
V_DrawCharacter(220-w + offset*2 - 8 - (skullAnimCounter/5), 103+6, '\x1C' | selectableflags, false); // left arrow
|
||||
V_DrawCharacter(220+w + offset*2 + (skullAnimCounter/5), 103+6, '\x1D' | selectableflags, false); // right arrow
|
||||
}
|
||||
|
||||
if (maintext != NULL)
|
||||
{
|
||||
// This is a regular menu option. Try to break it onto two lines.
|
||||
|
||||
char word1[MAXSTRINGLENGTH];
|
||||
INT16 word1len = 0;
|
||||
char word2[MAXSTRINGLENGTH];
|
||||
INT16 word2len = 0;
|
||||
boolean sok = false;
|
||||
|
||||
while (maintext[j] && j < MAXSTRINGLENGTH)
|
||||
{
|
||||
if (maintext[j] == ' ' && !sok)
|
||||
{
|
||||
sok = true;
|
||||
j++;
|
||||
continue; // We don't care about this :moyai:
|
||||
}
|
||||
|
||||
if (sok)
|
||||
{
|
||||
word2[word2len] = maintext[j];
|
||||
word2len++;
|
||||
}
|
||||
else
|
||||
{
|
||||
word1[word1len] = maintext[j];
|
||||
word1len++;
|
||||
}
|
||||
|
||||
j++;
|
||||
}
|
||||
|
||||
word1[word1len] = '\0';
|
||||
word2[word2len] = '\0';
|
||||
|
||||
// If there's no 2nd word, take this opportunity to center this line of text.
|
||||
if (word1len)
|
||||
V_DrawCenteredLSTitleHighString(220 + offset*2, 75 + (!word2len ? 10 : 0), 0, word1);
|
||||
V_DrawCenteredLSTitleHighString(220 + offset*2, 75 + (!word2len ? 10 : 0), mainflags, word1);
|
||||
|
||||
if (word2len)
|
||||
V_DrawCenteredLSTitleLowString(220 + offset*2, 103, 0, word2);
|
||||
V_DrawCenteredLSTitleLowString(220 + offset*2, 103, mainflags, word2);
|
||||
}
|
||||
|
||||
if (gamestate != GS_INTERMISSION && roundqueue.size > 0)
|
||||
|
|
@ -4539,6 +4588,106 @@ void M_DrawPause(void)
|
|||
}
|
||||
}
|
||||
|
||||
void M_DrawKickHandler(void)
|
||||
{
|
||||
// fake round queue drawer simply to make release
|
||||
INT32 x = 29 + 4, y = 70, returny = y;
|
||||
INT32 pokeamount = (playerkickmenu.poke & 1) ? -playerkickmenu.poke/2 : playerkickmenu.poke/2;
|
||||
INT32 x2 = x + pokeamount - 9 - 8;
|
||||
|
||||
boolean datarightofcolumn = false;
|
||||
|
||||
patch_t *resbar = W_CachePatchName("R_RESBAR", PU_CACHE); // Results bars for players
|
||||
|
||||
UINT8 i;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
V_DrawMappedPatch(
|
||||
x, y,
|
||||
(playeringame[i] == true)
|
||||
? ((players[i].spectator == true) ? V_TRANSLUCENT : 0)
|
||||
: V_MODULATE,
|
||||
resbar, NULL
|
||||
);
|
||||
|
||||
V_DrawRightAlignedThinString(
|
||||
x+13, y-2,
|
||||
((i == playerkickmenu.player)
|
||||
? highlightflags
|
||||
: 0
|
||||
),
|
||||
va("%u", i)
|
||||
);
|
||||
|
||||
if (playeringame[i] == true)
|
||||
{
|
||||
if (players[i].skincolor != SKINCOLOR_NONE)
|
||||
{
|
||||
UINT8 *charcolormap;
|
||||
if ((players[i].pflags & PF_NOCONTEST) && players[i].bot)
|
||||
{
|
||||
// RETIRED !!
|
||||
charcolormap = R_GetTranslationColormap(TC_DEFAULT, players[i].skincolor, GTC_CACHE);
|
||||
V_DrawMappedPatch(x+14, y-5, 0, W_CachePatchName("MINIDEAD", PU_CACHE), charcolormap);
|
||||
}
|
||||
else
|
||||
{
|
||||
charcolormap = R_GetTranslationColormap(players[i].skin, players[i].skincolor, GTC_CACHE);
|
||||
V_DrawMappedPatch(x+14, y-5, 0, faceprefix[players[i].skin][FACE_MINIMAP], charcolormap);
|
||||
}
|
||||
}
|
||||
|
||||
V_DrawThinString(
|
||||
x+27, y-2,
|
||||
(
|
||||
P_IsMachineLocalPlayer(&players[i])
|
||||
? highlightflags
|
||||
: 0
|
||||
)|V_ALLOWLOWERCASE|V_6WIDTHSPACE,
|
||||
player_names[i]
|
||||
);
|
||||
|
||||
V_DrawRightAlignedThinString(
|
||||
x+118, y-2,
|
||||
V_ALLOWLOWERCASE|V_6WIDTHSPACE,
|
||||
(players[i].spectator) ? "SPECTATOR" : "PLAYING"
|
||||
);
|
||||
}
|
||||
|
||||
if (i == playerkickmenu.player)
|
||||
{
|
||||
V_DrawScaledPatch(
|
||||
x2, y-1,
|
||||
(datarightofcolumn ? V_FLIP : 0),
|
||||
W_CachePatchName("M_CURSOR", PU_CACHE)
|
||||
);
|
||||
}
|
||||
|
||||
y += 13;
|
||||
|
||||
if (i == (MAXPLAYERS-1)/2)
|
||||
{
|
||||
x = 169 - 4;
|
||||
y = returny;
|
||||
|
||||
datarightofcolumn = true;
|
||||
x2 = x + 118 + 9 + 8 + 4 - pokeamount;
|
||||
}
|
||||
}
|
||||
|
||||
//V_DrawFill(32 + (playerkickmenu.player & 8), 32 + (playerkickmenu.player & 7)*8, 8, 8, playeringame[playerkickmenu.player] ? 0 : 16);
|
||||
|
||||
V_DrawFixedPatch(0, 0, FRACUNIT, 0, W_CachePatchName("MENUHINT", PU_CACHE), NULL);
|
||||
V_DrawCenteredThinString(
|
||||
BASEVIDWIDTH/2, 12,
|
||||
V_ALLOWLOWERCASE|V_6WIDTHSPACE,
|
||||
(playerkickmenu.adminpowered)
|
||||
? "You are using ""\x85""Admin Tools""\x80"", ""\x83""(A)""\x80"" to kick and ""\x84""(C)""\x80"" to ban"
|
||||
: K_GetMidVoteLabel(menucallvote)
|
||||
);
|
||||
}
|
||||
|
||||
void M_DrawPlaybackMenu(void)
|
||||
{
|
||||
INT16 i;
|
||||
|
|
|
|||
|
|
@ -209,7 +209,6 @@ static boolean M_GamestateCanOpenMenu(void)
|
|||
{
|
||||
case GS_INTRO:
|
||||
case GS_CUTSCENE:
|
||||
case GS_GAMEEND:
|
||||
case GS_CREDITS:
|
||||
case GS_EVALUATION:
|
||||
case GS_CEREMONY:
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
#ifndef k_objects_H
|
||||
#define k_objects_H
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "m_fixed.h"
|
||||
#include "tables.h" // angle_t
|
||||
#include "taglist.h"
|
||||
|
||||
|
|
@ -135,6 +137,7 @@ void Obj_RandomItemVisuals(mobj_t *mobj);
|
|||
boolean Obj_RandomItemSpawnIn(mobj_t *mobj);
|
||||
fixed_t Obj_RandomItemScale(fixed_t oldScale);
|
||||
void Obj_RandomItemSpawn(mobj_t *mobj);
|
||||
#define RINGBOX_TIME (70)
|
||||
|
||||
/* Gachabom Rebound */
|
||||
void Obj_GachaBomReboundThink(mobj_t *mobj);
|
||||
|
|
@ -143,6 +146,21 @@ void Obj_SpawnGachaBomRebound(mobj_t *source, mobj_t *target);
|
|||
/* Servant Hand */
|
||||
void Obj_ServantHandHandling(player_t *player);
|
||||
|
||||
/* Super Flicky Controller */
|
||||
void Obj_SpawnSuperFlickySwarm(player_t *owner, tic_t time);
|
||||
void Obj_SuperFlickyControllerThink(mobj_t *controller);
|
||||
void Obj_EndSuperFlickySwarm(mobj_t *controller);
|
||||
void Obj_ExtendSuperFlickySwarm(mobj_t *controller, tic_t time);
|
||||
tic_t Obj_SuperFlickySwarmTime(const mobj_t *controller);
|
||||
|
||||
/* Super Flicky */
|
||||
void Obj_SuperFlickyThink(mobj_t *flicky);
|
||||
void Obj_WhipSuperFlicky(mobj_t *flicky);
|
||||
void Obj_BlockSuperFlicky(mobj_t *flicky);
|
||||
void Obj_SuperFlickyPlayerCollide(mobj_t *flicky, mobj_t *player);
|
||||
void Obj_SuperFlickyLanding(mobj_t *flicky);
|
||||
boolean Obj_IsSuperFlickyWhippable(const mobj_t *flicky);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -235,16 +235,25 @@ void K_UpdatePodiumWaypoints(player_t *const player)
|
|||
--------------------------------------------------*/
|
||||
boolean K_StartCeremony(void)
|
||||
{
|
||||
INT32 podiumMapNum = nummapheaders;
|
||||
INT32 i;
|
||||
|
||||
if (grandprixinfo.gp == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (podiummap
|
||||
&& ((podiumMapNum = G_MapNumber(podiummap)) < nummapheaders)
|
||||
INT32 i;
|
||||
INT32 podiumMapNum = NEXTMAP_INVALID;
|
||||
|
||||
if (grandprixinfo.cup != NULL
|
||||
&& grandprixinfo.cup->cachedlevels[CUPCACHE_PODIUM] != NEXTMAP_INVALID)
|
||||
{
|
||||
podiumMapNum = grandprixinfo.cup->cachedlevels[CUPCACHE_PODIUM];
|
||||
}
|
||||
else if (podiummap)
|
||||
{
|
||||
podiumMapNum = G_MapNumber(podiummap);
|
||||
}
|
||||
|
||||
if (podiumMapNum < nummapheaders
|
||||
&& mapheaderinfo[podiumMapNum]
|
||||
&& mapheaderinfo[podiumMapNum]->lumpnum != LUMPERROR)
|
||||
{
|
||||
|
|
|
|||
50
src/k_powerup.cpp
Normal file
50
src/k_powerup.cpp
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/// \brief Battle mode power-up code
|
||||
|
||||
#include "k_kart.h"
|
||||
#include "k_objects.h"
|
||||
#include "k_powerup.h"
|
||||
|
||||
tic_t K_PowerUpRemaining(const player_t* player, kartitems_t powerup)
|
||||
{
|
||||
switch (powerup)
|
||||
{
|
||||
case POWERUP_SUPERFLICKY:
|
||||
return Obj_SuperFlickySwarmTime(player->powerup.flickyController);
|
||||
|
||||
default:
|
||||
return 0u;
|
||||
}
|
||||
}
|
||||
|
||||
void K_GivePowerUp(player_t* player, kartitems_t powerup, tic_t time)
|
||||
{
|
||||
switch (powerup)
|
||||
{
|
||||
case POWERUP_SUPERFLICKY:
|
||||
if (K_PowerUpRemaining(player, POWERUP_SUPERFLICKY))
|
||||
{
|
||||
Obj_ExtendSuperFlickySwarm(player->powerup.flickyController, time);
|
||||
}
|
||||
else
|
||||
{
|
||||
Obj_SpawnSuperFlickySwarm(player, time);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void K_DropPowerUps(player_t* player)
|
||||
{
|
||||
if (K_PowerUpRemaining(player, POWERUP_SUPERFLICKY))
|
||||
{
|
||||
mobj_t* swarm = player->powerup.flickyController;
|
||||
|
||||
// Be sure to measure the remaining time before ending the power-up
|
||||
K_DropPaperItem(player, POWERUP_SUPERFLICKY, Obj_SuperFlickySwarmTime(swarm));
|
||||
|
||||
Obj_EndSuperFlickySwarm(swarm);
|
||||
}
|
||||
}
|
||||
19
src/k_powerup.h
Normal file
19
src/k_powerup.h
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#ifndef __K_POWERUP__
|
||||
#define __K_POWERUP__
|
||||
|
||||
#include "doomtype.h"
|
||||
#include "d_player.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
tic_t K_PowerUpRemaining(const player_t *player, kartitems_t powerup);
|
||||
void K_GivePowerUp(player_t *player, kartitems_t powerup, tic_t timer);
|
||||
void K_DropPowerUps(player_t *player);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // __K_POWERUP__
|
||||
|
|
@ -218,6 +218,17 @@ static kartitems_t K_KartItemReelBoss[] =
|
|||
KITEM_NONE
|
||||
};
|
||||
|
||||
static kartslotmachine_t K_KartItemReelRingBox[] =
|
||||
{
|
||||
KSM_BAR,
|
||||
KSM_DOUBLEBAR,
|
||||
KSM_TRIPLEBAR,
|
||||
KSM_RING,
|
||||
KSM_SEVEN,
|
||||
KSM_JACKPOT,
|
||||
KSM__MAX
|
||||
};
|
||||
|
||||
/*--------------------------------------------------
|
||||
boolean K_ItemEnabled(kartitems_t item)
|
||||
|
||||
|
|
@ -438,7 +449,7 @@ static UINT32 K_ScaleItemDistance(UINT32 distance, UINT8 numPlayers)
|
|||
Return:-
|
||||
The player's finalized item distance.
|
||||
--------------------------------------------------*/
|
||||
static UINT32 K_GetItemRouletteDistance(const player_t *player, UINT8 numPlayers)
|
||||
UINT32 K_GetItemRouletteDistance(const player_t *player, UINT8 numPlayers)
|
||||
{
|
||||
UINT32 pdis = 0;
|
||||
|
||||
|
|
@ -1052,6 +1063,7 @@ static void K_InitRoulette(itemroulette_t *const roulette)
|
|||
|
||||
roulette->active = true;
|
||||
roulette->eggman = false;
|
||||
roulette->ringbox = false;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
|
|
@ -1104,19 +1116,20 @@ static void K_InitRoulette(itemroulette_t *const roulette)
|
|||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static void K_PushToRouletteItemList(itemroulette_t *const roulette, kartitems_t item)
|
||||
static void K_PushToRouletteItemList(itemroulette_t *const roulette, INT32 item)
|
||||
|
||||
Pushes a new item to the end of the item
|
||||
roulette's item list.
|
||||
roulette's item list. Also accepts slot machine
|
||||
values instead of items.
|
||||
|
||||
Input Arguments:-
|
||||
roulette - The item roulette data to modify.
|
||||
item - The item to push to the list.
|
||||
item - The item / slot machine index to push to the list.
|
||||
|
||||
Return:-
|
||||
N/A
|
||||
--------------------------------------------------*/
|
||||
static void K_PushToRouletteItemList(itemroulette_t *const roulette, kartitems_t item)
|
||||
static void K_PushToRouletteItemList(itemroulette_t *const roulette, INT32 item)
|
||||
{
|
||||
#ifdef ITEM_LIST_SIZE
|
||||
if (roulette->itemListLen >= ITEM_LIST_SIZE)
|
||||
|
|
@ -1253,11 +1266,11 @@ static void K_CalculateRouletteSpeed(itemroulette_t *const roulette)
|
|||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_FillItemRouletteData(const player_t *player, itemroulette_t *const roulette)
|
||||
void K_FillItemRouletteData(const player_t *player, itemroulette_t *const roulette, boolean ringbox)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
void K_FillItemRouletteData(const player_t *player, itemroulette_t *const roulette)
|
||||
void K_FillItemRouletteData(const player_t *player, itemroulette_t *const roulette, boolean ringbox)
|
||||
{
|
||||
UINT32 spawnChance[NUMKARTRESULTS] = {0};
|
||||
UINT32 totalSpawnChance = 0;
|
||||
|
|
@ -1276,6 +1289,20 @@ void K_FillItemRouletteData(const player_t *player, itemroulette_t *const roulet
|
|||
K_CalculateRouletteSpeed(roulette);
|
||||
}
|
||||
|
||||
if (ringbox == true)
|
||||
{
|
||||
// If this is being invoked by a Ring Box, it should literally never produce items.
|
||||
kartslotmachine_t *presetlist = K_KartItemReelRingBox;
|
||||
roulette->ringbox = true;
|
||||
|
||||
for (i = 0; presetlist[i] != KSM__MAX; i++)
|
||||
{
|
||||
K_PushToRouletteItemList(roulette, presetlist[i]);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// SPECIAL CASE No. 1:
|
||||
// Give only the debug item if specified
|
||||
if (cv_kartdebugitem.value != KITEM_NONE)
|
||||
|
|
@ -1412,12 +1439,12 @@ void K_FillItemRouletteData(const player_t *player, itemroulette_t *const roulet
|
|||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
void K_StartItemRoulette(player_t *const player)
|
||||
void K_StartItemRoulette(player_t *const player, boolean ringbox)
|
||||
{
|
||||
itemroulette_t *const roulette = &player->itemRoulette;
|
||||
size_t i;
|
||||
|
||||
K_FillItemRouletteData(player, roulette);
|
||||
K_FillItemRouletteData(player, roulette, ringbox);
|
||||
|
||||
if (K_PlayerUsesBotMovement(player) == true)
|
||||
{
|
||||
|
|
@ -1444,7 +1471,7 @@ void K_StartItemRoulette(player_t *const player)
|
|||
void K_StartEggmanRoulette(player_t *const player)
|
||||
{
|
||||
itemroulette_t *const roulette = &player->itemRoulette;
|
||||
K_StartItemRoulette(player);
|
||||
K_StartItemRoulette(player, false);
|
||||
roulette->eggman = true;
|
||||
}
|
||||
|
||||
|
|
@ -1461,6 +1488,19 @@ fixed_t K_GetRouletteOffset(itemroulette_t *const roulette, fixed_t renderDelta)
|
|||
return FixedMul(FixedDiv(midTic - curTic, ((roulette->speed + 1) << FRACBITS)), ROULETTE_SPACING);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
fixed_t K_GetSlotOffset(itemroulette_t *const roulette, fixed_t renderDelta)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
fixed_t K_GetSlotOffset(itemroulette_t *const roulette, fixed_t renderDelta)
|
||||
{
|
||||
const fixed_t curTic = (roulette->tics << FRACBITS) - renderDelta;
|
||||
const fixed_t midTic = roulette->speed * (FRACUNIT >> 1);
|
||||
|
||||
return FixedMul(FixedDiv(midTic - curTic, ((roulette->speed + 1) << FRACBITS)), SLOT_SPACING);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static void K_KartGetItemResult(player_t *const player, kartitems_t getitem)
|
||||
|
||||
|
|
@ -1572,9 +1612,17 @@ void K_KartItemRoulette(player_t *const player, ticcmd_t *const cmd)
|
|||
// And one more nudge for the remaining delay.
|
||||
roulette->tics = (roulette->tics + fudgedDelay) % roulette->speed;
|
||||
|
||||
kartitems_t finalItem = roulette->itemList[ roulette->index ];
|
||||
INT32 finalItem = roulette->itemList[ roulette->index ];
|
||||
|
||||
K_KartGetItemResult(player, finalItem);
|
||||
if (roulette->ringbox == true)
|
||||
{
|
||||
player->ringboxdelay = TICRATE;
|
||||
player->ringboxaward = finalItem;
|
||||
}
|
||||
else
|
||||
{
|
||||
K_KartGetItemResult(player, finalItem);
|
||||
}
|
||||
|
||||
player->karthud[khud_itemblink] = TICRATE;
|
||||
player->karthud[khud_itemblinkmode] = 0;
|
||||
|
|
@ -1582,7 +1630,10 @@ void K_KartItemRoulette(player_t *const player, ticcmd_t *const cmd)
|
|||
|
||||
if (P_IsDisplayPlayer(player) && !demo.freecam)
|
||||
{
|
||||
S_StartSound(NULL, sfx_itrolf);
|
||||
if (roulette->ringbox)
|
||||
S_StartSound(NULL, sfx_s245);
|
||||
else
|
||||
S_StartSound(NULL, sfx_itrolf);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1603,7 +1654,10 @@ void K_KartItemRoulette(player_t *const player, ticcmd_t *const cmd)
|
|||
|
||||
if (P_IsDisplayPlayer(player) && !demo.freecam)
|
||||
{
|
||||
S_StartSound(NULL, sfx_itrol1 + roulette->sound);
|
||||
if (roulette->ringbox)
|
||||
S_StartSound(NULL, sfx_s240);
|
||||
else
|
||||
S_StartSound(NULL, sfx_itrol1 + roulette->sound);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -23,6 +23,9 @@ extern "C" {
|
|||
#define ROULETTE_SPACING (36 << FRACBITS)
|
||||
#define ROULETTE_SPACING_SPLITSCREEN (16 << FRACBITS)
|
||||
|
||||
#define SLOT_SPACING (40 << FRACBITS)
|
||||
#define SLOT_SPACING_SPLITSCREEN (22 << FRACBITS)
|
||||
|
||||
/*--------------------------------------------------
|
||||
boolean K_ItemEnabled(kartitems_t item);
|
||||
|
||||
|
|
@ -98,7 +101,7 @@ INT32 K_KartGetItemOdds(const player_t *player, itemroulette_t *const roulette,
|
|||
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_FillItemRouletteData(const player_t *player, itemroulette_t *const roulette);
|
||||
void K_FillItemRouletteData(const player_t *player, itemroulette_t *const roulette, boolean ringbox);
|
||||
|
||||
Fills out the item roulette struct when it is
|
||||
initially created. This function needs to be
|
||||
|
|
@ -109,16 +112,17 @@ INT32 K_KartGetItemOdds(const player_t *player, itemroulette_t *const roulette,
|
|||
player - The player this roulette data is for.
|
||||
Can be NULL for generic use.
|
||||
roulette - The roulette data struct to fill out.
|
||||
ringbox - Is this roulette fill triggered by a just-respawned Ring Box?
|
||||
|
||||
Return:-
|
||||
N/A
|
||||
--------------------------------------------------*/
|
||||
|
||||
void K_FillItemRouletteData(const player_t *player, itemroulette_t *const roulette);
|
||||
void K_FillItemRouletteData(const player_t *player, itemroulette_t *const roulette, boolean ringbox);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_StartItemRoulette(player_t *const player);
|
||||
void K_StartItemRoulette(player_t *const player, boolean ringbox);
|
||||
|
||||
Starts the item roulette sequence for a player.
|
||||
This stage can only be used by gameplay, thus
|
||||
|
|
@ -126,12 +130,13 @@ void K_FillItemRouletteData(const player_t *player, itemroulette_t *const roulet
|
|||
|
||||
Input Arguments:-
|
||||
player - The player to start the item roulette for.
|
||||
ringbox - Is this roulette being started from a just-respawned Ring Box?
|
||||
|
||||
Return:-
|
||||
N/A
|
||||
--------------------------------------------------*/
|
||||
|
||||
void K_StartItemRoulette(player_t *const player);
|
||||
void K_StartItemRoulette(player_t *const player, boolean ringbox);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
|
|
@ -169,6 +174,23 @@ void K_StartEggmanRoulette(player_t *const player);
|
|||
|
||||
fixed_t K_GetRouletteOffset(itemroulette_t *const roulette, fixed_t renderDelta);
|
||||
|
||||
/*--------------------------------------------------
|
||||
fixed_t K_GetSlotOffset(itemroulette_t *const roulette, fixed_t renderDelta);
|
||||
|
||||
Gets the Y offset, for use in the slot HUD.
|
||||
A separate function since it is used both by the
|
||||
HUD itself, as well as when confirming an item.
|
||||
|
||||
Input Arguments:-
|
||||
roulette - The roulette we are drawing for.
|
||||
renderDelta - Fractional tic delta, when used for HUD.
|
||||
|
||||
Return:-
|
||||
The Y offset when drawing the item.
|
||||
--------------------------------------------------*/
|
||||
|
||||
fixed_t K_GetSlotOffset(itemroulette_t *const roulette, fixed_t renderDelta);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_KartItemRoulette(player_t *const player, ticcmd_t *cmd);
|
||||
|
|
@ -186,6 +208,8 @@ fixed_t K_GetRouletteOffset(itemroulette_t *const roulette, fixed_t renderDelta)
|
|||
|
||||
void K_KartItemRoulette(player_t *const player, ticcmd_t *cmd);
|
||||
|
||||
UINT32 K_GetItemRouletteDistance(const player_t *player, UINT8 numPlayers);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
|
|
|||
199
src/k_zvote.c
199
src/k_zvote.c
|
|
@ -57,10 +57,7 @@ static void K_MidVoteKick(void)
|
|||
return;
|
||||
}
|
||||
|
||||
if (server)
|
||||
{
|
||||
SendKick(g_midVote.victim - players, KICK_MSG_VOTE_KICK);
|
||||
}
|
||||
SendKick(g_midVote.victim - players, KICK_MSG_VOTE_KICK);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
|
|
@ -70,7 +67,29 @@ static void K_MidVoteKick(void)
|
|||
--------------------------------------------------*/
|
||||
static void K_MidVoteRockTheVote(void)
|
||||
{
|
||||
G_ExitLevel();
|
||||
if (G_GamestateUsesExitLevel() == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SendNetXCmd(XD_EXITLEVEL, NULL, 0);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static void K_MidVoteRunItBack(void)
|
||||
|
||||
MVT_RUNITBACK's success function.
|
||||
--------------------------------------------------*/
|
||||
static void K_MidVoteRunItBack(void)
|
||||
{
|
||||
boolean newencore = false;
|
||||
|
||||
if (cv_kartencore.value != 0)
|
||||
{
|
||||
newencore = (cv_kartencore.value == 1) || encoremode;
|
||||
}
|
||||
|
||||
D_MapChange(gamemap, gametype, newencore, false, 0, false, false);
|
||||
}
|
||||
|
||||
static midVoteTypeDef_t g_midVoteTypeDefs[MVT__MAX] =
|
||||
|
|
@ -85,25 +104,24 @@ static midVoteTypeDef_t g_midVoteTypeDefs[MVT__MAX] =
|
|||
{ // MVT_RTV
|
||||
"RTV",
|
||||
"Skip Level?",
|
||||
CVAR_INIT ("zvote_rtv_allowed", "No", CV_SAVE|CV_NETVAR, CV_YesNo, NULL),
|
||||
CVAR_INIT ("zvote_rtv_allowed", "Yes", CV_SAVE|CV_NETVAR, CV_YesNo, NULL),
|
||||
K_MidVoteRockTheVote
|
||||
},
|
||||
|
||||
{ // MVT_RUNITBACK
|
||||
"RUNITBACK",
|
||||
"Redo Level?",
|
||||
CVAR_INIT ("zvote_runitback_allowed", "Yes", CV_SAVE|CV_NETVAR, CV_YesNo, NULL),
|
||||
K_MidVoteRunItBack
|
||||
},
|
||||
};
|
||||
|
||||
/*--------------------------------------------------
|
||||
static boolean K_MidVoteTypeUsesVictim(midVoteType_e voteType)
|
||||
boolean K_MidVoteTypeUsesVictim(midVoteType_e voteType)
|
||||
|
||||
Specifies whenever or not a vote type is intended
|
||||
to specify a "victim", or a player that would be
|
||||
negatively affected by the vote.
|
||||
|
||||
Input Arguments:-
|
||||
voteType - The vote type to check.
|
||||
|
||||
Return:-
|
||||
true if it uses a victim, otherwise false.
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
static boolean K_MidVoteTypeUsesVictim(midVoteType_e voteType)
|
||||
boolean K_MidVoteTypeUsesVictim(midVoteType_e voteType)
|
||||
{
|
||||
switch (voteType)
|
||||
{
|
||||
|
|
@ -125,9 +143,6 @@ static boolean K_MidVoteTypeUsesVictim(midVoteType_e voteType)
|
|||
--------------------------------------------------*/
|
||||
static void Command_CallVote(void)
|
||||
{
|
||||
UINT8 buf[MAXTEXTCMD];
|
||||
UINT8 *buf_p = buf;
|
||||
|
||||
size_t numArgs = 0;
|
||||
|
||||
const char *voteTypeStr = NULL;
|
||||
|
|
@ -136,8 +151,6 @@ static void Command_CallVote(void)
|
|||
const char *voteVariableStr = NULL;
|
||||
INT32 voteVariable = 0;
|
||||
|
||||
player_t *victim = NULL;
|
||||
|
||||
INT32 i = INT32_MAX;
|
||||
|
||||
if (netgame == false)
|
||||
|
|
@ -184,11 +197,26 @@ static void Command_CallVote(void)
|
|||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (voteVariable >= 0 && voteVariable < MAXPLAYERS)
|
||||
{
|
||||
victim = &players[voteVariable];
|
||||
}
|
||||
K_SendCallMidVote(voteType, voteVariable);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_SendCallMidVote(midVoteType_e voteType, INT32 voteVariable)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
void K_SendCallMidVote(midVoteType_e voteType, INT32 voteVariable)
|
||||
{
|
||||
player_t *victim = NULL;
|
||||
|
||||
if (K_MidVoteTypeUsesVictim(voteType) == true)
|
||||
{
|
||||
if (voteVariable >= 0 && voteVariable < MAXPLAYERS)
|
||||
{
|
||||
victim = &players[voteVariable];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -198,6 +226,9 @@ static void Command_CallVote(void)
|
|||
return;
|
||||
}
|
||||
|
||||
UINT8 buf[MAXTEXTCMD];
|
||||
UINT8 *buf_p = buf;
|
||||
|
||||
WRITEUINT8(buf_p, voteType);
|
||||
WRITEINT32(buf_p, voteVariable);
|
||||
|
||||
|
|
@ -341,6 +372,51 @@ boolean K_AnyMidVotesAllowed(void)
|
|||
return false;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
midVoteType_e K_GetNextCallableMidVote(INT32 seed, boolean backwards)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
|
||||
midVoteType_e K_GetNextAllowedMidVote(midVoteType_e seed, boolean backwards)
|
||||
{
|
||||
if (seed >= MVT__MAX)
|
||||
seed = 0;
|
||||
|
||||
midVoteType_e i = seed;
|
||||
|
||||
if (backwards)
|
||||
{
|
||||
do
|
||||
{
|
||||
if (i <= 0)
|
||||
i = MVT__MAX;
|
||||
i--;
|
||||
|
||||
if (g_midVoteTypeDefs[i].cv_allowed.value != 0)
|
||||
return i;
|
||||
|
||||
}
|
||||
while (i != seed);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
i++;
|
||||
if (i >= MVT__MAX)
|
||||
i = 0;
|
||||
|
||||
if (g_midVoteTypeDefs[i].cv_allowed.value != 0)
|
||||
return i;
|
||||
|
||||
}
|
||||
while (i != seed);
|
||||
}
|
||||
|
||||
return MVT__MAX;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
boolean K_PlayerIDAllowedInMidVote(const UINT8 id)
|
||||
|
||||
|
|
@ -468,6 +544,46 @@ UINT8 K_CountMidVotes(void)
|
|||
return voteCount;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
boolean K_MinimalCheckNewMidVote(midVoteType_e type)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
boolean K_MinimalCheckNewMidVote(midVoteType_e type)
|
||||
{
|
||||
if (g_midVote.active == true)
|
||||
{
|
||||
// Don't allow another vote if one is already running.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (g_midVote.delay > 0)
|
||||
{
|
||||
// Don't allow another vote if one has recently just ran.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (type < 0 || type >= MVT__MAX)
|
||||
{
|
||||
// Invalid range.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (g_midVoteTypeDefs[type].cv_allowed.value == 0)
|
||||
{
|
||||
// These types of votes aren't allowed on this server.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (K_PlayerIDAllowedInMidVote(consoleplayer) == false)
|
||||
{
|
||||
// Invalid calling player.
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
boolean K_AllowNewMidVote(player_t *caller, midVoteType_e type, INT32 variable, player_t *victim)
|
||||
|
||||
|
|
@ -630,7 +746,11 @@ void K_MidVoteFinalize(fixed_t delayMul)
|
|||
--------------------------------------------------*/
|
||||
void K_MidVoteSuccess(void)
|
||||
{
|
||||
if (g_midVoteTypeDefs[ g_midVote.type ].callback != NULL)
|
||||
if (
|
||||
server == true
|
||||
&& demo.playback == false
|
||||
&& g_midVoteTypeDefs[ g_midVote.type ].callback != NULL
|
||||
)
|
||||
{
|
||||
g_midVoteTypeDefs[ g_midVote.type ].callback();
|
||||
}
|
||||
|
|
@ -823,6 +943,25 @@ void K_UpdateMidVotePatches(void)
|
|||
HU_UpdatePatch(&g_zBarEnds[1][1][1], "TLBXB0");
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
const char *K_GetMidVoteLabel(midVoteType_e i)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
|
||||
const char *K_GetMidVoteLabel(midVoteType_e i)
|
||||
{
|
||||
if (
|
||||
i < 0
|
||||
|| i >= MVT__MAX
|
||||
|| g_midVoteTypeDefs[i].label == NULL)
|
||||
{
|
||||
return "N/A";
|
||||
}
|
||||
|
||||
return g_midVoteTypeDefs[i].label;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static void K_DrawMidVoteBar(fixed_t x, fixed_t y, INT32 flags, fixed_t fill, skincolornum_t color, boolean flipped)
|
||||
|
||||
|
|
@ -1006,11 +1145,13 @@ void K_DrawMidVote(void)
|
|||
(id & 1)
|
||||
);
|
||||
|
||||
const char *label = K_GetMidVoteLabel(g_midVote.type);
|
||||
|
||||
// Vote main label
|
||||
strWidth = V__OneScaleStringWidth(
|
||||
FRACUNIT,
|
||||
V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_SPLITSCREEN,
|
||||
KART_FONT, g_midVoteTypeDefs[g_midVote.type].label
|
||||
KART_FONT, label
|
||||
);
|
||||
|
||||
V__DrawOneScaleString(
|
||||
|
|
@ -1018,7 +1159,7 @@ void K_DrawMidVote(void)
|
|||
y - (18 * FRACUNIT),
|
||||
FRACUNIT,
|
||||
V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_SPLITSCREEN, NULL,
|
||||
KART_FONT, g_midVoteTypeDefs[g_midVote.type].label
|
||||
KART_FONT, label
|
||||
);
|
||||
|
||||
// Vote extra text
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ typedef enum
|
|||
{
|
||||
MVT_KICK, // Kick another player in the server
|
||||
MVT_RTV, // Exit level early
|
||||
MVT_RUNITBACK, // Restart level fresh
|
||||
MVT__MAX, // Total number of vote types
|
||||
} midVoteType_e;
|
||||
|
||||
|
|
@ -63,6 +64,39 @@ struct midVote_t
|
|||
|
||||
extern midVote_t g_midVote;
|
||||
|
||||
/*--------------------------------------------------
|
||||
boolean K_MidVoteTypeUsesVictim(midVoteType_e voteType)
|
||||
|
||||
Specifies whenever or not a vote type is intended
|
||||
to specify a "victim", or a player that would be
|
||||
negatively affected by the vote.
|
||||
|
||||
Input Arguments:-
|
||||
voteType - The vote type to check.
|
||||
|
||||
Return:-
|
||||
true if it uses a victim, otherwise false.
|
||||
--------------------------------------------------*/
|
||||
|
||||
boolean K_MidVoteTypeUsesVictim(midVoteType_e voteType);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_SendCallMidVote(midVoteType_e voteType, INT32 voteVariable)
|
||||
|
||||
Prepares and sends net packet for calling a midvote.
|
||||
|
||||
Input Arguments:-
|
||||
voteType - The type of vote a local player is trying to call.
|
||||
variable - Extra arguments for the vote type.
|
||||
|
||||
Return:-
|
||||
N/A
|
||||
--------------------------------------------------*/
|
||||
|
||||
void K_SendCallMidVote(midVoteType_e voteType, INT32 voteVariable);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_RegisterMidVoteCVars(void);
|
||||
|
||||
|
|
@ -99,6 +133,22 @@ void K_ResetMidVote(void);
|
|||
boolean K_AnyMidVotesAllowed(void);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
midVoteType_e K_GetNextCallableMidVote(midVoteType_e seed, boolean backwards)
|
||||
|
||||
Gets the next enabled Z-vote type in the list.
|
||||
|
||||
Input Arguments:-
|
||||
seed - position in the list to start with
|
||||
backwards - if true, traverses list in reverse order
|
||||
|
||||
Return:-
|
||||
next Z-vote id if any vote types are enabled, otherwise MVT__MAX.
|
||||
--------------------------------------------------*/
|
||||
|
||||
midVoteType_e K_GetNextAllowedMidVote(midVoteType_e seed, boolean backwards);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
boolean K_PlayerIDAllowedInMidVote(const UINT8 id);
|
||||
|
||||
|
|
@ -170,6 +220,18 @@ boolean K_PlayerIDMidVoted(const UINT8 id);
|
|||
UINT8 K_CountMidVotes(void);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
boolean K_MinimalCheckNewMidVote(midVoteType_e type)
|
||||
|
||||
Returns if the variables given are a valid state for
|
||||
pause menu Z-vote flow.
|
||||
|
||||
Input Arguments:-
|
||||
type - The type of vote they're trying to call.
|
||||
--------------------------------------------------*/
|
||||
|
||||
boolean K_MinimalCheckNewMidVote(midVoteType_e type);
|
||||
|
||||
/*--------------------------------------------------
|
||||
boolean K_AllowNewMidVote(player_t *caller, midVoteType_e type, INT32 variable, player_t *victim);
|
||||
|
||||
|
|
@ -263,6 +325,19 @@ void K_TickMidVote(void);
|
|||
void K_UpdateMidVotePatches(void);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
const char *K_GetMidVoteLabel(midVoteType_e i)
|
||||
|
||||
Input Arguments:-
|
||||
i - id in the list to retrieve label for
|
||||
|
||||
Return:-
|
||||
label associated with that id, or a sensible default (not NULL)
|
||||
--------------------------------------------------*/
|
||||
|
||||
const char *K_GetMidVoteLabel(midVoteType_e i);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_DrawMidVote(void);
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
#include "p_spec.h" // P_StartQuake
|
||||
#include "i_system.h" // I_GetPreciseTime, I_GetPrecisePrecision
|
||||
#include "hu_stuff.h" // for the cecho
|
||||
#include "k_powerup.h"
|
||||
|
||||
#include "lua_script.h"
|
||||
#include "lua_libs.h"
|
||||
|
|
@ -3845,6 +3846,40 @@ static int lib_kAddHitLag(lua_State *L)
|
|||
}
|
||||
|
||||
|
||||
static int lib_kPowerUpRemaining(lua_State *L)
|
||||
{
|
||||
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
kartitems_t powerup = luaL_checkinteger(L, 2);
|
||||
//HUDSAFE
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
lua_pushinteger(L, K_PowerUpRemaining(player, powerup));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_kGivePowerUp(lua_State *L)
|
||||
{
|
||||
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
kartitems_t powerup = luaL_checkinteger(L, 2);
|
||||
tic_t time = (tic_t)luaL_checkinteger(L, 3);
|
||||
NOHUD
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
K_GivePowerUp(player, powerup, time);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_kDropPowerUps(lua_State *L)
|
||||
{
|
||||
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
NOHUD
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
K_DropPowerUps(player);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int lib_kInitBossHealthBar(lua_State *L)
|
||||
{
|
||||
const char *enemyname = luaL_checkstring(L, 1);
|
||||
|
|
@ -4167,6 +4202,11 @@ static luaL_Reg lib[] = {
|
|||
{"K_GetCollideAngle",lib_kGetCollideAngle},
|
||||
{"K_AddHitLag",lib_kAddHitLag},
|
||||
|
||||
// k_powerup
|
||||
{"K_PowerUpRemaining",lib_kPowerUpRemaining},
|
||||
{"K_GivePowerUp",lib_kGivePowerUp},
|
||||
{"K_DropPowerUps",lib_kDropPowerUps},
|
||||
|
||||
// k_boss
|
||||
{"K_InitBossHealthBar", lib_kInitBossHealthBar},
|
||||
{"K_UpdateBossHealthBar", lib_kUpdateBossHealthBar},
|
||||
|
|
|
|||
|
|
@ -251,6 +251,10 @@ static int player_get(lua_State *L)
|
|||
lua_pushboolean(L, plr->flipDI);
|
||||
else if (fastcmp(field,"markedfordeath"))
|
||||
lua_pushboolean(L, plr->markedfordeath);
|
||||
else if (fastcmp(field,"ringboxdelay"))
|
||||
lua_pushinteger(L, plr->ringboxdelay);
|
||||
else if (fastcmp(field,"ringboxaward"))
|
||||
lua_pushinteger(L, plr->ringboxaward);
|
||||
else if (fastcmp(field,"drift"))
|
||||
lua_pushinteger(L, plr->drift);
|
||||
else if (fastcmp(field,"driftcharge"))
|
||||
|
|
@ -651,6 +655,10 @@ static int player_set(lua_State *L)
|
|||
plr->flipDI = luaL_checkboolean(L, 3);
|
||||
else if (fastcmp(field,"markedfordeath"))
|
||||
plr->markedfordeath = luaL_checkboolean(L, 3);
|
||||
else if (fastcmp(field,"ringboxdelay"))
|
||||
plr->ringboxdelay = luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"ringboxaward"))
|
||||
plr->ringboxaward = luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"drift"))
|
||||
plr->drift = luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"driftcharge"))
|
||||
|
|
|
|||
|
|
@ -394,8 +394,6 @@ int LUA_WriteGlobals(lua_State *L, const char *word)
|
|||
skincolor_redring = (UINT16)luaL_checkinteger(L, 2);
|
||||
else if (fastcmp(word, "skincolor_bluering"))
|
||||
skincolor_bluering = (UINT16)luaL_checkinteger(L, 2);
|
||||
else if (fastcmp(word, "emeralds"))
|
||||
emeralds = (UINT16)luaL_checkinteger(L, 2);
|
||||
else if (fastcmp(word, "gravity"))
|
||||
gravity = (fixed_t)luaL_checkinteger(L, 2);
|
||||
else if (fastcmp(word, "stoppedclock"))
|
||||
|
|
|
|||
|
|
@ -469,29 +469,6 @@ void Command_Savecheckpoint_f(void)
|
|||
}
|
||||
}
|
||||
|
||||
// Like M_GetAllEmeralds() but for console devmode junkies.
|
||||
/*
|
||||
void Command_Getallemeralds_f(void)
|
||||
{
|
||||
REQUIRE_CHEATS;
|
||||
REQUIRE_SINGLEPLAYER;
|
||||
|
||||
emeralds = EMERALD_ALL;
|
||||
|
||||
CONS_Printf(M_GetText("You now have all 7 emeralds.\n"));
|
||||
}
|
||||
|
||||
void Command_Resetemeralds_f(void)
|
||||
{
|
||||
REQUIRE_CHEATS;
|
||||
REQUIRE_SINGLEPLAYER;
|
||||
|
||||
emeralds = 0;
|
||||
|
||||
CONS_Printf(M_GetText("Emeralds reset to zero.\n"));
|
||||
}
|
||||
*/
|
||||
|
||||
//
|
||||
// Devmode
|
||||
//
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ typedef enum {
|
|||
CHEAT_SCORE,
|
||||
CHEAT_ANGLE,
|
||||
CHEAT_RESPAWNAT,
|
||||
CHEAT_GIVEPOWERUP,
|
||||
|
||||
NUMBER_OF_CHEATS
|
||||
} cheat_t;
|
||||
|
|
|
|||
62
src/m_cond.c
62
src/m_cond.c
|
|
@ -610,6 +610,7 @@ void M_ClearStats(void)
|
|||
gamedata->timesBeaten = 0;
|
||||
|
||||
gamedata->everloadedaddon = false;
|
||||
gamedata->everfinishedcredits = false;
|
||||
gamedata->eversavedreplay = false;
|
||||
gamedata->everseenspecial = false;
|
||||
gamedata->evercrashed = false;
|
||||
|
|
@ -738,6 +739,43 @@ boolean M_NotFreePlay(player_t *player)
|
|||
return false;
|
||||
}
|
||||
|
||||
UINT16 M_CheckCupEmeralds(UINT8 difficulty)
|
||||
{
|
||||
if (difficulty == 0)
|
||||
return 0;
|
||||
|
||||
if (difficulty >= KARTGP_MAX)
|
||||
difficulty = KARTGP_MASTER;
|
||||
|
||||
cupheader_t *cup;
|
||||
UINT16 ret = 0, seen = 0;
|
||||
|
||||
for (cup = kartcupheaders; cup; cup = cup->next)
|
||||
{
|
||||
// Does it not *have* an emerald?
|
||||
if (cup->emeraldnum == 0 || cup->emeraldnum > 14)
|
||||
continue;
|
||||
|
||||
UINT16 emerald = 1<<(cup->emeraldnum-1);
|
||||
|
||||
// Only count the first reference.
|
||||
if (seen & emerald)
|
||||
continue;
|
||||
|
||||
// We've seen it, prevent future repetitions.
|
||||
seen |= emerald;
|
||||
|
||||
// Did you actually get it?
|
||||
if (cup->windata[difficulty].got_emerald == false)
|
||||
continue;
|
||||
|
||||
// Wa hoo !
|
||||
ret |= emerald;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// See also M_GetConditionString
|
||||
boolean M_CheckCondition(condition_t *cn, player_t *player)
|
||||
{
|
||||
|
|
@ -791,30 +829,12 @@ boolean M_CheckCondition(condition_t *cn, player_t *player)
|
|||
case UC_ALLSUPER:
|
||||
case UC_ALLEMERALDS:
|
||||
{
|
||||
cupheader_t *cup;
|
||||
UINT16 ret = 0;
|
||||
UINT8 i;
|
||||
|
||||
if (gamestate == GS_LEVEL)
|
||||
return false; // this one could be laggy with many cups available
|
||||
|
||||
for (cup = kartcupheaders; cup; cup = cup->next)
|
||||
{
|
||||
if (cup->emeraldnum == 0)
|
||||
continue;
|
||||
|
||||
i = cn->requirement;
|
||||
for (i = cn->requirement; i < KARTGP_MAX; i++)
|
||||
{
|
||||
if (cup->windata[i].got_emerald == true)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == KARTGP_MAX)
|
||||
continue;
|
||||
|
||||
ret |= 1<<(cup->emeraldnum-1);
|
||||
}
|
||||
ret = M_CheckCupEmeralds(cn->requirement);
|
||||
|
||||
if (cn->type == UC_ALLCHAOS)
|
||||
return ALLCHAOSEMERALDS(ret);
|
||||
|
|
@ -835,6 +855,8 @@ boolean M_CheckCondition(condition_t *cn, player_t *player)
|
|||
case UC_ADDON:
|
||||
return ((gamedata->everloadedaddon == true)
|
||||
&& M_SecretUnlocked(SECRET_ADDONS, true));
|
||||
case UC_CREDITS:
|
||||
return (gamedata->everfinishedcredits == true);
|
||||
case UC_REPLAY:
|
||||
return (gamedata->eversavedreplay == true);
|
||||
case UC_CRASH:
|
||||
|
|
@ -1289,6 +1311,8 @@ static const char *M_GetConditionString(condition_t *cn)
|
|||
if (!M_SecretUnlocked(SECRET_ADDONS, true))
|
||||
return NULL;
|
||||
return "load a custom addon into \"Dr. Robotnik's Ring Racers\"";
|
||||
case UC_CREDITS:
|
||||
return "watch the developer credits all the way from start to finish";
|
||||
case UC_REPLAY:
|
||||
return "save a replay after finishing a round";
|
||||
case UC_CRASH:
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ typedef enum
|
|||
UC_CONDITIONSET, // CONDITIONSET [condition set number]
|
||||
|
||||
UC_ADDON, // Ever loaded a custom file?
|
||||
UC_CREDITS, // Finish watching the credits
|
||||
UC_REPLAY, // Save a replay
|
||||
UC_CRASH, // Hee ho !
|
||||
|
||||
|
|
@ -288,6 +289,7 @@ struct gamedata_t
|
|||
|
||||
// SPECIFIC SPECIAL EVENTS
|
||||
boolean everloadedaddon;
|
||||
boolean everfinishedcredits;
|
||||
boolean eversavedreplay;
|
||||
boolean everseenspecial;
|
||||
boolean evercrashed;
|
||||
|
|
@ -341,6 +343,7 @@ void M_ClearSecrets(void);
|
|||
void M_ClearStats(void);
|
||||
|
||||
boolean M_NotFreePlay(player_t *player);
|
||||
UINT16 M_CheckCupEmeralds(UINT8 difficulty);
|
||||
|
||||
// Updating conditions and unlockables
|
||||
boolean M_ConditionInterpret(const char *password);
|
||||
|
|
|
|||
|
|
@ -5,6 +5,15 @@
|
|||
#include "../m_cond.h"
|
||||
#include "../m_cheat.h"
|
||||
#include "../s_sound.h"
|
||||
#include "../f_finale.h"
|
||||
|
||||
static void M_Credits(INT32 choice)
|
||||
{
|
||||
(void)choice;
|
||||
restoreMenu = currentMenu;
|
||||
M_ClearMenus(true);
|
||||
F_StartCredits();
|
||||
}
|
||||
|
||||
menuitem_t EXTRAS_Main[] =
|
||||
{
|
||||
|
|
@ -32,6 +41,9 @@ menuitem_t EXTRAS_Main[] =
|
|||
|
||||
{IT_STRING | IT_CVAR | IT_CV_STRING, "Password", "If you don't know any passwords, come back later!",
|
||||
NULL, {.cvar = &cv_dummyextraspassword}, 0, 0},
|
||||
|
||||
{IT_STRING | IT_CALL, "Credits", "It's important to know who makes the video games you play.",
|
||||
NULL, {.routine = M_Credits}, 0, 0},
|
||||
};
|
||||
|
||||
// the extras menu essentially reuses the options menu stuff
|
||||
|
|
|
|||
|
|
@ -485,7 +485,6 @@ void M_StartTimeAttack(INT32 choice)
|
|||
|
||||
// Still need to reset devmode
|
||||
cht_debug = 0;
|
||||
emeralds = 0;
|
||||
|
||||
if (demo.playback)
|
||||
G_StopDemo();
|
||||
|
|
|
|||
|
|
@ -80,8 +80,8 @@ void M_MPOptSelectInit(INT32 choice)
|
|||
memcpy(&mpmenu.modewinextend, &arrcpy, sizeof(mpmenu.modewinextend));
|
||||
|
||||
// Guarantee menugametype is good
|
||||
M_NextMenuGametype(forbidden);
|
||||
M_PrevMenuGametype(forbidden);
|
||||
M_NextMenuGametype(forbidden);
|
||||
|
||||
if (choice != -1)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ menuitem_t PLAY_MP_Host[] =
|
|||
{IT_STRING | IT_CVAR, "Max. Players", "Set how many players can play at once. Others will spectate.",
|
||||
NULL, {.cvar = &cv_maxplayers}, 0, 0},
|
||||
|
||||
{IT_STRING | IT_KEYHANDLER, "Gamemode", "Choose the type of play on your server.",
|
||||
{IT_STRING | IT_ARROWS, "Gamemode", "Choose the type of play on your server.",
|
||||
NULL, {.routine = M_HandleHostMenuGametype}, 0, 0},
|
||||
|
||||
{IT_STRING | IT_CALL, "GO", "Select a map with the currently selected gamemode",
|
||||
|
|
@ -54,41 +54,21 @@ void M_MPHostInit(INT32 choice)
|
|||
|
||||
void M_HandleHostMenuGametype(INT32 choice)
|
||||
{
|
||||
const UINT8 pid = 0;
|
||||
const UINT32 forbidden = GTR_FORBIDMP;
|
||||
|
||||
(void)choice;
|
||||
|
||||
if (M_MenuBackPressed(pid))
|
||||
{
|
||||
M_GoBack(0);
|
||||
M_SetMenuDelay(pid);
|
||||
return;
|
||||
}
|
||||
else if (menucmd[pid].dpad_lr > 0 || M_MenuConfirmPressed(pid))
|
||||
if (choice > 0)
|
||||
{
|
||||
M_NextMenuGametype(forbidden);
|
||||
S_StartSound(NULL, sfx_s3k5b);
|
||||
M_SetMenuDelay(pid);
|
||||
}
|
||||
else if (menucmd[pid].dpad_lr < 0)
|
||||
else if (choice == -1)
|
||||
{
|
||||
menugametype = GT_RACE;
|
||||
M_PrevMenuGametype(forbidden);
|
||||
M_NextMenuGametype(forbidden);
|
||||
}
|
||||
else
|
||||
{
|
||||
M_PrevMenuGametype(forbidden);
|
||||
S_StartSound(NULL, sfx_s3k5b);
|
||||
M_SetMenuDelay(pid);
|
||||
}
|
||||
|
||||
if (menucmd[pid].dpad_ud > 0)
|
||||
{
|
||||
M_NextOpt();
|
||||
S_StartSound(NULL, sfx_s3k5b);
|
||||
M_SetMenuDelay(pid);
|
||||
}
|
||||
else if (menucmd[pid].dpad_ud < 0)
|
||||
{
|
||||
M_PrevOpt();
|
||||
S_StartSound(NULL, sfx_s3k5b);
|
||||
M_SetMenuDelay(pid);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ target_sources(SRB2SDL2 PRIVATE
|
|||
discord-requests.c
|
||||
message-box.c
|
||||
pause-game.c
|
||||
pause-kick.c
|
||||
pause-replay.c
|
||||
virtual-keyboard.c
|
||||
)
|
||||
|
|
|
|||
|
|
@ -155,7 +155,8 @@ static void M_StartCup(UINT8 entry)
|
|||
NULL, MM_NOTHING, NULL, NULL
|
||||
);
|
||||
|
||||
G_HandleSaveLevel(true);
|
||||
if (FIL_FileExists(gpbackup))
|
||||
remove(gpbackup);
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -266,7 +266,7 @@ boolean M_LevelListFromGametype(INT16 gt)
|
|||
|
||||
G_GetBackupCupData(
|
||||
cupgrid.grandprix == true
|
||||
|| cv_splitplayers.value <= 1
|
||||
&& cv_splitplayers.value <= 1
|
||||
);
|
||||
|
||||
templevelsearch.cup = kartcupheaders;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include "../../k_grandprix.h" // K_CanChangeRules
|
||||
#include "../../m_cond.h"
|
||||
#include "../../s_sound.h"
|
||||
#include "../../k_zvote.h"
|
||||
|
||||
#ifdef HAVE_DISCORDRPC
|
||||
#include "../../discord.h"
|
||||
|
|
@ -22,7 +23,7 @@ menuitem_t PAUSE_Main[] =
|
|||
{IT_STRING | IT_CALL, "STEREO MODE", "M_ICOSTM",
|
||||
NULL, {.routine = M_SoundTest}, 0, 0},
|
||||
|
||||
{IT_STRING | IT_KEYHANDLER, "GAMETYPE", "M_ICOGAM",
|
||||
{IT_STRING | IT_ARROWS, "GAMETYPE", "M_ICOGAM",
|
||||
NULL, {.routine = M_HandlePauseMenuGametype}, 0, 0},
|
||||
|
||||
{IT_STRING | IT_CALL, "CHANGE MAP", "M_ICOMAP",
|
||||
|
|
@ -39,6 +40,12 @@ menuitem_t PAUSE_Main[] =
|
|||
NULL, {.routine = M_DiscordRequests}, 0, 0},
|
||||
#endif
|
||||
|
||||
{IT_STRING | IT_ARROWS, "ADMIN TOOLS", "M_ICOADM",
|
||||
NULL, {.routine = M_KickHandler}, 0, 0},
|
||||
|
||||
{IT_STRING | IT_ARROWS, "CALL VOTE", "M_ICOVOT",
|
||||
NULL, {.routine = M_HandlePauseMenuCallVote}, 0, 0},
|
||||
|
||||
{IT_STRING | IT_CALL, "RESUME GAME", "M_ICOUNP",
|
||||
NULL, {.routine = M_QuitPauseMenu}, 0, 0},
|
||||
|
||||
|
|
@ -71,7 +78,7 @@ menu_t PAUSE_MainDef = {
|
|||
PAUSE_Main,
|
||||
0, 0,
|
||||
0, 0,
|
||||
0,
|
||||
MBF_SOUNDLESS,
|
||||
NULL,
|
||||
1, 10, // For transition with some menus!
|
||||
M_DrawPause,
|
||||
|
|
@ -123,6 +130,8 @@ void M_OpenPauseMenu(void)
|
|||
PAUSE_Main[mpause_switchmap].status = IT_DISABLED;
|
||||
PAUSE_Main[mpause_restartmap].status = IT_DISABLED;
|
||||
PAUSE_Main[mpause_tryagain].status = IT_DISABLED;
|
||||
PAUSE_Main[mpause_callvote].status = IT_DISABLED;
|
||||
PAUSE_Main[mpause_admin].status = IT_DISABLED;
|
||||
#ifdef HAVE_DISCORDRPC
|
||||
PAUSE_Main[mpause_discordrequests].status = IT_DISABLED;
|
||||
#endif
|
||||
|
|
@ -146,7 +155,7 @@ void M_OpenPauseMenu(void)
|
|||
|
||||
if (server || IsPlayerAdmin(consoleplayer))
|
||||
{
|
||||
PAUSE_Main[mpause_changegametype].status = IT_STRING | IT_KEYHANDLER;
|
||||
PAUSE_Main[mpause_changegametype].status = IT_STRING | IT_ARROWS;
|
||||
menugametype = gametype;
|
||||
|
||||
PAUSE_Main[mpause_switchmap].status = IT_STRING | IT_CALL;
|
||||
|
|
@ -156,12 +165,21 @@ void M_OpenPauseMenu(void)
|
|||
{
|
||||
PAUSE_Main[mpause_addons].status = IT_STRING | IT_CALL;
|
||||
}
|
||||
|
||||
if (netgame)
|
||||
{
|
||||
PAUSE_Main[mpause_admin].status = IT_STRING | IT_CALL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!netgame && !demo.playback)
|
||||
{
|
||||
boolean retryallowed = (modeattacking != ATTACKING_NONE);
|
||||
if (G_GametypeUsesLives())
|
||||
if (
|
||||
retryallowed == false
|
||||
&& gamestate == GS_LEVEL
|
||||
&& G_GametypeUsesLives()
|
||||
)
|
||||
{
|
||||
for (i = 0; i <= splitscreen; i++)
|
||||
{
|
||||
|
|
@ -178,6 +196,18 @@ void M_OpenPauseMenu(void)
|
|||
}
|
||||
}
|
||||
|
||||
if (netgame) // && (PAUSE_Main[mpause_admin].status == IT_DISABLED))
|
||||
{
|
||||
menucallvote = K_GetNextAllowedMidVote(menucallvote, true);
|
||||
|
||||
if (menucallvote != MVT__MAX)
|
||||
{
|
||||
menucallvote = K_GetNextAllowedMidVote(menucallvote, false);
|
||||
|
||||
PAUSE_Main[mpause_callvote].status = IT_STRING | IT_ARROWS;
|
||||
}
|
||||
}
|
||||
|
||||
if (G_GametypeHasSpectators())
|
||||
{
|
||||
if (splitscreen)
|
||||
|
|
@ -267,12 +297,9 @@ boolean M_PauseInputs(INT32 ch)
|
|||
// Change gametype
|
||||
void M_HandlePauseMenuGametype(INT32 choice)
|
||||
{
|
||||
const UINT8 pid = 0;
|
||||
const UINT32 forbidden = GTR_FORBIDMP;
|
||||
|
||||
(void)choice;
|
||||
|
||||
if (M_MenuConfirmPressed(pid))
|
||||
if (choice == 2)
|
||||
{
|
||||
if (menugametype != gametype)
|
||||
{
|
||||
|
|
@ -281,27 +308,60 @@ void M_HandlePauseMenuGametype(INT32 choice)
|
|||
return;
|
||||
}
|
||||
|
||||
M_SetMenuDelay(pid);
|
||||
S_StartSound(NULL, sfx_s3k7b);
|
||||
|
||||
return;
|
||||
}
|
||||
else if (M_MenuExtraPressed(pid))
|
||||
|
||||
if (choice == -1)
|
||||
{
|
||||
menugametype = gametype;
|
||||
M_SetMenuDelay(pid);
|
||||
S_StartSound(NULL, sfx_s3k7b);
|
||||
return;
|
||||
}
|
||||
else if (menucmd[pid].dpad_lr > 0)
|
||||
{
|
||||
M_NextMenuGametype(forbidden);
|
||||
S_StartSound(NULL, sfx_s3k5b);
|
||||
M_SetMenuDelay(pid);
|
||||
}
|
||||
else if (menucmd[pid].dpad_lr < 0)
|
||||
|
||||
if (choice == 0)
|
||||
{
|
||||
M_PrevMenuGametype(forbidden);
|
||||
S_StartSound(NULL, sfx_s3k5b);
|
||||
M_SetMenuDelay(pid);
|
||||
}
|
||||
else
|
||||
{
|
||||
M_NextMenuGametype(forbidden);
|
||||
S_StartSound(NULL, sfx_s3k5b);
|
||||
}
|
||||
}
|
||||
|
||||
// Call vote
|
||||
UINT32 menucallvote = MVT__MAX;
|
||||
|
||||
void M_HandlePauseMenuCallVote(INT32 choice)
|
||||
{
|
||||
if (choice == 2)
|
||||
{
|
||||
if (K_MinimalCheckNewMidVote(menucallvote) == false)
|
||||
{
|
||||
// Invalid.
|
||||
S_StartSound(NULL, sfx_s3k7b);
|
||||
}
|
||||
else if (K_MidVoteTypeUsesVictim(menucallvote) == true)
|
||||
{
|
||||
S_StartSound(NULL, sfx_s3k5b);
|
||||
M_KickHandler(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Bog standard and victimless, let's send it on its way!
|
||||
M_ClearMenus(true);
|
||||
K_SendCallMidVote(menucallvote, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
menucallvote = K_GetNextAllowedMidVote(menucallvote, (choice == 0));
|
||||
S_StartSound(NULL, sfx_s3k5b);
|
||||
}
|
||||
|
||||
// Restart map
|
||||
|
|
|
|||
135
src/menus/transient/pause-kick.c
Normal file
135
src/menus/transient/pause-kick.c
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
/// \file menus/transient/pause-kick.c
|
||||
/// \brief Player Kick menu
|
||||
|
||||
#include "../../k_menu.h"
|
||||
#include "../../s_sound.h"
|
||||
#include "../../p_local.h"
|
||||
#include "../../k_zvote.h"
|
||||
|
||||
struct playerkickmenu_s playerkickmenu;
|
||||
|
||||
static void M_PlayerKickHandler(INT32 choice)
|
||||
{
|
||||
const UINT8 pid = 0;
|
||||
|
||||
UINT8 kicktype = UINT8_MAX;
|
||||
|
||||
(void)choice;
|
||||
|
||||
if (menucmd[pid].dpad_lr != 0) // symmetrical in this case
|
||||
{
|
||||
S_StartSound(NULL, sfx_s3k5b);
|
||||
|
||||
playerkickmenu.player = ((playerkickmenu.player + 8) % MAXPLAYERS);
|
||||
|
||||
M_SetMenuDelay(pid);
|
||||
}
|
||||
|
||||
else if (menucmd[pid].dpad_ud > 0)
|
||||
{
|
||||
S_StartSound(NULL, sfx_s3k5b);
|
||||
|
||||
playerkickmenu.player = ((playerkickmenu.player + 1) & 7) + (playerkickmenu.player & 8);
|
||||
|
||||
M_SetMenuDelay(pid);
|
||||
}
|
||||
|
||||
else if (menucmd[pid].dpad_ud < 0)
|
||||
{
|
||||
S_StartSound(NULL, sfx_s3k5b);
|
||||
|
||||
playerkickmenu.player = ((playerkickmenu.player + 7) & 7) + (playerkickmenu.player & 8);
|
||||
|
||||
M_SetMenuDelay(pid);
|
||||
}
|
||||
|
||||
else if (M_MenuBackPressed(pid))
|
||||
{
|
||||
M_GoBack(0);
|
||||
M_SetMenuDelay(pid);
|
||||
}
|
||||
|
||||
else if (M_MenuExtraPressed(pid) && playerkickmenu.adminpowered)
|
||||
{
|
||||
kicktype = KICK_MSG_BANNED;
|
||||
}
|
||||
|
||||
else if (M_MenuConfirmPressed(pid))
|
||||
{
|
||||
kicktype = KICK_MSG_KICKED;
|
||||
}
|
||||
|
||||
if (kicktype != UINT8_MAX)
|
||||
{
|
||||
M_SetMenuDelay(pid);
|
||||
|
||||
if (
|
||||
playeringame[playerkickmenu.player]
|
||||
&& P_IsMachineLocalPlayer(&players[playerkickmenu.player]) == false
|
||||
&& playerkickmenu.player != serverplayer
|
||||
)
|
||||
{
|
||||
if (playerkickmenu.adminpowered)
|
||||
{
|
||||
if (consoleplayer == serverplayer || IsPlayerAdmin(consoleplayer))
|
||||
{
|
||||
playerkickmenu.poke = (kicktype == KICK_MSG_BANNED) ? 16 : 12;
|
||||
SendKick(playerkickmenu.player, kicktype);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (
|
||||
K_MinimalCheckNewMidVote(menucallvote) == true
|
||||
#ifndef DEVELOP
|
||||
&& IsPlayerAdmin(playerkickmenu.player) == false
|
||||
#endif
|
||||
)
|
||||
{
|
||||
M_ClearMenus(true);
|
||||
K_SendCallMidVote(menucallvote, playerkickmenu.player);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
playerkickmenu.poke = 8;
|
||||
S_StartSound(NULL, sfx_s3k7b);
|
||||
}
|
||||
}
|
||||
|
||||
static menuitem_t PAUSE_KickHandler[] =
|
||||
{
|
||||
{IT_NOTHING | IT_KEYHANDLER, NULL, NULL, NULL, {.routine = M_PlayerKickHandler}, 0, 0},
|
||||
};
|
||||
|
||||
static void M_KickHandlerTick(void)
|
||||
{
|
||||
playerkickmenu.ticker++;
|
||||
|
||||
if (playerkickmenu.poke)
|
||||
playerkickmenu.poke--;
|
||||
}
|
||||
|
||||
menu_t PAUSE_KickHandlerDef = {
|
||||
sizeof(PAUSE_KickHandler) / sizeof(menuitem_t),
|
||||
&PAUSE_MainDef,
|
||||
0,
|
||||
PAUSE_KickHandler,
|
||||
0, 0,
|
||||
0, 0,
|
||||
0,
|
||||
NULL,
|
||||
0, 0,
|
||||
M_DrawKickHandler,
|
||||
M_KickHandlerTick,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
void M_KickHandler(INT32 choice)
|
||||
{
|
||||
playerkickmenu.adminpowered = (choice >= 0);
|
||||
|
||||
PAUSE_KickHandlerDef.prevMenu = currentMenu;
|
||||
M_SetupNextMenu(&PAUSE_KickHandlerDef, true);
|
||||
}
|
||||
|
|
@ -21,4 +21,5 @@ target_sources(SRB2SDL2 PRIVATE
|
|||
block.c
|
||||
gachabom-rebound.cpp
|
||||
servant-hand.c
|
||||
super-flicky.cpp
|
||||
)
|
||||
|
|
|
|||
|
|
@ -102,6 +102,29 @@ void Obj_RandomItemVisuals(mobj_t *mobj)
|
|||
ItemBoxBob(mobj);
|
||||
ItemBoxScaling(mobj);
|
||||
item_vfxtimer(mobj)++;
|
||||
|
||||
if (mobj->type != MT_RANDOMITEM)
|
||||
return;
|
||||
|
||||
// Respawn flow, documented by a dumb asshole:
|
||||
// P_TouchSpecialThing -> P_ItemPop sets fuse, NOCLIPTHING and DONTDRAW.
|
||||
// P_FuseThink does visual flicker, and when fuse is 0, unsets NOCLIPTHING/DONTDRAW/etc...
|
||||
// ...unless it's a map-start box from Battle, in which case it does nothing and waits for
|
||||
// P_RespawnBattleBoxes to trigger the effect instead, since Battle boxes don't respawn until
|
||||
// the player's cleared out a good portion of the map.
|
||||
//
|
||||
// Then extraval1 starts ticking up and triggers the transformation from Ringbox to Random Item.
|
||||
if (mobj->fuse == 0 && !(mobj->flags & MF_NOCLIPTHING) && !cv_thunderdome.value)
|
||||
{
|
||||
mobj->extravalue1++;
|
||||
if (mobj->extravalue1 == RINGBOX_TIME)
|
||||
{
|
||||
// Sync the position in RINGBOX and RANDOMITEM animations.
|
||||
statenum_t animDelta = mobj->state - states - S_RINGBOX1;
|
||||
P_SetMobjState(mobj, S_RANDOMITEM1 + (animDelta%12));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
boolean Obj_RandomItemSpawnIn(mobj_t *mobj)
|
||||
|
|
@ -116,6 +139,7 @@ boolean Obj_RandomItemSpawnIn(mobj_t *mobj)
|
|||
}
|
||||
else
|
||||
{
|
||||
// Spawn a battle monitor in your place and Fucking Die
|
||||
mobj_t *paperspawner = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_PAPERITEMSPOT);
|
||||
paperspawner->spawnpoint = mobj->spawnpoint;
|
||||
mobj->spawnpoint->mobj = paperspawner;
|
||||
|
|
@ -148,6 +172,14 @@ void Obj_RandomItemSpawn(mobj_t *mobj)
|
|||
{
|
||||
item_vfxtimer(mobj) = P_RandomRange(PR_DECORATION, 0, SCALE_TIME - 1);
|
||||
|
||||
// Respawns are handled by P_RespawnBattleBoxes,
|
||||
// but we do need to start MT_RANDOMITEMs in the right state...
|
||||
if (mobj->type == MT_RANDOMITEM && (gametyperules & GTR_BUMPERS))
|
||||
{
|
||||
mobj->extravalue1 = RINGBOX_TIME;
|
||||
P_SetMobjState(mobj, S_RANDOMITEM1);
|
||||
}
|
||||
|
||||
mobj->destscale = Obj_RandomItemScale(mobj->destscale);
|
||||
P_SetScale(mobj, mobj->destscale);
|
||||
}
|
||||
|
|
|
|||
769
src/objects/super-flicky.cpp
Normal file
769
src/objects/super-flicky.cpp
Normal file
|
|
@ -0,0 +1,769 @@
|
|||
// DR. ROBOTNIK'S RING RACERS
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2023 by James R.
|
||||
// Copyright (C) 2023 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \brief Super Flicky power-up, hunts other players
|
||||
|
||||
#include "../d_player.h"
|
||||
#include "../doomdef.h"
|
||||
#include "../g_game.h"
|
||||
#include "../k_battle.h"
|
||||
#include "../k_kart.h"
|
||||
#include "../k_objects.h"
|
||||
#include "../k_respawn.h"
|
||||
#include "../m_fixed.h"
|
||||
#include "../m_random.h"
|
||||
#include "../p_local.h"
|
||||
#include "../r_main.h"
|
||||
#include "../s_sound.h"
|
||||
#include "../tables.h"
|
||||
|
||||
#define flicky_controller(o) ((o)->target)
|
||||
#define flicky_chasing(o) ((o)->tracer)
|
||||
#define flicky_next(o) ((o)->hnext)
|
||||
#define flicky_next_target(o) ((o)->hprev)
|
||||
#define flicky_phase(o) ((o)->threshold)
|
||||
#define flicky_delay(o) ((o)->movecount)
|
||||
#define flicky_mode(o) ((o)->extravalue1)
|
||||
#define flicky_fly(o) ((o)->extravalue2)
|
||||
|
||||
#define controller_source(o) ((o)->target)
|
||||
#define controller_chasing(o) ((o)->tracer)
|
||||
#define controller_flicky(o) ((o)->hnext)
|
||||
#define controller_mode(o) ((o)->movecount)
|
||||
#define controller_zofs(o) ((o)->sprzoff)
|
||||
#define controller_expiry(o) ((o)->fuse)
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
constexpr tic_t kOrbitSpeed = 2*TICRATE;
|
||||
constexpr int kOrbitSpacing = ANGLE_90;
|
||||
|
||||
// Multiples of player radius
|
||||
constexpr fixed_t kOrbitRadiusInitial = 32*FRACUNIT;
|
||||
constexpr fixed_t kOrbitRadius = 2*FRACUNIT;
|
||||
|
||||
constexpr int kDescendHeight = 256;
|
||||
constexpr int kDescendSmoothing = 16;
|
||||
|
||||
constexpr int kSearchRadius = 1920;
|
||||
constexpr int kFlightRadius = 1280;
|
||||
constexpr int kPeckingRadius = 256;
|
||||
|
||||
constexpr int kFlightSpeed = 2;
|
||||
constexpr int kPeckingSpeed = 8;
|
||||
|
||||
constexpr fixed_t kRebound = 8*FRACUNIT/9;
|
||||
|
||||
constexpr tic_t kDelay = 8;
|
||||
constexpr tic_t kStunTime = 5*TICRATE;
|
||||
constexpr tic_t kBlockTime = 1*TICRATE;
|
||||
|
||||
constexpr int kRiseTime = 1*TICRATE;
|
||||
constexpr int kRiseSpeed = 4;
|
||||
|
||||
// TODO: skincolor must be updated to 2.2 palette
|
||||
constexpr skincolornum_t kSuperStart = SKINCOLOR_SUPERGOLD1;
|
||||
constexpr skincolornum_t kSuperEnd = SKINCOLOR_SUPERGOLD5;
|
||||
|
||||
// copied from objects/hyudoro.c
|
||||
void
|
||||
sine_bob
|
||||
( mobj_t * hyu,
|
||||
angle_t a,
|
||||
fixed_t sineofs)
|
||||
{
|
||||
const fixed_t kBobHeight = 4 * mapobjectscale;
|
||||
|
||||
// slightly modified from objects/hyudoro.c
|
||||
hyu->sprzoff = FixedMul(kBobHeight,
|
||||
sineofs + FINESINE(a >> ANGLETOFINESHIFT));
|
||||
}
|
||||
|
||||
void
|
||||
bob_in_place
|
||||
( mobj_t * hyu,
|
||||
INT32 phase,
|
||||
INT32 bob_speed)
|
||||
{
|
||||
sine_bob(hyu,
|
||||
((leveltime + phase) & (bob_speed - 1)) *
|
||||
(ANGLE_MAX / bob_speed), -(3*FRACUNIT/4));
|
||||
}
|
||||
|
||||
struct Flicky;
|
||||
|
||||
struct Controller : mobj_t
|
||||
{
|
||||
enum class Mode : int
|
||||
{
|
||||
kDescend,
|
||||
kOrbit,
|
||||
kEnRoute,
|
||||
kAttached,
|
||||
kReturning,
|
||||
};
|
||||
|
||||
mobj_t* source() const { return controller_source(this); }
|
||||
void source(mobj_t* n) { P_SetTarget(&controller_source(this), n); }
|
||||
|
||||
mobj_t* chasing() const { return controller_chasing(this); }
|
||||
void chasing(mobj_t* n) { P_SetTarget(&controller_chasing(this), n); }
|
||||
|
||||
Flicky* flicky() const;
|
||||
void flicky(Flicky* n);
|
||||
|
||||
Mode mode() const { return static_cast<Mode>(controller_mode(this)); }
|
||||
void mode(Mode n) { controller_mode(this) = static_cast<int>(n); }
|
||||
|
||||
fixed_t zofs() const { return controller_zofs(this); }
|
||||
void zofs(fixed_t n) { controller_zofs(this) = n; }
|
||||
|
||||
tic_t expiry() const { return controller_expiry(this); }
|
||||
void expiry(tic_t n) { controller_expiry(this) = n; }
|
||||
|
||||
static Controller* spawn(player_t* player, tic_t time)
|
||||
{
|
||||
Controller* x = static_cast<Controller*>(P_SpawnMobjFromMobjUnscaled(
|
||||
player->mo,
|
||||
0,
|
||||
0,
|
||||
kDescendHeight * mapobjectscale,
|
||||
MT_SUPER_FLICKY_CONTROLLER
|
||||
));
|
||||
|
||||
x->source(player->mo);
|
||||
x->mode(Mode::kDescend);
|
||||
x->zofs(0);
|
||||
x->expiry(leveltime + time);
|
||||
|
||||
P_SetTarget(&player->powerup.flickyController, x);
|
||||
|
||||
S_StartSound(x, sfx_s3k46);
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
bool valid() { return !P_MobjWasRemoved(source()); }
|
||||
tic_t time_remaining() const { return expiry() - leveltime; }
|
||||
tic_t powerup_remaining() const { return ending() ? 0u : time_remaining() - kRiseTime; }
|
||||
bool ending() const { return time_remaining() <= kRiseTime; }
|
||||
|
||||
void descend()
|
||||
{
|
||||
fixed_t head = P_GetMobjHead(source());
|
||||
fixed_t tz = head;
|
||||
|
||||
if (mode() == Mode::kDescend)
|
||||
{
|
||||
tz = z - ((z - head) / kDescendSmoothing);
|
||||
|
||||
if ((tz - head) < mapobjectscale)
|
||||
{
|
||||
mode(Mode::kOrbit);
|
||||
tz = head;
|
||||
}
|
||||
}
|
||||
|
||||
z = tz + zofs();
|
||||
|
||||
if (ending())
|
||||
{
|
||||
zofs(zofs() + (kRiseSpeed * mapobjectscale * P_MobjFlip(this)));
|
||||
}
|
||||
}
|
||||
|
||||
void expand()
|
||||
{
|
||||
fixed_t n = FixedMul(kOrbitRadiusInitial, ((z - P_GetMobjHead(source())) / kDescendHeight));
|
||||
|
||||
radius = FixedMul(FixedMul(kOrbitRadius, source()->radius), FRACUNIT + n);
|
||||
}
|
||||
|
||||
void end()
|
||||
{
|
||||
// +1 in case flicky already thunk this tic
|
||||
expiry(leveltime + kRiseTime + 1);
|
||||
}
|
||||
|
||||
void search();
|
||||
};
|
||||
|
||||
struct Flicky : mobj_t
|
||||
{
|
||||
enum class Mode : int
|
||||
{
|
||||
kReserved,
|
||||
kHunting,
|
||||
kStunned,
|
||||
kWeak,
|
||||
};
|
||||
|
||||
enum class Fly : int
|
||||
{
|
||||
kNormal,
|
||||
kZoom,
|
||||
kSlow,
|
||||
};
|
||||
|
||||
Controller* controller() const { return static_cast<Controller*>(flicky_controller(this)); }
|
||||
void controller(Controller* n) { P_SetTarget(&flicky_controller(this), n); }
|
||||
|
||||
mobj_t* chasing() const { return flicky_chasing(this); }
|
||||
void chasing(mobj_t* n) { P_SetTarget(&flicky_chasing(this), n); }
|
||||
|
||||
Flicky* next() const { return static_cast<Flicky*>(flicky_next(this)); }
|
||||
void next(Flicky* n) { P_SetTarget(&flicky_next(this), n); }
|
||||
|
||||
mobj_t* next_target() const { return flicky_next_target(this); }
|
||||
void next_target(mobj_t* n) { P_SetTarget(&flicky_next_target(this), n); }
|
||||
|
||||
int phase() const { return flicky_phase(this); }
|
||||
void phase(int n) { flicky_phase(this) = n; }
|
||||
|
||||
int delay() const { return flicky_delay(this); }
|
||||
void delay(int n) { flicky_delay(this) = n; }
|
||||
|
||||
Mode mode() const { return static_cast<Mode>(flicky_mode(this)); }
|
||||
void mode(Mode n) { flicky_mode(this) = static_cast<int>(n); }
|
||||
|
||||
Fly fly() const { return static_cast<Fly>(flicky_fly(this)); }
|
||||
void fly(Fly n) { flicky_fly(this) = static_cast<int>(n); }
|
||||
|
||||
mobj_t* source() const { return controller()->source(); }
|
||||
|
||||
static void spawn(Controller* controller, int phase)
|
||||
{
|
||||
Flicky* x = static_cast<Flicky*>(P_SpawnMobjFromMobj(controller, 0, 0, 0, MT_SUPER_FLICKY));
|
||||
|
||||
x->controller(controller);
|
||||
x->phase(phase);
|
||||
x->delay(0);
|
||||
x->mode(Mode::kReserved);
|
||||
x->light_up(true);
|
||||
|
||||
x->next(controller->flicky());
|
||||
controller->flicky(x);
|
||||
}
|
||||
|
||||
static skincolornum_t super_color()
|
||||
{
|
||||
return static_cast<skincolornum_t>(kSuperStart + ((leveltime / 4) % ((kSuperEnd - kSuperStart) + 1)));
|
||||
}
|
||||
|
||||
bool valid() const { return !P_MobjWasRemoved(controller()) && controller()->valid(); }
|
||||
|
||||
bool stunned() const { return mode() == Mode::kStunned || mode() == Mode::kWeak; }
|
||||
|
||||
void light_up(bool n)
|
||||
{
|
||||
if (n)
|
||||
{
|
||||
renderflags |= RF_FULLBRIGHT;
|
||||
color = super_color();
|
||||
}
|
||||
else
|
||||
{
|
||||
renderflags &= ~(RF_FULLBRIGHT);
|
||||
color = source()->player ? source()->player->skincolor : source()->color;
|
||||
}
|
||||
}
|
||||
|
||||
void animate()
|
||||
{
|
||||
P_InstaScale(this, source()->scale * (chasing() ? 2 : 1));
|
||||
|
||||
if (color >= kSuperStart && color <= kSuperEnd)
|
||||
{
|
||||
color = super_color();
|
||||
}
|
||||
|
||||
bob_in_place(this, phase() * 8, 32);
|
||||
}
|
||||
|
||||
void refocus()
|
||||
{
|
||||
if (controller()->ending())
|
||||
{
|
||||
if (controller()->time_remaining() == kRiseTime)
|
||||
{
|
||||
light_up(false);
|
||||
rise();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (delay() > 0)
|
||||
{
|
||||
delay(delay() - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (chasing() != next_target())
|
||||
{
|
||||
chasing(next_target());
|
||||
mode(Mode::kHunting);
|
||||
|
||||
S_StartSound(this, sfx_fhurt2);
|
||||
}
|
||||
|
||||
if (stunned())
|
||||
{
|
||||
light_up(true);
|
||||
flags = info->flags;
|
||||
mode(Mode::kHunting);
|
||||
|
||||
S_StartSound(this, sfx_s3k9f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
angle_t orbit_angle() const { return controller()->angle + (phase() * kOrbitSpacing); }
|
||||
|
||||
vector3_t orbit_position() const
|
||||
{
|
||||
return {
|
||||
source()->x + FixedMul(FCOS(orbit_angle()), controller()->radius),
|
||||
source()->y + FixedMul(FSIN(orbit_angle()), controller()->radius),
|
||||
controller()->z
|
||||
};
|
||||
}
|
||||
|
||||
void orbit()
|
||||
{
|
||||
vector3_t pos = orbit_position();
|
||||
|
||||
P_MoveOrigin(this, pos.x, pos.y, pos.z);
|
||||
|
||||
momx = 0;
|
||||
momy = 0;
|
||||
momz = 0;
|
||||
|
||||
angle = orbit_angle() + ANGLE_90; // face direction of orbit
|
||||
}
|
||||
|
||||
|
||||
// copied from objects/spb.c
|
||||
void spawn_speed_lines(angle_t direction)
|
||||
{
|
||||
if (mode() != Mode::kHunting)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mobj_t *fast = P_SpawnMobjFromMobjUnscaled(
|
||||
this,
|
||||
P_RandomRange(PR_DECORATION, -24, 24) * mapobjectscale,
|
||||
P_RandomRange(PR_DECORATION, -24, 24) * mapobjectscale,
|
||||
(height / 2) + (P_RandomRange(PR_DECORATION, -24, 24) * mapobjectscale),
|
||||
MT_FASTLINE
|
||||
);
|
||||
|
||||
P_SetTarget(&fast->target, this);
|
||||
fast->angle = direction;
|
||||
|
||||
fast->color = source()->color;
|
||||
fast->colorized = true;
|
||||
fast->renderflags |= RF_ADD;
|
||||
|
||||
K_MatchGenericExtraFlags(fast, this);
|
||||
}
|
||||
|
||||
void chase()
|
||||
{
|
||||
if (controller()->ending())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
vector3_t pos = chasing() ? vector3_t{chasing()->x, chasing()->y, P_GetMobjFeet(chasing())} : orbit_position();
|
||||
angle_t th = R_PointToAngle2(x, y, pos.x, pos.y);
|
||||
|
||||
momz = (pos.z - z) / kDescendSmoothing;
|
||||
angle = K_MomentumAngleReal(this);
|
||||
|
||||
angle_t d = AngleDelta(th, angle);
|
||||
fixed_t dist = FixedHypot(x - pos.x, y - pos.y);
|
||||
|
||||
const Fly oldFly = fly();
|
||||
|
||||
if (d < ANGLE_11hh && dist < kPeckingRadius * mapobjectscale)
|
||||
{
|
||||
// Drastically speed up when about to intersect
|
||||
P_Thrust(this, th, kPeckingSpeed * mapobjectscale);
|
||||
fly(Fly::kZoom);
|
||||
}
|
||||
else
|
||||
{
|
||||
P_Thrust(this, th, kFlightSpeed * mapobjectscale);
|
||||
fly(Fly::kNormal);
|
||||
}
|
||||
|
||||
if (d > ANGLE_45 && dist > kFlightRadius * mapobjectscale)
|
||||
{
|
||||
// Cut momentum when too far outside of intended trajectory
|
||||
momx = FixedMul(momx, kRebound);
|
||||
momy = FixedMul(momy, kRebound);
|
||||
|
||||
spawn_speed_lines(th);
|
||||
|
||||
fly(Fly::kSlow);
|
||||
}
|
||||
else
|
||||
{
|
||||
spawn_speed_lines(angle);
|
||||
}
|
||||
|
||||
// Returning to owner
|
||||
if (!chasing())
|
||||
{
|
||||
if (AngleDelta(th, R_PointToAngle2(x + momx, y + momy, pos.x, pos.y)) > ANG1)
|
||||
{
|
||||
mode(Mode::kReserved);
|
||||
}
|
||||
else
|
||||
{
|
||||
P_InstaThrust(this, th, FixedHypot(momx, momy));
|
||||
}
|
||||
}
|
||||
|
||||
if (fly() != oldFly)
|
||||
{
|
||||
switch (fly())
|
||||
{
|
||||
case Fly::kNormal:
|
||||
break;
|
||||
|
||||
case Fly::kZoom:
|
||||
S_StartSound(this, sfx_fbird);
|
||||
break;
|
||||
|
||||
case Fly::kSlow:
|
||||
S_StartSound(this, sfx_fbost1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rise()
|
||||
{
|
||||
P_SetObjectMomZ(this, kRiseSpeed * FRACUNIT, false);
|
||||
}
|
||||
|
||||
void damage(mobj_t* mobj)
|
||||
{
|
||||
if (!mobj->player)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (mobj != chasing())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode() != Mode::kHunting)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (P_DamageMobj(mobj, this, source(), 1, DMG_NORMAL))
|
||||
{
|
||||
P_InstaThrust(mobj, K_MomentumAngleReal(this), FixedHypot(momx, momy));
|
||||
K_StumblePlayer(mobj->player);
|
||||
|
||||
mobj->player->spinouttimer = 1; // need invulnerability for one tic
|
||||
|
||||
P_SetTarget(&mobj->player->flickyAttacker, this);
|
||||
|
||||
controller()->mode(Controller::Mode::kAttached);
|
||||
}
|
||||
|
||||
S_StartSound(this, sfx_supflk);
|
||||
}
|
||||
|
||||
void reflect()
|
||||
{
|
||||
momx = -(momx);
|
||||
momy = -(momy);
|
||||
}
|
||||
|
||||
void nerf()
|
||||
{
|
||||
light_up(false);
|
||||
|
||||
flags &= ~(MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT);
|
||||
}
|
||||
|
||||
void whip()
|
||||
{
|
||||
reflect();
|
||||
P_SetObjectMomZ(this, 8*FRACUNIT, false);
|
||||
|
||||
nerf();
|
||||
|
||||
mode(Mode::kStunned);
|
||||
delay(kStunTime);
|
||||
|
||||
S_StartSound(this, sfx_fhurt1);
|
||||
}
|
||||
|
||||
void block()
|
||||
{
|
||||
reflect();
|
||||
|
||||
mode(Mode::kStunned);
|
||||
delay(kBlockTime);
|
||||
}
|
||||
|
||||
void land()
|
||||
{
|
||||
flags |= MF_NOGRAVITY;
|
||||
|
||||
mode(Mode::kWeak);
|
||||
}
|
||||
};
|
||||
|
||||
Flicky* Controller::flicky() const
|
||||
{
|
||||
return static_cast<Flicky*>(controller_flicky(this));
|
||||
}
|
||||
|
||||
void Controller::flicky(Flicky* n)
|
||||
{
|
||||
P_SetTarget(&controller_flicky(this), n);
|
||||
}
|
||||
|
||||
void Controller::search()
|
||||
{
|
||||
if (ending())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
fixed_t nearestDistance = INT32_MAX;
|
||||
mobj_t* nearestMobj = nullptr;
|
||||
|
||||
mobj_t* origin = chasing() ? chasing() : source();
|
||||
|
||||
for (int i = 0; i < MAXPLAYERS; ++i)
|
||||
{
|
||||
player_t* player = &players[i];
|
||||
mobj_t* mobj = player->mo;
|
||||
|
||||
if (!playeringame[i] || P_MobjWasRemoved(mobj))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Do not retarget existing target or owner.
|
||||
if (mobj == chasing() || mobj == source())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Target is already being hunted.
|
||||
if (player->flickyAttacker)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (player->respawn.state != RESPAWNST_NONE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
fixed_t dist = FixedHypot(origin->x - mobj->x, origin->y - mobj->y);
|
||||
|
||||
if (dist < kSearchRadius * mapobjectscale && dist < nearestDistance)
|
||||
{
|
||||
nearestDistance = dist;
|
||||
nearestMobj = mobj;
|
||||
}
|
||||
}
|
||||
|
||||
if (nearestMobj)
|
||||
{
|
||||
if (chasing() && flicky())
|
||||
{
|
||||
// Detach flicky from swarm. This one keeps its previous target.
|
||||
flicky(flicky()->next());
|
||||
}
|
||||
|
||||
chasing(nearestMobj);
|
||||
mode(Mode::kEnRoute);
|
||||
|
||||
// Update entire swarm
|
||||
for (Flicky* x = flicky(); x; x = x->next())
|
||||
{
|
||||
x->next_target(chasing());
|
||||
x->delay(x->phase() * kDelay);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}; // namespace
|
||||
|
||||
void Obj_SpawnSuperFlickySwarm(player_t* owner, tic_t time)
|
||||
{
|
||||
Controller* controller = Controller::spawn(owner, time);
|
||||
|
||||
Flicky::spawn(controller, 0);
|
||||
Flicky::spawn(controller, 1);
|
||||
Flicky::spawn(controller, 2);
|
||||
Flicky::spawn(controller, 3);
|
||||
}
|
||||
|
||||
void Obj_SuperFlickyThink(mobj_t* mobj)
|
||||
{
|
||||
Flicky* x = static_cast<Flicky*>(mobj);
|
||||
|
||||
if (!x->valid())
|
||||
{
|
||||
P_RemoveMobj(x);
|
||||
return;
|
||||
}
|
||||
|
||||
x->animate();
|
||||
x->refocus();
|
||||
|
||||
switch (x->mode())
|
||||
{
|
||||
case Flicky::Mode::kReserved:
|
||||
x->orbit();
|
||||
break;
|
||||
|
||||
case Flicky::Mode::kHunting:
|
||||
x->chase();
|
||||
break;
|
||||
|
||||
case Flicky::Mode::kStunned:
|
||||
break;
|
||||
|
||||
case Flicky::Mode::kWeak:
|
||||
x->chase();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Obj_SuperFlickyControllerThink(mobj_t* mobj)
|
||||
{
|
||||
Controller* x = static_cast<Controller*>(mobj);
|
||||
|
||||
if (!x->valid())
|
||||
{
|
||||
P_RemoveMobj(x);
|
||||
return;
|
||||
}
|
||||
|
||||
if (x->time_remaining() <= 1)
|
||||
{
|
||||
P_RemoveMobj(x);
|
||||
return;
|
||||
}
|
||||
|
||||
x->angle += ANGLE_MAX / kOrbitSpeed;
|
||||
|
||||
switch (x->mode())
|
||||
{
|
||||
case Controller::Mode::kDescend:
|
||||
x->descend();
|
||||
x->expand();
|
||||
break;
|
||||
|
||||
case Controller::Mode::kOrbit:
|
||||
x->descend();
|
||||
x->expand();
|
||||
x->search();
|
||||
break;
|
||||
|
||||
case Controller::Mode::kEnRoute:
|
||||
break;
|
||||
|
||||
case Controller::Mode::kAttached:
|
||||
x->search();
|
||||
break;
|
||||
|
||||
case Controller::Mode::kReturning:
|
||||
x->descend();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Obj_WhipSuperFlicky(mobj_t* t1)
|
||||
{
|
||||
Flicky* x = static_cast<Flicky*>(t1);
|
||||
|
||||
if (x->valid())
|
||||
{
|
||||
x->whip();
|
||||
}
|
||||
}
|
||||
|
||||
void Obj_BlockSuperFlicky(mobj_t* t1)
|
||||
{
|
||||
Flicky* x = static_cast<Flicky*>(t1);
|
||||
|
||||
if (x->valid())
|
||||
{
|
||||
x->block();
|
||||
}
|
||||
}
|
||||
|
||||
void Obj_SuperFlickyPlayerCollide(mobj_t* t1, mobj_t* t2)
|
||||
{
|
||||
Flicky* x = static_cast<Flicky*>(t1);
|
||||
|
||||
if (x->valid())
|
||||
{
|
||||
x->damage(t2);
|
||||
}
|
||||
}
|
||||
|
||||
void Obj_SuperFlickyLanding(mobj_t* mobj)
|
||||
{
|
||||
Flicky* x = static_cast<Flicky*>(mobj);
|
||||
|
||||
if (x->valid())
|
||||
{
|
||||
x->land();
|
||||
}
|
||||
}
|
||||
|
||||
void Obj_EndSuperFlickySwarm(mobj_t* mobj)
|
||||
{
|
||||
Controller* x = static_cast<Controller*>(mobj);
|
||||
|
||||
if (x->valid())
|
||||
{
|
||||
x->end();
|
||||
}
|
||||
}
|
||||
|
||||
void Obj_ExtendSuperFlickySwarm(mobj_t* mobj, tic_t time)
|
||||
{
|
||||
Controller* x = static_cast<Controller*>(mobj);
|
||||
|
||||
x->expiry(x->expiry() + time);
|
||||
}
|
||||
|
||||
tic_t Obj_SuperFlickySwarmTime(const mobj_t* mobj)
|
||||
{
|
||||
const Controller* x = static_cast<const Controller*>(mobj);
|
||||
|
||||
return x ? x->powerup_remaining() : 0u;
|
||||
}
|
||||
|
||||
boolean Obj_IsSuperFlickyWhippable(const mobj_t* mobj)
|
||||
{
|
||||
const Flicky* x = static_cast<const Flicky*>(mobj);
|
||||
|
||||
return !x->stunned();
|
||||
}
|
||||
|
|
@ -312,7 +312,6 @@ void A_ChangeHeight(mobj_t *actor);
|
|||
//
|
||||
// SRB2Kart
|
||||
//
|
||||
void A_ItemPop(mobj_t *actor);
|
||||
void A_JawzExplode(mobj_t *actor);
|
||||
void A_SSMineSearch(mobj_t *actor);
|
||||
void A_SSMineExplode(mobj_t *actor);
|
||||
|
|
@ -12984,54 +12983,6 @@ void A_ChangeHeight(mobj_t *actor)
|
|||
// SRB2Kart
|
||||
//
|
||||
|
||||
void A_ItemPop(mobj_t *actor)
|
||||
{
|
||||
INT32 locvar1 = var1;
|
||||
|
||||
if (LUA_CallAction(A_ITEMPOP, actor))
|
||||
return;
|
||||
|
||||
if (!(actor->target && actor->target->player))
|
||||
{
|
||||
if (cht_debug && !(actor->target && actor->target->player))
|
||||
CONS_Printf("ERROR: Powerup has no target!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// de-solidify
|
||||
P_UnsetThingPosition(actor);
|
||||
actor->flags &= ~MF_SOLID;
|
||||
actor->flags |= MF_NOCLIP;
|
||||
P_SetThingPosition(actor);
|
||||
|
||||
// RF_DONTDRAW will flicker as the object's fuse gets
|
||||
// closer to running out (see P_FuseThink)
|
||||
actor->renderflags |= RF_DONTDRAW|RF_TRANS50;
|
||||
actor->color = SKINCOLOR_GREY;
|
||||
actor->colorized = true;
|
||||
|
||||
Obj_SpawnItemDebrisEffects(actor, actor->target);
|
||||
|
||||
if (locvar1 == 1)
|
||||
{
|
||||
P_GivePlayerSpheres(actor->target->player, actor->extravalue1);
|
||||
}
|
||||
else if (locvar1 == 0)
|
||||
{
|
||||
K_StartItemRoulette(actor->target->player);
|
||||
}
|
||||
|
||||
// Here at mapload in battle?
|
||||
if (!(gametyperules & GTR_CIRCUIT) && (actor->flags2 & MF2_BOSSNOTRAP))
|
||||
{
|
||||
numgotboxes++;
|
||||
|
||||
// do not flicker back in just yet, handled by
|
||||
// P_RespawnBattleBoxes eventually
|
||||
P_SetMobjState(actor, S_INVISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
void A_JawzExplode(mobj_t *actor)
|
||||
{
|
||||
INT32 shrapnel = 2;
|
||||
|
|
|
|||
104
src/p_inter.c
104
src/p_inter.c
|
|
@ -41,6 +41,7 @@
|
|||
#include "k_roulette.h"
|
||||
#include "k_boss.h"
|
||||
#include "acs/interface.h"
|
||||
#include "k_powerup.h"
|
||||
|
||||
// CTF player names
|
||||
#define CTFTEAMCODE(pl) pl->ctfteam ? (pl->ctfteam == 1 ? "\x85" : "\x84") : ""
|
||||
|
|
@ -140,6 +141,7 @@ boolean P_CanPickupItem(player_t *player, UINT8 weapon)
|
|||
|
||||
// Item slot already taken up
|
||||
if (player->itemRoulette.active == true
|
||||
|| player->ringboxdelay > 0
|
||||
|| (weapon != 3 && player->itemamount)
|
||||
|| (player->pflags & PF_ITEMOUT))
|
||||
return false;
|
||||
|
|
@ -186,6 +188,61 @@ boolean P_EmblemWasCollected(INT32 emblemID)
|
|||
return gamedata->collected[emblemID];
|
||||
}
|
||||
|
||||
static void P_ItemPop(mobj_t *actor)
|
||||
{
|
||||
/*
|
||||
INT32 locvar1 = var1;
|
||||
|
||||
if (LUA_CallAction(A_ITEMPOP, actor))
|
||||
return;
|
||||
|
||||
if (!(actor->target && actor->target->player))
|
||||
{
|
||||
if (cht_debug && !(actor->target && actor->target->player))
|
||||
CONS_Printf("ERROR: Powerup has no target!\n");
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
P_SetMobjState(actor, S_RINGBOX1);
|
||||
actor->extravalue1 = 0;
|
||||
|
||||
// de-solidify
|
||||
actor->flags |= MF_NOCLIPTHING;
|
||||
|
||||
// RF_DONTDRAW will flicker as the object's fuse gets
|
||||
// closer to running out (see P_FuseThink)
|
||||
actor->renderflags |= RF_DONTDRAW|RF_TRANS50;
|
||||
actor->color = SKINCOLOR_GREY;
|
||||
actor->colorized = true;
|
||||
|
||||
Obj_SpawnItemDebrisEffects(actor, actor->target);
|
||||
|
||||
/*
|
||||
if (locvar1 == 1)
|
||||
{
|
||||
P_GivePlayerSpheres(actor->target->player, actor->extravalue1);
|
||||
}
|
||||
else if (locvar1 == 0)
|
||||
{
|
||||
if (actor->extravalue1 >= TICRATE)
|
||||
K_StartItemRoulette(actor->target->player, false);
|
||||
else
|
||||
K_StartItemRoulette(actor->target->player, true);
|
||||
}
|
||||
*/
|
||||
|
||||
// Here at mapload in battle?
|
||||
if (!(gametyperules & GTR_CIRCUIT) && (actor->flags2 & MF2_BOSSNOTRAP))
|
||||
{
|
||||
numgotboxes++;
|
||||
|
||||
// do not flicker back in just yet, handled by
|
||||
// P_RespawnBattleBoxes eventually
|
||||
P_SetMobjState(actor, S_INVISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
/** Takes action based on a ::MF_SPECIAL thing touched by a player.
|
||||
* Actually, this just checks a few things (heights, toucher->player, no
|
||||
* objectplace, no dead or disappearing things)
|
||||
|
|
@ -276,14 +333,21 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
P_InstaThrust(player->mo, player->mo->angle, 20<<FRACBITS);
|
||||
return;
|
||||
case MT_FLOATINGITEM: // SRB2Kart
|
||||
if (!P_CanPickupItem(player, 3) || (player->itemamount && player->itemtype != special->threshold))
|
||||
return;
|
||||
|
||||
player->itemtype = special->threshold;
|
||||
if ((UINT16)(player->itemamount) + special->movecount > 255)
|
||||
player->itemamount = 255;
|
||||
if (special->threshold >= FIRSTPOWERUP)
|
||||
{
|
||||
K_GivePowerUp(player, special->threshold, special->movecount);
|
||||
}
|
||||
else
|
||||
player->itemamount += special->movecount;
|
||||
{
|
||||
if (!P_CanPickupItem(player, 3) || (player->itemamount && player->itemtype != special->threshold))
|
||||
return;
|
||||
|
||||
player->itemtype = special->threshold;
|
||||
if ((UINT16)(player->itemamount) + special->movecount > 255)
|
||||
player->itemamount = 255;
|
||||
else
|
||||
player->itemamount += special->movecount;
|
||||
}
|
||||
|
||||
S_StartSound(special, special->info->deathsound);
|
||||
|
||||
|
|
@ -300,7 +364,13 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
|
||||
special->momx = special->momy = special->momz = 0;
|
||||
P_SetTarget(&special->target, toucher);
|
||||
P_KillMobj(special, toucher, toucher, DMG_NORMAL);
|
||||
// P_KillMobj(special, toucher, toucher, DMG_NORMAL);
|
||||
if (special->extravalue1 >= RINGBOX_TIME)
|
||||
K_StartItemRoulette(player, false);
|
||||
else
|
||||
K_StartItemRoulette(player, true);
|
||||
P_ItemPop(special);
|
||||
special->fuse = TICRATE;
|
||||
return;
|
||||
case MT_SPHEREBOX:
|
||||
if (!P_CanPickupItem(player, 0))
|
||||
|
|
@ -308,7 +378,9 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
|
||||
special->momx = special->momy = special->momz = 0;
|
||||
P_SetTarget(&special->target, toucher);
|
||||
P_KillMobj(special, toucher, toucher, DMG_NORMAL);
|
||||
// P_KillMobj(special, toucher, toucher, DMG_NORMAL);
|
||||
P_ItemPop(special);
|
||||
P_GivePlayerSpheres(player, special->extravalue1);
|
||||
return;
|
||||
case MT_ITEMCAPSULE:
|
||||
if (special->scale < special->extravalue1) // don't break it while it's respawning
|
||||
|
|
@ -434,7 +506,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
if (special->fuse || !P_CanPickupItem(player, 1))
|
||||
return;
|
||||
|
||||
K_StartItemRoulette(player);
|
||||
K_StartItemRoulette(player, false);
|
||||
|
||||
// Karma fireworks
|
||||
/*for (i = 0; i < 5; i++)
|
||||
|
|
@ -584,6 +656,10 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
Obj_PlayerUsedRingShooter(special, player);
|
||||
return;
|
||||
|
||||
case MT_SUPER_FLICKY:
|
||||
Obj_SuperFlickyPlayerCollide(special, toucher);
|
||||
return;
|
||||
|
||||
default: // SOC or script pickup
|
||||
P_SetTarget(&special->target, toucher);
|
||||
break;
|
||||
|
|
@ -2258,8 +2334,16 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
if (clash)
|
||||
{
|
||||
player->spheres = max(player->spheres - 10, 0);
|
||||
|
||||
if (inflictor)
|
||||
{
|
||||
K_DoPowerClash(target, inflictor);
|
||||
|
||||
if (inflictor->type == MT_SUPER_FLICKY)
|
||||
{
|
||||
Obj_BlockSuperFlicky(inflictor);
|
||||
}
|
||||
}
|
||||
else if (source)
|
||||
K_DoPowerClash(target, source);
|
||||
}
|
||||
|
|
|
|||
69
src/p_mobj.c
69
src/p_mobj.c
|
|
@ -2464,6 +2464,12 @@ boolean P_ZMovement(mobj_t *mo)
|
|||
return false;
|
||||
}
|
||||
}
|
||||
else if (mo->type == MT_SUPER_FLICKY)
|
||||
{
|
||||
mom.z = -mom.z;
|
||||
|
||||
Obj_SuperFlickyLanding(mo);
|
||||
}
|
||||
else if (mo->type == MT_DRIFTCLIP)
|
||||
{
|
||||
mom.z = -mom.z/2;
|
||||
|
|
@ -6684,6 +6690,14 @@ static void P_MobjSceneryThink(mobj_t *mobj)
|
|||
case MT_INSTAWHIP_RECHARGE:
|
||||
Obj_InstaWhipRechargeThink(mobj);
|
||||
|
||||
if (P_MobjWasRemoved(mobj))
|
||||
{
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case MT_SUPER_FLICKY_CONTROLLER:
|
||||
Obj_SuperFlickyControllerThink(mobj);
|
||||
|
||||
if (P_MobjWasRemoved(mobj))
|
||||
{
|
||||
return;
|
||||
|
|
@ -7197,29 +7211,12 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
|||
}
|
||||
}
|
||||
|
||||
switch (mobj->threshold)
|
||||
if (mobj->threshold == KITEM_SPB || mobj->threshold == KITEM_SHRINK)
|
||||
{
|
||||
case KITEM_ORBINAUT:
|
||||
mobj->sprite = SPR_ITMO;
|
||||
mobj->frame = FF_FULLBRIGHT|FF_PAPERSPRITE|K_GetOrbinautItemFrame(mobj->movecount);
|
||||
break;
|
||||
case KITEM_INVINCIBILITY:
|
||||
mobj->sprite = SPR_ITMI;
|
||||
mobj->frame = FF_FULLBRIGHT|FF_PAPERSPRITE|K_GetInvincibilityItemFrame();
|
||||
break;
|
||||
case KITEM_SAD:
|
||||
mobj->sprite = SPR_ITEM;
|
||||
mobj->frame = FF_FULLBRIGHT|FF_PAPERSPRITE;
|
||||
break;
|
||||
case KITEM_SPB:
|
||||
case KITEM_SHRINK:
|
||||
K_SetItemCooldown(mobj->threshold, 20*TICRATE);
|
||||
/* FALLTHRU */
|
||||
default:
|
||||
mobj->sprite = SPR_ITEM;
|
||||
mobj->frame = FF_FULLBRIGHT|FF_PAPERSPRITE|(mobj->threshold);
|
||||
break;
|
||||
K_SetItemCooldown(mobj->threshold, 20*TICRATE);
|
||||
}
|
||||
|
||||
K_UpdateMobjItemOverlay(mobj, mobj->threshold, mobj->movecount);
|
||||
break;
|
||||
}
|
||||
case MT_ITEMCAPSULE:
|
||||
|
|
@ -9533,6 +9530,14 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
|||
case MT_GACHABOM_REBOUND:
|
||||
Obj_GachaBomReboundThink(mobj);
|
||||
|
||||
if (P_MobjWasRemoved(mobj))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case MT_SUPER_FLICKY:
|
||||
Obj_SuperFlickyThink(mobj);
|
||||
|
||||
if (P_MobjWasRemoved(mobj))
|
||||
{
|
||||
return false;
|
||||
|
|
@ -9718,7 +9723,7 @@ static boolean P_FuseThink(mobj_t *mobj)
|
|||
case MT_RANDOMITEM:
|
||||
if (mobj->flags2 & MF2_DONTRESPAWN)
|
||||
{
|
||||
;
|
||||
P_RemoveMobj(mobj);
|
||||
}
|
||||
else if (!(gametyperules & GTR_CIRCUIT) && (mobj->state == &states[S_INVISIBLE]))
|
||||
{
|
||||
|
|
@ -9726,22 +9731,10 @@ static boolean P_FuseThink(mobj_t *mobj)
|
|||
}
|
||||
else
|
||||
{
|
||||
mobj_t *newmobj;
|
||||
|
||||
// Respawn from mapthing if you have one!
|
||||
if (mobj->spawnpoint)
|
||||
{
|
||||
P_SpawnMapThing(mobj->spawnpoint);
|
||||
newmobj = mobj->spawnpoint->mobj; // this is set to the new mobj in P_SpawnMapThing
|
||||
}
|
||||
else
|
||||
newmobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobj->type);
|
||||
|
||||
// Transfer flags2 (strongbox, objectflip, bossnotrap)
|
||||
newmobj->flags2 = mobj->flags2;
|
||||
mobj->flags &= ~MF_NOCLIPTHING;
|
||||
mobj->renderflags &= ~(RF_DONTDRAW|RF_TRANSMASK);
|
||||
}
|
||||
|
||||
P_RemoveMobj(mobj); // make sure they disappear
|
||||
return false;
|
||||
case MT_ITEMCAPSULE:
|
||||
if (mobj->spawnpoint)
|
||||
|
|
@ -11592,11 +11585,11 @@ void P_RespawnBattleBoxes(void)
|
|||
|
||||
if (box->type != MT_RANDOMITEM
|
||||
|| (box->flags2 & MF2_DONTRESPAWN)
|
||||
|| box->health > 0
|
||||
|| !(box->flags & MF_NOCLIPTHING)
|
||||
|| box->fuse)
|
||||
continue; // only popped items
|
||||
|
||||
box->fuse = TICRATE; // flicker back in (A_ItemPop preps this effect)
|
||||
box->fuse = TICRATE; // flicker back in
|
||||
P_SetMobjState(box, box->info->raisestate);
|
||||
|
||||
if (numgotboxes > 0)
|
||||
|
|
|
|||
|
|
@ -566,8 +566,6 @@ extern INT32 modulothing;
|
|||
#define MAXHUNTEMERALDS 64
|
||||
extern mapthing_t *huntemeralds[MAXHUNTEMERALDS];
|
||||
extern INT32 numhuntemeralds;
|
||||
extern boolean runemeraldmanager;
|
||||
extern UINT16 emeraldspawndelay;
|
||||
extern INT32 numstarposts;
|
||||
extern UINT16 bossdisabled;
|
||||
extern boolean stoppedclock;
|
||||
|
|
|
|||
|
|
@ -79,6 +79,8 @@ typedef enum
|
|||
RINGSHOOTER = 0x0100,
|
||||
WHIP = 0x0200,
|
||||
HAND = 0x0400,
|
||||
FLICKYATTACKER = 0x0800,
|
||||
FLICKYCONTROLLER = 0x1000,
|
||||
} player_saveflags;
|
||||
|
||||
static inline void P_ArchivePlayer(savebuffer_t *save)
|
||||
|
|
@ -319,6 +321,12 @@ static void P_NetArchivePlayers(savebuffer_t *save)
|
|||
if (players[i].ringShooter)
|
||||
flags |= RINGSHOOTER;
|
||||
|
||||
if (players[i].flickyAttacker)
|
||||
flags |= FLICKYATTACKER;
|
||||
|
||||
if (players[i].powerup.flickyController)
|
||||
flags |= FLICKYCONTROLLER;
|
||||
|
||||
WRITEUINT16(save->p, flags);
|
||||
|
||||
if (flags & SKYBOXVIEW)
|
||||
|
|
@ -351,6 +359,12 @@ static void P_NetArchivePlayers(savebuffer_t *save)
|
|||
if (flags & RINGSHOOTER)
|
||||
WRITEUINT32(save->p, players[i].ringShooter->mobjnum);
|
||||
|
||||
if (flags & FLICKYATTACKER)
|
||||
WRITEUINT32(save->p, players[i].flickyAttacker->mobjnum);
|
||||
|
||||
if (flags & FLICKYCONTROLLER)
|
||||
WRITEUINT32(save->p, players[i].powerup.flickyController->mobjnum);
|
||||
|
||||
WRITEUINT32(save->p, (UINT32)players[i].followitem);
|
||||
|
||||
WRITEUINT32(save->p, players[i].charflags);
|
||||
|
|
@ -527,6 +541,8 @@ static void P_NetArchivePlayers(savebuffer_t *save)
|
|||
|
||||
WRITEUINT8(save->p, players[i].markedfordeath);
|
||||
|
||||
WRITEUINT8(save->p, players[i].ringboxdelay);
|
||||
WRITEUINT8(save->p, players[i].ringboxaward);
|
||||
WRITEFIXED(save->p, players[i].outrun);
|
||||
|
||||
// respawnvars_t
|
||||
|
|
@ -600,6 +616,7 @@ static void P_NetArchivePlayers(savebuffer_t *save)
|
|||
WRITEUINT32(save->p, players[i].itemRoulette.tics);
|
||||
WRITEUINT32(save->p, players[i].itemRoulette.elapsed);
|
||||
WRITEUINT8(save->p, players[i].itemRoulette.eggman);
|
||||
WRITEUINT8(save->p, players[i].itemRoulette.ringbox);
|
||||
|
||||
// sonicloopsvars_t
|
||||
WRITEFIXED(save->p, players[i].loop.radius);
|
||||
|
|
@ -754,6 +771,12 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
|
|||
if (flags & RINGSHOOTER)
|
||||
players[i].ringShooter = (mobj_t *)(size_t)READUINT32(save->p);
|
||||
|
||||
if (flags & FLICKYATTACKER)
|
||||
players[i].flickyAttacker = (mobj_t *)(size_t)READUINT32(save->p);
|
||||
|
||||
if (flags & FLICKYCONTROLLER)
|
||||
players[i].powerup.flickyController = (mobj_t *)(size_t)READUINT32(save->p);
|
||||
|
||||
players[i].followitem = (mobjtype_t)READUINT32(save->p);
|
||||
|
||||
//SetPlayerSkinByNum(i, players[i].skin);
|
||||
|
|
@ -931,6 +954,8 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
|
|||
|
||||
players[i].markedfordeath = READUINT8(save->p);
|
||||
|
||||
players[i].ringboxdelay = READUINT8(save->p);
|
||||
players[i].ringboxaward = READUINT8(save->p);
|
||||
players[i].outrun = READFIXED(save->p);
|
||||
|
||||
// respawnvars_t
|
||||
|
|
@ -1015,6 +1040,7 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
|
|||
players[i].itemRoulette.tics = (tic_t)READUINT32(save->p);
|
||||
players[i].itemRoulette.elapsed = (tic_t)READUINT32(save->p);
|
||||
players[i].itemRoulette.eggman = (boolean)READUINT8(save->p);
|
||||
players[i].itemRoulette.ringbox = (boolean)READUINT8(save->p);
|
||||
|
||||
// sonicloopsvars_t
|
||||
players[i].loop.radius = READFIXED(save->p);
|
||||
|
|
@ -5258,6 +5284,20 @@ static void P_RelinkPointers(void)
|
|||
if (!P_SetTarget(&players[i].ringShooter, P_FindNewPosition(temp)))
|
||||
CONS_Debug(DBG_GAMELOGIC, "ringShooter not found on player %d\n", i);
|
||||
}
|
||||
if (players[i].flickyAttacker)
|
||||
{
|
||||
temp = (UINT32)(size_t)players[i].flickyAttacker;
|
||||
players[i].flickyAttacker = NULL;
|
||||
if (!P_SetTarget(&players[i].flickyAttacker, P_FindNewPosition(temp)))
|
||||
CONS_Debug(DBG_GAMELOGIC, "flickyAttacker not found on player %d\n", i);
|
||||
}
|
||||
if (players[i].powerup.flickyController)
|
||||
{
|
||||
temp = (UINT32)(size_t)players[i].powerup.flickyController;
|
||||
players[i].powerup.flickyController = NULL;
|
||||
if (!P_SetTarget(&players[i].powerup.flickyController, P_FindNewPosition(temp)))
|
||||
CONS_Debug(DBG_GAMELOGIC, "powerup.flickyController not found on player %d\n", i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -5622,7 +5662,6 @@ static void P_NetArchiveMisc(savebuffer_t *save, boolean resending)
|
|||
|
||||
WRITESINT8(save->p, g_pickedVote);
|
||||
|
||||
WRITEUINT16(save->p, emeralds);
|
||||
{
|
||||
UINT8 globools = 0;
|
||||
if (stagefailed)
|
||||
|
|
@ -5796,7 +5835,6 @@ static boolean P_NetUnArchiveMisc(savebuffer_t *save, boolean reloading)
|
|||
|
||||
g_pickedVote = READSINT8(save->p);
|
||||
|
||||
emeralds = READUINT16(save->p);
|
||||
{
|
||||
UINT8 globools = READUINT8(save->p);
|
||||
stagefailed = !!(globools & 1);
|
||||
|
|
|
|||
|
|
@ -7351,10 +7351,6 @@ static void P_InitLevelSettings(void)
|
|||
|
||||
K_TimerReset();
|
||||
|
||||
// special stage tokens, emeralds, and ring total
|
||||
runemeraldmanager = false;
|
||||
emeraldspawndelay = 60*TICRATE;
|
||||
|
||||
nummaprings = 0;
|
||||
nummapboxes = numgotboxes = 0;
|
||||
maptargets = numtargets = 0;
|
||||
|
|
@ -8362,7 +8358,7 @@ void P_PostLoadLevel(void)
|
|||
|
||||
P_RunCachedActions();
|
||||
|
||||
G_HandleSaveLevel(gamestate == GS_CEREMONY);
|
||||
G_HandleSaveLevel(false);
|
||||
|
||||
if (marathonmode & MA_INGAME)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -4647,11 +4647,12 @@ void P_SetupSignExit(player_t *player, boolean tie)
|
|||
thinker_t *think;
|
||||
INT32 numfound = 0;
|
||||
|
||||
angle_t bestAngle = K_MomentumAngle(player->mo) + ANGLE_180;
|
||||
|
||||
if (player->position != 1)
|
||||
if (player->position != 1
|
||||
|| (gametyperules & GTR_SPECIALSTART))
|
||||
return;
|
||||
|
||||
angle_t bestAngle = K_MomentumAngle(player->mo) + ANGLE_180;
|
||||
|
||||
for (; node; node = node->m_thinglist_next)
|
||||
{
|
||||
thing = node->m_thing;
|
||||
|
|
|
|||
47
src/p_user.c
47
src/p_user.c
|
|
@ -342,7 +342,6 @@ void P_GiveEmerald(boolean spawnObj)
|
|||
UINT8 em = P_GetNextEmerald();
|
||||
|
||||
S_StartSound(NULL, sfx_cgot); // Got the emerald!
|
||||
emeralds |= (1 << em);
|
||||
stagefailed = false;
|
||||
|
||||
if (spawnObj)
|
||||
|
|
@ -714,12 +713,50 @@ void P_PlayVictorySound(mobj_t *source)
|
|||
void P_EndingMusic(void)
|
||||
{
|
||||
const char *jingle = NULL;
|
||||
boolean nointer = false;
|
||||
UINT8 bestPos = UINT8_MAX;
|
||||
player_t *bestPlayer = NULL;
|
||||
|
||||
SINT8 i;
|
||||
|
||||
// See G_DoCompleted and Y_DetermineIntermissionType
|
||||
boolean nointer = ((modeattacking && (players[consoleplayer].pflags & PF_NOCONTEST))
|
||||
|| (grandprixinfo.gp == true && grandprixinfo.eventmode != GPEVENT_NONE));
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i]
|
||||
|| players[i].spectator)
|
||||
continue;
|
||||
|
||||
// Battle powerstone win
|
||||
if ((gametyperules & GTR_POWERSTONES)
|
||||
&& ALLCHAOSEMERALDS(players[i].emeralds))
|
||||
break;
|
||||
|
||||
// Special round?
|
||||
if (((gametyperules & GTR_SPECIALSTART)
|
||||
|| (grandprixinfo.gp == true
|
||||
&& grandprixinfo.eventmode == GPEVENT_SPECIAL)
|
||||
) == false)
|
||||
continue;
|
||||
|
||||
// Any player has completed well?
|
||||
if (!players[i].exiting
|
||||
|| players[i].bot
|
||||
|| K_IsPlayerLosing(&players[i]))
|
||||
continue;
|
||||
|
||||
// Special win
|
||||
break;
|
||||
}
|
||||
|
||||
// Event - Emerald Finish
|
||||
if (i != MAXPLAYERS)
|
||||
{
|
||||
jingle = "EMRLD";
|
||||
goto skippingposition;
|
||||
}
|
||||
|
||||
// Event - Level Finish
|
||||
// Check for if this is valid or not
|
||||
for (i = 0; i <= r_splitscreen; i++)
|
||||
|
|
@ -756,10 +793,6 @@ void P_EndingMusic(void)
|
|||
}
|
||||
}
|
||||
|
||||
// See G_DoCompleted and Y_DetermineIntermissionType
|
||||
nointer = ((modeattacking && (players[consoleplayer].pflags & PF_NOCONTEST))
|
||||
|| (grandprixinfo.gp == true && grandprixinfo.eventmode != GPEVENT_NONE));
|
||||
|
||||
if (bestPlayer == NULL)
|
||||
{
|
||||
// No jingle for you
|
||||
|
|
@ -798,6 +831,8 @@ void P_EndingMusic(void)
|
|||
}
|
||||
}
|
||||
|
||||
skippingposition:
|
||||
|
||||
if (nointer == true)
|
||||
{
|
||||
// Do not set "racent" in G_Ticker
|
||||
|
|
|
|||
|
|
@ -1189,6 +1189,13 @@ sfxinfo_t S_sfx[NUMSFX] =
|
|||
{"iwhp", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Instawhip attack
|
||||
{"gbrk", false, 255, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Guard break!
|
||||
|
||||
// Super Flicky Power-Up
|
||||
{"supflk", false, 255, 32, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Woodpecking - SF_NOINTERRUPT
|
||||
{"fbost1", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Slowing down
|
||||
{"fbird", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Speeding up
|
||||
{"fhurt1", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Whipped
|
||||
{"fhurt2", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Hunting
|
||||
|
||||
// SRB2Kart - Engine sounds
|
||||
// Engine class A
|
||||
{"krta00", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
|
|
|
|||
|
|
@ -1258,6 +1258,12 @@ typedef enum
|
|||
sfx_iwhp,
|
||||
sfx_gbrk,
|
||||
|
||||
sfx_supflk,
|
||||
sfx_fbost1,
|
||||
sfx_fbird,
|
||||
sfx_fhurt1,
|
||||
sfx_fhurt2,
|
||||
|
||||
// Next up: UNIQUE ENGINE SOUNDS! Hoooooo boy...
|
||||
// Engine class A - Low Speed, Low Weight
|
||||
sfx_krta00,
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ TYPEDEF (botvars_t);
|
|||
TYPEDEF (roundconditions_t);
|
||||
TYPEDEF (skybox_t);
|
||||
TYPEDEF (itemroulette_t);
|
||||
TYPEDEF (powerupvars_t);
|
||||
TYPEDEF (altview_t);
|
||||
TYPEDEF (player_t);
|
||||
|
||||
|
|
|
|||
|
|
@ -2286,7 +2286,7 @@ void V_DrawStringScaled(
|
|||
break;
|
||||
case LSHI_FONT:
|
||||
case LSLOW_FONT:
|
||||
spacew = 16;
|
||||
spacew = 10;
|
||||
break;
|
||||
case OPPRF_FONT:
|
||||
spacew = 5;
|
||||
|
|
@ -2579,7 +2579,7 @@ fixed_t V_StringScaledWidth(
|
|||
break;
|
||||
case LSHI_FONT:
|
||||
case LSLOW_FONT:
|
||||
spacew = 16;
|
||||
spacew = 10;
|
||||
break;
|
||||
case OPPRF_FONT:
|
||||
spacew = 5;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue