Merge branch 'master' into just-tumble

This commit is contained in:
Sally Coolatta 2021-01-06 23:02:51 -05:00
commit cfda66103d
53 changed files with 3056 additions and 1685 deletions

View file

@ -546,6 +546,7 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i)
// Score is resynched in the rspfirm resync packet
rsp->rings = SHORT(players[i].rings);
rsp->spheres = SHORT(players[i].spheres);
rsp->lives = players[i].lives;
rsp->lostlife = players[i].lostlife;
rsp->continues = players[i].continues;
@ -615,6 +616,15 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i)
rsp->kartstuff[j] = LONG(players[i].kartstuff[j]);
rsp->airtime = (tic_t)LONG(players[i].airtime);
rsp->trickpanel = (UINT8)players[i].trickpanel;
rsp->trickdelay = (boolean)players[i].trickdelay;
rsp->trickmomx = (fixed_t)LONG(players[i].trickmomx);
rsp->trickmomy = (fixed_t)LONG(players[i].trickmomy);
rsp->trickmomz = (fixed_t)LONG(players[i].trickmomz);
rsp->bumpers = players[i].bumpers;
rsp->karmadelay = SHORT(players[i].karmadelay);
rsp->eliminated = players[i].eliminated;
rsp->tumbleBounces = players[i].tumbleBounces;
rsp->tumbleHeight = SHORT(players[i].tumbleHeight);
@ -694,6 +704,7 @@ static void resynch_read_player(resynch_pak *rsp)
// Score is resynched in the rspfirm resync packet
players[i].rings = SHORT(rsp->rings);
players[i].spheres = SHORT(rsp->spheres);
players[i].lives = rsp->lives;
players[i].lostlife = rsp->lostlife;
players[i].continues = rsp->continues;
@ -762,6 +773,15 @@ static void resynch_read_player(resynch_pak *rsp)
players[i].kartstuff[j] = LONG(rsp->kartstuff[j]);
players[i].airtime = (tic_t)LONG(rsp->airtime);
players[i].trickpanel = (UINT8)rsp->trickpanel;
players[i].trickdelay = (boolean)rsp->trickdelay;
players[i].trickmomx = (fixed_t)LONG(rsp->trickmomx);
players[i].trickmomy = (fixed_t)LONG(rsp->trickmomy);
players[i].trickmomz = (fixed_t)LONG(rsp->trickmomz);
players[i].bumpers = rsp->bumpers;
players[i].karmadelay = SHORT(rsp->karmadelay);
players[i].eliminated = rsp->eliminated;
players[i].tumbleBounces = rsp->tumbleBounces;
players[i].tumbleHeight = SHORT(rsp->tumbleHeight);
@ -1254,7 +1274,7 @@ static inline void CL_DrawConnectionStatus(void)
cltext = M_GetText("Server full, waiting for a slot...");
else
cltext = M_GetText("Requesting to join...");
break;
#ifdef HAVE_CURL
case CL_PREPAREHTTPFILES:
@ -2123,7 +2143,7 @@ void CL_UpdateServerList (void)
static void M_ConfirmConnect(event_t *ev)
{
#ifndef NONET
#ifndef NONET
if (ev->type == ev_keydown)
{
if (ev->data1 == ' ' || ev->data1 == 'y' || ev->data1 == KEY_ENTER || ev->data1 == gamecontrol[0][gc_accelerate][0] || ev->data1 == gamecontrol[0][gc_accelerate][1])
@ -2146,7 +2166,7 @@ static void M_ConfirmConnect(event_t *ev)
}
else
cl_mode = CL_LOADFILES;
M_ClearMenus(true);
}
else if (ev->data1 == 'n' || ev->data1 == KEY_ESCAPE|| ev->data1 == gamecontrol[0][gc_brake][0] || ev->data1 == gamecontrol[0][gc_brake][1])
@ -2394,7 +2414,7 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
{
boolean waitmore;
INT32 i;
#ifdef NONET
(void)tmpsave;
#endif
@ -2431,7 +2451,7 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
{
curl_transfers++;
}
cl_mode = CL_DOWNLOADHTTPFILES;
}
break;
@ -2996,9 +3016,7 @@ void CL_RemovePlayer(INT32 playernum, kickreason_t reason)
}
}
if (K_IsPlayerWanted(&players[playernum]))
K_CalculateBattleWanted();
K_CalculateBattleWanted();
LUAh_PlayerQuit(&players[playernum], reason); // Lua hook for player quitting
// don't look through someone's view who isn't there

View file

@ -214,6 +214,7 @@ typedef struct
// Score is resynched in the confirm resync packet
INT16 rings;
INT16 spheres;
SINT8 lives;
boolean lostlife;
SINT8 continues;
@ -280,6 +281,15 @@ typedef struct
// SRB2kart
INT32 kartstuff[NUMKARTSTUFF];
tic_t airtime;
UINT8 trickpanel;
boolean trickdelay;
fixed_t trickmomx;
fixed_t trickmomy;
fixed_t trickmomz;
UINT8 bumpers;
INT16 karmadelay;
boolean eliminated;
UINT8 tumbleBounces;
UINT16 tumbleHeight;

View file

@ -1494,6 +1494,11 @@ void D_SRB2Main(void)
CON_Init();
memset(timelimits, 0, sizeof(timelimits));
memset(pointlimits, 0, sizeof(pointlimits));
timelimits[GT_BATTLE] = 2;
D_RegisterServerCommands();
D_RegisterClientCommands(); // be sure that this is called before D_CheckNetGame
R_RegisterEngineStuff();

View file

@ -289,10 +289,10 @@ consvar_t cv_skin[MAXSPLITSCREENPLAYERS] = {
// player's followers. Also saved.
consvar_t cv_follower[MAXSPLITSCREENPLAYERS] = {
CVAR_INIT ("follower", "-1", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Follower_OnChange),
CVAR_INIT ("follower2", "-1", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Follower2_OnChange),
CVAR_INIT ("follower3", "-1", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Follower3_OnChange),
CVAR_INIT ("follower4", "-1", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Follower4_OnChange)
CVAR_INIT ("follower", "None", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Follower_OnChange),
CVAR_INIT ("follower2", "None", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Follower2_OnChange),
CVAR_INIT ("follower3", "None", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Follower3_OnChange),
CVAR_INIT ("follower4", "None", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Follower4_OnChange)
};
// player's follower colors... Also saved...
@ -454,8 +454,7 @@ consvar_t cv_scrambleonchange = CVAR_INIT ("scrambleonchange", "Off", CV_SAVE|CV
consvar_t cv_itemfinder = CVAR_INIT ("itemfinder", "Off", CV_CALL|CV_NOSHOWHELP, CV_OnOff, ItemFinder_OnChange);
// Scoring type options
static CV_PossibleValue_t overtime_cons_t[] = {{0, "No"}, {1, "Yes"}, {2, "Super"}, {0, NULL}};
consvar_t cv_overtime = CVAR_INIT ("overtime", "Yes", CV_NETVAR|CV_CHEAT, overtime_cons_t, NULL);
consvar_t cv_overtime = CVAR_INIT ("overtime", "Yes", CV_NETVAR|CV_CHEAT, CV_YesNo, NULL);
consvar_t cv_rollingdemos = CVAR_INIT ("rollingdemos", "On", CV_SAVE, CV_OnOff, NULL);
@ -463,9 +462,9 @@ static CV_PossibleValue_t pointlimit_cons_t[] = {{1, "MIN"}, {MAXSCORE, "MAX"},
consvar_t cv_pointlimit = CVAR_INIT ("pointlimit", "None", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT, pointlimit_cons_t, PointLimit_OnChange);
static CV_PossibleValue_t timelimit_cons_t[] = {{1, "MIN"}, {30, "MAX"}, {0, "None"}, {0, NULL}};
consvar_t cv_timelimit = CVAR_INIT ("timelimit", "None", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT, timelimit_cons_t, TimeLimit_OnChange);
static CV_PossibleValue_t numlaps_cons_t[] = {{1, "MIN"}, {50, "MAX"}, {0, NULL}};
consvar_t cv_numlaps = CVAR_INIT ("numlaps", "4", CV_NETVAR|CV_CALL|CV_NOINIT, numlaps_cons_t, NumLaps_OnChange);
static CV_PossibleValue_t basenumlaps_cons_t[] = {{1, "MIN"}, {50, "MAX"}, {0, "Map default"}, {0, NULL}};
static CV_PossibleValue_t numlaps_cons_t[] = {{1, "MIN"}, {99, "MAX"}, {0, NULL}};
consvar_t cv_numlaps = CVAR_INIT ("numlaps", "3", CV_NETVAR|CV_CALL|CV_NOINIT, numlaps_cons_t, NumLaps_OnChange);
static CV_PossibleValue_t basenumlaps_cons_t[] = {{1, "MIN"}, {99, "MAX"}, {0, "Map default"}, {0, NULL}};
consvar_t cv_basenumlaps = CVAR_INIT ("basenumlaps", "Map default", CV_SAVE|CV_NETVAR|CV_CALL|CV_CHEAT, basenumlaps_cons_t, BaseNumLaps_OnChange);
// Point and time limits for every gametype
@ -2859,13 +2858,6 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum)
memset(&luabanks, 0, sizeof(luabanks));
}
if (modeattacking)
{
SetPlayerSkinByNum(0, cv_chooseskin.value-1);
players[0].skincolor = skins[players[0].skin].prefcolor;
CV_StealthSetValue(&cv_playercolor[0], players[0].skincolor);
}
mapnumber = M_MapNumber(mapname[3], mapname[4]);
LUAh_MapChange(mapnumber);
@ -3475,8 +3467,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
if (gametyperules & GTR_BUMPERS) // SRB2kart
{
players[playernum].marescore = 0;
if (K_IsPlayerWanted(&players[playernum]))
K_CalculateBattleWanted();
K_CalculateBattleWanted();
}
K_PlayerForfeit(playernum, true);
@ -4335,15 +4326,13 @@ static void TimeLimit_OnChange(void)
if (cv_timelimit.value != 0)
{
CONS_Printf(M_GetText("Levels will end after %d second%s.\n"),cv_timelimit.value,cv_timelimit.value == 1 ? "" : "s"); // Graue 11-17-2003
timelimitintics = cv_timelimit.value * TICRATE;
CONS_Printf(M_GetText("Rounds will end after %d minute%s.\n"),cv_timelimit.value,cv_timelimit.value == 1 ? "" : "s"); // Graue 11-17-2003
timelimitintics = cv_timelimit.value * (60*TICRATE);
// Note the deliberate absence of any code preventing
// pointlimit and timelimit from being set simultaneously.
// Some people might like to use them together. It works.
}
else if (netgame || multiplayer)
CONS_Printf(M_GetText("Time limit disabled\n"));
#ifdef HAVE_DISCORDRPC
DRPC_UpdatePresence();

View file

@ -336,7 +336,7 @@ typedef enum
k_sparkleanim, // Angle offset for ring sparkle animation
k_jmp, // In Mario Kart, letting go of the jump button stops the drift
k_offroad, // In Super Mario Kart, going offroad has lee-way of about 1 second before you start losing speed
k_pogospring, // Pogo spring bounce effect
k_brakestop, // Wait until you've made a complete stop for a few tics before letting brake go in reverse.
k_spindash, // Spindash charge timer
k_spindashspeed, // Spindash release speed
k_spindashboost, // Spindash release boost timer
@ -450,6 +450,10 @@ typedef enum
// QUICKLY GET RING TOTAL, INCLUDING RINGS CURRENTLY IN THE PICKUP ANIMATION
#define RINGTOTAL(p) (p->rings + p->kartstuff[k_pickuprings])
// CONSTANTS FOR TRICK PANELS
#define TRICKMOMZRAMP (30)
#define TRICKLAG (9)
//}
// player_t struct for all respawn variables
@ -513,6 +517,7 @@ typedef struct player_s
// player's ring count
INT16 rings;
INT16 spheres;
// Power ups. invinc and invis are tic counters.
UINT16 powers[NUMPOWERS];
@ -523,7 +528,18 @@ typedef struct player_s
UINT32 distancetofinish;
waypoint_t *nextwaypoint;
respawnvars_t respawn; // Respawn info
tic_t airtime; // Keep track of how long you've been in the air
tic_t airtime; // Keep track of how long you've been in the air
UINT8 trickpanel; // Trick panel state
boolean trickdelay; // Prevent tricks until control stick is neutral
fixed_t trickmomx;
fixed_t trickmomy;
fixed_t trickmomz; // Instead of stupid auxiliary variables let's... just make some ourselves.
UINT8 bumpers;
INT16 karmadelay;
boolean eliminated;
// Bit flags.
// See pflags_t, above.

View file

@ -1271,8 +1271,6 @@ static void readspriteframe(MYFILE *f, spriteinfo_t *sprinfo, UINT8 frame)
sprinfo->pivot[frame].x = value;
else if (fastcmp(word, "YPIVOT"))
sprinfo->pivot[frame].y = value;
else if (fastcmp(word, "ROTAXIS"))
sprinfo->pivot[frame].rotaxis = value;
else
{
f->curpos = lastline;
@ -6174,10 +6172,43 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_FASTRING11",
"S_FASTRING12",
// Blue Sphere for special stages
// Blue Sphere
"S_BLUESPHERE",
"S_BLUESPHEREBONUS",
"S_BLUESPHERESPARK",
"S_BLUESPHERE_SPAWN",
"S_BLUESPHERE_BOUNCE1",
"S_BLUESPHERE_BOUNCE2",
"S_BLUESPHERE_BOUNCE3",
"S_BLUESPHERE_BOUNCE4",
"S_BLUESPHERE_BOUNCE5",
"S_BLUESPHERE_BOUNCE6",
"S_BLUESPHERE_BOUNCE7",
"S_BLUESPHERE_BOUNCE8",
"S_BLUESPHERE_BOUNCE9",
"S_BLUESPHERE_BOUNCE10",
"S_BLUESPHERE_BOUNCE11",
"S_BLUESPHERE_BOUNCE12",
"S_BLUESPHERE_BOUNCE13",
"S_BLUESPHERE_BOUNCE14",
"S_BLUESPHERE_BOUNCE15",
"S_BLUESPHERE_BOUNCE16",
"S_BLUESPHERE_BOUNCE17",
"S_BLUESPHERE_BOUNCE18",
"S_BLUESPHERE_BOUNCE19",
"S_BLUESPHERE_BOUNCE20",
"S_BLUESPHERE_BOUNCE21",
"S_BLUESPHERE_BOUNCE22",
"S_BLUESPHERE_BOUNCE23",
"S_BLUESPHERE_BOUNCE24",
"S_BLUESPHERE_BOUNCE25",
"S_BLUESPHERE_BOUNCE26",
"S_BLUESPHERE_BOUNCE27",
"S_BLUESPHERE_BOUNCE28",
// Bomb Sphere
"S_BOMBSPHERE1",
@ -6236,13 +6267,17 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_EMBLEM26",
// Chaos Emeralds
"S_CEMG1",
"S_CEMG2",
"S_CEMG3",
"S_CEMG4",
"S_CEMG5",
"S_CEMG6",
"S_CEMG7",
"S_CHAOSEMERALD1",
"S_CHAOSEMERALD2",
"S_CHAOSEMERALD_UNDER",
"S_EMERALDSPARK1",
"S_EMERALDSPARK2",
"S_EMERALDSPARK3",
"S_EMERALDSPARK4",
"S_EMERALDSPARK5",
"S_EMERALDSPARK6",
"S_EMERALDSPARK7",
// Emerald hunt shards
"S_SHRD1",
@ -8691,6 +8726,44 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_BATTLEBUMPER2",
"S_BATTLEBUMPER3",
"S_BATTLEBUMPER_EXCRYSTALA1",
"S_BATTLEBUMPER_EXCRYSTALA2",
"S_BATTLEBUMPER_EXCRYSTALA3",
"S_BATTLEBUMPER_EXCRYSTALA4",
"S_BATTLEBUMPER_EXCRYSTALB1",
"S_BATTLEBUMPER_EXCRYSTALB2",
"S_BATTLEBUMPER_EXCRYSTALB3",
"S_BATTLEBUMPER_EXCRYSTALB4",
"S_BATTLEBUMPER_EXCRYSTALC1",
"S_BATTLEBUMPER_EXCRYSTALC2",
"S_BATTLEBUMPER_EXCRYSTALC3",
"S_BATTLEBUMPER_EXCRYSTALC4",
"S_BATTLEBUMPER_EXSHELLA1",
"S_BATTLEBUMPER_EXSHELLA2",
"S_BATTLEBUMPER_EXSHELLB1",
"S_BATTLEBUMPER_EXSHELLB2",
"S_BATTLEBUMPER_EXSHELLC1",
"S_BATTLEBUMPER_EXSHELLC2",
"S_BATTLEBUMPER_EXDEBRIS1",
"S_BATTLEBUMPER_EXDEBRIS2",
"S_BATTLEBUMPER_EXBLAST1",
"S_BATTLEBUMPER_EXBLAST2",
"S_BATTLEBUMPER_EXBLAST3",
"S_BATTLEBUMPER_EXBLAST4",
"S_BATTLEBUMPER_EXBLAST5",
"S_BATTLEBUMPER_EXBLAST6",
"S_BATTLEBUMPER_EXBLAST7",
"S_BATTLEBUMPER_EXBLAST8",
"S_BATTLEBUMPER_EXBLAST9",
"S_BATTLEBUMPER_EXBLAST10",
// DEZ respawn laser
"S_DEZLASER",
"S_DEZLASER_TRAIL1",
@ -9291,9 +9364,10 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_TIREGREASE",
"S_OVERTIMEFOG",
"S_OVERTIMEORB",
"S_OVERTIMEBEAM",
"S_OVERTIME_BULB1",
"S_OVERTIME_BULB2",
"S_OVERTIME_LASER",
"S_OVERTIME_CENTER",
"S_BATTLECAPSULE_SIDE1",
"S_BATTLECAPSULE_SIDE2",
@ -9472,16 +9546,10 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_REDFLAG", // Red CTF Flag
"MT_BLUEFLAG", // Blue CTF Flag
"MT_EMBLEM",
"MT_EMERALD1",
"MT_EMERALD2",
"MT_EMERALD3",
"MT_EMERALD4",
"MT_EMERALD5",
"MT_EMERALD6",
"MT_EMERALD7",
"MT_EMERALD",
"MT_EMERALDSPARK",
"MT_EMERHUNT", // Emerald Hunt
"MT_EMERALDSPAWN", // Emerald spawner w/ delay
"MT_FLINGEMERALD", // Lost emerald
// Springs and others
"MT_FAN",
@ -10178,6 +10246,8 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_SINKTRAIL",
"MT_BATTLEBUMPER", // Battle Mode bumper
"MT_BATTLEBUMPER_DEBRIS",
"MT_BATTLEBUMPER_BLAST",
"MT_DEZLASER",
@ -10392,9 +10462,8 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_SPBDUST",
"MT_TIREGREASE",
"MT_OVERTIMEFOG",
"MT_OVERTIMEORB",
"MT_OVERTIMEBEAM",
"MT_OVERTIME_PARTICLE",
"MT_OVERTIME_CENTER",
"MT_BATTLECAPSULE",
"MT_BATTLECAPSULE_PIECE",
@ -10409,6 +10478,8 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_SPINDASHDUST",
"MT_SPINDASHWIND",
"MT_PAPERITEMSPOT",
#ifdef SEENAMES
"MT_NAMECHECK",
#endif
@ -10729,67 +10800,67 @@ static const char *COLOR_ENUMS[] = { // Rejigged for Kart.
// Special super colors
// Super Sonic Yellow
"SUPER1", // SKINCOLOR_SUPER1
"SUPER2", // SKINCOLOR_SUPER2,
"SUPER3", // SKINCOLOR_SUPER3,
"SUPER4", // SKINCOLOR_SUPER4,
"SUPER5", // SKINCOLOR_SUPER5,
"SUPERSILVER1",
"SUPERSILVER2",
"SUPERSILVER3",
"SUPERSILVER4",
"SUPERSILVER5",
// Super Tails Orange
"TSUPER1", // SKINCOLOR_TSUPER1,
"TSUPER2", // SKINCOLOR_TSUPER2,
"TSUPER3", // SKINCOLOR_TSUPER3,
"TSUPER4", // SKINCOLOR_TSUPER4,
"TSUPER5", // SKINCOLOR_TSUPER5,
"SUPERRED1",
"SUPERRED2",
"SUPERRED3",
"SUPERRED4",
"SUPERRED5",
// Super Knuckles Red
"KSUPER1", // SKINCOLOR_KSUPER1,
"KSUPER2", // SKINCOLOR_KSUPER2,
"KSUPER3", // SKINCOLOR_KSUPER3,
"KSUPER4", // SKINCOLOR_KSUPER4,
"KSUPER5", // SKINCOLOR_KSUPER5,
"SUPERORANGE1",
"SUPERORANGE2",
"SUPERORANGE3",
"SUPERORANGE4",
"SUPERORANGE5",
// Hyper Sonic Pink
"PSUPER1", // SKINCOLOR_PSUPER1,
"PSUPER2", // SKINCOLOR_PSUPER2,
"PSUPER3", // SKINCOLOR_PSUPER3,
"PSUPER4", // SKINCOLOR_PSUPER4,
"PSUPER5", // SKINCOLOR_PSUPER5,
"SUPERGOLD1",
"SUPERGOLD2",
"SUPERGOLD3",
"SUPERGOLD4",
"SUPERGOLD5",
// Hyper Sonic Blue
"BSUPER1", // SKINCOLOR_BSUPER1,
"BSUPER2", // SKINCOLOR_BSUPER2,
"BSUPER3", // SKINCOLOR_BSUPER3,
"BSUPER4", // SKINCOLOR_BSUPER4,
"BSUPER5", // SKINCOLOR_BSUPER5,
"SUPERPERIDOT1",
"SUPERPERIDOT2",
"SUPERPERIDOT3",
"SUPERPERIDOT4",
"SUPERPERIDOT5",
// Aqua Super
"ASUPER1", // SKINCOLOR_ASUPER1,
"ASUPER2", // SKINCOLOR_ASUPER2,
"ASUPER3", // SKINCOLOR_ASUPER3,
"ASUPER4", // SKINCOLOR_ASUPER4,
"ASUPER5", // SKINCOLOR_ASUPER5,
"SUPERSKY1",
"SUPERSKY2",
"SUPERSKY3",
"SUPERSKY4",
"SUPERSKY5",
// Hyper Sonic Green
"GSUPER1", // SKINCOLOR_GSUPER1,
"GSUPER2", // SKINCOLOR_GSUPER2,
"GSUPER3", // SKINCOLOR_GSUPER3,
"GSUPER4", // SKINCOLOR_GSUPER4,
"GSUPER5", // SKINCOLOR_GSUPER5,
"SUPERPURPLE1",
"SUPERPURPLE2",
"SUPERPURPLE3",
"SUPERPURPLE4",
"SUPERPURPLE5",
// Hyper Sonic White
"WSUPER1", // SKINCOLOR_WSUPER1,
"WSUPER2", // SKINCOLOR_WSUPER2,
"WSUPER3", // SKINCOLOR_WSUPER3,
"WSUPER4", // SKINCOLOR_WSUPER4,
"WSUPER5", // SKINCOLOR_WSUPER5,
"SUPERRUST1",
"SUPERRUST2",
"SUPERRUST3",
"SUPERRUST4",
"SUPERRUST5",
// Creamy Super (Shadow?)
"CSUPER1", // SKINCOLOR_CSUPER1,
"CSUPER2", // SKINCOLOR_CSUPER2,
"CSUPER3", // SKINCOLOR_CSUPER3,
"CSUPER4", // SKINCOLOR_CSUPER4,
"CSUPER5" // SKINCOLOR_CSUPER5,
"SUPERTAN1",
"SUPERTAN2",
"SUPERTAN3",
"SUPERTAN4",
"SUPERTAN5",
"CHAOSEMERALD1",
"CHAOSEMERALD2",
"CHAOSEMERALD3",
"CHAOSEMERALD4",
"CHAOSEMERALD5",
"CHAOSEMERALD6",
"CHAOSEMERALD7"
};
static const char *const POWERS_LIST[] = {
@ -10863,7 +10934,7 @@ static const char *const KARTSTUFF_LIST[] = {
"SPARKLEANIM",
"JMP",
"OFFROAD",
"POGOSPRING",
"BRAKESTOP",
"SPINDASH",
"SPINDASHSPEED",
"SPINDASHBOOST",
@ -11181,13 +11252,23 @@ struct {
{"LF2_VISITNEEDED",LF2_VISITNEEDED},
// Emeralds
{"EMERALD1",EMERALD1},
{"EMERALD2",EMERALD2},
{"EMERALD3",EMERALD3},
{"EMERALD4",EMERALD4},
{"EMERALD5",EMERALD5},
{"EMERALD6",EMERALD6},
{"EMERALD7",EMERALD7},
{"EMERALD_CHAOS1",EMERALD_CHAOS1},
{"EMERALD_CHAOS2",EMERALD_CHAOS2},
{"EMERALD_CHAOS3",EMERALD_CHAOS3},
{"EMERALD_CHAOS4",EMERALD_CHAOS4},
{"EMERALD_CHAOS5",EMERALD_CHAOS5},
{"EMERALD_CHAOS6",EMERALD_CHAOS6},
{"EMERALD_CHAOS7",EMERALD_CHAOS7},
{"EMERALD_ALLCHAOS",EMERALD_ALLCHAOS},
{"EMERALD_SUPER1",EMERALD_SUPER1},
{"EMERALD_SUPER2",EMERALD_SUPER2},
{"EMERALD_SUPER3",EMERALD_SUPER3},
{"EMERALD_SUPER4",EMERALD_SUPER4},
{"EMERALD_SUPER5",EMERALD_SUPER5},
{"EMERALD_SUPER6",EMERALD_SUPER6},
{"EMERALD_SUPER7",EMERALD_SUPER7},
{"EMERALD_ALLSUPER",EMERALD_ALLSUPER},
{"EMERALD_ALL",EMERALD_ALL},
// SKINCOLOR_ doesn't include these..!
{"MAXSKINCOLORS",MAXSKINCOLORS},
@ -11281,6 +11362,7 @@ struct {
{"DMG_EXPLODE",DMG_EXPLODE},
{"DMG_TUMBLE",DMG_TUMBLE},
{"DMG_STING",DMG_STING},
{"DMG_KARMA",DMG_KARMA},
//// Death types
{"DMG_INSTAKILL",DMG_INSTAKILL},
{"DMG_DEATHPIT",DMG_DEATHPIT},
@ -11492,11 +11574,6 @@ struct {
{"DI_SOUTHEAST",DI_SOUTHEAST},
{"NUMDIRS",NUMDIRS},
// Sprite rotation axis (rotaxis_t)
{"ROTAXIS_X",ROTAXIS_X},
{"ROTAXIS_Y",ROTAXIS_Y},
{"ROTAXIS_Z",ROTAXIS_Z},
// Buttons (ticcmd_t) // SRB2kart
{"BT_ACCELERATE",BT_ACCELERATE},
{"BT_DRIFT",BT_DRIFT},

View file

@ -386,6 +386,14 @@ typedef enum
SKINCOLOR_SUPERTAN4,
SKINCOLOR_SUPERTAN5,
SKINCOLOR_CHAOSEMERALD1,
SKINCOLOR_CHAOSEMERALD2,
SKINCOLOR_CHAOSEMERALD3,
SKINCOLOR_CHAOSEMERALD4,
SKINCOLOR_CHAOSEMERALD5,
SKINCOLOR_CHAOSEMERALD6,
SKINCOLOR_CHAOSEMERALD7,
SKINCOLOR_FIRSTFREESLOT,
SKINCOLOR_LASTFREESLOT = SKINCOLOR_FIRSTFREESLOT + NUMCOLORFREESLOTS - 1,
@ -661,10 +669,6 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
/// Render flats on walls
#define WALLFLATS
/// - SRB2Kart options -
/// Camera always has noclip.
#define NOCLIPCAM
/// Divide volume of music and sounds by this much (loudest sounds on earth)
#define VOLUME_DIVIDER 4
#define USER_VOLUME_SCALE 2
@ -682,4 +686,11 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
#undef UPDATE_ALERT
#endif
/// - SRB2Kart options -
/// Camera always has noclip.
#define NOCLIPCAM
/// Other karma comeback modes
//#define OTHERKARMAMODES
#endif // __DOOMDEF__

View file

@ -456,30 +456,31 @@ enum GameTypeRules
{
// Race rules
GTR_CIRCUIT = 1, // Enables the finish line, laps, and the waypoint system.
GTR_RINGS = 1<<1, // Rings will be spawned in this mode. (Don't get too cheeky, ring sting is still enabled :])
GTR_BOTS = 1<<2, // Allows bots in this gametype. Combine with BotTiccmd hooks to make bots support your gametype.
// Battle gametype rules
GTR_BUMPERS = 1<<3, // Enables the bumper health system
GTR_WANTED = 1<<4, // Enables the wanted anti-camping system
GTR_KARMA = 1<<5, // Enables the Karma system if you're out of bumpers
GTR_ITEMARROWS = 1<<6, // Show item box arrows above players
GTR_CAPSULES = 1<<7, // Enables the wanted anti-camping system
GTR_BATTLESTARTS = 1<<8, // Use Battle Mode start positions.
GTR_SPHERES = 1<<4, // Replaces rings with blue spheres
GTR_PAPERITEMS = 1<<5, // Replaces item boxes with paper item spawners
GTR_WANTED = 1<<6, // Enables the wanted anti-camping system
GTR_KARMA = 1<<7, // Enables the Karma system if you're out of bumpers
GTR_ITEMARROWS = 1<<8, // Show item box arrows above players
GTR_CAPSULES = 1<<9, // Enables the wanted anti-camping system
GTR_BATTLESTARTS = 1<<10, // Use Battle Mode start positions.
GTR_POINTLIMIT = 1<<9, // Reaching point limit ends the round
GTR_TIMELIMIT = 1<<10, // Reaching time limit ends the round
GTR_OVERTIME = 1<<11, // Allow overtime behavior
GTR_POINTLIMIT = 1<<11, // Reaching point limit ends the round
GTR_TIMELIMIT = 1<<12, // Reaching time limit ends the round
GTR_OVERTIME = 1<<13, // Allow overtime behavior
// Custom gametype rules
GTR_TEAMS = 1<<12, // Teams are forced on
GTR_NOTEAMS = 1<<13, // Teams are forced off
GTR_TEAMSTARTS = 1<<14, // Use team-based start positions
GTR_TEAMS = 1<<14, // Teams are forced on
GTR_NOTEAMS = 1<<15, // Teams are forced off
GTR_TEAMSTARTS = 1<<16, // Use team-based start positions
// Grand Prix rules
GTR_CAMPAIGN = 1<<15, // Handles cup-based progression
GTR_LIVES = 1<<16, // Lives system, players are forced to spectate during Game Over.
GTR_SPECIALBOTS = 1<<17, // Bot difficulty gets stronger between rounds, and the rival system is enabled.
GTR_CAMPAIGN = 1<<17, // Handles cup-based progression
GTR_LIVES = 1<<18, // Lives system, players are forced to spectate during Game Over.
GTR_SPECIALBOTS = 1<<19, // Bot difficulty gets stronger between rounds, and the rival system is enabled.
// free: to and including 1<<31
};
@ -521,15 +522,34 @@ extern UINT32 matchesplayed;
extern UINT8 stagefailed;
// Emeralds stored as bits to throw savegame hackers off.
typedef enum
{
EMERALD_CHAOS1 = 1,
EMERALD_CHAOS2 = 1<<1,
EMERALD_CHAOS3 = 1<<2,
EMERALD_CHAOS4 = 1<<3,
EMERALD_CHAOS5 = 1<<4,
EMERALD_CHAOS6 = 1<<5,
EMERALD_CHAOS7 = 1<<6,
EMERALD_ALLCHAOS = EMERALD_CHAOS1|EMERALD_CHAOS2|EMERALD_CHAOS3|EMERALD_CHAOS4|EMERALD_CHAOS5|EMERALD_CHAOS6|EMERALD_CHAOS7,
EMERALD_SUPER1 = 1<<7,
EMERALD_SUPER2 = 1<<8,
EMERALD_SUPER3 = 1<<9,
EMERALD_SUPER4 = 1<<10,
EMERALD_SUPER5 = 1<<11,
EMERALD_SUPER6 = 1<<12,
EMERALD_SUPER7 = 1<<13,
EMERALD_ALLSUPER = EMERALD_SUPER1|EMERALD_SUPER2|EMERALD_SUPER3|EMERALD_SUPER4|EMERALD_SUPER5|EMERALD_SUPER6|EMERALD_SUPER7,
EMERALD_ALL = EMERALD_ALLCHAOS|EMERALD_ALLSUPER
} emeraldflags_t;
extern UINT16 emeralds;
#define EMERALD1 1
#define EMERALD2 2
#define EMERALD3 4
#define EMERALD4 8
#define EMERALD5 16
#define EMERALD6 32
#define EMERALD7 64
#define ALL7EMERALDS(v) ((v & (EMERALD1|EMERALD2|EMERALD3|EMERALD4|EMERALD5|EMERALD6|EMERALD7)) == (EMERALD1|EMERALD2|EMERALD3|EMERALD4|EMERALD5|EMERALD6|EMERALD7))
#define ALLCHAOSEMERALDS(v) ((v & EMERALD_ALLCHAOS) == EMERALD_ALLCHAOS)
#define ALLSUPEREMERALDS(v) ((v & EMERALD_ALLSUPER) == EMERALD_ALLSUPER)
#define ALLEMERALDS(v) ((v & EMERALD_ALL) == EMERALD_ALL)
#define NUM_LUABANKS 16 // please only make this number go up between versions, never down. you'll break saves otherwise. also, must fit in UINT8
extern INT32 luabanks[NUM_LUABANKS];

View file

@ -889,7 +889,7 @@ void F_StartGameEvaluation(void)
// Just in case they're open ... somehow
M_ClearMenus(true);
goodending = (ALL7EMERALDS(emeralds));
goodending = (ALLCHAOSEMERALDS(emeralds));
gameaction = ga_nothing;
paused = false;
@ -1154,7 +1154,7 @@ static void F_CacheEnding(void)
endescp[4] = W_CachePatchName("ENDESCP4", PU_PATCH);
// so we only need to check once
if ((goodending = ALL7EMERALDS(emeralds)))
if ((goodending = ALLCHAOSEMERALDS(emeralds)))
{
endfwrk[0] = W_CachePatchName("ENDFWRK3", PU_PATCH);
endfwrk[1] = W_CachePatchName("ENDFWRK4", PU_PATCH);

View file

@ -104,7 +104,7 @@ demoghost *ghosts = NULL;
// DEMO RECORDING
//
#define DEMOVERSION 0x0004
#define DEMOVERSION 0x0007
#define DEMOHEADER "\xF0" "KartReplay" "\x0F"
#define DF_GHOST 0x01 // This demo contains ghost data too!
@ -112,7 +112,7 @@ demoghost *ghosts = NULL;
#define DF_BREAKTHECAPSULES 0x04 // This demo is from Break the Capsules and contains its final completion time!
#define DF_ATTACKMASK 0x06 // This demo is from ??? attack and contains ???
#define DF_LUAVARS 0x20 // this demo contains extra lua vars; this is mostly used for backwards compability
#define DF_LUAVARS 0x20 // this demo contains extra lua vars
#define DF_ATTACKSHIFT 1
#define DF_ENCORE 0x40
@ -419,7 +419,10 @@ void G_WriteDemoExtraData(void)
{
// write follower
memset(name, 0, 16);
strncpy(name, followers[players[i].followerskin].skinname, 16);
if (players[i].followerskin == -1)
strncpy(name, "None", 16);
else
strncpy(name, followers[players[i].followerskin].skinname, 16);
M_Memcpy(demo_p, name, 16);
demo_p += 16;
@ -619,13 +622,21 @@ void G_WriteAllGhostTics(void)
counter++;
if (counter % cv_netdemosyncquality.value != 0) // Only write 1 in this many ghost datas per tic to cut down on multiplayer replay size.
if (multiplayer && ((counter % cv_netdemosyncquality.value) != 0)) // Only write 1 in this many ghost datas per tic to cut down on multiplayer replay size.
continue;
WRITEUINT8(demo_p, i);
G_WriteGhostTic(players[i].mo, i);
}
WRITEUINT8(demo_p, 0xFF);
// attention here for the ticcmd size!
// latest demos with mouse aiming byte in ticcmd
if (demo_p >= demoend - (13 + 9 + 9))
{
G_CheckDemoStatus(); // no more space
return;
}
}
void G_WriteGhostTic(mobj_t *ghost, INT32 playernum)
@ -722,26 +733,22 @@ void G_WriteGhostTic(mobj_t *ghost, INT32 playernum)
ghostext[playernum].flags |= EZT_SPRITE;
}
if (ghost->player && (
ghostext[playernum].kartitem != ghost->player->kartstuff[k_itemtype] ||
ghostext[playernum].kartamount != ghost->player->kartstuff[k_itemamount] ||
ghostext[playernum].kartbumpers != ghost->player->kartstuff[k_bumper]
))
{
ghostext[playernum].flags |= EZT_KART;
ghostext[playernum].kartitem = ghost->player->kartstuff[k_itemtype];
ghostext[playernum].kartamount = ghost->player->kartstuff[k_itemamount];
ghostext[playernum].kartbumpers = ghost->player->kartstuff[k_bumper];
}
if (ghostext[playernum].flags)
{
ziptic |= GZT_EXTRA;
if (ghost->player)
{
if (
ghostext[playernum].kartitem != ghost->player->kartstuff[k_itemtype] ||
ghostext[playernum].kartamount != ghost->player->kartstuff[k_itemamount] ||
ghostext[playernum].kartbumpers != ghost->player->kartstuff[k_bumper]
)
{
ghostext[playernum].flags |= EZT_KART;
ghostext[playernum].kartitem = ghost->player->kartstuff[k_itemtype];
ghostext[playernum].kartamount = ghost->player->kartstuff[k_itemamount];
ghostext[playernum].kartbumpers = ghost->player->kartstuff[k_bumper];
}
}
if (ghostext[playernum].color == ghostext[playernum].lastcolor)
ghostext[playernum].flags &= ~EZT_COLOR;
if (ghostext[playernum].scale == ghostext[playernum].lastscale)
@ -836,14 +843,6 @@ void G_WriteGhostTic(mobj_t *ghost, INT32 playernum)
oldghost[playernum].flags2 &= ~MF2_AMBUSH;
*ziptic_p = ziptic;
// attention here for the ticcmd size!
// latest demos with mouse aiming byte in ticcmd
if (demo_p >= demoend - (13 + 9 + 9))
{
G_CheckDemoStatus(); // no more space
return;
}
}
void G_ConsAllGhostTics(void)
@ -1067,16 +1066,18 @@ void G_GhostTicker(void)
if (ziptic & DXD_FOLLOWER)
g->p += 32; // ok (32 because there's both the skin and the colour)
if (ziptic & DXD_PLAYSTATE && READUINT8(g->p) != DXD_PST_PLAYING)
I_Error("Ghost is not a record attack ghost"); //@TODO lmao don't blow up like this
I_Error("Ghost is not a record attack ghost PLAYSTATE"); //@TODO lmao don't blow up like this
}
else if (ziptic == DW_RNG)
g->p += 4; // RNG seed
else
I_Error("Ghost is not a record attack ghost"); //@TODO lmao don't blow up like this
I_Error("Ghost is not a record attack ghost DXD"); //@TODO lmao don't blow up like this
ziptic = READUINT8(g->p);
}
ziptic = READUINT8(g->p);
if (ziptic & ZT_FWD)
g->p++;
if (ziptic & ZT_TURNING)
@ -1086,9 +1087,9 @@ void G_GhostTicker(void)
if (ziptic & ZT_AIMING)
g->p += 2;
if (ziptic & ZT_LATENCY)
g->p += 1;
g->p++;
if (ziptic & ZT_FLAGS)
g->p += 1;
g->p++;
// Grab ghost data.
ziptic = READUINT8(g->p);
@ -1096,7 +1097,7 @@ void G_GhostTicker(void)
if (ziptic == 0xFF)
goto skippedghosttic; // Didn't write ghost info this frame
else if (ziptic != 0)
I_Error("Ghost is not a record attack ghost"); //@TODO lmao don't blow up like this
I_Error("Ghost is not a record attack ghost ZIPTIC"); //@TODO lmao don't blow up like this
ziptic = READUINT8(g->p);
if (ziptic & GZT_XYZ)
@ -1109,17 +1110,17 @@ void G_GhostTicker(void)
{
if (ziptic & GZT_MOMXY)
{
g->oldmo.momx = (g->version < 0x000e) ? READINT16(g->p)<<8 : READFIXED(g->p);
g->oldmo.momy = (g->version < 0x000e) ? READINT16(g->p)<<8 : READFIXED(g->p);
g->oldmo.momx = READFIXED(g->p);
g->oldmo.momy = READFIXED(g->p);
}
if (ziptic & GZT_MOMZ)
g->oldmo.momz = (g->version < 0x000e) ? READINT16(g->p)<<8 : READFIXED(g->p);
g->oldmo.momz = READFIXED(g->p);
g->oldmo.x += g->oldmo.momx;
g->oldmo.y += g->oldmo.momy;
g->oldmo.z += g->oldmo.momz;
}
if (ziptic & GZT_ANGLE)
g->mo->angle = READUINT8(g->p)<<24;
g->oldmo.angle = READUINT8(g->p)<<24;
if (ziptic & GZT_FRAME)
g->oldmo.frame = READUINT8(g->p);
if (ziptic & GZT_SPR2)
@ -1205,30 +1206,6 @@ void G_GhostTicker(void)
g->p += 12; // kartitem, kartamount, kartbumpers
}
if (READUINT8(g->p) != 0xFF) // Make sure there isn't other ghost data here.
I_Error("Ghost is not a record attack ghost"); //@TODO lmao don't blow up like this
skippedghosttic:
// Tick ghost colors (Super and Mario Invincibility flashing)
switch(g->color)
{
case GHC_SUPER: // Super (P_DoSuperStuff)
if (g->mo->skin)
{
skin_t *skin = (skin_t *)g->mo->skin;
g->mo->color = skin->supercolor;
}
else
g->mo->color = SKINCOLOR_SUPERGOLD1;
g->mo->color += abs( ( (signed)( (unsigned)leveltime >> 1 ) % 9) - 4);
break;
case GHC_INVINCIBLE: // Mario invincibility (P_CheckInvincibilityTimer)
g->mo->color = (UINT16)(SKINCOLOR_RUBY + (leveltime % (FIRSTSUPERCOLOR - SKINCOLOR_RUBY))); // Passes through all saturated colours
break;
default:
break;
}
#define follow g->mo->tracer
if (ziptic & GZT_FOLLOW)
{ // Even more...
@ -1294,6 +1271,31 @@ skippedghosttic:
P_RemoveMobj(follow);
P_SetTarget(&follow, NULL);
}
skippedghosttic:
// Tick ghost colors (Super and Mario Invincibility flashing)
switch(g->color)
{
case GHC_SUPER: // Super (P_DoSuperStuff)
if (g->mo->skin)
{
skin_t *skin = (skin_t *)g->mo->skin;
g->mo->color = skin->supercolor;
}
else
g->mo->color = SKINCOLOR_SUPERGOLD1;
g->mo->color += abs( ( (signed)( (unsigned)leveltime >> 1 ) % 9) - 4);
break;
case GHC_INVINCIBLE: // Mario invincibility (P_CheckInvincibilityTimer)
g->mo->color = (UINT16)(SKINCOLOR_RUBY + (leveltime % (FIRSTSUPERCOLOR - SKINCOLOR_RUBY))); // Passes through all saturated colours
break;
default:
break;
}
if (READUINT8(g->p) != 0xFF) // Make sure there isn't other ghost data here.
I_Error("Ghost is not a record attack ghost GHOSTEND"); //@TODO lmao don't blow up like this
// Demo ends after ghost data.
if (*g->p == DEMOMARKER)
{
@ -1314,6 +1316,7 @@ skippedghosttic:
Z_Free(g);
continue;
}
p = g;
#undef follow
}
@ -1436,8 +1439,11 @@ void G_PreviewRewind(tic_t previewtime)
players[i].drawangle = info->playerinfo[i].player.drawangle + FixedMul((INT32) (next_info->playerinfo[i].player.drawangle - info->playerinfo[i].player.drawangle), tweenvalue);
players[i].mo->sprite = info->playerinfo[i].mobj.sprite;
players[i].mo->sprite2 = info->playerinfo[i].mobj.sprite2;
players[i].mo->frame = info->playerinfo[i].mobj.frame;
players[i].mo->hitlag = info->playerinfo[i].mobj.hitlag;
players[i].realtime = info->playerinfo[i].player.realtime;
for (j = 0; j < NUMKARTSTUFF; j++)
players[i].kartstuff[j] = info->playerinfo[i].player.kartstuff[j];
@ -1462,7 +1468,7 @@ void G_ConfirmRewind(tic_t rewindtime)
if (rewindtime <= starttime)
{
demo.rewinding = false;
demo.rewinding = true; // this doesn't APPEAR to cause any misery, and it allows us to prevent running all the wipes again
G_DoPlayDemo(NULL); // Restart the current demo
}
else
@ -1899,7 +1905,8 @@ void G_BeginRecording(void)
if (encoremode)
demoflags |= DF_ENCORE;
demoflags |= DF_LUAVARS;
if (multiplayer)
demoflags |= DF_LUAVARS;
// Setup header.
M_Memcpy(demo_p, DEMOHEADER, 12); demo_p += 12;
@ -2033,9 +2040,8 @@ void G_BeginRecording(void)
WRITEUINT8(demo_p, 0xFF); // Denote the end of the player listing
// player lua vars, always saved even if empty
LUA_Archive(&demo_p);
WRITEUINT32(demo_p,P_GetInitSeed());
if (demoflags & DF_LUAVARS)
LUA_Archive(&demo_p);
memset(&oldcmd,0,sizeof(oldcmd));
memset(&oldghost,0,sizeof(oldghost));
@ -2712,7 +2718,6 @@ void G_DoPlayDemo(char *defdemoname)
demo.version = READUINT16(demo_p);
switch(demo.version)
{
case 0x000d:
case DEMOVERSION: // latest always supported
break;
// too old, cannot support.
@ -3101,7 +3106,6 @@ void G_AddGhost(char *defdemoname)
ghostversion = READUINT16(p);
switch(ghostversion)
{
case 0x000d:
case DEMOVERSION: // latest always supported
break;
// too old, cannot support.
@ -3145,6 +3149,14 @@ void G_AddGhost(char *defdemoname)
return;
}
if (flags & DF_LUAVARS) // can't be arsed to add support for grinding away ported lua material
{
CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Replay data contains luavars, cannot continue.\n"), pdemoname);
Z_Free(pdemoname);
Z_Free(buffer);
return;
}
p++; // gametype
G_SkipDemoExtraFiles(&p); // Don't wanna modify the file list for ghosts.
@ -3211,6 +3223,8 @@ void G_AddGhost(char *defdemoname)
kartspeed = READUINT8(p);
kartweight = READUINT8(p);
p += 4; // followitem (maybe change later)
if (READUINT8(p) != 0xFF)
{
CONS_Alert(CONS_NOTICE, M_GetText("Failed to add ghost %s: Invalid player slot.\n"), pdemoname);

View file

@ -1252,7 +1252,7 @@ void G_StartTitleCard(void)
{
// The title card has been disabled for this map.
// Oh well.
if (!G_IsTitleCardAvailable())
if (!G_IsTitleCardAvailable() || demo.rewinding)
{
WipeStageTitle = false;
return;
@ -1575,7 +1575,7 @@ boolean G_CouldView(INT32 playernum)
// I don't know if we want this actually, but I'll humor the suggestion anyway
if ((gametyperules & GTR_BUMPERS) && !demo.playback)
{
if (player->kartstuff[k_bumper] <= 0)
if (player->bumpers <= 0)
return false;
}
@ -2056,6 +2056,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
UINT8 botdifficulty;
INT16 rings;
INT16 spheres;
angle_t playerangleturn;
UINT8 botdiffincrease;
@ -2071,9 +2072,9 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
INT32 roulettetype;
INT32 growshrinktimer;
INT32 bumper;
INT32 comebackpoints;
INT32 wanted;
boolean songcredit = false;
boolean eliminated;
score = players[player].score;
marescore = players[player].marescore;
@ -2139,8 +2140,9 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
itemamount = 0;
growshrinktimer = 0;
bumper = ((gametyperules & GTR_BUMPERS) ? K_StartingBumperCount() : 0);
rings = ((gametyperules & GTR_RINGS) ? 5 : 0);
comebackpoints = 0;
rings = ((gametyperules & GTR_SPHERES) ? 0 : 5);
spheres = 0;
eliminated = false;
wanted = 0;
}
else
@ -2165,9 +2167,10 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
else
growshrinktimer = 0;
bumper = players[player].kartstuff[k_bumper];
bumper = players[player].bumpers;
rings = players[player].rings;
comebackpoints = players[player].kartstuff[k_comebackpoints];
spheres = players[player].spheres;
eliminated = players[player].eliminated;
wanted = players[player].kartstuff[k_wanted];
}
@ -2215,6 +2218,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
p->bot = bot;
p->botvars.difficulty = botdifficulty;
p->rings = rings;
p->spheres = spheres;
p->botvars.diffincrease = botdiffincrease;
p->botvars.rival = botrival;
p->xtralife = xtralife;
@ -2225,9 +2229,9 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
p->kartstuff[k_itemtype] = itemtype;
p->kartstuff[k_itemamount] = itemamount;
p->kartstuff[k_growshrinktimer] = growshrinktimer;
p->kartstuff[k_bumper] = bumper;
p->kartstuff[k_comebackpoints] = comebackpoints;
p->kartstuff[k_comebacktimer] = comebacktime;
p->bumpers = bumper;
p->karmadelay = comebacktime;
p->eliminated = eliminated;
p->kartstuff[k_wanted] = wanted;
p->kartstuff[k_eggmanblame] = -1;
p->kartstuff[k_lastdraft] = -1;
@ -2787,9 +2791,9 @@ const char *Gametype_ConstantNames[NUMGAMETYPES] =
UINT32 gametypedefaultrules[NUMGAMETYPES] =
{
// Race
GTR_CIRCUIT|GTR_RINGS|GTR_BOTS,
GTR_CIRCUIT|GTR_BOTS,
// Battle
GTR_BUMPERS|GTR_WANTED|GTR_KARMA|GTR_ITEMARROWS|GTR_CAPSULES|GTR_BATTLESTARTS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_OVERTIME
GTR_SPHERES|GTR_BUMPERS|GTR_PAPERITEMS|GTR_WANTED|GTR_KARMA|GTR_ITEMARROWS|GTR_CAPSULES|GTR_BATTLESTARTS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_OVERTIME
};
//

View file

@ -101,21 +101,13 @@ typedef struct
//Hurdler: Transform (coords + angles)
//BP: transform order : scale(rotation_x(rotation_y(translation(v))))
// Kart features
//#define USE_FTRANSFORM_ANGLEZ
//#define USE_FTRANSFORM_MIRROR
// Vanilla features
#define USE_MODEL_NEXTFRAME
typedef struct
{
FLOAT x,y,z; // position
#ifdef USE_FTRANSFORM_ANGLEZ
FLOAT anglex,angley,anglez; // aimingangle / viewangle
#else
FLOAT anglex,angley; // aimingangle / viewangle
#endif
FLOAT scalex,scaley,scalez;
FLOAT fovxangle, fovyangle;
UINT8 splitscreen;
@ -123,13 +115,10 @@ typedef struct
boolean shearing; // 14042019
angle_t viewaiming; // 17052019
boolean roll;
SINT8 rollflip;
FLOAT rollangle; // done to not override USE_FTRANSFORM_ANGLEZ
UINT8 rotaxis;
FLOAT centerx, centery;
#ifdef USE_FTRANSFORM_MIRROR
FLOAT rollx, rollz;
boolean mirror; // SRB2Kart: Encore Mode
#endif
} FTransform;
// Transformed vector, as passed to HWR API

View file

@ -50,7 +50,7 @@ EXPORT void HWRAPI(ClearMipMapCache) (void);
EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value);
//Hurdler: added for new development
EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface);
EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface, FBITFIELD blendmode);
EXPORT void HWRAPI(CreateModelVBOs) (model_t *model);
EXPORT void HWRAPI(SetTransform) (FTransform *stransform);
EXPORT INT32 HWRAPI(GetTextureUsed) (void);

View file

@ -4905,6 +4905,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
#ifdef ROTSPRITE
patch_t *rotsprite = NULL;
INT32 rollangle = 0;
angle_t spriterotangle = 0;
#endif
if (!thing)
@ -5043,9 +5044,11 @@ static void HWR_ProjectSprite(mobj_t *thing)
spr_topoffset = spritecachedinfo[lumpoff].topoffset;
#ifdef ROTSPRITE
if (thing->rollangle)
spriterotangle = R_SpriteRotationAngle(thing);
if (spriterotangle != 0)
{
rollangle = R_GetRollAngle(thing->rollangle);
rollangle = R_GetRollAngle(spriterotangle);
if (!(sprframe->rotsprite.cached & (1<<rot)))
R_CacheRotSprite(thing->sprite, (thing->frame & FF_FRAMEMASK), sprinfo, sprframe, rot, flip);
rotsprite = sprframe->rotsprite.patch[rot][rollangle];
@ -5526,6 +5529,8 @@ static void HWR_DrawSkyBackground(player_t *player)
fixed_t rol = AngleFixed(player->viewrollangle);
dometransform.rollangle = FIXED_TO_FLOAT(rol);
dometransform.roll = true;
dometransform.rollx = 1.0f;
dometransform.rollz = 0.0f;
}
dometransform.splitscreen = r_splitscreen;
@ -5804,6 +5809,8 @@ void HWR_RenderSkyboxView(player_t *player)
fixed_t rol = AngleFixed(player->viewrollangle);
atransform.rollangle = FIXED_TO_FLOAT(rol);
atransform.roll = true;
atransform.rollx = 1.0f;
atransform.rollz = 0.0f;
}
atransform.splitscreen = r_splitscreen;
@ -6005,6 +6012,8 @@ void HWR_RenderPlayerView(void)
fixed_t rol = AngleFixed(player->viewrollangle);
atransform.rollangle = FIXED_TO_FLOAT(rol);
atransform.roll = true;
atransform.rollx = 1.0f;
atransform.rollz = 0.0f;
}
atransform.splitscreen = r_splitscreen;

View file

@ -1353,10 +1353,9 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
const UINT8 hflip = (UINT8)(!(spr->mobj->mirrored) != !(spr->mobj->frame & FF_HORIZONTALFLIP));
spritedef_t *sprdef;
spriteframe_t *sprframe;
spriteinfo_t *sprinfo;
angle_t ang;
INT32 mod;
float finalscale;
FBITFIELD blendmode = PF_Masked;
// hitlag vibrating
if (spr->mobj->hitlag > 0)
@ -1378,12 +1377,17 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
//durs = tics;
if (spr->mobj->drawflags & MFD_TRANSMASK)
HWR_TranstableToAlpha((spr->mobj->drawflags & MFD_TRANSMASK)>>MFD_TRANSSHIFT, &Surf);
blendmode = HWR_TranstableToAlpha((spr->mobj->drawflags & MFD_TRANSMASK)>>MFD_TRANSSHIFT, &Surf);
else if (spr->mobj->frame & FF_TRANSMASK)
HWR_TranstableToAlpha((spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf);
blendmode = HWR_TranstableToAlpha((spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf);
else
Surf.PolyColor.s.alpha = 0xFF;
if (blendmode == PF_Masked)
{
blendmode |= PF_Occlude;
}
// dont forget to enabled the depth test because we can't do this like
// before: polygons models are not sorted
@ -1393,12 +1397,10 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
{
md2 = &md2_playermodels[(skin_t*)spr->mobj->skin-skins];
md2->skin = (skin_t*)spr->mobj->skin-skins;
sprinfo = &((skin_t *)spr->mobj->skin)->sprinfo[spr->mobj->sprite2];
}
else
{
md2 = &md2_models[spr->mobj->sprite];
sprinfo = &spriteinfo[spr->mobj->sprite];
}
// texture loading before model init, so it knows if sprite graphics are used, which
@ -1593,60 +1595,35 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
}
p.rollangle = 0.0f;
p.rollflip = 1;
p.rotaxis = 0;
if (spr->mobj->rollangle)
{
fixed_t camAngleDiff = AngleFixed(viewangle) - FLOAT_TO_FIXED(p.angley); // dumb reconversion back, I know
fixed_t anglef = AngleFixed(spr->mobj->rollangle);
p.rollangle = FIXED_TO_FLOAT(anglef);
p.roll = true;
// rotation pivot
p.centerx = FIXED_TO_FLOAT(spr->mobj->radius/2);
p.centery = FIXED_TO_FLOAT(spr->mobj->height/(flip ? -2 : 2));
p.centerx = FIXED_TO_FLOAT(spr->mobj->radius / 2);
p.centery = FIXED_TO_FLOAT(spr->mobj->height / 2);
// rotation axis
if (sprinfo->available)
p.rotaxis = (UINT8)(sprinfo->pivot[(spr->mobj->frame & FF_FRAMEMASK)].rotaxis);
// for NiGHTS specifically but should work everywhere else
ang = R_PointToAngle (spr->mobj->x, spr->mobj->y) - (spr->mobj->player ? spr->mobj->player->drawangle : spr->mobj->angle);
if ((sprframe->rotate & SRF_RIGHT) && (ang < ANGLE_180)) // See from right
p.rollflip = 1;
else if ((sprframe->rotate & SRF_LEFT) && (ang >= ANGLE_180)) // See from left
p.rollflip = -1;
if (flip)
p.rollflip *= -1;
// rotation axes relative to camera
p.rollx = FIXED_TO_FLOAT(FINECOSINE(FixedAngle(camAngleDiff) >> ANGLETOFINESHIFT));
p.rollz = FIXED_TO_FLOAT(FINESINE(FixedAngle(camAngleDiff) >> ANGLETOFINESHIFT));
}
p.anglex = 0.0f;
#ifdef USE_FTRANSFORM_ANGLEZ
// Slope rotation from Kart
p.anglez = 0.0f;
if (spr->mobj->standingslope)
{
fixed_t tempz = spr->mobj->standingslope->normal.z;
fixed_t tempy = spr->mobj->standingslope->normal.y;
fixed_t tempx = spr->mobj->standingslope->normal.x;
fixed_t tempangle = AngleFixed(R_PointToAngle2(0, 0, FixedSqrt(FixedMul(tempy, tempy) + FixedMul(tempz, tempz)), tempx));
p.anglez = FIXED_TO_FLOAT(tempangle);
tempangle = -AngleFixed(R_PointToAngle2(0, 0, tempz, tempy));
p.anglex = FIXED_TO_FLOAT(tempangle);
}
#endif
p.anglez = FIXED_TO_FLOAT(AngleFixed(spr->mobj->pitch));
p.anglex = FIXED_TO_FLOAT(AngleFixed(spr->mobj->roll));
// SRB2CBTODO: MD2 scaling support
finalscale *= FIXED_TO_FLOAT(spr->mobj->scale);
p.flip = atransform.flip;
#ifdef USE_FTRANSFORM_MIRROR
p.mirror = atransform.mirror; // from Kart
#endif
p.mirror = atransform.mirror;
HWD.pfnSetShader(SHADER_MODEL); // model shader
HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, finalscale, flip, hflip, &Surf);
HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, finalscale, flip, hflip, &Surf, blendmode);
}
return true;

View file

@ -2513,7 +2513,7 @@ EXPORT void HWRAPI(CreateModelVBOs) (model_t *model)
#define BUFFER_OFFSET(i) ((void*)(i))
static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface)
static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface, FBITFIELD blendmode)
{
static GLRGBAFloat poly = {0,0,0,0};
static GLRGBAFloat tint = {0,0,0,0};
@ -2593,7 +2593,7 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32
else
pglColor4ubv((GLubyte*)&Surface->PolyColor.s);
SetBlend((poly.alpha < 1 ? PF_Translucent : (PF_Masked|PF_Occlude))|PF_Modulated);
SetBlend(blendmode|PF_Modulated);
tint.red = byte2float[Surface->TintColor.s.red];
tint.green = byte2float[Surface->TintColor.s.green];
@ -2610,7 +2610,6 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32
pglEnable(GL_CULL_FACE);
pglEnable(GL_NORMALIZE);
#ifdef USE_FTRANSFORM_MIRROR
// flipped is if the object is vertically flipped
// hflipped is if the object is horizontally flipped
// pos->flip is if the screen is flipped vertically
@ -2623,17 +2622,6 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32
else
pglCullFace(GL_BACK);
}
#else
// pos->flip is if the screen is flipped too
if (flipped ^ hflipped ^ pos->flip) // If one or three of these are active, but not two, invert the model's culling
{
pglCullFace(GL_FRONT);
}
else
{
pglCullFace(GL_BACK);
}
#endif
pglPushMatrix(); // should be the same as glLoadIdentity
//Hurdler: now it seems to work
@ -2643,22 +2631,14 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32
if (hflipped)
scalez = -scalez;
#ifdef USE_FTRANSFORM_ANGLEZ
pglRotatef(pos->anglez, 0.0f, 0.0f, -1.0f); // rotate by slope from Kart
#endif
pglRotatef(pos->angley, 0.0f, -1.0f, 0.0f);
pglRotatef(pos->anglez, 0.0f, 0.0f, -1.0f);
pglRotatef(pos->anglex, 1.0f, 0.0f, 0.0f);
pglRotatef(pos->angley, 0.0f, -1.0f, 0.0f);
if (pos->roll)
{
float roll = (1.0f * pos->rollflip);
pglTranslatef(pos->centerx, pos->centery, 0);
if (pos->rotaxis == 2) // Z
pglRotatef(pos->rollangle, 0.0f, 0.0f, roll);
else if (pos->rotaxis == 1) // Y
pglRotatef(pos->rollangle, 0.0f, roll, 0.0f);
else // X
pglRotatef(pos->rollangle, roll, 0.0f, 0.0f);
pglRotatef(pos->rollangle, pos->rollx, 0.0f, pos->rollz);
pglTranslatef(-pos->centerx, -pos->centery, 0);
}
@ -2812,9 +2792,9 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32
// -----------------+
// HWRAPI DrawModel : Draw a model
// -----------------+
EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface)
EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface, FBITFIELD blendmode)
{
DrawModelEx(model, frameIndex, duration, tics, nextFrameIndex, pos, scale, flipped, hflipped, Surface);
DrawModelEx(model, frameIndex, duration, tics, nextFrameIndex, pos, scale, flipped, hflipped, Surface, blendmode);
}
// -----------------+
@ -2831,13 +2811,9 @@ EXPORT void HWRAPI(SetTransform) (FTransform *stransform)
if (stransform)
{
used_fov = stransform->fovxangle;
#ifdef USE_FTRANSFORM_MIRROR
// mirroring from Kart
if (stransform->mirror)
pglScalef(-stransform->scalex, stransform->scaley, -stransform->scalez);
else
#endif
if (stransform->flip)
else if (stransform->flip)
pglScalef(stransform->scalex, -stransform->scaley, -stransform->scalez);
else
pglScalef(stransform->scalex, stransform->scaley, -stransform->scalez);

View file

@ -135,11 +135,12 @@ char sprnames[NUMSPRITES + 1][5] =
"TOKE", // Special Stage Token
"RFLG", // Red CTF Flag
"BFLG", // Blue CTF Flag
//"SPHR", // Sphere
"BSPH", // Sphere
"NCHP", // NiGHTS chip
"NSTR", // NiGHTS star
"EMBM", // Emblem
"CEMG", // Chaos Emeralds
"EMRC", // Chaos Emeralds
"ESPK",
"SHRD", // Emerald Hunt
// Interactive Objects
@ -558,6 +559,10 @@ char sprnames[NUMSPRITES + 1][5] =
"SINK", // Kitchen Sink
"SITR", // Kitchen Sink Trail
"KBLN", // Battle Mode Bumper
"BEXC", // Battle Bumper Explosion: Crystal
"BEXS", // Battle Bumper Explosion: Shell
"BDEB", // Battle Bumper Explosion: Debris
"BEXB", // Battle Bumper Explosion: Blast
"DEZL", // DEZ Laser respawn
@ -714,7 +719,9 @@ char sprnames[NUMSPRITES + 1][5] =
"DRAF",
"GRES",
"OTFG",
"OTBU",
"OTLS",
"OTCP",
"DBOS", // Drift boost flame
@ -1803,20 +1810,49 @@ state_t states[NUMSTATES] =
{SPR_RING, 20, 1, {NULL}, 0, 0, S_FASTRING12}, // S_FASTRING11
{SPR_RING, 22, 1, {NULL}, 0, 0, S_FASTRING1}, // S_FASTRING12
// Blue Sphere for special stages
{SPR_SPHR, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_BLUESPHERE
{SPR_SPHR, FF_FULLBRIGHT
#ifdef MANIASPHERES
|FF_ANIMATE|FF_RANDOMANIM
#endif
, -1, {NULL}, 1, 4, S_NULL}, // S_BLUESPHEREBONUS
{SPR_SPHR, 0, 20, {NULL}, 0, 0, S_NULL}, // S_BLUESPHERESPARK
// Blue Sphere
{SPR_BSPH, FF_SEMIBRIGHT|2, TICRATE, {NULL}, 0, 0, S_BLUESPHERE_BOUNCE1}, // S_BLUESPHERE
{SPR_BSPH, FF_SEMIBRIGHT|2, TICRATE, {A_SetRandomTics}, 1, TICRATE, S_BLUESPHERE_BOUNCE1}, // S_BLUESPHERE_SPAWN
{SPR_BSPH, FF_SEMIBRIGHT, 1, {NULL}, 0, 0, S_BLUESPHERE_BOUNCE2}, // S_BLUESPHERE_BOUNCE1
{SPR_BSPH, FF_SEMIBRIGHT|4, 1, {NULL}, 0, 0, S_BLUESPHERE_BOUNCE3}, // S_BLUESPHERE_BOUNCE2
{SPR_BSPH, FF_SEMIBRIGHT, 1, {NULL}, 0, 0, S_BLUESPHERE_BOUNCE4}, // S_BLUESPHERE_BOUNCE3
{SPR_BSPH, FF_SEMIBRIGHT|4, 1, {NULL}, 0, 0, S_BLUESPHERE_BOUNCE5}, // S_BLUESPHERE_BOUNCE4
{SPR_BSPH, FF_SEMIBRIGHT, 1, {NULL}, 0, 0, S_BLUESPHERE_BOUNCE6}, // S_BLUESPHERE_BOUNCE5
{SPR_BSPH, FF_SEMIBRIGHT|2, 1, {NULL}, 0, 0, S_BLUESPHERE_BOUNCE7}, // S_BLUESPHERE_BOUNCE6
{SPR_BSPH, FF_SEMIBRIGHT|4, 1, {NULL}, 0, 0, S_BLUESPHERE_BOUNCE8}, // S_BLUESPHERE_BOUNCE7
{SPR_BSPH, FF_SEMIBRIGHT|2, 1, {NULL}, 0, 0, S_BLUESPHERE_BOUNCE9}, // S_BLUESPHERE_BOUNCE8
{SPR_BSPH, FF_SEMIBRIGHT, 1, {NULL}, 0, 0, S_BLUESPHERE_BOUNCE10}, // S_BLUESPHERE_BOUNCE9
{SPR_BSPH, FF_SEMIBRIGHT|2, 1, {NULL}, 0, 0, S_BLUESPHERE_BOUNCE11}, // S_BLUESPHERE_BOUNCE10
{SPR_BSPH, FF_SEMIBRIGHT|4, 1, {NULL}, 0, 0, S_BLUESPHERE_BOUNCE12}, // S_BLUESPHERE_BOUNCE11
{SPR_BSPH, FF_SEMIBRIGHT|2, 1, {NULL}, 0, 0, S_BLUESPHERE_BOUNCE13}, // S_BLUESPHERE_BOUNCE12
{SPR_BSPH, FF_SEMIBRIGHT, 2, {NULL}, 0, 0, S_BLUESPHERE_BOUNCE14}, // S_BLUESPHERE_BOUNCE13
{SPR_BSPH, FF_SEMIBRIGHT|1, 2, {NULL}, 0, 0, S_BLUESPHERE_BOUNCE15}, // S_BLUESPHERE_BOUNCE14
{SPR_BSPH, FF_SEMIBRIGHT|2, 2, {NULL}, 0, 0, S_BLUESPHERE_BOUNCE16}, // S_BLUESPHERE_BOUNCE15
{SPR_BSPH, FF_SEMIBRIGHT|3, 2, {NULL}, 0, 0, S_BLUESPHERE_BOUNCE17}, // S_BLUESPHERE_BOUNCE16
{SPR_BSPH, FF_SEMIBRIGHT|4, 2, {NULL}, 0, 0, S_BLUESPHERE_BOUNCE18}, // S_BLUESPHERE_BOUNCE17
{SPR_BSPH, FF_SEMIBRIGHT|3, 4, {NULL}, 0, 0, S_BLUESPHERE_BOUNCE19}, // S_BLUESPHERE_BOUNCE18
{SPR_BSPH, FF_SEMIBRIGHT|2, 4, {NULL}, 0, 0, S_BLUESPHERE_BOUNCE20}, // S_BLUESPHERE_BOUNCE19
{SPR_BSPH, FF_SEMIBRIGHT|1, 4, {NULL}, 0, 0, S_BLUESPHERE_BOUNCE21}, // S_BLUESPHERE_BOUNCE20
{SPR_BSPH, FF_SEMIBRIGHT, 6, {NULL}, 0, 0, S_BLUESPHERE_BOUNCE22}, // S_BLUESPHERE_BOUNCE21
{SPR_BSPH, FF_SEMIBRIGHT|1, 6, {NULL}, 0, 0, S_BLUESPHERE_BOUNCE23}, // S_BLUESPHERE_BOUNCE22
{SPR_BSPH, FF_SEMIBRIGHT|2, 6, {NULL}, 0, 0, S_BLUESPHERE_BOUNCE24}, // S_BLUESPHERE_BOUNCE23
{SPR_BSPH, FF_SEMIBRIGHT|3, 9, {NULL}, 0, 0, S_BLUESPHERE_BOUNCE25}, // S_BLUESPHERE_BOUNCE24
{SPR_BSPH, FF_SEMIBRIGHT|4, 9, {NULL}, 0, 0, S_BLUESPHERE_BOUNCE26}, // S_BLUESPHERE_BOUNCE25
{SPR_BSPH, FF_SEMIBRIGHT|3, 9, {NULL}, 0, 0, S_BLUESPHERE_BOUNCE27}, // S_BLUESPHERE_BOUNCE26
{SPR_BSPH, FF_SEMIBRIGHT|2, 9, {NULL}, 0, 0, S_BLUESPHERE_BOUNCE28}, // S_BLUESPHERE_BOUNCE27
{SPR_BSPH, FF_SEMIBRIGHT|1, 9, {NULL}, 0, 0, S_BLUESPHERE}, // S_BLUESPHERE_BOUNCE28
// Bomb Sphere
{SPR_SPHR, FF_FULLBRIGHT|3, 2, {NULL}, 0, 0, S_BOMBSPHERE2}, // S_BOMBSPHERE1
{SPR_SPHR, FF_FULLBRIGHT|4, 1, {NULL}, 0, 0, S_BOMBSPHERE3}, // S_BOMBSPHERE2
{SPR_SPHR, FF_FULLBRIGHT|5, 2, {NULL}, 0, 0, S_BOMBSPHERE4}, // S_BOMBSPHERE3
{SPR_SPHR, FF_FULLBRIGHT|4, 1, {NULL}, 0, 0, S_BOMBSPHERE1}, // S_BOMBSPHERE4
{SPR_BSPH, FF_FULLBRIGHT|3, 2, {NULL}, 0, 0, S_BOMBSPHERE2}, // S_BOMBSPHERE1
{SPR_BSPH, FF_FULLBRIGHT|4, 1, {NULL}, 0, 0, S_BOMBSPHERE3}, // S_BOMBSPHERE2
{SPR_BSPH, FF_FULLBRIGHT|5, 2, {NULL}, 0, 0, S_BOMBSPHERE4}, // S_BOMBSPHERE3
{SPR_BSPH, FF_FULLBRIGHT|4, 1, {NULL}, 0, 0, S_BOMBSPHERE1}, // S_BOMBSPHERE4
// NiGHTS Chip
{SPR_NCHP, FF_FULLBRIGHT|FF_ANIMATE, -1, {NULL}, 15, 2, S_NULL}, // S_NIGHTSCHIP
@ -1869,13 +1905,17 @@ state_t states[NUMSTATES] =
{SPR_EMBM, 25, -1, {NULL}, 0, 0, S_NULL}, // S_EMBLEM26
// Chaos Emeralds
{SPR_CEMG, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_CEMG1
{SPR_CEMG, FF_FULLBRIGHT|1, -1, {NULL}, 0, 0, S_NULL}, // S_CEMG2
{SPR_CEMG, FF_FULLBRIGHT|2, -1, {NULL}, 0, 0, S_NULL}, // S_CEMG3
{SPR_CEMG, FF_FULLBRIGHT|3, -1, {NULL}, 0, 0, S_NULL}, // S_CEMG4
{SPR_CEMG, FF_FULLBRIGHT|4, -1, {NULL}, 0, 0, S_NULL}, // S_CEMG5
{SPR_CEMG, FF_FULLBRIGHT|5, -1, {NULL}, 0, 0, S_NULL}, // S_CEMG6
{SPR_CEMG, FF_FULLBRIGHT|6, -1, {NULL}, 0, 0, S_NULL}, // S_CEMG7
{SPR_EMRC, FF_SEMIBRIGHT, 1, {NULL}, 0, 0, S_CHAOSEMERALD2}, // S_CHAOSEMERALD1
{SPR_EMRC, FF_FULLBRIGHT|FF_TRANSADD, 1, {NULL}, 0, 0, S_CHAOSEMERALD1}, // S_CHAOSEMERALD2
{SPR_EMRC, FF_FULLBRIGHT|1, -1, {NULL}, 1, 0, S_NULL}, // S_CHAOSEMERALD_UNDER
{SPR_ESPK, FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_EMERALDSPARK2}, // S_EMERALDSPARK1
{SPR_ESPK, FF_FULLBRIGHT|1, 3, {NULL}, 0, 0, S_EMERALDSPARK3}, // S_EMERALDSPARK2
{SPR_ESPK, FF_FULLBRIGHT|2, 3, {NULL}, 0, 0, S_EMERALDSPARK4}, // S_EMERALDSPARK3
{SPR_ESPK, FF_FULLBRIGHT|3, 3, {NULL}, 0, 0, S_EMERALDSPARK5}, // S_EMERALDSPARK4
{SPR_ESPK, FF_FULLBRIGHT|4, 3, {NULL}, 0, 0, S_EMERALDSPARK6}, // S_EMERALDSPARK5
{SPR_ESPK, FF_FULLBRIGHT|5, 3, {NULL}, 0, 0, S_EMERALDSPARK7}, // S_EMERALDSPARK6
{SPR_ESPK, FF_FULLBRIGHT|6, 3, {NULL}, 0, 0, S_NULL}, // S_EMERALDSPARK7
// Emerald hunt shards
{SPR_SHRD, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SHRD1
@ -3719,14 +3759,14 @@ state_t states[NUMSTATES] =
{SPR_CAPS, 0, -1, {NULL}, 0, 0, S_NULL}, // S_EGGCAPSULE
// Orbiting Chaos Emeralds/Ideya for NiGHTS
{SPR_CEMG, FF_FULLBRIGHT, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM1}, // S_ORBITEM1
{SPR_CEMG, FF_FULLBRIGHT|1, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM2}, // S_ORBITEM2
{SPR_CEMG, FF_FULLBRIGHT|2, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM3}, // S_ORBITEM3
{SPR_CEMG, FF_FULLBRIGHT|3, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM4}, // S_ORBITEM4
{SPR_CEMG, FF_FULLBRIGHT|4, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM5}, // S_ORBITEM5
{SPR_CEMG, FF_FULLBRIGHT|5, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM6}, // S_ORBITEM6
{SPR_CEMG, FF_FULLBRIGHT|6, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM7}, // S_ORBITEM7
{SPR_CEMG, FF_FULLBRIGHT|7, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM8}, // S_ORBITEM8
{SPR_EMRC, FF_FULLBRIGHT, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM1}, // S_ORBITEM1
{SPR_EMRC, FF_FULLBRIGHT, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM2}, // S_ORBITEM2
{SPR_EMRC, FF_FULLBRIGHT, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM3}, // S_ORBITEM3
{SPR_EMRC, FF_FULLBRIGHT, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM4}, // S_ORBITEM4
{SPR_EMRC, FF_FULLBRIGHT, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM5}, // S_ORBITEM5
{SPR_EMRC, FF_FULLBRIGHT, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM6}, // S_ORBITEM6
{SPR_EMRC, FF_FULLBRIGHT, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM7}, // S_ORBITEM7
{SPR_EMRC, FF_FULLBRIGHT, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM8}, // S_ORBITEM8
{SPR_IDYA, FF_TRANS20|FF_FULLBRIGHT, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBIDYA1}, // S_ORBIDYA1
{SPR_IDYA, FF_TRANS20|FF_FULLBRIGHT|1, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBIDYA2}, // S_ORBIDYA2
{SPR_IDYA, FF_TRANS20|FF_FULLBRIGHT|2, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBIDYA3}, // S_ORBIDYA3
@ -4369,9 +4409,47 @@ state_t states[NUMSTATES] =
{SPR_SITR, 1, 5, {NULL}, 0, 0, S_SINKTRAIL3}, // S_SINKTRAIL2
{SPR_SITR, 2, 3, {NULL}, 0, 0, S_NULL}, // S_SINKTRAIL3
{SPR_KBLN, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_BATTLEBUMPER1}, // S_BATTLEBUMPER1
{SPR_KBLN, FF_FULLBRIGHT|1, -1, {NULL}, 0, 0, S_BATTLEBUMPER2}, // S_BATTLEBUMPER2
{SPR_KBLN, FF_FULLBRIGHT|2, -1, {NULL}, 0, 0, S_BATTLEBUMPER3}, // S_BATTLEBUMPER3
{SPR_KBLN, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_BATTLEBUMPER1
{SPR_KBLN, FF_FULLBRIGHT|1, -1, {NULL}, 0, 0, S_NULL}, // S_BATTLEBUMPER2
{SPR_KBLN, FF_FULLBRIGHT|2, -1, {NULL}, 0, 0, S_NULL}, // S_BATTLEBUMPER3
{SPR_BEXC, FF_SEMIBRIGHT, 1, {NULL}, 0, 0, S_BATTLEBUMPER_EXCRYSTALA2}, // S_BATTLEBUMPER_EXCRYSTALA1
{SPR_BEXC, FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_BATTLEBUMPER_EXCRYSTALA3}, // S_BATTLEBUMPER_EXCRYSTALA2
{SPR_BEXC, FF_SEMIBRIGHT, 1, {NULL}, 0, 0, S_BATTLEBUMPER_EXCRYSTALA4}, // S_BATTLEBUMPER_EXCRYSTALA3
{SPR_BEXC, FF_FULLBRIGHT|2, 1, {NULL}, 0, 0, S_BATTLEBUMPER_EXCRYSTALA1}, // S_BATTLEBUMPER_EXCRYSTALA4
{SPR_BEXC, FF_SEMIBRIGHT|3, 1, {NULL}, 0, 0, S_BATTLEBUMPER_EXCRYSTALB2}, // S_BATTLEBUMPER_EXCRYSTALB1
{SPR_BEXC, FF_FULLBRIGHT|4, 1, {NULL}, 0, 0, S_BATTLEBUMPER_EXCRYSTALB3}, // S_BATTLEBUMPER_EXCRYSTALB2
{SPR_BEXC, FF_SEMIBRIGHT|3, 1, {NULL}, 0, 0, S_BATTLEBUMPER_EXCRYSTALB4}, // S_BATTLEBUMPER_EXCRYSTALB3
{SPR_BEXC, FF_FULLBRIGHT|5, 1, {NULL}, 0, 0, S_BATTLEBUMPER_EXCRYSTALB1}, // S_BATTLEBUMPER_EXCRYSTALB4
{SPR_BEXC, FF_SEMIBRIGHT|6, 1, {NULL}, 0, 0, S_BATTLEBUMPER_EXCRYSTALC2}, // S_BATTLEBUMPER_EXCRYSTALC1
{SPR_BEXC, FF_FULLBRIGHT|7, 1, {NULL}, 0, 0, S_BATTLEBUMPER_EXCRYSTALC3}, // S_BATTLEBUMPER_EXCRYSTALC2
{SPR_BEXC, FF_SEMIBRIGHT|6, 1, {NULL}, 0, 0, S_BATTLEBUMPER_EXCRYSTALC4}, // S_BATTLEBUMPER_EXCRYSTALC3
{SPR_BEXC, FF_FULLBRIGHT|8, 1, {NULL}, 0, 0, S_BATTLEBUMPER_EXCRYSTALC1}, // S_BATTLEBUMPER_EXCRYSTALC4
{SPR_BEXS, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_BATTLEBUMPER_EXSHELLA2}, // S_BATTLEBUMPER_EXSHELLA1
{SPR_BEXS, FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_BATTLEBUMPER_EXSHELLA1}, // S_BATTLEBUMPER_EXSHELLA2
{SPR_BEXS, FF_FULLBRIGHT|2, 1, {NULL}, 0, 0, S_BATTLEBUMPER_EXSHELLB2}, // S_BATTLEBUMPER_EXSHELLB1
{SPR_BEXS, FF_FULLBRIGHT|3, 1, {NULL}, 0, 0, S_BATTLEBUMPER_EXSHELLB1}, // S_BATTLEBUMPER_EXSHELLB2
{SPR_BEXS, FF_FULLBRIGHT|4, 1, {NULL}, 0, 0, S_BATTLEBUMPER_EXSHELLC2}, // S_BATTLEBUMPER_EXSHELLC1
{SPR_BEXS, FF_FULLBRIGHT|5, 1, {NULL}, 0, 0, S_BATTLEBUMPER_EXSHELLC1}, // S_BATTLEBUMPER_EXSHELLC2
{SPR_BDEB, FF_FULLBRIGHT|FF_ANIMATE, 84, {NULL}, 13, 6, S_BATTLEBUMPER_EXDEBRIS2}, // S_BATTLEBUMPER_EXDEBRIS1
{SPR_BDEB, FF_FULLBRIGHT|13, 20, {NULL}, 0, 0, S_NULL}, // S_BATTLEBUMPER_EXDEBRIS2
{SPR_BEXB, FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {NULL}, 0, 0, S_BATTLEBUMPER_EXBLAST2}, // S_BATTLEBUMPER_EXBLAST1
{SPR_BEXB, FF_FULLBRIGHT|FF_PAPERSPRITE|FF_TRANS10, 2, {NULL}, 0, 0, S_BATTLEBUMPER_EXBLAST3}, // S_BATTLEBUMPER_EXBLAST2
{SPR_BEXB, FF_FULLBRIGHT|FF_PAPERSPRITE|FF_TRANS20, 2, {NULL}, 0, 0, S_BATTLEBUMPER_EXBLAST4}, // S_BATTLEBUMPER_EXBLAST3
{SPR_BEXB, FF_FULLBRIGHT|FF_PAPERSPRITE|FF_TRANS30, 2, {NULL}, 0, 0, S_BATTLEBUMPER_EXBLAST5}, // S_BATTLEBUMPER_EXBLAST4
{SPR_BEXB, FF_FULLBRIGHT|FF_PAPERSPRITE|FF_TRANS40, 2, {NULL}, 0, 0, S_BATTLEBUMPER_EXBLAST6}, // S_BATTLEBUMPER_EXBLAST5
{SPR_BEXB, FF_FULLBRIGHT|FF_PAPERSPRITE|FF_TRANS50, 2, {NULL}, 0, 0, S_BATTLEBUMPER_EXBLAST7}, // S_BATTLEBUMPER_EXBLAST6
{SPR_BEXB, FF_FULLBRIGHT|FF_PAPERSPRITE|FF_TRANS60, 2, {NULL}, 0, 0, S_BATTLEBUMPER_EXBLAST8}, // S_BATTLEBUMPER_EXBLAST7
{SPR_BEXB, FF_FULLBRIGHT|FF_PAPERSPRITE|FF_TRANS70, 2, {NULL}, 0, 0, S_BATTLEBUMPER_EXBLAST9}, // S_BATTLEBUMPER_EXBLAST8
{SPR_BEXB, FF_FULLBRIGHT|FF_PAPERSPRITE|FF_TRANS80, 2, {NULL}, 0, 0, S_BATTLEBUMPER_EXBLAST10}, // S_BATTLEBUMPER_EXBLAST9
{SPR_BEXB, FF_FULLBRIGHT|FF_PAPERSPRITE|FF_TRANS90, 2, {NULL}, 0, 0, S_NULL}, // S_BATTLEBUMPER_EXBLAST10
{SPR_DEZL, FF_FULLBRIGHT|FF_PAPERSPRITE, 8, {NULL}, 0, 0, S_NULL}, // S_DEZLASER
{SPR_DEZL, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_DEZLASER_TRAIL2}, // S_DEZLASER_TRAIL1
@ -5002,9 +5080,10 @@ state_t states[NUMSTATES] =
{SPR_GRES, FF_ANIMATE|FF_PAPERSPRITE, -1, {NULL}, 2, 4, S_NULL}, // S_TIREGREASE
{SPR_OTFG, FF_FULLBRIGHT|FF_TRANS50, TICRATE, {NULL}, 0, 0, S_NULL}, // S_OVERTIMEFOG
{SPR_OTFG, 2|FF_FULLBRIGHT|FF_PAPERSPRITE, 1, {NULL}, 0, 0, S_NULL}, // S_OVERTIMEORB
{SPR_OTFG, 1|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_NULL}, // S_OVERTIMEBEAM
{SPR_OTBU, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_NULL}, // S_OVERTIME_BULB1
{SPR_OTBU, FF_FULLBRIGHT|2, 1, {NULL}, 0, 0, S_NULL}, // S_OVERTIME_BULB2
{SPR_OTLS, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_NULL}, // S_OVERTIME_LASER
{SPR_OTCP, 0, -1, {NULL}, 0, 0, S_NULL}, // S_OVERTIME_CENTER
{SPR_CAPS, FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_BATTLECAPSULE_SIDE1
{SPR_CAPS, FF_PAPERSPRITE|1, -1, {NULL}, 0, 0, S_NULL}, // S_BATTLECAPSULE_SIDE2
@ -7933,35 +8012,35 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
},
{ // MT_BLUESPHERE
1706, // doomednum
S_BLUESPHERE, // spawnstate
-1, // doomednum
S_BLUESPHERE_SPAWN, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
MT_FLINGBLUESPHERE, // reactiontime
MT_FLINGBLUESPHERE, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_BLUESPHERESPARK, // deathstate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_s3k65, // deathsound
38*FRACUNIT, // speed
16*FRACUNIT, // radius
24*FRACUNIT, // height
48*FRACUNIT, // radius
48*FRACUNIT, // height
0, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_SLIDEME|MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
S_BLUESPHEREBONUS // raisestate
MF_RUNSPAWNFUNC|MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags
S_NULL // raisestate
},
{ // MT_FLINGBLUESPHERE
-1, // doomednum
S_BLUESPHERE, // spawnstate
S_BLUESPHERE_SPAWN, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
@ -7972,7 +8051,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_BLUESPHERESPARK, // deathstate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_s3k65, // deathsound
38*FRACUNIT, // speed
@ -7983,7 +8062,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // damage
sfx_None, // activesound
MF_SLIDEME|MF_SPECIAL, // flags
S_BLUESPHEREBONUS // raisestate
S_NULL // raisestate
},
{ // MT_BOMBSPHERE
@ -8175,9 +8254,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
{ // MT_EMERALD1
313, // doomednum
S_CEMG1, // spawnstate
{ // MT_EMERALD
-1, // doomednum
S_CHAOSEMERALD1, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
@ -8188,22 +8267,23 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_SPRK1, // deathstate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_cgot, // deathsound
EMERALD1, // speed
16*FRACUNIT, // radius
32*FRACUNIT, // height
sfx_s3k9c, // deathsound
0, // speed
72*FRACUNIT, // radius
72*FRACUNIT, // height
0, // display offset
16, // mass
0, // damage
sfx_None, // activesound
MF_NOGRAVITY|MF_SPECIAL, // flags
MF_SPECIAL|MF_PICKUPFROMBELOW|MF_DONTENCOREMAP, // flags
S_NULL // raisestate
},
{ // MT_EMERALD2
314, // doomednum
S_CEMG2, // spawnstate
{ // MT_EMERALDSPARK
-1, // doomednum
S_EMERALDSPARK1,// spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
@ -8214,147 +8294,17 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_SPRK1, // deathstate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_cgot, // deathsound
EMERALD2, // speed
16*FRACUNIT, // radius
32*FRACUNIT, // height
sfx_None, // deathsound
0, // speed
8*FRACUNIT, // radius
8*FRACUNIT, // height
0, // display offset
16, // mass
0, // damage
sfx_None, // activesound
MF_NOGRAVITY|MF_SPECIAL, // flags
S_NULL // raisestate
},
{ // MT_EMERALD3
315, // doomednum
S_CEMG3, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_SPRK1, // deathstate
S_NULL, // xdeathstate
sfx_cgot, // deathsound
EMERALD3, // speed
16*FRACUNIT, // radius
32*FRACUNIT, // height
0, // display offset
16, // mass
0, // damage
sfx_None, // activesound
MF_NOGRAVITY|MF_SPECIAL, // flags
S_NULL // raisestate
},
{ // MT_EMERALD4
316, // doomednum
S_CEMG4, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_SPRK1, // deathstate
S_NULL, // xdeathstate
sfx_cgot, // deathsound
EMERALD4, // speed
16*FRACUNIT, // radius
32*FRACUNIT, // height
0, // display offset
16, // mass
0, // damage
sfx_None, // activesound
MF_NOGRAVITY|MF_SPECIAL, // flags
S_NULL // raisestate
},
{ // MT_EMERALD5
317, // doomednum
S_CEMG5, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_SPRK1, // deathstate
S_NULL, // xdeathstate
sfx_cgot, // deathsound
EMERALD5, // speed
16*FRACUNIT, // radius
32*FRACUNIT, // height
0, // display offset
16, // mass
0, // damage
sfx_None, // activesound
MF_NOGRAVITY|MF_SPECIAL, // flags
S_NULL // raisestate
},
{ // MT_EMERALD6
318, // doomednum
S_CEMG6, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_SPRK1, // deathstate
S_NULL, // xdeathstate
sfx_cgot, // deathsound
EMERALD6, // speed
16*FRACUNIT, // radius
32*FRACUNIT, // height
0, // display offset
16, // mass
0, // damage
sfx_None, // activesound
MF_NOGRAVITY|MF_SPECIAL, // flags
S_NULL // raisestate
},
{ // MT_EMERALD7
319, // doomednum
S_CEMG7, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_SPRK1, // deathstate
S_NULL, // xdeathstate
sfx_cgot, // deathsound
EMERALD7, // speed
16*FRACUNIT, // radius
32*FRACUNIT, // height
0, // display offset
16, // mass
0, // damage
sfx_None, // activesound
MF_NOGRAVITY|MF_SPECIAL, // flags
MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags
S_NULL // raisestate
},
@ -8412,33 +8362,6 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
{ // MT_FLINGEMERALD
-1, // doomednum
S_CEMG1, // 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_SPRK1, // deathstate
S_NULL, // xdeathstate
sfx_cgot, // deathsound
60*FRACUNIT, // speed
16*FRACUNIT, // radius
48*FRACUNIT, // height
0, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_SLIDEME|MF_SPECIAL, // flags
S_NULL // raisestate
},
{ // MT_FAN
540, // doomednum
S_FAN, // spawnstate
@ -18654,22 +18577,22 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_RAIN1, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_rainin, // seesound
0, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_SPLASH1, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
-72*FRACUNIT, // speed
1*FRACUNIT, // radius
8*FRACUNIT, // height
0, // display offset
4, // mass
80, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP, // flags
@ -18682,7 +18605,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
0, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
@ -18696,8 +18619,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
4*FRACUNIT, // radius
4*FRACUNIT, // height
0, // display offset
4, // mass
0, // damage
0, // mass
2, // damage
sfx_None, // activesound
MF_NOBLOCKMAP, // flags
S_NULL // raisestate
@ -19083,7 +19006,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
{ // MT_GOTEMERALD
-1, // doomednum
S_CEMG1, // spawnstate
S_CHAOSEMERALD1, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
@ -22918,13 +22841,13 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_itpick, // deathsound
0, // speed
32*FRACUNIT, // radius
32*FRACUNIT, // height
48*FRACUNIT, // radius
64*FRACUNIT, // height
0, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_SLIDEME|MF_SPECIAL|MF_DONTENCOREMAP, // flags
MF_SLIDEME|MF_SPECIAL|MF_PICKUPFROMBELOW|MF_DONTENCOREMAP, // flags
S_NULL // raisestate
},
@ -24237,7 +24160,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_BATTLEBUMPER1, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
4*FRACUNIT, // speed
@ -24251,6 +24174,60 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
{ // MT_BATTLEBUMPER_DEBRIS
-1, // doomednum
S_BATTLEBUMPER_EXDEBRIS1,// spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
8*FRACUNIT, // radius
16*FRACUNIT, // height
0, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_SCENERY|MF_DONTENCOREMAP, // flags
S_NULL // raisestate
},
{ // MT_BATTLEBUMPER_BLAST
-1, // doomednum
S_BATTLEBUMPER_EXBLAST1, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
8*FRACUNIT, // radius
16*FRACUNIT, // height
0, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_SCENERY|MF_DONTENCOREMAP, // flags
S_NULL // raisestate
},
{ // MT_DEZLASER
-1, // doomednum
S_DEZLASER, // spawnstate
@ -28439,9 +28416,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
{ // MT_OVERTIMEFOG
{ // MT_OVERTIME_PARTICLE
-1, // doomednum
S_OVERTIMEFOG, // spawnstate
S_NULL, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
@ -28457,8 +28434,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_None, // deathsound
0, // speed
16<<FRACBITS, // radius
32<<FRACBITS, // height
-1, // display offset
24<<FRACBITS, // height
0, // display offset
100, // mass
0, // damage
sfx_None, // activesound
@ -28466,9 +28443,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
{ // MT_OVERTIMEORB
-1, // doomednum
S_OVERTIMEORB, // spawnstate
{ // MT_OVERTIME_CENTER
3775, // doomednum
S_OVERTIME_CENTER, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
@ -28483,40 +28460,13 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
16<<FRACBITS, // radius
48<<FRACBITS, // height
-1, // display offset
12<<FRACBITS, // radius
72<<FRACBITS, // height
0, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags
S_NULL // raisestate
},
{ // MT_OVERTIMEBEAM
-1, // doomednum
S_OVERTIMEBEAM, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
48<<FRACBITS, // radius
48<<FRACBITS, // height
-1, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags
MF_SOLID|MF_DONTENCOREMAP, // flags
S_NULL // raisestate
},
@ -28766,6 +28716,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
{ // MT_PAPERITEMSPOT
-1, // doomednum
S_INVISIBLE, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
48*FRACUNIT, // radius
32*FRACUNIT, // height
0, // display offset
100, // mass
1, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags
S_NULL // raisestate
},
// ============================================================================================================================//
#ifdef SEENAMES
@ -28955,7 +28932,15 @@ skincolor_t skincolors[MAXSKINCOLORS] = {
{"Super Tan 2", {0x00, 0x50, 0x50, 0x51, 0x51, 0x52, 0x52, 0x52, 0x54, 0x54, 0x54, 0x54, 0x55, 0x56, 0x57, 0xf5}, SKINCOLOR_BROWN, 13, V_BROWNMAP, false}, // SKINCOLOR_SUPERTAN2
{"Super Tan 3", {0x50, 0x51, 0x51, 0x52, 0x52, 0x52, 0x54, 0x54, 0x54, 0x54, 0x55, 0x56, 0x57, 0xf5, 0xf7, 0xf9}, SKINCOLOR_BROWN, 12, V_BROWNMAP, false}, // SKINCOLOR_SUPERTAN3
{"Super Tan 4", {0x51, 0x52, 0x52, 0x52, 0x52, 0x54, 0x54, 0x54, 0x55, 0x56, 0x57, 0xf5, 0xf7, 0xf9, 0xfb, 0xed}, SKINCOLOR_BROWN, 11, V_BROWNMAP, false}, // SKINCOLOR_SUPERTAN4
{"Super Tan 5", {0x52, 0x52, 0x54, 0x54, 0x54, 0x55, 0x56, 0x57, 0xf5, 0xf7, 0xf9, 0xfb, 0xed, 0xee, 0xef, 0xef}, SKINCOLOR_BROWN, 10, V_BROWNMAP, false} // SKINCOLOR_SUPERTAN5
{"Super Tan 5", {0x52, 0x52, 0x54, 0x54, 0x54, 0x55, 0x56, 0x57, 0xf5, 0xf7, 0xf9, 0xfb, 0xed, 0xee, 0xef, 0xef}, SKINCOLOR_BROWN, 10, V_BROWNMAP, false}, // SKINCOLOR_SUPERTAN5
{"Chaos Emerald 1", { 0, 88, 188, 98, 114, 116, 117, 119, 0, 0, 0, 0, 0, 0, 0, 0}, SKINCOLOR_NONE, 0, 0, false}, // SKINCOLOR_CHAOSEMERALD1
{"Chaos Emerald 2", { 0, 80, 82, 74, 65, 52, 56, 60, 0, 0, 0, 0, 0, 0, 0, 0}, SKINCOLOR_NONE, 0, 0, false}, // SKINCOLOR_CHAOSEMERALD2
{"Chaos Emerald 3", { 0, 252, 201, 179, 182, 183, 185, 187, 0, 0, 0, 0, 0, 0, 0, 0}, SKINCOLOR_NONE, 0, 0, false}, // SKINCOLOR_CHAOSEMERALD3
{"Chaos Emerald 4", { 0, 144, 146, 147, 149, 165, 167, 169, 0, 0, 0, 0, 0, 0, 0, 0}, SKINCOLOR_NONE, 0, 0, false}, // SKINCOLOR_CHAOSEMERALD4
{"Chaos Emerald 5", { 0, 1, 144, 4, 9, 170, 14, 21, 0, 0, 0, 0, 0, 0, 0, 0}, SKINCOLOR_NONE, 0, 0, false}, // SKINCOLOR_CHAOSEMERALD5
{"Chaos Emerald 6", { 0, 208, 50, 32, 34, 37, 40, 44, 0, 0, 0, 0, 0, 0, 0, 0}, SKINCOLOR_NONE, 0, 0, false}, // SKINCOLOR_CHAOSEMERALD6
{"Chaos Emerald 7", { 0, 120, 121, 140, 133, 135, 149, 156, 0, 0, 0, 0, 0, 0, 0, 0}, SKINCOLOR_NONE, 0, 0, false} // SKINCOLOR_CHAOSEMERALD7
};
/** Patches the mobjinfo, state, and skincolor tables.

View file

@ -406,11 +406,12 @@ typedef enum sprite
SPR_TOKE, // Special Stage Token
SPR_RFLG, // Red CTF Flag
SPR_BFLG, // Blue CTF Flag
//SPR_SPHR, // Sphere
SPR_BSPH, // Sphere
SPR_NCHP, // NiGHTS chip
SPR_NSTR, // NiGHTS star
SPR_EMBM, // Emblem
SPR_CEMG, // Chaos Emeralds
SPR_EMRC, // Chaos Emeralds
SPR_ESPK,
SPR_SHRD, // Emerald Hunt
// Interactive Objects
@ -829,6 +830,10 @@ typedef enum sprite
SPR_SINK, // Kitchen Sink
SPR_SITR, // Kitchen Sink Trail
SPR_KBLN, // Battle Mode Bumper
SPR_BEXC, // Battle Bumper Explosion: Crystal
SPR_BEXS, // Battle Bumper Explosion: Shell
SPR_BDEB, // Battle Bumper Explosion: Debris
SPR_BEXB, // Battle Bumper Explosion: Blast
SPR_DEZL, // DEZ Laser respawn
@ -985,7 +990,9 @@ typedef enum sprite
SPR_DRAF,
SPR_GRES,
SPR_OTFG,
SPR_OTBU,
SPR_OTLS,
SPR_OTCP,
SPR_DBOS, // Drift boost flame
@ -2020,8 +2027,41 @@ typedef enum state
// Blue Sphere for special stages
S_BLUESPHERE,
S_BLUESPHEREBONUS,
S_BLUESPHERESPARK,
S_BLUESPHERE_SPAWN,
S_BLUESPHERE_BOUNCE1,
S_BLUESPHERE_BOUNCE2,
S_BLUESPHERE_BOUNCE3,
S_BLUESPHERE_BOUNCE4,
S_BLUESPHERE_BOUNCE5,
S_BLUESPHERE_BOUNCE6,
S_BLUESPHERE_BOUNCE7,
S_BLUESPHERE_BOUNCE8,
S_BLUESPHERE_BOUNCE9,
S_BLUESPHERE_BOUNCE10,
S_BLUESPHERE_BOUNCE11,
S_BLUESPHERE_BOUNCE12,
S_BLUESPHERE_BOUNCE13,
S_BLUESPHERE_BOUNCE14,
S_BLUESPHERE_BOUNCE15,
S_BLUESPHERE_BOUNCE16,
S_BLUESPHERE_BOUNCE17,
S_BLUESPHERE_BOUNCE18,
S_BLUESPHERE_BOUNCE19,
S_BLUESPHERE_BOUNCE20,
S_BLUESPHERE_BOUNCE21,
S_BLUESPHERE_BOUNCE22,
S_BLUESPHERE_BOUNCE23,
S_BLUESPHERE_BOUNCE24,
S_BLUESPHERE_BOUNCE25,
S_BLUESPHERE_BOUNCE26,
S_BLUESPHERE_BOUNCE27,
S_BLUESPHERE_BOUNCE28,
// Bomb Sphere
S_BOMBSPHERE1,
@ -2080,13 +2120,17 @@ typedef enum state
S_EMBLEM26,
// Chaos Emeralds
S_CEMG1,
S_CEMG2,
S_CEMG3,
S_CEMG4,
S_CEMG5,
S_CEMG6,
S_CEMG7,
S_CHAOSEMERALD1,
S_CHAOSEMERALD2,
S_CHAOSEMERALD_UNDER,
S_EMERALDSPARK1,
S_EMERALDSPARK2,
S_EMERALDSPARK3,
S_EMERALDSPARK4,
S_EMERALDSPARK5,
S_EMERALDSPARK6,
S_EMERALDSPARK7,
// Emerald hunt shards
S_SHRD1,
@ -4535,6 +4579,44 @@ typedef enum state
S_BATTLEBUMPER2,
S_BATTLEBUMPER3,
S_BATTLEBUMPER_EXCRYSTALA1,
S_BATTLEBUMPER_EXCRYSTALA2,
S_BATTLEBUMPER_EXCRYSTALA3,
S_BATTLEBUMPER_EXCRYSTALA4,
S_BATTLEBUMPER_EXCRYSTALB1,
S_BATTLEBUMPER_EXCRYSTALB2,
S_BATTLEBUMPER_EXCRYSTALB3,
S_BATTLEBUMPER_EXCRYSTALB4,
S_BATTLEBUMPER_EXCRYSTALC1,
S_BATTLEBUMPER_EXCRYSTALC2,
S_BATTLEBUMPER_EXCRYSTALC3,
S_BATTLEBUMPER_EXCRYSTALC4,
S_BATTLEBUMPER_EXSHELLA1,
S_BATTLEBUMPER_EXSHELLA2,
S_BATTLEBUMPER_EXSHELLB1,
S_BATTLEBUMPER_EXSHELLB2,
S_BATTLEBUMPER_EXSHELLC1,
S_BATTLEBUMPER_EXSHELLC2,
S_BATTLEBUMPER_EXDEBRIS1,
S_BATTLEBUMPER_EXDEBRIS2,
S_BATTLEBUMPER_EXBLAST1,
S_BATTLEBUMPER_EXBLAST2,
S_BATTLEBUMPER_EXBLAST3,
S_BATTLEBUMPER_EXBLAST4,
S_BATTLEBUMPER_EXBLAST5,
S_BATTLEBUMPER_EXBLAST6,
S_BATTLEBUMPER_EXBLAST7,
S_BATTLEBUMPER_EXBLAST8,
S_BATTLEBUMPER_EXBLAST9,
S_BATTLEBUMPER_EXBLAST10,
// DEZ Laser respawn
S_DEZLASER,
S_DEZLASER_TRAIL1,
@ -5155,9 +5237,10 @@ typedef enum state
S_TIREGREASE,
S_OVERTIMEFOG,
S_OVERTIMEORB,
S_OVERTIMEBEAM,
S_OVERTIME_BULB1,
S_OVERTIME_BULB2,
S_OVERTIME_LASER,
S_OVERTIME_CENTER,
S_BATTLECAPSULE_SIDE1,
S_BATTLECAPSULE_SIDE2,
@ -5356,16 +5439,10 @@ typedef enum mobj_type
MT_REDFLAG, // Red CTF Flag
MT_BLUEFLAG, // Blue CTF Flag
MT_EMBLEM,
MT_EMERALD1,
MT_EMERALD2,
MT_EMERALD3,
MT_EMERALD4,
MT_EMERALD5,
MT_EMERALD6,
MT_EMERALD7,
MT_EMERALD,
MT_EMERALDSPARK,
MT_EMERHUNT, // Emerald Hunt
MT_EMERALDSPAWN, // Emerald spawner w/ delay
MT_FLINGEMERALD, // Lost emerald
// Springs and others
MT_FAN,
@ -6062,6 +6139,8 @@ typedef enum mobj_type
MT_SINKTRAIL,
MT_BATTLEBUMPER, // Battle Mode bumpers
MT_BATTLEBUMPER_DEBRIS,
MT_BATTLEBUMPER_BLAST,
MT_DEZLASER,
@ -6276,9 +6355,8 @@ typedef enum mobj_type
MT_SPBDUST,
MT_TIREGREASE,
MT_OVERTIMEFOG,
MT_OVERTIMEORB,
MT_OVERTIMEBEAM,
MT_OVERTIME_PARTICLE,
MT_OVERTIME_CENTER,
MT_BATTLECAPSULE,
MT_BATTLECAPSULE_PIECE,
@ -6293,6 +6371,8 @@ typedef enum mobj_type
MT_SPINDASHDUST,
MT_SPINDASHWIND,
MT_PAPERITEMSPOT,
#ifdef SEENAMES
MT_NAMECHECK,
#endif

View file

@ -41,6 +41,9 @@ INT32 K_StartingBumperCount(void)
boolean K_IsPlayerWanted(player_t *player)
{
#if 1
return (player->kartstuff[k_position] == 1);
#else
UINT8 i;
if (!(gametyperules & GTR_WANTED))
@ -54,28 +57,26 @@ boolean K_IsPlayerWanted(player_t *player)
return true;
}
return false;
#endif
}
void K_CalculateBattleWanted(void)
{
UINT8 numingame = 0, numplaying = 0, numwanted = 0;
SINT8 bestbumperplayer = -1, bestbumper = -1;
UINT8 numingame = 0, numwanted = 0;
SINT8 camppos[MAXPLAYERS]; // who is the biggest camper
UINT8 ties = 0, nextcamppos = 0;
boolean setbumper = false;
UINT8 i, j;
#if 0
if (!(gametyperules & GTR_WANTED))
#endif
{
for (i = 0; i < 4; i++)
battlewanted[i] = -1;
memset(battlewanted, -1, sizeof (battlewanted));
return;
}
wantedcalcdelay = wantedfrequency;
for (i = 0; i < MAXPLAYERS; i++)
camppos[i] = -1; // initialize
memset(camppos, -1, sizeof (camppos)); // initialize
for (i = 0; i < MAXPLAYERS; i++)
{
@ -87,33 +88,38 @@ void K_CalculateBattleWanted(void)
if (players[i].exiting) // We're done, don't calculate.
return;
numplaying++;
if (players[i].kartstuff[k_bumper] <= 0) // Not alive, so don't do anything else
if (players[i].bumpers <= 0) // Not alive, so don't do anything else
continue;
numingame++;
if (bestbumper == -1 || players[i].kartstuff[k_bumper] > bestbumper)
{
bestbumper = players[i].kartstuff[k_bumper];
bestbumperplayer = i;
}
else if (players[i].kartstuff[k_bumper] == bestbumper)
bestbumperplayer = -1; // Tie, no one has best bumper.
for (j = 0; j < MAXPLAYERS; j++)
{
if (!playeringame[j] || players[j].spectator)
continue;
if (players[j].kartstuff[k_bumper] <= 0)
if (players[j].bumpers <= 0)
continue;
if (j == i)
continue;
if (players[j].kartstuff[k_wanted] == players[i].kartstuff[k_wanted] && players[j].marescore > players[i].marescore)
if (K_NumEmeralds(&players[j]) > K_NumEmeralds(&players[i]))
{
position++;
}
else if (players[j].bumpers > players[i].bumpers)
{
position++;
}
else if (players[j].marescore > players[i].marescore)
{
position++;
}
else if (players[j].kartstuff[k_wanted] > players[i].kartstuff[k_wanted])
{
position++;
}
}
position--; // Make zero based
@ -124,7 +130,7 @@ void K_CalculateBattleWanted(void)
camppos[position] = i;
}
if (numplaying <= 2 || (numingame <= 2 && bestbumper == 1)) // In 1v1s then there's no need for WANTED. In bigger netgames, don't show anyone as WANTED when they're equally matched.
if (numingame <= 2) // In 1v1s then there's no need for WANTED.
numwanted = 0;
else
numwanted = min(4, 1 + ((numingame-2) / 4));
@ -132,19 +138,11 @@ void K_CalculateBattleWanted(void)
for (i = 0; i < 4; i++)
{
if (i+1 > numwanted) // Not enough players for this slot to be wanted!
battlewanted[i] = -1;
else if (bestbumperplayer != -1 && !setbumper) // If there's a player who has an untied bumper lead over everyone else, they are the first to be wanted.
{
battlewanted[i] = bestbumperplayer;
setbumper = true; // Don't set twice
battlewanted[i] = -1;
}
else
{
// Don't accidentally set the same player, if the bestbumperplayer is also a huge camper.
while (bestbumperplayer != -1 && camppos[nextcamppos] != -1
&& bestbumperplayer == camppos[nextcamppos])
nextcamppos++;
// Do not add *any* more people if there's too many times that are tied with others.
// This could theoretically happen very easily if people don't hit each other for a while after the start of a match.
// (I will be sincerely impressed if more than 2 people tie after people start hitting each other though)
@ -230,7 +228,7 @@ void K_CheckBumpers(void)
numingame++;
winnerscoreadd += players[i].marescore;
if (players[i].kartstuff[k_bumper] <= 0) // if you don't have any bumpers, you're probably not a winner
if (players[i].bumpers <= 0) // if you don't have any bumpers, you're probably not a winner
{
nobumpers = true;
continue;
@ -277,125 +275,411 @@ void K_CheckBumpers(void)
P_DoPlayerExit(&players[i]);
}
#define MAXPLANESPERSECTOR (MAXFFLOORS+1)*2
static void K_SpawnOvertimeParticles(fixed_t x, fixed_t y, fixed_t scale, mobjtype_t type, boolean ceiling)
void K_CheckEmeralds(player_t *player)
{
UINT8 i;
fixed_t flatz[MAXPLANESPERSECTOR];
boolean flip[MAXPLANESPERSECTOR];
UINT8 numflats = 0;
mobj_t *mo;
subsector_t *ss = R_PointInSubsectorOrNull(x, y);
sector_t *sec;
if (!ss)
if (!ALLCHAOSEMERALDS(player->powers[pw_emeralds]))
{
return;
sec = ss->sector;
// convoluted stuff JUST to get all of the planes we need to draw orbs on :V
for (i = 0; i < MAXPLANESPERSECTOR; i++)
flip[i] = false;
if (sec->floorpic != skyflatnum)
{
flatz[numflats] = P_GetZAt(sec->f_slope, x, y, sec->floorheight);
numflats++;
}
if (sec->ceilingpic != skyflatnum && ceiling)
{
flatz[numflats] = P_GetZAt(sec->c_slope, x, y, sec->ceilingheight) - FixedMul(mobjinfo[type].height, scale);
flip[numflats] = true;
numflats++;
}
if (sec->ffloors)
player->marescore++; // lol
for (i = 0; i < MAXPLAYERS; i++)
{
ffloor_t *rover;
for (rover = sec->ffloors; rover; rover = rover->next)
if (!playeringame[i] || players[i].spectator)
{
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER))
continue;
if (*rover->toppic != skyflatnum)
{
flatz[numflats] = P_GetZAt(*rover->t_slope, x, y, *rover->topheight);
numflats++;
}
if (*rover->bottompic != skyflatnum && ceiling)
{
flatz[numflats] = P_GetZAt(*rover->b_slope, x, y, *rover->bottomheight);
flip[numflats] = true;
numflats++;
}
continue;
}
if (&players[i] == player)
{
continue;
}
players[i].bumpers = 0;
}
if (numflats <= 0) // no flats
return;
K_CheckBumpers();
}
for (i = 0; i < numflats; i++)
mobj_t *K_SpawnChaosEmerald(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8 flip, UINT32 emeraldType)
{
boolean validEmerald = true;
mobj_t *emerald = P_SpawnMobj(x, y, z, MT_EMERALD);
mobj_t *overlay;
P_Thrust(emerald,
FixedAngle(P_RandomFixed() * 180) + angle,
32 * mapobjectscale);
emerald->momz = flip * 24 * mapobjectscale;
if (emerald->eflags & MFE_UNDERWATER)
emerald->momz = (117 * emerald->momz) / 200;
emerald->threshold = 10;
switch (emeraldType)
{
mo = P_SpawnMobj(x, y, flatz[i], type);
case EMERALD_CHAOS1:
emerald->color = SKINCOLOR_CHAOSEMERALD1;
break;
case EMERALD_CHAOS2:
emerald->color = SKINCOLOR_CHAOSEMERALD2;
break;
case EMERALD_CHAOS3:
emerald->color = SKINCOLOR_CHAOSEMERALD3;
break;
case EMERALD_CHAOS4:
emerald->color = SKINCOLOR_CHAOSEMERALD4;
break;
case EMERALD_CHAOS5:
emerald->color = SKINCOLOR_CHAOSEMERALD5;
break;
case EMERALD_CHAOS6:
emerald->color = SKINCOLOR_CHAOSEMERALD6;
break;
case EMERALD_CHAOS7:
emerald->color = SKINCOLOR_CHAOSEMERALD7;
break;
default:
CONS_Printf("Invalid emerald type %d\n", emeraldType);
validEmerald = false;
break;
}
// Lastly, if this can see the skybox mobj, then... we just wasted our time :V
if (skyboxmo[0] && !P_MobjWasRemoved(skyboxmo[0]))
if (validEmerald == true)
{
emerald->extravalue1 = emeraldType;
}
overlay = P_SpawnMobjFromMobj(emerald, 0, 0, 0, MT_OVERLAY);
P_SetTarget(&overlay->target, emerald);
P_SetMobjState(overlay, S_CHAOSEMERALD_UNDER);
overlay->color = emerald->color;
return emerald;
}
void K_DropEmeraldsFromPlayer(player_t *player, UINT32 emeraldType)
{
UINT8 i;
SINT8 flip = P_MobjFlip(player->mo);
for (i = 0; i < 14; i++)
{
UINT32 emeraldFlag = (1 << i);
if ((player->powers[pw_emeralds] & emeraldFlag) && (emeraldFlag & emeraldType))
{
const fixed_t sbz = skyboxmo[0]->z;
fixed_t checkz = sec->floorheight;
mobj_t *emerald = K_SpawnChaosEmerald(player->mo->x, player->mo->y, player->mo->z, player->mo->angle - ANGLE_90, flip, emeraldFlag);
P_SetTarget(&emerald->target, player->mo);
while (checkz < sec->ceilingheight)
{
P_TeleportMove(skyboxmo[0], skyboxmo[0]->x, skyboxmo[0]->y, checkz);
if (P_CheckSight(skyboxmo[0], mo))
{
P_RemoveMobj(mo);
break;
}
else
checkz += 32*mapobjectscale;
}
P_TeleportMove(skyboxmo[0], skyboxmo[0]->x, skyboxmo[0]->y, sbz);
if (P_MobjWasRemoved(mo))
continue;
}
P_SetScale(mo, scale);
if (flip[i])
{
mo->flags2 |= MF2_OBJECTFLIP;
mo->eflags |= MFE_VERTICALFLIP;
}
switch(type)
{
case MT_OVERTIMEFOG:
mo->destscale = 8*mo->scale;
mo->momz = P_RandomRange(1,8)*mo->scale;
break;
case MT_OVERTIMEORB:
//mo->destscale = mo->scale/4;
mo->frame += ((leveltime/4) % 8);
/*if (battleovertime.enabled < 10*TICRATE)
mo->drawflags |= MFD_SHADOW;*/
mo->angle = R_PointToAngle2(mo->x, mo->y, battleovertime.x, battleovertime.y) + ANGLE_90;
mo->z += P_RandomRange(0,48) * mo->scale;
break;
default:
break;
player->powers[pw_emeralds] &= ~emeraldFlag;
}
}
}
#undef MAXPLANESPERSECTOR
UINT8 K_NumEmeralds(player_t *player)
{
UINT8 i;
UINT8 num = 0;
for (i = 0; i < 14; i++)
{
UINT32 emeraldFlag = (1 << i);
if (player->powers[pw_emeralds] & emeraldFlag)
{
num++;
}
}
return num;
}
void K_RunPaperItemSpawners(void)
{
const boolean overtime = (battleovertime.enabled >= 10*TICRATE);
tic_t interval = 8*TICRATE;
UINT32 emeraldsSpawned = 0;
UINT32 firstUnspawnedEmerald = 0;
thinker_t *th;
mobj_t *mo;
UINT8 pcount = 0;
INT16 i;
if (leveltime < starttime)
{
// Round hasn't started yet!
return;
}
if (overtime == true)
{
if (battleovertime.radius < 512*mapobjectscale)
{
// Barrier has closed in too much
return;
}
// Double frequency of items
interval /= 2;
}
if (((leveltime - starttime) % interval) != 0)
{
return;
}
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator)
{
continue;
}
emeraldsSpawned |= players[i].powers[pw_emeralds];
if ((players[i].exiting > 0 || players[i].eliminated)
|| ((gametyperules & GTR_BUMPERS) && players[i].bumpers <= 0))
{
continue;
}
pcount++;
}
if (overtime == true)
{
SINT8 flip = 1;
// Just find emeralds, no paper spots
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo = (mobj_t *)th;
if (mo->type == MT_EMERALD)
{
emeraldsSpawned |= mo->extravalue1;
}
}
for (i = 0; i < 7; i++)
{
UINT32 emeraldFlag = (1 << i);
if (!(emeraldsSpawned & emeraldFlag))
{
firstUnspawnedEmerald = emeraldFlag;
break;
}
}
if (firstUnspawnedEmerald != 0)
{
K_SpawnChaosEmerald(
battleovertime.x, battleovertime.y, battleovertime.z + (128 * mapobjectscale * flip),
FixedAngle(P_RandomRange(0, 359) * FRACUNIT), flip,
firstUnspawnedEmerald
);
}
else
{
K_CreatePaperItem(
battleovertime.x, battleovertime.y, battleovertime.z + (128 * mapobjectscale * flip),
FixedAngle(P_RandomRange(0, 359) * FRACUNIT), flip,
0, 0
);
}
}
else
{
if (pcount > 0)
{
#define MAXITEM 64
UINT8 item = 0;
mobj_t *spotList[MAXITEM];
boolean spotUsed[MAXITEM];
INT16 starti = 0;
memset(spotUsed, false, sizeof(spotUsed));
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo = (mobj_t *)th;
if (mo->type == MT_PAPERITEMSPOT)
{
if (item >= MAXITEM)
continue;
spotList[item] = mo;
item++;
}
else if (mo->type == MT_EMERALD)
{
emeraldsSpawned |= mo->extravalue1;
}
}
if (item <= 0)
{
return;
}
for (i = 0; i < 7; i++)
{
UINT32 emeraldFlag = (1 << i);
if (!(emeraldsSpawned & emeraldFlag))
{
firstUnspawnedEmerald = emeraldFlag;
starti = -1;
break;
}
}
for (i = starti; i < min(item + starti, pcount); i++)
{
UINT8 r = P_RandomKey(item);
UINT8 recursion = 0;
mobj_t *drop = NULL;
SINT8 flip = 1;
while (spotUsed[r] == true)
{
r = P_RandomKey(item);
if ((recursion++) > MAXITEM)
{
// roll with it anyway I guess
break;
}
}
flip = P_MobjFlip(spotList[r]);
// When -1, we're spawning a Chaos Emerald.
if (i == -1)
{
drop = K_SpawnChaosEmerald(
spotList[r]->x, spotList[r]->y, spotList[r]->z + (128 * mapobjectscale * flip),
FixedAngle(P_RandomRange(0, 359) * FRACUNIT), flip,
firstUnspawnedEmerald
);
}
else
{
drop = K_CreatePaperItem(
spotList[r]->x, spotList[r]->y, spotList[r]->z + (128 * mapobjectscale * flip),
FixedAngle(P_RandomRange(0, 359) * FRACUNIT), flip,
0, 0
);
}
K_FlipFromObject(drop, spotList[r]);
spotUsed[r] = true;
}
}
}
}
static void K_SpawnOvertimeLaser(fixed_t x, fixed_t y, fixed_t scale)
{
UINT8 i, j;
for (i = 0; i <= r_splitscreen; i++)
{
player_t *player = &players[displayplayers[i]];
fixed_t zpos;
SINT8 flip;
if (player == NULL || player->mo == NULL || P_MobjWasRemoved(player->mo) == true)
{
continue;
}
if (player->mo->eflags & MFE_VERTICALFLIP)
{
zpos = player->mo->z + player->mo->height;
}
else
{
zpos = player->mo->z;
}
flip = P_MobjFlip(player->mo);
for (j = 0; j < 3; j++)
{
mobj_t *mo = P_SpawnMobj(x, y, zpos, MT_OVERTIME_PARTICLE);
if (player->mo->eflags & MFE_VERTICALFLIP)
{
mo->flags2 |= MF2_OBJECTFLIP;
mo->eflags |= MFE_VERTICALFLIP;
}
mo->angle = R_PointToAngle2(mo->x, mo->y, battleovertime.x, battleovertime.y) + ANGLE_90;
mo->drawflags |= (MFD_DONTDRAW & ~(K_GetPlayerDontDrawFlag(player)));
P_SetScale(mo, scale);
switch (j)
{
case 0:
P_SetMobjState(mo, S_OVERTIME_BULB1);
if (leveltime & 1)
mo->frame += 1;
//P_SetScale(mo, mapobjectscale);
zpos += 35 * mo->scale * flip;
break;
case 1:
P_SetMobjState(mo, S_OVERTIME_LASER);
if (leveltime & 1)
mo->frame += 3;
else
mo->frame += (leveltime / 2) % 3;
//P_SetScale(mo, scale);
zpos += 346 * mo->scale * flip;
if (battleovertime.enabled < 10*TICRATE)
mo->drawflags |= MFD_TRANS50;
break;
case 2:
P_SetMobjState(mo, S_OVERTIME_BULB2);
if (leveltime & 1)
mo->frame += 1;
//P_SetScale(mo, mapobjectscale);
break;
default:
I_Error("Bruh moment has occured\n");
return;
}
}
}
}
void K_RunBattleOvertime(void)
{
UINT16 i, j;
if (battleovertime.enabled < 10*TICRATE)
{
battleovertime.enabled++;
@ -404,70 +688,37 @@ void K_RunBattleOvertime(void)
if (battleovertime.enabled == 10*TICRATE)
S_StartSound(NULL, sfx_kc40);
}
else
else if (battleovertime.radius > 0)
{
if (battleovertime.radius > battleovertime.minradius)
battleovertime.radius -= mapobjectscale;
if (battleovertime.radius > 2*mapobjectscale)
battleovertime.radius -= 2*mapobjectscale;
else
battleovertime.radius = battleovertime.minradius;
battleovertime.radius = 0;
}
if (leveltime & 1)
if (battleovertime.radius > 0)
{
UINT8 transparency = tr_trans50;
const fixed_t pi = (22 * FRACUNIT) / 7; // loose approximation, this doesn't need to be incredibly precise
const INT32 orbs = 32;
const angle_t angoff = ANGLE_MAX / orbs;
const UINT8 spriteSpacing = 128;
if (!splitscreen && players[displayplayers[0]].mo)
{
INT32 dist = P_AproxDistance(battleovertime.x-players[displayplayers[0]].mo->x, battleovertime.y-players[displayplayers[0]].mo->y);
transparency = max(0, NUMTRANSMAPS - ((256 + (dist>>FRACBITS)) / 256));
}
fixed_t circumference = FixedMul(pi, battleovertime.radius * 2);
fixed_t scale = max(circumference / spriteSpacing / orbs, mapobjectscale);
if (transparency < NUMTRANSMAPS)
{
mobj_t *beam = P_SpawnMobj(battleovertime.x, battleovertime.y, battleovertime.z + (mobjinfo[MT_RANDOMITEM].height/2), MT_OVERTIMEBEAM);
P_SetScale(beam, beam->scale*2);
if (transparency > 0)
beam->frame |= transparency<<FF_TRANSSHIFT;
}
}
fixed_t size = FixedMul(mobjinfo[MT_OVERTIME_PARTICLE].radius, scale);
fixed_t posOffset = max(battleovertime.radius - size, 0);
// 16 orbs at the normal minimum size of 512
{
const fixed_t pi = (22<<FRACBITS) / 7; // loose approximation, this doesn't need to be incredibly precise
fixed_t scale = mapobjectscale + (battleovertime.radius/2048);
fixed_t sprwidth = 32*scale;
fixed_t circumference = FixedMul(pi, battleovertime.radius<<1);
UINT16 orbs = circumference / sprwidth;
angle_t angoff = ANGLE_MAX / orbs;
INT32 i;
for (i = 0; i < orbs; i++)
{
angle_t ang = (i * angoff) + FixedAngle((leveltime/2)<<FRACBITS);
fixed_t x = battleovertime.x + P_ReturnThrustX(NULL, ang, battleovertime.radius - FixedMul(mobjinfo[MT_OVERTIMEORB].radius, scale));
fixed_t y = battleovertime.y + P_ReturnThrustY(NULL, ang, battleovertime.radius - FixedMul(mobjinfo[MT_OVERTIMEORB].radius, scale));
K_SpawnOvertimeParticles(x, y, scale, MT_OVERTIMEORB, false);
}
}
angle_t ang = (i * angoff) + FixedAngle((leveltime * FRACUNIT) / 4);
if (battleovertime.enabled < 10*TICRATE)
return;
fixed_t x = battleovertime.x + P_ReturnThrustX(NULL, ang, posOffset);
fixed_t y = battleovertime.y + P_ReturnThrustY(NULL, ang, posOffset);
/*if (!S_IdPlaying(sfx_s3kd4s)) // global ambience
S_StartSoundAtVolume(NULL, sfx_s3kd4s, min(255, ((4096*mapobjectscale) - battleovertime.radius)>>FRACBITS / 2));*/
for (i = 0; i < 16; i++)
{
j = 0;
while (j < 32) // max attempts
{
fixed_t x = battleovertime.x + ((P_RandomRange(-64,64) * 128)<<FRACBITS);
fixed_t y = battleovertime.y + ((P_RandomRange(-64,64) * 128)<<FRACBITS);
fixed_t closestdist = battleovertime.radius + (8*mobjinfo[MT_OVERTIMEFOG].radius);
j++;
if (P_AproxDistance(x-battleovertime.x, y-battleovertime.y) < closestdist)
continue;
K_SpawnOvertimeParticles(x, y, 4*mapobjectscale, MT_OVERTIMEFOG, false);
break;
K_SpawnOvertimeLaser(x, y, scale);
}
}
}

View file

@ -7,7 +7,7 @@
extern struct battleovertime
{
UINT16 enabled; ///< Has this been initalized yet?
fixed_t radius, minradius; ///< Radius of kill field
fixed_t radius; ///< Radius of kill field
fixed_t x, y, z; ///< Position to center on
} battleovertime;
@ -20,6 +20,11 @@ boolean K_IsPlayerWanted(player_t *player);
void K_CalculateBattleWanted(void);
void K_SpawnBattlePoints(player_t *source, player_t *victim, UINT8 amount);
void K_CheckBumpers(void);
void K_CheckEmeralds(player_t *player);
mobj_t *K_SpawnChaosEmerald(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8 flip, UINT32 emeraldType);
void K_DropEmeraldsFromPlayer(player_t *player, UINT32 emeraldType);
UINT8 K_NumEmeralds(player_t *player);
void K_RunPaperItemSpawners(void);
void K_RunBattleOvertime(void);
void K_SetupMovingCapsule(mapthing_t *mt, mobj_t *mobj);
void K_SpawnBattleCapsules(void);

View file

@ -204,11 +204,15 @@ boolean K_EggItemCollide(mobj_t *t1, mobj_t *t2)
if (!P_CanPickupItem(t2->player, 2))
return true;
if ((gametyperules & GTR_BUMPERS) && t2->player->kartstuff[k_bumper] <= 0)
if ((gametyperules & GTR_BUMPERS) && t2->player->bumpers <= 0)
{
if (t2->player->kartstuff[k_comebackmode] || t2->player->kartstuff[k_comebacktimer])
#ifdef OTHERKARMAMODES
if (t2->player->kartstuff[k_comebackmode] || t2->player->karmadelay)
return true;
t2->player->kartstuff[k_comebackmode] = 2;
#else
return true;
#endif
}
else
{
@ -238,7 +242,7 @@ boolean K_EggItemCollide(mobj_t *t1, mobj_t *t2)
if (t1->target && t1->target->player)
{
if ((gametyperules & GTR_CIRCUIT) || t1->target->player->kartstuff[k_bumper] > 0)
if ((gametyperules & GTR_CIRCUIT) || t1->target->player->bumpers > 0)
t2->player->kartstuff[k_eggmanblame] = t1->target->player-players;
else
t2->player->kartstuff[k_eggmanblame] = t2->player-players;

View file

@ -50,6 +50,7 @@ static patch_t *kp_bumperstickerwide;
static patch_t *kp_capsulesticker;
static patch_t *kp_capsulestickerwide;
static patch_t *kp_karmasticker;
static patch_t *kp_spheresticker;
static patch_t *kp_splitkarmabomb;
static patch_t *kp_timeoutsticker;
@ -87,6 +88,9 @@ static patch_t *kp_rankbumper;
static patch_t *kp_tinybumper[2];
static patch_t *kp_ranknobumpers;
static patch_t *kp_rankcapsule;
static patch_t *kp_rankemerald;
static patch_t *kp_rankemeraldflash;
static patch_t *kp_rankemeraldback;
static patch_t *kp_battlewin;
static patch_t *kp_battlecool;
@ -175,6 +179,7 @@ void K_LoadKartHUDGraphics(void)
kp_capsulesticker = W_CachePatchName("K_STCAPN", PU_HUDGFX);
kp_capsulestickerwide = W_CachePatchName("K_STCAPW", PU_HUDGFX);
kp_karmasticker = W_CachePatchName("K_STKARM", PU_HUDGFX);
kp_spheresticker = W_CachePatchName("K_STBSMT", PU_HUDGFX);
kp_splitkarmabomb = W_CachePatchName("K_SPTKRM", PU_HUDGFX);
kp_timeoutsticker = W_CachePatchName("K_STTOUT", PU_HUDGFX);
@ -349,6 +354,9 @@ void K_LoadKartHUDGraphics(void)
kp_tinybumper[1] = W_CachePatchName("K_BLNB", PU_HUDGFX);
kp_ranknobumpers = W_CachePatchName("K_NOBLNS", PU_HUDGFX);
kp_rankcapsule = W_CachePatchName("K_CAPICO", PU_HUDGFX);
kp_rankemerald = W_CachePatchName("K_EMERC", PU_HUDGFX);
kp_rankemeraldflash = W_CachePatchName("K_EMERW", PU_HUDGFX);
kp_rankemeraldback = W_CachePatchName("K_EMERBK", PU_HUDGFX);
// Battle graphics
kp_battlewin = W_CachePatchName("K_BWIN", PU_HUDGFX);
@ -734,11 +742,12 @@ void K_AdjustXYWithSnap(INT32 *x, INT32 *y, UINT32 options, INT32 dupx, INT32 du
if (options & V_SLIDEIN)
{
tic_t length = TICRATE/2;
const tic_t length = TICRATE/2;
const tic_t end = (lt_endtime + length);
if (leveltime < introtime + length)
if (lt_ticker < end)
{
INT32 offset = screenwidth - (((leveltime - introtime) * screenwidth) / length);
INT32 offset = screenwidth - ((lt_exitticker * screenwidth) / length);
boolean slidefromright = false;
if (r_splitscreen > 1)
@ -1525,7 +1534,7 @@ static boolean K_drawKartPositionFaces(void)
INT32 i, j, ranklines, strank = -1;
boolean completed[MAXPLAYERS];
INT32 rankplayer[MAXPLAYERS];
INT32 bumperx, numplayersingame = 0;
INT32 bumperx, emeraldx, numplayersingame = 0;
UINT8 *colormap;
ranklines = 0;
@ -1606,6 +1615,7 @@ static boolean K_drawKartPositionFaces(void)
if (!players[rankplayer[i]].mo) continue;
bumperx = FACE_X+19;
emeraldx = FACE_X+16;
if (players[rankplayer[i]].mo->color)
{
@ -1619,22 +1629,35 @@ static boolean K_drawKartPositionFaces(void)
if (LUA_HudEnabled(hud_battlebumpers))
{
if (gametype == GT_BATTLE && players[rankplayer[i]].kartstuff[k_bumper] > 0)
if ((gametyperules & GTR_BUMPERS) && players[rankplayer[i]].bumpers > 0)
{
V_DrawMappedPatch(bumperx-2, Y, V_HUDTRANS|V_SLIDEIN|V_SNAPTOLEFT, kp_tinybumper[0], colormap);
for (j = 1; j < players[rankplayer[i]].kartstuff[k_bumper]; j++)
for (j = 1; j < players[rankplayer[i]].bumpers; j++)
{
bumperx += 5;
V_DrawMappedPatch(bumperx, Y, V_HUDTRANS|V_SLIDEIN|V_SNAPTOLEFT, kp_tinybumper[1], colormap);
}
}
} // A new level of stupidity: checking if lua is enabled to close a bracket. :Fascinating:
}
}
for (j = 0; j < 7; j++)
{
UINT32 emeraldFlag = (1 << j);
UINT16 emeraldColor = SKINCOLOR_CHAOSEMERALD1 + j;
if (players[rankplayer[i]].powers[pw_emeralds] & emeraldFlag)
{
colormap = R_GetTranslationColormap(TC_DEFAULT, emeraldColor, GTC_CACHE);
V_DrawMappedPatch(emeraldx, Y+7, V_HUDTRANS|V_SLIDEIN|V_SNAPTOLEFT, kp_rankemerald, colormap);
emeraldx += 7;
}
}
if (i == strank)
V_DrawScaledPatch(FACE_X, Y, V_HUDTRANS|V_SLIDEIN|V_SNAPTOLEFT, kp_facehighlight[(leveltime / 4) % 8]);
if (gametype == GT_BATTLE && players[rankplayer[i]].kartstuff[k_bumper] <= 0)
if (gametype == GT_BATTLE && players[rankplayer[i]].bumpers <= 0)
V_DrawScaledPatch(FACE_X-4, Y-3, V_HUDTRANS|V_SLIDEIN|V_SNAPTOLEFT, kp_ranknobumpers);
else
{
@ -1651,6 +1674,59 @@ static boolean K_drawKartPositionFaces(void)
return false;
}
static void K_drawKartEmeralds(void)
{
static const INT32 emeraldOffsets[7][2] = {
{34, 0},
{25, 8},
{43, 8},
{16, 0},
{52, 0},
{7, 8},
{61, 8}
};
const INT32 startx = BASEVIDWIDTH - 77 - 8;
const INT32 starty = BASEVIDHEIGHT - 29 - 8;
INT32 i;
V_DrawScaledPatch(startx, starty, V_HUDTRANS|V_SLIDEIN|V_SNAPTOBOTTOM|V_SNAPTORIGHT, kp_rankemeraldback);
for (i = 0; i < 7; i++)
{
UINT32 emeraldFlag = (1 << i);
UINT16 emeraldColor = SKINCOLOR_CHAOSEMERALD1 + i;
if (stplyr->powers[pw_emeralds] & emeraldFlag)
{
boolean whiteFlash = (leveltime & 1);
UINT8 *colormap;
if (i & 1)
{
whiteFlash = !whiteFlash;
}
colormap = R_GetTranslationColormap(TC_DEFAULT, emeraldColor, GTC_CACHE);
V_DrawMappedPatch(
startx + emeraldOffsets[i][0], starty + emeraldOffsets[i][1],
V_HUDTRANS|V_SLIDEIN|V_SNAPTOBOTTOM|V_SNAPTORIGHT,
kp_rankemerald, colormap
);
if (whiteFlash == true)
{
V_DrawScaledPatch(
startx + emeraldOffsets[i][0], starty + emeraldOffsets[i][1],
V_HUDTRANSHALF|V_SLIDEIN|V_SNAPTOBOTTOM|V_SNAPTORIGHT,
kp_rankemeraldflash
);
}
}
}
}
//
// HU_DrawTabRankings -- moved here to take advantage of kart stuff!
//
@ -1732,11 +1808,11 @@ void K_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, IN
colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo->color, GTC_CACHE);
V_DrawMappedPatch(x, y-4, 0, faceprefix[players[tab[i].num].skin][FACE_RANK], colormap);
/*if (gametype == GT_BATTLE && players[tab[i].num].kartstuff[k_bumper] > 0) -- not enough space for this
/*if (gametype == GT_BATTLE && players[tab[i].num].bumpers > 0) -- not enough space for this
{
INT32 bumperx = x+19;
V_DrawMappedPatch(bumperx-2, y-4, 0, kp_tinybumper[0], colormap);
for (j = 1; j < players[tab[i].num].kartstuff[k_bumper]; j++)
for (j = 1; j < players[tab[i].num].bumpers; j++)
{
bumperx += 5;
V_DrawMappedPatch(bumperx, y-4, 0, kp_tinybumper[1], colormap);
@ -1747,7 +1823,7 @@ void K_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, IN
if (tab[i].num == whiteplayer)
V_DrawScaledPatch(x, y-4, 0, kp_facehighlight[(leveltime / 4) % 8]);
if (gametype == GT_BATTLE && players[tab[i].num].kartstuff[k_bumper] <= 0)
if (gametype == GT_BATTLE && players[tab[i].num].bumpers <= 0)
V_DrawScaledPatch(x-4, y-7, 0, kp_ranknobumpers);
else
{
@ -1915,11 +1991,7 @@ static void K_drawKartLapsAndRings(void)
{
// Laps
V_DrawScaledPatch(LAPS_X, LAPS_Y, V_HUDTRANS|V_SLIDEIN|splitflags, kp_lapsticker);
if (stplyr->exiting)
V_DrawKartString(LAPS_X+33, LAPS_Y+3, V_HUDTRANS|V_SLIDEIN|splitflags, "FIN");
else
V_DrawKartString(LAPS_X+33, LAPS_Y+3, V_HUDTRANS|V_SLIDEIN|splitflags, va("%d/%d", stplyr->laps, cv_numlaps.value));
V_DrawKartString(LAPS_X+33, LAPS_Y+3, V_HUDTRANS|V_SLIDEIN|splitflags, va("%d/%d", min(stplyr->laps, cv_numlaps.value), cv_numlaps.value));
// Rings
if (!uselives)
@ -1963,7 +2035,7 @@ static void K_drawKartSpeedometer(void)
UINT8 labeln = 0;
UINT8 numbers[3];
INT32 splitflags = V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_SPLITSCREEN;
UINT8 battleoffset = 0;
INT32 battleoffset = 0;
if (!stplyr->exiting) // Keep the same speed value as when you crossed the finish line!
{
@ -1998,7 +2070,7 @@ static void K_drawKartSpeedometer(void)
numbers[2] = (convSpeed % 10);
if (gametype == GT_BATTLE)
battleoffset = 8;
battleoffset = -4;
V_DrawScaledPatch(LAPS_X, LAPS_Y-25 + battleoffset, V_HUDTRANS|V_SLIDEIN|splitflags, kp_speedometersticker);
V_DrawScaledPatch(LAPS_X+7, LAPS_Y-25 + battleoffset, V_HUDTRANS|V_SLIDEIN|splitflags, kp_facenum[numbers[0]]);
@ -2007,6 +2079,36 @@ static void K_drawKartSpeedometer(void)
V_DrawScaledPatch(LAPS_X+29, LAPS_Y-25 + battleoffset, V_HUDTRANS|V_SLIDEIN|splitflags, kp_speedometerlabel[labeln]);
}
static void K_drawBlueSphereMeter(void)
{
const UINT8 maxBars = 4;
const UINT8 segColors[] = {73, 64, 52, 54, 55, 35, 34, 33, 202, 180, 181, 182, 164, 165, 166, 153, 152};
const UINT8 sphere = max(min(stplyr->spheres, 40), 0);
UINT8 numBars = min((sphere / 10), maxBars);
UINT8 colorIndex = (sphere * sizeof(segColors)) / (40 + 1);
INT32 x = LAPS_X + 25;
UINT8 i;
V_DrawScaledPatch(LAPS_X, LAPS_Y - 22, V_HUDTRANS|V_SLIDEIN|V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_SPLITSCREEN, kp_spheresticker);
for (i = 0; i <= numBars; i++)
{
UINT8 segLen = 10;
if (i == numBars)
{
segLen = (sphere % 10);
}
V_DrawFill(x, LAPS_Y - 16, segLen, 3, segColors[max(colorIndex-1, 0)] | V_HUDTRANS|V_SLIDEIN|V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_SPLITSCREEN);
V_DrawFill(x, LAPS_Y - 15, segLen, 1, segColors[max(colorIndex-2, 0)] | V_HUDTRANS|V_SLIDEIN|V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_SPLITSCREEN);
V_DrawFill(x, LAPS_Y - 13, segLen, 3, segColors[colorIndex] | V_HUDTRANS|V_SLIDEIN|V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_SPLITSCREEN);
x += 15;
}
}
static void K_drawKartBumpersOrKarma(void)
{
UINT8 *colormap = R_GetTranslationColormap(TC_DEFAULT, stplyr->skincolor, GTC_CACHE);
@ -2070,37 +2172,28 @@ static void K_drawKartBumpersOrKarma(void)
}
else
{
if (stplyr->kartstuff[k_bumper] <= 0)
INT32 maxbumper = K_StartingBumperCount();
V_DrawMappedPatch(fx+1, fy-2, V_HUDTRANS|V_SLIDEIN|splitflags, kp_rankbumper, colormap);
if (stplyr->bumpers > 9 || maxbumper > 9)
{
V_DrawMappedPatch(fx+1, fy-2, V_HUDTRANS|V_SLIDEIN|splitflags, kp_splitkarmabomb, colormap);
V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|V_SLIDEIN|splitflags, kp_facenum[(stplyr->kartstuff[k_comebackpoints]) % 10]);
V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|V_SLIDEIN|splitflags, kp_facenum[2]);
UINT8 ln[2];
ln[0] = (stplyr->bumpers / 10 % 10);
ln[1] = (stplyr->bumpers % 10);
V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|V_SLIDEIN|splitflags, fontv[PINGNUM_FONT].font[ln[0]]);
V_DrawScaledPatch(fx+17, fy, V_HUDTRANS|V_SLIDEIN|splitflags, fontv[PINGNUM_FONT].font[ln[1]]);
ln[0] = ((abs(maxbumper) / 10) % 10);
ln[1] = (abs(maxbumper) % 10);
V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|V_SLIDEIN|splitflags, fontv[PINGNUM_FONT].font[ln[0]]);
V_DrawScaledPatch(fx+31, fy, V_HUDTRANS|V_SLIDEIN|splitflags, fontv[PINGNUM_FONT].font[ln[1]]);
}
else
{
INT32 maxbumper = K_StartingBumperCount();
V_DrawMappedPatch(fx+1, fy-2, V_HUDTRANS|V_SLIDEIN|splitflags, kp_rankbumper, colormap);
if (stplyr->kartstuff[k_bumper] > 9 || maxbumper > 9)
{
UINT8 ln[2];
ln[0] = ((abs(stplyr->kartstuff[k_bumper]) / 10) % 10);
ln[1] = (abs(stplyr->kartstuff[k_bumper]) % 10);
V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|V_SLIDEIN|splitflags, fontv[PINGNUM_FONT].font[ln[0]]);
V_DrawScaledPatch(fx+17, fy, V_HUDTRANS|V_SLIDEIN|splitflags, fontv[PINGNUM_FONT].font[ln[1]]);
ln[0] = ((abs(maxbumper) / 10) % 10);
ln[1] = (abs(maxbumper) % 10);
V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|V_SLIDEIN|splitflags, fontv[PINGNUM_FONT].font[ln[0]]);
V_DrawScaledPatch(fx+31, fy, V_HUDTRANS|V_SLIDEIN|splitflags, fontv[PINGNUM_FONT].font[ln[1]]);
}
else
{
V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|V_SLIDEIN|splitflags, kp_facenum[(stplyr->kartstuff[k_bumper]) % 10]);
V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|V_SLIDEIN|splitflags, kp_facenum[(maxbumper) % 10]);
}
V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|V_SLIDEIN|splitflags, kp_facenum[(stplyr->bumpers) % 10]);
V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|V_SLIDEIN|splitflags, kp_facenum[(maxbumper) % 10]);
}
}
}
@ -2116,22 +2209,14 @@ static void K_drawKartBumpersOrKarma(void)
}
else
{
if (stplyr->kartstuff[k_bumper] <= 0)
{
V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|V_SLIDEIN|splitflags, kp_karmasticker, colormap);
V_DrawKartString(LAPS_X+47, LAPS_Y+3, V_HUDTRANS|V_SLIDEIN|splitflags, va("%d/2", stplyr->kartstuff[k_comebackpoints]));
}
INT32 maxbumper = K_StartingBumperCount();
if (stplyr->bumpers > 9 && maxbumper > 9)
V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|V_SLIDEIN|splitflags, kp_bumperstickerwide, colormap);
else
{
INT32 maxbumper = K_StartingBumperCount();
V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|V_SLIDEIN|splitflags, kp_bumpersticker, colormap);
if (stplyr->kartstuff[k_bumper] > 9 && maxbumper > 9)
V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|V_SLIDEIN|splitflags, kp_bumperstickerwide, colormap);
else
V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|V_SLIDEIN|splitflags, kp_bumpersticker, colormap);
V_DrawKartString(LAPS_X+47, LAPS_Y+3, V_HUDTRANS|V_SLIDEIN|splitflags, va("%d/%d", stplyr->kartstuff[k_bumper], maxbumper));
}
V_DrawKartString(LAPS_X+47, LAPS_Y+3, V_HUDTRANS|V_SLIDEIN|splitflags, va("%d/%d", stplyr->bumpers, maxbumper));
}
}
}
@ -2142,6 +2227,9 @@ static void K_drawKartWanted(void)
UINT8 *colormap = NULL;
INT32 basex = 0, basey = 0;
if (!splitscreen)
return;
if (stplyr != &players[displayplayers[0]])
return;
@ -2554,6 +2642,18 @@ static void K_drawKartNameTags(void)
continue;
}
if (ntplayer->mo->drawflags & K_GetPlayerDontDrawFlag(stplyr))
{
// Invisible on this screen
continue;
}
if ((gametyperules & GTR_BUMPERS) && (ntplayer->bumpers <= 0))
{
// Dead in Battle
continue;
}
if (!P_CheckSight(stplyr->mo, ntplayer->mo))
{
// Can't see
@ -2876,7 +2976,7 @@ static void K_drawKartMinimap(void)
if (i != displayplayers[0] || r_splitscreen)
{
if (gametype == GT_BATTLE && players[i].kartstuff[k_bumper] <= 0)
if (gametype == GT_BATTLE && players[i].bumpers <= 0)
continue;
if (players[i].kartstuff[k_hyudorotimer] > 0)
@ -3312,9 +3412,9 @@ static void K_drawBattleFullscreen(void)
else
K_drawKartFinish();
}
else if (stplyr->kartstuff[k_bumper] <= 0 && stplyr->kartstuff[k_comebacktimer] && comeback && !stplyr->spectator && drawcomebacktimer)
else if (stplyr->bumpers <= 0 && stplyr->karmadelay && comeback && !stplyr->spectator && drawcomebacktimer)
{
UINT16 t = stplyr->kartstuff[k_comebacktimer]/(10*TICRATE);
UINT16 t = stplyr->karmadelay/(10*TICRATE);
INT32 txoff, adjust = (r_splitscreen > 1) ? 4 : 6; // normal string is 8, kart string is 12, half of that for ease
INT32 ty = (BASEVIDHEIGHT/2)+66;
@ -3344,11 +3444,11 @@ static void K_drawBattleFullscreen(void)
V_DrawFixedPatch(x<<FRACBITS, y<<FRACBITS, scale, splitflags, kp_battlewait, NULL);
if (r_splitscreen > 1)
V_DrawString(x-txoff, ty, 0, va("%d", stplyr->kartstuff[k_comebacktimer]/TICRATE));
V_DrawString(x-txoff, ty, 0, va("%d", stplyr->karmadelay/TICRATE));
else
{
V_DrawFixedPatch(x<<FRACBITS, ty<<FRACBITS, scale, 0, kp_timeoutsticker, NULL);
V_DrawKartString(x-txoff, ty, 0, va("%d", stplyr->kartstuff[k_comebacktimer]/TICRATE));
V_DrawKartString(x-txoff, ty, 0, va("%d", stplyr->karmadelay/TICRATE));
}
}
@ -3535,7 +3635,7 @@ static void K_drawInput(void)
#define BUTTH 11
#define drawbutt(xoffs, butt, symb)\
if (stplyr->cmd.buttons & butt)\
if (!stplyr->exiting && (cmd->buttons & butt))\
{\
offs = 2;\
col = accent1;\
@ -3561,7 +3661,7 @@ static void K_drawInput(void)
y -= 1;
if (!cmd->turning) // no turn
if (stplyr->exiting || !cmd->turning) // no turn
target = 0;
else // turning of multiple strengths!
{
@ -3770,8 +3870,8 @@ static void K_drawDistributionDebugger(void)
if (!playeringame[i] || players[i].spectator)
continue;
pingame++;
if (players[i].kartstuff[k_bumper] > bestbumper)
bestbumper = players[i].kartstuff[k_bumper];
if (players[i].bumpers > bestbumper)
bestbumper = players[i].bumpers;
}
// lovely double loop......
@ -3892,11 +3992,12 @@ void K_drawKartHUD(void)
return;
}
battlefullscreen = ((gametype == GT_BATTLE)
battlefullscreen = ((gametyperules & (GTR_BUMPERS|GTR_KARMA)) == (GTR_BUMPERS|GTR_KARMA)
&& (stplyr->exiting
|| (stplyr->kartstuff[k_bumper] <= 0
&& stplyr->kartstuff[k_comebacktimer]
&& comeback
|| (stplyr->bumpers <= 0
&& stplyr->karmadelay > 0
&& stplyr->eliminated == false
&& comeback == true
&& stplyr->playerstate == PST_LIVE)));
if (!demo.title && (!battlefullscreen || r_splitscreen))
@ -4008,6 +4109,11 @@ void K_drawKartHUD(void)
if (LUA_HudEnabled(hud_gametypeinfo))
K_drawKartBumpersOrKarma();
}
if (gametyperules & GTR_SPHERES)
{
K_drawBlueSphereMeter();
}
}
// Draw the countdowns after everything else.
@ -4097,4 +4203,9 @@ void K_drawKartHUD(void)
}
K_DrawWaypointDebugger();
if (gametype == GT_BATTLE)
{
K_drawKartEmeralds();
}
}

File diff suppressed because it is too large Load diff

View file

@ -27,7 +27,7 @@ UINT8 K_FindUseodds(player_t *player, fixed_t mashed, UINT32 pdis, UINT8 bestbum
INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean spbrush, boolean bot, boolean rival);
INT32 K_GetShieldFromItem(INT32 item);
fixed_t K_GetMobjWeight(mobj_t *mobj, mobj_t *against);
void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid);
boolean K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid);
void K_KartPainEnergyFling(player_t *player);
void K_FlipFromObject(mobj_t *mo, mobj_t *master);
void K_MatchGenericExtraFlags(mobj_t *mo, mobj_t *master);
@ -42,13 +42,14 @@ void K_KartPlayerAfterThink(player_t *player);
angle_t K_MomentumAngle(mobj_t *mo);
void K_SetHitLagForObjects(mobj_t *mo1, mobj_t *mo2, INT32 tics);
void K_DoInstashield(player_t *player);
void K_BattleHitPlayer(player_t *player, player_t *victim, UINT8 points, boolean reducewanted);
void K_RemoveBumper(player_t *player, mobj_t *inflictor, mobj_t *source);
void K_BattleAwardHit(player_t *player, player_t *victim, mobj_t *inflictor, UINT8 bumpersRemoved);
void K_SpinPlayer(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 type);
void K_TumblePlayer(player_t *player, mobj_t *inflictor, mobj_t *source);
void K_ExplodePlayer(player_t *player, mobj_t *inflictor, mobj_t *source);
void K_DebtStingPlayer(player_t *player, mobj_t *source);
void K_StealBumper(player_t *player, player_t *victim);
void K_HandleBumperChanges(player_t *player, UINT8 prevBumpers);
void K_DestroyBumpers(player_t *player, UINT8 amount);
void K_TakeBumpersFromPlayer(player_t *player, player_t *victim, UINT8 amount);
void K_SpawnKartExplosion(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 number, mobjtype_t type, angle_t rotangle, boolean spawncenter, boolean ghostit, mobj_t *source);
void K_SpawnMineExplosion(mobj_t *source, UINT8 color);
UINT16 K_DriftSparkColor(player_t *player, INT32 charge);
@ -72,6 +73,7 @@ INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue);
INT32 K_GetKartDriftSparkValue(player_t *player);
void K_SpawnDriftBoostExplosion(player_t *player, int stage);
void K_KartUpdatePosition(player_t *player);
mobj_t *K_CreatePaperItem(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8 flip, UINT8 type, UINT8 amount);
void K_DropItems(player_t *player);
void K_DropRocketSneaker(player_t *player);
void K_DropKitchenSink(player_t *player);

View file

@ -314,7 +314,7 @@ waypoint_t *K_GetBestWaypointForMobj(mobj_t *const mobj)
}
else if (checkdist < closestdist && bestfindist == INT32_MAX)
{
if (!P_CheckSight(mobj, checkwaypoint->mobj))
if (!P_TraceBlockingLines(mobj, checkwaypoint->mobj))
{
// Save sight checks for the end, so we only do it if we have to
continue;

View file

@ -1410,6 +1410,18 @@ static int lib_pCheckSight(lua_State *L)
return 1;
}
static int lib_pTraceBlockingLines(lua_State *L)
{
mobj_t *t1 = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
mobj_t *t2 = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
//HUDSAFE?
INLEVEL
if (!t1 || !t2)
return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_TraceBlockingLines(t1, t2));
return 1;
}
static int lib_pCheckHoopPosition(lua_State *L)
{
mobj_t *hoopthing = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
@ -3432,16 +3444,17 @@ static int lib_kExplodePlayer(lua_State *L)
return 0;
}
static int lib_kStealBumper(lua_State *L)
static int lib_kTakeBumpersFromPlayer(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
player_t *victim = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
UINT8 amount = (UINT8)luaL_optinteger(L, 3, 1);
NOHUD
if (!player)
return LUA_ErrInvalid(L, "player_t");
if (!victim)
return LUA_ErrInvalid(L, "player_t");
K_StealBumper(player, victim);
K_TakeBumpersFromPlayer(player, victim, amount);
return 0;
}
@ -3782,6 +3795,7 @@ static luaL_Reg lib[] = {
{"P_SlideMove",lib_pSlideMove},
{"P_BounceMove",lib_pBounceMove},
{"P_CheckSight", lib_pCheckSight},
{"P_TraceBlockingLines", lib_pTraceBlockingLines},
{"P_CheckHoopPosition",lib_pCheckHoopPosition},
{"P_RadiusAttack",lib_pRadiusAttack},
{"P_FloorzAtPos",lib_pFloorzAtPos},
@ -3918,7 +3932,7 @@ static luaL_Reg lib[] = {
{"K_SpinPlayer",lib_kSpinPlayer},
{"K_TumblePlayer",lib_kTumblePlayer},
{"K_ExplodePlayer",lib_kExplodePlayer},
{"K_StealBumper",lib_kStealBumper},
{"K_TakeBumpersFromPlayer",lib_kTakeBumpersFromPlayer},
{"K_SpawnKartExplosion",lib_kSpawnKartExplosion},
{"K_SpawnMineExplosion",lib_kSpawnMineExplosion},
{"K_SpawnBoostTrail",lib_kSpawnBoostTrail},

View file

@ -313,8 +313,6 @@ static int PopPivotSubTable(spriteframepivot_t *pivot, lua_State *L, int stk, in
pivot[idx].x = (INT32)value;
else if (ikey == 2 || (key && fastcmp(key, "y")))
pivot[idx].y = (INT32)value;
else if (ikey == 3 || (key && fastcmp(key, "rotaxis")))
pivot[idx].rotaxis = (UINT8)value;
else if (ikey == -1 && (key != NULL))
FIELDERROR("pivot key", va("invalid option %s", key));
okcool = 1;
@ -579,8 +577,6 @@ static int framepivot_get(lua_State *L)
lua_pushinteger(L, framepivot->x);
else if (fastcmp("y", field))
lua_pushinteger(L, framepivot->y);
else if (fastcmp("rotaxis", field))
lua_pushinteger(L, (UINT8)framepivot->rotaxis);
else
return luaL_error(L, va("Field %s does not exist in spriteframepivot_t", field));
@ -605,8 +601,6 @@ static int framepivot_set(lua_State *L)
framepivot->x = luaL_checkinteger(L, 3);
else if (fastcmp("y", field))
framepivot->y = luaL_checkinteger(L, 3);
else if (fastcmp("rotaxis", field))
framepivot->rotaxis = luaL_checkinteger(L, 3);
else
return luaL_error(L, va("Field %s does not exist in spriteframepivot_t", field));

View file

@ -14,7 +14,7 @@
//#include "fastcmp.h"
#include "tables.h"
#include "p_local.h"
#include "doomstat.h" // for ALL7EMERALDS
#include "doomstat.h" // for ALLCHAOSEMERALDS
#include "lua_script.h"
#include "lua_libs.h"
@ -162,7 +162,7 @@ static int lib_getsecspecial(lua_State *L)
static int lib_all7emeralds(lua_State *L)
{
lua_pushboolean(L, ALL7EMERALDS(luaL_checkinteger(L, 1)));
lua_pushboolean(L, ALLCHAOSEMERALDS(luaL_checkinteger(L, 1)));
return 1;
}

View file

@ -206,6 +206,8 @@ static int player_get(lua_State *L)
lua_pushangle(L, plr->drawangle);
else if (fastcmp(field,"rings"))
lua_pushinteger(L, plr->rings);
else if (fastcmp(field,"spheres"))
lua_pushinteger(L, plr->spheres);
else if (fastcmp(field,"powers"))
LUA_PushUserdata(L, plr->powers, META_POWERS);
else if (fastcmp(field,"kartstuff"))
@ -218,6 +220,16 @@ static int player_get(lua_State *L)
lua_pushinteger(L, plr->tumbleHeight);
else if (fastcmp(field,"tumbleLastBounce"))
lua_pushboolean(L, plr->tumbleLastBounce);
else if (fastcmp(field,"trickpanel"))
lua_pushinteger(L, plr->trickpanel);
else if (fastcmp(field,"trickdelay"))
lua_pushinteger(L, plr->trickdelay);
else if (fastcmp(field,"trickmomx"))
lua_pushfixed(L, plr->trickmomx);
else if (fastcmp(field,"trickmomy"))
lua_pushfixed(L, plr->trickmomy);
else if (fastcmp(field,"trickmomz"))
lua_pushfixed(L, plr->trickmomz);
else if (fastcmp(field,"pflags"))
lua_pushinteger(L, plr->pflags);
else if (fastcmp(field,"panim"))
@ -481,6 +493,8 @@ static int player_set(lua_State *L)
plr->drawangle = luaL_checkangle(L, 3);
else if (fastcmp(field,"rings"))
plr->rings = (INT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"spheres"))
plr->spheres = (INT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"powers"))
return NOSET;
else if (fastcmp(field,"pflags"))
@ -511,6 +525,16 @@ static int player_set(lua_State *L)
plr->tumbleHeight = (UINT16)luaL_checkinteger(L, 3);
else if (fastcmp(field,"tumbleLastBounce"))
plr->tumbleLastBounce = luaL_checkboolean(L, 3);
else if (fastcmp(field,"trickpanel"))
plr->trickpanel = luaL_checkinteger(L, 3);
else if (fastcmp(field,"trickdelay"))
plr->trickdelay = (tic_t)luaL_checkinteger(L, 3);
else if (fastcmp(field,"trickmomx"))
plr->trickmomx = (fixed_t)luaL_checkfixed(L, 3);
else if (fastcmp(field,"trickmomy"))
plr->trickmomy = (fixed_t)luaL_checkfixed(L, 3);
else if (fastcmp(field,"trickmomz"))
plr->trickmomz = (fixed_t)luaL_checkfixed(L, 3);
else if (fastcmp(field,"kartspeed"))
plr->kartspeed = (UINT8)luaL_checkinteger(L, 3);
else if (fastcmp(field,"kartweight"))

View file

@ -771,12 +771,13 @@ void Command_Savecheckpoint_f(void)
}
// Like M_GetAllEmeralds() but for console devmode junkies.
/*void Command_Getallemeralds_f(void)
/*
void Command_Getallemeralds_f(void)
{
REQUIRE_SINGLEPLAYER;
REQUIRE_PANDORA;
emeralds = ((EMERALD7)*2)-1;
emeralds = EMERALD_ALL;
CONS_Printf(M_GetText("You now have all 7 emeralds.\n"));
}
@ -788,7 +789,8 @@ void Command_Resetemeralds_f(void)
emeralds = 0;
CONS_Printf(M_GetText("Emeralds reset to zero.\n"));
}*/
}
*/
void Command_Devmode_f(void)
{

View file

@ -341,6 +341,12 @@ UINT8 M_CompletionEmblems(void) // Bah! Duplication sucks, but it's for a separa
UINT8 M_AnySecretUnlocked(void)
{
INT32 i;
#ifdef DEVELOP
if (1)
return true;
#endif
for (i = 0; i < MAXUNLOCKABLES; ++i)
{
if (!unlockables[i].nocecho && unlockables[i].unlocked)
@ -376,6 +382,12 @@ UINT8 M_SecretUnlocked(INT32 type)
UINT8 M_MapLocked(INT32 mapnum)
{
#ifdef DEVELOP
if (1)
return false;
#endif
if (!mapheaderinfo[mapnum-1] || mapheaderinfo[mapnum-1]->unlockrequired < 0)
return false;
if (!unlockables[mapheaderinfo[mapnum-1]->unlockrequired].unlocked)

View file

@ -6374,7 +6374,7 @@ static void M_GetAllEmeralds(INT32 choice)
{
(void)choice;
emeralds = ((EMERALD7)*2)-1;
emeralds = EMERALD_ALL;
M_StartMessage(M_GetText("You now have all 7 emeralds.\nUse them wisely.\nWith great power comes great ring drain.\n"),NULL,MM_NOTHING);
G_SetGameModified(multiplayer, true);
@ -8139,11 +8139,11 @@ static void M_ReplayTimeAttack(INT32 choice)
break;
case 3: // guest
// srb2/replay/main/map01-guest.lmp
G_DoPlayDemo(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-guest.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value)));
G_DoPlayDemo(va("%s"PATHSEP"media"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-guest.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value)));
return;
}
// srb2/replay/main/map01-sonic-time-best.lmp
G_DoPlayDemo(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), cv_chooseskin.string, which));
G_DoPlayDemo(va("%s"PATHSEP"media"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), cv_chooseskin.string, which));
}
/*else if (currentMenu == &SP_NightsReplayDef)
{
@ -8165,13 +8165,13 @@ static void M_ReplayTimeAttack(INT32 choice)
break;
}
// srb2/replay/main/map01-score-best.lmp
G_DoPlayDemo(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), which));
G_DoPlayDemo(va("%s"PATHSEP"media"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), which));
}*/
}
static void M_EraseGuest(INT32 choice)
{
const char *rguest = va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-guest.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value));
const char *rguest = va("%s"PATHSEP"media"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-guest.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value));
(void)choice;
if (FIL_FileExists(rguest))
remove(rguest);
@ -8186,10 +8186,10 @@ static void M_EraseGuest(INT32 choice)
static void M_OverwriteGuest(const char *which)
{
char *rguest = Z_StrDup(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-guest.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value)));
char *rguest = Z_StrDup(va("%s"PATHSEP"media"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-guest.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value)));
UINT8 *buf;
size_t len;
len = FIL_ReadFile(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), cv_chooseskin.string, which), &buf);
len = FIL_ReadFile(va("%s"PATHSEP"media"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), cv_chooseskin.string, which), &buf);
if (!len) {
return;
}
@ -8258,7 +8258,7 @@ static void M_SetGuestReplay(INT32 choice)
M_StartMessage(M_GetText("Are you sure you want to\ndelete the guest replay data?\n\n(Press 'Y' to confirm)\n"),M_EraseGuest,MM_YESNO);
return;
}
if (FIL_FileExists(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-guest.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value))))
if (FIL_FileExists(va("%s"PATHSEP"media"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-guest.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value))))
M_StartMessage(M_GetText("Are you sure you want to\noverwrite the guest replay data?\n\n(Press 'Y' to confirm)\n"),which,MM_YESNO);
else
which(0);

View file

@ -4428,7 +4428,7 @@ static inline boolean PIT_GrenadeRing(mobj_t *thing)
return true;
if (thing->player && (thing->player->kartstuff[k_hyudorotimer]
|| ((gametyperules & GTR_BUMPERS) && thing->player && thing->player->kartstuff[k_bumper] <= 0 && thing->player->kartstuff[k_comebacktimer])))
|| ((gametyperules & GTR_BUMPERS) && thing->player && thing->player->bumpers <= 0 && thing->player->karmadelay)))
return true;
// see if it went over / under
@ -4457,9 +4457,6 @@ void A_GrenadeRing(mobj_t *actor)
if (actor->flags2 & MF2_DEBRIS)
return;
if (actor->hitlag > 0)
return;
if (actor->state == &states[S_SSMINE_DEPLOY8])
explodedist = (3*explodedist)/2;
@ -4484,7 +4481,7 @@ static inline boolean PIT_MineExplode(mobj_t *thing)
if (!grenade || P_MobjWasRemoved(grenade))
return false; // There's the possibility these can chain react onto themselves after they've already died if there are enough all in one spot
if (grenade->flags2 & MF2_DEBRIS) // don't explode twice
if (grenade->flags2 & MF2_DEBRIS) // don't explode twice
return false;
if (thing == grenade || thing->type == MT_MINEEXPLOSIONSOUND) // Don't explode yourself! Endless loop!
@ -4496,7 +4493,7 @@ static inline boolean PIT_MineExplode(mobj_t *thing)
if (netgame && thing->player && thing->player->spectator)
return true;
if ((gametyperules & GTR_BUMPERS) && grenade->target && grenade->target->player && grenade->target->player->kartstuff[k_bumper] <= 0 && thing == grenade->target)
if ((gametyperules & GTR_BUMPERS) && grenade->target && grenade->target->player && grenade->target->player->bumpers <= 0 && thing == grenade->target)
return true;
// see if it went over / under
@ -4527,9 +4524,6 @@ void A_SSMineExplode(mobj_t *actor)
if (actor->flags2 & MF2_DEBRIS)
return;
if (actor->hitlag > 0)
return;
type = (mobjtype_t)locvar1;
// Use blockmap to check for nearby shootables
@ -8648,7 +8642,7 @@ void A_ItemPop(mobj_t *actor)
if (actor->info->deathsound)
S_StartSound(remains, actor->info->deathsound);
if (!((gametyperules & GTR_BUMPERS) && actor->target->player->kartstuff[k_bumper] <= 0))
if (!((gametyperules & GTR_BUMPERS) && actor->target->player->bumpers <= 0))
actor->target->player->kartstuff[k_itemroulette] = 1;
remains->flags2 &= ~MF2_AMBUSH;
@ -8682,7 +8676,7 @@ void A_JawzChase(mobj_t *actor)
angle_t angledelta = actor->angle - targetangle;
boolean turnclockwise = true;
if ((gametyperules & GTR_CIRCUIT))
if (gametyperules & GTR_CIRCUIT)
{
const fixed_t distbarrier = FixedMul(512*mapobjectscale, FRACUNIT + ((gamespeed-1) * (FRACUNIT/4)));
const fixed_t distaway = P_AproxDistance(actor->tracer->x - actor->x, actor->tracer->y - actor->y);
@ -9009,7 +9003,7 @@ void A_SPBChase(mobj_t *actor)
actor->lastlook = actor->tracer->player-players; // Save the player num for death scumming...
actor->tracer->player->kartstuff[k_ringlock] = 1; // set ring lock
if (!P_IsObjectOnGround(actor->tracer) /*&& !actor->tracer->player->kartstuff[k_pogospring]*/)
if (!P_IsObjectOnGround(actor->tracer))
{
// In the air you have no control; basically don't hit unless you make a near complete stop
defspeed = (7 * actor->tracer->player->speed) / 8;
@ -9714,7 +9708,7 @@ void A_ReaperThinker(mobj_t *actor)
continue;
player = &players[i];
if (player && player->mo && player->kartstuff[k_bumper] && player->score >= maxscore)
if (player && player->mo && player->bumpers && player->score >= maxscore)
{
targetplayermo = player->mo;
maxscore = player->score;

View file

@ -2371,7 +2371,7 @@ void EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher)
P_SetThingPosition(thing);
if (thing->flags & MF_SHOOTABLE)
P_DamageMobj(thing, puncher, puncher, 1, DMG_NORMAL);
else if (thing->type == MT_RING || thing->type == MT_COIN || thing->type == MT_RANDOMITEM)
else if (thing->type == MT_RING || thing->type == MT_RANDOMITEM)
{
thing->momz = FixedMul(3*FRACUNIT, thing->scale);
P_TouchSpecialThing(thing, puncher, false);

View file

@ -30,7 +30,7 @@
#include "f_finale.h"
// SRB2kart
#include "k_kart.h"
#include "k_kart.h"
#include "k_battle.h"
#include "k_pwrlv.h"
#include "k_grandprix.h"
@ -108,11 +108,13 @@ void P_RampConstant(const BasicFF_t *FFInfo, INT32 Start, INT32 End)
//
boolean P_CanPickupItem(player_t *player, UINT8 weapon)
{
if (player->exiting || mapreset)
if (player->exiting || mapreset || player->eliminated)
return false;
/*if ((gametyperules & GTR_BUMPERS) && player->kartstuff[k_bumper] <= 0) // No bumpers in Match
return false;*/
#ifndef OTHERKARMAMODES
if ((gametyperules & GTR_BUMPERS) && player->bumpers <= 0) // No bumpers in Match
return false;
#endif
if (weapon)
{
@ -182,15 +184,24 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (heightcheck)
{
fixed_t toucher_bottom = toucher->z;
fixed_t special_bottom = special->z;
if (toucher->flags & MF_PICKUPFROMBELOW)
toucher_bottom -= toucher->height;
if (special->flags & MF_PICKUPFROMBELOW)
special_bottom -= special->height;
if (toucher->momz < 0) {
if (toucher->z + toucher->momz > special->z + special->height)
if (toucher_bottom + toucher->momz > special->z + special->height)
return;
} else if (toucher->z > special->z + special->height)
} else if (toucher_bottom > special->z + special->height)
return;
if (toucher->momz > 0) {
if (toucher->z + toucher->height + toucher->momz < special->z)
if (toucher->z + toucher->height + toucher->momz < special_bottom)
return;
} else if (toucher->z + toucher->height < special->z)
} else if (toucher->z + toucher->height < special_bottom)
return;
}
@ -231,11 +242,11 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
P_SetObjectMomZ(player->mo, 12<<FRACBITS, false);
P_InstaThrust(player->mo, player->mo->angle, 20<<FRACBITS);
return;
case MT_FLOATINGITEM: // SRB2kart
case MT_FLOATINGITEM: // SRB2Kart
if (!P_CanPickupItem(player, 3) || (player->kartstuff[k_itemamount] && player->kartstuff[k_itemtype] != special->threshold))
return;
if ((gametyperules & GTR_BUMPERS) && player->kartstuff[k_bumper] <= 0)
if ((gametyperules & GTR_BUMPERS) && player->bumpers <= 0)
return;
player->kartstuff[k_itemtype] = special->threshold;
@ -252,15 +263,19 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
special->flags &= ~MF_SPECIAL;
return;
case MT_RANDOMITEM: // SRB2kart
case MT_RANDOMITEM:
if (!P_CanPickupItem(player, 1))
return;
if ((gametyperules & GTR_BUMPERS) && player->kartstuff[k_bumper] <= 0)
if ((gametyperules & GTR_BUMPERS) && player->bumpers <= 0)
{
if (player->kartstuff[k_comebackmode] || player->kartstuff[k_comebacktimer])
#ifdef OTHERKARMAMODES
if (player->kartstuff[k_comebackmode] || player->karmadelay)
return;
player->kartstuff[k_comebackmode] = 1;
#else
return;
#endif
}
special->momx = special->momy = special->momz = 0;
@ -272,7 +287,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
return;
if (player == special->target->player)
return;
if (player->kartstuff[k_bumper] <= 0)
if (player->bumpers <= 0)
return;
if (special->target->player->exiting || player->exiting)
return;
@ -280,53 +295,38 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (P_PlayerInPain(special->target->player))
return;
if (special->target->player->karmadelay > 0)
return;
#ifdef OTHERKARMAMODES
if (!special->target->player->kartstuff[k_comebackmode])
{
if (player->kartstuff[k_growshrinktimer]
|| player->kartstuff[k_hyudorotimer] || P_PlayerInPain(player)
|| player->kartstuff[k_invincibilitytimer] || player->powers[pw_flashing])
return;
else
#endif
{
mobj_t *boom = P_SpawnMobj(special->target->x, special->target->y, special->target->z, MT_BOOMEXPLODE);
UINT8 ptadd = (K_IsPlayerWanted(player) ? 2 : 1);
mobj_t *boom;
if (P_DamageMobj(toucher, special, special->target, 1, DMG_KARMA) == false)
{
return;
}
boom = P_SpawnMobj(special->target->x, special->target->y, special->target->z, MT_BOOMEXPLODE);
boom->scale = special->target->scale;
boom->destscale = special->target->scale;
boom->momz = 5*FRACUNIT;
if (special->target->color)
boom->color = special->target->color;
else
boom->color = SKINCOLOR_KETCHUP;
S_StartSound(boom, special->info->attacksound);
if (player->kartstuff[k_bumper] == 1) // If you have only one bumper left, and see if it's a 1v1
{
INT32 numingame = 0;
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator || players[i].kartstuff[k_bumper] <= 0)
continue;
numingame++;
}
if (numingame <= 2) // If so, then an extra karma point so they are 100% certain to switch places; it's annoying to end matches with a bomb kill
ptadd++;
}
special->target->player->kartstuff[k_comebackpoints] += ptadd;
if (ptadd > 1)
special->target->player->karthud[khud_yougotem] = 2*TICRATE;
if (special->target->player->kartstuff[k_comebackpoints] >= 2)
K_StealBumper(special->target->player, player);
special->target->player->kartstuff[k_comebacktimer] = comebacktime;
P_DamageMobj(toucher, special, special->target, 1, DMG_EXPLODE);
special->target->player->karthud[khud_yougotem] = 2*TICRATE;
special->target->player->karmadelay = comebacktime;
}
#ifdef OTHERKARMAMODES
}
else if (special->target->player->kartstuff[k_comebackmode] == 1 && P_CanPickupItem(player, 1))
{
@ -349,8 +349,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
special->target->player->kartstuff[k_comebackpoints]++;
if (special->target->player->kartstuff[k_comebackpoints] >= 2)
K_StealBumper(special->target->player, player);
special->target->player->kartstuff[k_comebacktimer] = comebacktime;
K_StealBumper(special->target->player, player, 1);
special->target->player->karmadelay = comebacktime;
player->kartstuff[k_itemroulette] = 1;
player->kartstuff[k_roulettetype] = 1;
@ -362,13 +362,13 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
S_StartSound(poof, special->info->seesound);
if (player->kartstuff[k_bumper] == 1) // If you have only one bumper left, and see if it's a 1v1
if (player->bumpers == 1) // If you have only one bumper left, and see if it's a 1v1
{
INT32 numingame = 0;
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator || players[i].kartstuff[k_bumper] <= 0)
if (!playeringame[i] || players[i].spectator || players[i].bumpers <= 0)
continue;
numingame++;
}
@ -384,9 +384,9 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
special->target->player->karthud[khud_yougotem] = 2*TICRATE;
if (special->target->player->kartstuff[k_comebackpoints] >= 2)
K_StealBumper(special->target->player, player);
K_StealBumper(special->target->player, player, 1);
special->target->player->kartstuff[k_comebacktimer] = comebacktime;
special->target->player->karmadelay = comebacktime;
K_DropItems(player); //K_StripItems(player);
//K_StripOther(player);
@ -404,6 +404,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
special->target->player->kartstuff[k_eggmanblame] = -1;
}
#endif
return;
case MT_SPB:
if ((special->target == toucher || special->target == toucher->target) && (special->threshold > 0))
@ -441,10 +442,25 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
P_DamageMobj(player->mo, special, special->target, 1, DMG_NORMAL);
}
return;
/*case MT_EERIEFOG:
case MT_EMERALD:
if (!P_CanPickupItem(player, 0))
return;
if (special->threshold > 0)
return;
if (toucher->hitlag > 0)
return;
player->powers[pw_emeralds] |= special->extravalue1;
K_CheckEmeralds(player);
break;
/*
case MT_EERIEFOG:
special->frame &= ~FF_TRANS80;
special->frame |= FF_TRANS90;
return;*/
return;
*/
case MT_SMK_MOLE:
if (special->target && !P_MobjWasRemoved(special->target))
return;
@ -473,7 +489,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
S_StartSound(special, sfx_s1a2);
return;
case MT_CDUFO: // SRB2kart
if (special->fuse || !P_CanPickupItem(player, 1) || ((gametyperules & GTR_BUMPERS) && player->kartstuff[k_bumper] <= 0))
if (special->fuse || !P_CanPickupItem(player, 1) || ((gametyperules & GTR_BUMPERS) && player->bumpers <= 0))
return;
player->kartstuff[k_itemroulette] = 1;
@ -552,6 +568,22 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
return;
case MT_BLUESPHERE:
if (!(P_CanPickupItem(player, 0)))
return;
// Reached the cap, don't waste 'em!
if (player->spheres >= 40)
return;
// Not alive
if ((gametyperules & GTR_BUMPERS) && (player->bumpers <= 0))
return;
special->momx = special->momy = special->momz = 0;
player->spheres++;
break;
// Secret emblem thingy
case MT_EMBLEM:
{
@ -713,7 +745,7 @@ void P_TouchStarPost(mobj_t *post, player_t *player, boolean snaptopost)
}
// Easily make it so that overtime works offline
//#define TESTOVERTIMEINFREEPLAY
#define TESTOVERTIMEINFREEPLAY
/** Checks if the level timer is over the timelimit and the round should end,
* unless you are in overtime. In which case leveltime may stretch out beyond
@ -730,11 +762,10 @@ void P_CheckTimeLimit(void)
if (!cv_timelimit.value)
return;
if (!(multiplayer || netgame))
return;
#ifndef TESTOVERTIMEINFREEPLAY
if (battlecapsules) // capsules override any time limit settings
return;
#endif
if (!(gametyperules & GTR_TIMELIMIT))
return;
@ -753,58 +784,53 @@ void P_CheckTimeLimit(void)
{
if (!playeringame[i] || players[i].spectator)
continue;
if (foundone)
{
#endif
// Initiate the kill zone
if (!battleovertime.enabled)
{
INT32 b = 0;
thinker_t *th;
mobj_t *item = NULL;
mobj_t *center = NULL;
P_RespawnBattleBoxes(); // FORCE THESE TO BE RESPAWNED FOR THIS!!!!!!!
// Find us an item box to center on.
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
mobj_t *thismo;
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
thismo = (mobj_t *)th;
if (thismo->type != MT_RANDOMITEM)
continue;
if (thismo->threshold == 69) // Disappears
continue;
b++;
// Only select items that are on the ground, ignore ones in the air. Ambush flag inverts this rule.
if ((!P_IsObjectOnGround(thismo)) != (thismo->flags2 & MF2_AMBUSH))
continue;
if (item == NULL || (b < nummapboxes && P_RandomChance(((nummapboxes-b)*FRACUNIT)/nummapboxes))) // This is to throw off the RNG some
item = thismo;
if (b >= nummapboxes) // end early if we've found them all already
if (thismo->type == MT_OVERTIME_CENTER)
{
center = thismo;
break;
}
}
if (item == NULL) // no item found, could happen if every item is in the air or has ambush flag, or the map has none
if (center == NULL || P_MobjWasRemoved(center))
{
CONS_Alert(CONS_WARNING, "No usuable items for Battle overtime!\n");
return;
CONS_Alert(CONS_WARNING, "No center point for overtime!\n");
battleovertime.x = 0;
battleovertime.y = 0;
battleovertime.z = 0;
}
else
{
battleovertime.x = center->x;
battleovertime.y = center->y;
battleovertime.z = center->z;
}
item->threshold = 70; // Set constant respawn
battleovertime.x = item->x;
battleovertime.y = item->y;
battleovertime.z = item->z;
battleovertime.radius = 4096*mapobjectscale;
battleovertime.minradius = (cv_overtime.value == 2 ? 40 : 512) * mapobjectscale;
battleovertime.radius = 4096 * mapobjectscale;
battleovertime.enabled = 1;
S_StartSound(NULL, sfx_kc47);
}
return;
#ifndef TESTOVERTIMEINFREEPLAY
}
@ -1038,12 +1064,6 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
{
mobj_t *mo;
//if (inflictor && (inflictor->type == MT_SHELL || inflictor->type == MT_FIREBALL))
// P_SetTarget(&target->tracer, inflictor);
if (G_IsSpecialStage(gamemap) && target->player && target->player->nightstime > 6)
target->player->nightstime = 6; // Just let P_Ticker take care of the rest.
if (target->flags & (MF_ENEMY|MF_BOSS))
target->momx = target->momy = target->momz = 0;
@ -1069,7 +1089,11 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
target->flags &= ~(MF_SHOOTABLE|MF_FLOAT|MF_SPECIAL);
target->flags2 &= ~(MF2_SKULLFLY|MF2_NIGHTSPULL);
target->health = 0; // This makes it easy to check if something's dead elsewhere.
target->shadowscale = 0;
if (target->type != MT_BATTLEBUMPER)
{
target->shadowscale = 0;
}
if (LUAh_MobjDeath(target, inflictor, source, damagetype) || P_MobjWasRemoved(target))
return;
@ -1192,10 +1216,10 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
}
}
if ((gametyperules & GTR_BUMPERS))
if (gametyperules & GTR_BUMPERS)
K_CheckBumpers();
target->player->kartstuff[k_pogospring] = 0;
target->player->trickpanel = 0;
}
if (source && target && target->player && source->player)
@ -1422,6 +1446,35 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
}
break;
case MT_BATTLEBUMPER:
{
mobj_t *owner = target->target;
mobj_t *overlay;
S_StartSound(target, sfx_kc52);
target->flags &= ~MF_NOGRAVITY;
target->destscale = (3 * target->destscale) / 2;
target->scalespeed = FRACUNIT/100;
if (owner && !P_MobjWasRemoved(owner))
{
P_Thrust(target, R_PointToAngle2(owner->x, owner->y, target->x, target->y), 4 * target->scale);
}
target->momz += (24 * target->scale) * P_MobjFlip(target);
target->fuse = 8;
overlay = P_SpawnMobjFromMobj(target, 0, 0, 0, MT_OVERLAY);
P_SetTarget(&target->tracer, overlay);
P_SetTarget(&overlay->target, target);
overlay->color = target->color;
P_SetMobjState(overlay, S_INVISIBLE);
}
break;
default:
break;
}
@ -1658,7 +1711,7 @@ static boolean P_KillPlayer(player_t *player, mobj_t *inflictor, mobj_t *source,
return false;
}
K_RemoveBumper(player, NULL, NULL);
K_DestroyBumpers(player, 1);
switch (type)
{
@ -1671,14 +1724,12 @@ static boolean P_KillPlayer(player_t *player, mobj_t *inflictor, mobj_t *source,
break;
}
K_DropEmeraldsFromPlayer(player, player->powers[pw_emeralds]);
K_SetHitLagForObjects(player->mo, inflictor, 15);
player->pflags &= ~PF_SLIDING;
player->powers[pw_carry] = CR_NONE;
// Get rid of shield
player->powers[pw_shield] = SH_NONE;
player->mo->color = player->skincolor;
player->mo->colorized = false;
@ -1693,15 +1744,21 @@ static boolean P_KillPlayer(player_t *player, mobj_t *inflictor, mobj_t *source,
if (type == DMG_TIMEOVER)
{
mobj_t *boom;
if (gametyperules & GTR_CIRCUIT)
{
mobj_t *boom;
player->mo->flags |= (MF_NOGRAVITY|MF_NOCLIP);
player->mo->drawflags |= MFD_DONTDRAW;
player->mo->flags |= (MF_NOGRAVITY|MF_NOCLIP);
player->mo->drawflags |= MFD_DONTDRAW;
boom = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_FZEROBOOM);
boom->scale = player->mo->scale;
boom->angle = player->mo->angle;
P_SetTarget(&boom->target, player->mo);
boom = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_FZEROBOOM);
boom->scale = player->mo->scale;
boom->angle = player->mo->angle;
P_SetTarget(&boom->target, player->mo);
}
K_DestroyBumpers(player, player->bumpers);
player->eliminated = true;
}
return true;
@ -1796,8 +1853,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
if (!(target->flags & MF_SHOOTABLE))
return false; // shouldn't happen...
// Make sure that boxes cannot be popped by enemies, red rings, etc.
if (target->flags & MF_MONITOR && ((!source || !source->player) || (inflictor && !inflictor->player)))
if (target->hitlag > 0)
return false;
}
@ -1821,7 +1877,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
if (player) // Player is the target
{
const UINT8 type = (damagetype & DMG_TYPEMASK);
const boolean combo = (type == DMG_EXPLODE || type == DMG_TUMBLE); // This damage type can be comboed from other damage
const boolean combo = (type == DMG_EXPLODE || type == DMG_KARMA || type == DMG_TUMBLE); // This damage type can be comboed from other damage
INT16 ringburst = 5;
if (player->pflags & PF_GODMODE)
@ -1855,9 +1911,9 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
{
if (gametyperules & GTR_BUMPERS)
{
if ((player->kartstuff[k_bumper] <= 0 && player->kartstuff[k_comebacktimer]) || player->kartstuff[k_comebackmode] == 1)
if ((player->bumpers <= 0 && player->karmadelay) || (player->kartstuff[k_comebackmode] == 1))
{
// No bumpers, can't be hurt
// No bumpers & in WAIT, can't be hurt
K_DoInstashield(player);
return false;
}
@ -1890,20 +1946,60 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
}
}
// We successfully hit 'em!
// We successfully damaged them! Give 'em some bumpers!
if (type != DMG_STING)
{
UINT8 takeBumpers = 1;
if (damagetype & DMG_STEAL)
{
takeBumpers = 2;
if (type == DMG_KARMA)
{
takeBumpers = player->bumpers;
}
}
else
{
if (type == DMG_KARMA)
{
// Take half of their bumpers for karma comeback damage
takeBumpers = max(1, player->bumpers / 2);
}
}
if (source && source != player->mo && source->player)
{
K_PlayHitEmSound(source);
K_BattleAwardHit(source->player, player, inflictor, takeBumpers);
K_TakeBumpersFromPlayer(source->player, player, takeBumpers);
if (type == DMG_KARMA)
{
// Destroy any remainder bumpers from the player for karma comeback damage
K_DestroyBumpers(player, player->bumpers);
}
if (damagetype & DMG_STEAL)
{
K_StealBumper(source->player, player);
// Give them ALL of your emeralds instantly :)
source->player->powers[pw_emeralds] |= player->powers[pw_emeralds];
player->powers[pw_emeralds] = 0;
K_CheckEmeralds(source->player);
}
}
else
{
K_DestroyBumpers(player, takeBumpers);
}
K_RemoveBumper(player, inflictor, source);
if (!(damagetype & DMG_STEAL))
{
// Drop all of your emeralds
K_DropEmeraldsFromPlayer(player, player->powers[pw_emeralds]);
}
}
player->kartstuff[k_sneakertimer] = player->kartstuff[k_numsneakers] = 0;
@ -1921,6 +2017,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
K_TumblePlayer(player, inflictor, source);
break;
case DMG_EXPLODE:
case DMG_KARMA:
K_ExplodePlayer(player, inflictor, source);
break;
case DMG_WIPEOUT:
@ -1936,11 +2033,17 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
}
if (type != DMG_STING)
{
player->powers[pw_flashing] = K_GetKartFlashing(player);
}
P_PlayRinglossSound(player->mo);
if (ringburst > 0)
{
P_PlayerRingBurst(player, ringburst);
}
K_PlayPainSound(player->mo);
if ((combo == true) || (cv_kartdebughuddrop.value && !modeattacking))
@ -2017,7 +2120,7 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings)
fixed_t momxy = 5<<FRACBITS, momz = 12<<FRACBITS; // base horizonal/vertical thrusts
// Rings shouldn't be in Battle!
if (!(gametyperules & GTR_RINGS))
if (gametyperules & GTR_SPHERES)
return;
// Better safe than sorry.

View file

@ -400,6 +400,7 @@ void P_UnsetThingPosition(mobj_t *thing);
void P_SetThingPosition(mobj_t *thing);
void P_SetUnderlayPosition(mobj_t *thing);
boolean P_IsLineBlocking(const line_t *ld, const mobj_t *thing);
boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y);
boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam);
boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff);
@ -409,6 +410,7 @@ void P_SlideMove(mobj_t *mo);
void P_BouncePlayerMove(mobj_t *mo);
void P_BounceMove(mobj_t *mo);
boolean P_CheckSight(mobj_t *t1, mobj_t *t2);
boolean P_TraceBlockingLines(mobj_t *t1, mobj_t *t2);
void P_CheckHoopPosition(mobj_t *hoopthing, fixed_t x, fixed_t y, fixed_t z, fixed_t radius);
boolean P_CheckSector(sector_t *sector, boolean crunch);
@ -467,6 +469,7 @@ typedef struct BasicFF_s
#define DMG_EXPLODE 0x02
#define DMG_TUMBLE 0x03
#define DMG_STING 0x04
#define DMG_KARMA 0x05 // Karma Bomb explosion -- works like DMG_EXPLODE, but steals half of their bumpers & deletes the rest
//// Death types - cannot be combined with damage types
#define DMG_INSTAKILL 0x80
#define DMG_DEATHPIT 0x81
@ -517,5 +520,6 @@ boolean P_CheckMissileSpawn(mobj_t *th);
void P_Thrust(mobj_t *mo, angle_t angle, fixed_t move);
void P_ExplodeMissile(mobj_t *mo);
void P_CheckGravity(mobj_t *mo, boolean affect);
void P_SetPitchRollFromSlope(mobj_t *mo, pslope_t *slope);
#endif // __P_LOCAL__

View file

@ -445,9 +445,14 @@ static void P_DoFanAndGasJet(mobj_t *spring, mobj_t *object)
{
if (object->eflags & MFE_SPRUNG)
break;
if (object->player)
object->player->kartstuff[k_pogospring] = 1;
K_DoPogoSpring(object, 0, 0);
{
object->player->trickpanel = 1;
object->player->trickdelay = 1;
}
K_DoPogoSpring(object, 32<<FRACBITS, 0);
return;
}
else
@ -1265,8 +1270,8 @@ static boolean PIT_CheckThing(mobj_t *thing)
}
if ((gametyperules & GTR_BUMPERS)
&& ((thing->player->kartstuff[k_bumper] && !tmthing->player->kartstuff[k_bumper])
|| (tmthing->player->kartstuff[k_bumper] && !thing->player->kartstuff[k_bumper])))
&& ((thing->player->bumpers && !tmthing->player->bumpers)
|| (tmthing->player->bumpers && !thing->player->bumpers)))
{
return true;
}
@ -1283,14 +1288,14 @@ static boolean PIT_CheckThing(mobj_t *thing)
mo1 = thing;
mo2 = tmthing;
if (tmthing->player->kartstuff[k_pogospring])
if (tmthing->player->trickpanel)
P_DamageMobj(thing, tmthing, tmthing, 1, DMG_WIPEOUT|DMG_STEAL);
}
else if (P_IsObjectOnGround(tmthing) && thing->momz < 0)
{
zbounce = true;
if (thing->player->kartstuff[k_pogospring])
if (thing->player->trickpanel)
P_DamageMobj(tmthing, thing, thing, 1, DMG_WIPEOUT|DMG_STEAL);
}
@ -1565,6 +1570,23 @@ static boolean PIT_CheckCameraLine(line_t *ld)
return true;
}
boolean P_IsLineBlocking(const line_t *ld, const mobj_t *thing)
{
// missiles can cross uncrossable lines
if ((thing->flags & MF_MISSILE))
return false;
else
{
return
(
(ld->flags & ML_IMPASSABLE) || // block objects from moving through this linedef.
(thing->player && !thing->player->spectator &&
ld->flags & ML_BLOCKPLAYERS) || // SRB2Kart: Only block players, not items
((thing->flags & (MF_ENEMY|MF_BOSS)) && ld->special == 81) // case 81: block monsters only
);
}
}
//
// PIT_CheckLine
// Adjusts tmfloorz and tmceilingz as lines are contacted
@ -1640,14 +1662,8 @@ static boolean PIT_CheckLine(line_t *ld)
return false;
}
// missiles can cross uncrossable lines
if (!(tmthing->flags & MF_MISSILE))
{
if (ld->flags & ML_IMPASSABLE) // block objects from moving through this linedef.
return false;
if (tmthing->player && !tmthing->player->spectator && ld->flags & ML_BLOCKPLAYERS)
return false; // SRB2Kart: Only block players, not items
}
if (P_IsLineBlocking(ld, tmthing))
return false;
// set openrange, opentop, openbottom
P_LineOpening(ld, tmthing);
@ -2216,7 +2232,7 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam)
{
subsector_t *s = R_PointInSubsector(x, y);
boolean retval = true;
UINT8 i;
floatok = false;
@ -2588,9 +2604,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
if (thing->momz <= 0)
{
thing->standingslope = tmfloorslope;
#ifdef HWRENDER
thing->modeltilt = thing->standingslope;
#endif
P_SetPitchRollFromSlope(thing, thing->standingslope);
if (thing->momz == 0 && thing->player && !startingonground)
P_PlayerHitFloor(thing->player, true);
@ -2603,9 +2617,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
if (thing->momz >= 0)
{
thing->standingslope = tmceilingslope;
#ifdef HWRENDER
thing->modeltilt = thing->standingslope;
#endif
P_SetPitchRollFromSlope(thing, thing->standingslope);
if (thing->momz == 0 && thing->player && !startingonground)
P_PlayerHitFloor(thing->player, true);
@ -3117,14 +3129,8 @@ static boolean PTR_LineIsBlocking(line_t *li)
if (!li->backsector)
return !P_PointOnLineSide(slidemo->x, slidemo->y, li);
if (!(slidemo->flags & MF_MISSILE))
{
if (li->flags & ML_IMPASSABLE)
return true;
if (slidemo->player && !slidemo->player->spectator && li->flags & ML_BLOCKPLAYERS)
return true;
}
if (P_IsLineBlocking(li, slidemo))
return true;
// set openrange, opentop, openbottom
P_LineOpening(li, slidemo);
@ -3611,7 +3617,7 @@ void P_BouncePlayerMove(mobj_t *mo)
mmomx = mo->player->rmomx;
mmomy = mo->player->rmomy;
mo->player->kartstuff[k_pogospring] = 0;
mo->player->trickpanel = 0;
// trace along the three leading corners
if (mo->momx > 0)

View file

@ -1096,16 +1096,16 @@ fixed_t P_GetMobjGravity(mobj_t *mo)
P_PlayerFlip(mo);
}
if (mo->player->kartstuff[k_pogospring])
{
gravityadd = (5*gravityadd)/2;
}
if (mo->player->kartstuff[k_waterskip])
{
gravityadd = (4*gravityadd)/3;
}
if (mo->player->trickpanel == 2 || mo->player->trickpanel == 3)
{
gravityadd = (5*gravityadd)/2;
}
if (mo->player->tumbleBounces > 0)
{
gravityadd = (5*gravityadd)/2;
@ -1135,7 +1135,6 @@ fixed_t P_GetMobjGravity(mobj_t *mo)
case MT_FLINGCOIN:
case MT_FLINGBLUESPHERE:
case MT_FLINGNIGHTSCHIP:
case MT_FLINGEMERALD:
case MT_BOUNCERING:
case MT_RAILRING:
case MT_INFINITYRING:
@ -1163,6 +1162,7 @@ fixed_t P_GetMobjGravity(mobj_t *mo)
break;
case MT_WATERDROP:
case MT_CYBRAKDEMON:
case MT_BATTLEBUMPER:
gravityadd /= 2;
break;
case MT_BANANA:
@ -1170,12 +1170,12 @@ fixed_t P_GetMobjGravity(mobj_t *mo)
case MT_SSMINE:
case MT_LANDMINE:
case MT_SINK:
case MT_EMERALD:
if (mo->extravalue2 > 0)
{
gravityadd *= mo->extravalue2;
/* FALLTHRU */
case MT_ORBINAUT:
case MT_JAWZ:
case MT_JAWZ_DUD:
}
gravityadd = (5*gravityadd)/2;
break;
case MT_KARMAFIREWORK:
@ -1222,6 +1222,26 @@ void P_CheckGravity(mobj_t *mo, boolean affect)
}
}
//
// P_SetPitchRollFromSlope
//
void P_SetPitchRollFromSlope(mobj_t *mo, pslope_t *slope)
{
if (slope)
{
fixed_t tempz = slope->normal.z;
fixed_t tempy = slope->normal.y;
fixed_t tempx = slope->normal.x;
mo->pitch = R_PointToAngle2(0, 0, FixedSqrt(FixedMul(tempy, tempy) + FixedMul(tempz, tempz)), tempx);
mo->roll = R_PointToAngle2(0, 0, tempz, tempy);
}
else
{
mo->pitch = mo->roll = 0;
}
}
#define STOPSPEED (FRACUNIT)
//
@ -1716,9 +1736,7 @@ void P_XYMovement(mobj_t *mo)
// Now compare the Zs of the different quantizations
if (oldangle-newangle > ANG30 && oldangle-newangle < ANGLE_180) { // Allow for a bit of sticking - this value can be adjusted later
mo->standingslope = oldslope;
#ifdef HWRENDER
mo->modeltilt = mo->standingslope;
#endif
P_SetPitchRollFromSlope(mo, mo->standingslope);
P_SlopeLaunch(mo);
//CONS_Printf("launched off of slope - ");
@ -2102,6 +2120,7 @@ boolean P_ZMovement(mobj_t *mo)
return false;
}
break;
case MT_REDFLAG:
case MT_BLUEFLAG:
// Remove from death pits. DON'T FUCKING DESPAWN IT DAMMIT
@ -2112,19 +2131,23 @@ boolean P_ZMovement(mobj_t *mo)
}
break;
case MT_EMERALD:
if (P_CheckDeathPitCollide(mo))
{
P_RemoveMobj(mo);
return false;
}
if (mo->z <= mo->floorz || mo->z + mo->height >= mo->ceilingz)
{
// Stop when hitting the floor
mo->momx = mo->momy = 0;
}
break;
case MT_RING: // Ignore still rings
case MT_COIN:
case MT_BLUESPHERE:
case MT_BOMBSPHERE:
case MT_NIGHTSCHIP:
case MT_NIGHTSSTAR:
case MT_REDTEAMRING:
case MT_BLUETEAMRING:
case MT_FLINGRING:
case MT_FLINGCOIN:
case MT_FLINGBLUESPHERE:
case MT_FLINGNIGHTSCHIP:
case MT_FLINGEMERALD:
// Remove flinged stuff from death pits.
if (P_CheckDeathPitCollide(mo))
{
@ -2237,9 +2260,7 @@ boolean P_ZMovement(mobj_t *mo)
if (((mo->eflags & MFE_VERTICALFLIP) ? tmceilingslope : tmfloorslope) && (mo->type != MT_STEAM))
{
mo->standingslope = (mo->eflags & MFE_VERTICALFLIP) ? tmceilingslope : tmfloorslope;
#ifdef HWRENDER
mo->modeltilt = mo->standingslope;
#endif
P_SetPitchRollFromSlope(mo, mo->standingslope);
P_ReverseQuantizeMomentumToSlope(&mom, mo->standingslope);
}
@ -5285,7 +5306,117 @@ static void P_MobjSceneryThink(mobj_t *mobj)
}
break;
case MT_BATTLEBUMPER:
if (mobj->health > 0 && mobj->target && mobj->target->player
if (mobj->health <= 0)
{
mobj->fuse--;
if (!S_SoundPlaying(mobj, sfx_cdfm71))
{
S_StartSound(mobj, sfx_cdfm71);
}
if (mobj->fuse <= 0)
{
statenum_t curState = (mobj->state - states);
if (curState == S_BATTLEBUMPER1)
{
P_SetMobjState(mobj, S_BATTLEBUMPER_EXCRYSTALA1);
if (mobj->tracer && !P_MobjWasRemoved(mobj->tracer))
{
P_SetMobjState(mobj->tracer, S_BATTLEBUMPER_EXSHELLA1);
}
mobj->shadowscale *= 2;
mobj->fuse = 12;
}
else if (curState >= S_BATTLEBUMPER_EXCRYSTALA1 && curState <= S_BATTLEBUMPER_EXCRYSTALA4)
{
P_SetMobjState(mobj, S_BATTLEBUMPER_EXCRYSTALB1);
if (mobj->tracer && !P_MobjWasRemoved(mobj->tracer))
{
P_SetMobjState(mobj->tracer, S_BATTLEBUMPER_EXSHELLB1);
}
mobj->shadowscale *= 2;
mobj->fuse = 24;
break;
}
else if (curState >= S_BATTLEBUMPER_EXCRYSTALB1 && curState <= S_BATTLEBUMPER_EXCRYSTALB4)
{
P_SetMobjState(mobj, S_BATTLEBUMPER_EXCRYSTALC1);
if (mobj->tracer && !P_MobjWasRemoved(mobj->tracer))
{
P_SetMobjState(mobj->tracer, S_BATTLEBUMPER_EXSHELLC1);
}
mobj->shadowscale *= 2;
mobj->fuse = 32;
break;
}
else
{
const INT16 spacing = 64;
UINT8 i;
for (i = 0; i < 10; i++)
{
mobj_t *debris = P_SpawnMobjFromMobj(
mobj,
P_RandomRange(-spacing, spacing) * FRACUNIT,
P_RandomRange(-spacing, spacing) * FRACUNIT,
P_RandomRange(-spacing, spacing) * FRACUNIT,
MT_BATTLEBUMPER_DEBRIS
);
P_SetScale(debris, (debris->destscale *= 2));
debris->color = mobj->color;
debris->momz = -debris->scale * P_MobjFlip(debris);
}
for (i = 0; i < 2; i++)
{
mobj_t *blast = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_BATTLEBUMPER_BLAST);
blast->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy) + ANGLE_45;
blast->destscale *= 4;
if (i & 1)
{
blast->angle += ANGLE_90;
S_StartSound(blast, sfx_cdfm64);
}
}
for (i = 0; i < 10; i++)
{
mobj_t *puff = P_SpawnMobjFromMobj(
mobj,
P_RandomRange(-spacing, spacing) * FRACUNIT,
P_RandomRange(-spacing, spacing) * FRACUNIT,
P_RandomRange(-spacing, spacing) * FRACUNIT,
MT_SPINDASHDUST
);
P_SetScale(puff, (puff->destscale *= 5));
puff->momz = puff->scale * P_MobjFlip(puff);
P_Thrust(puff, R_PointToAngle2(mobj->x, mobj->y, puff->x, puff->y), puff->scale);
}
P_RemoveMobj(mobj);
return;
}
}
break;
}
if (mobj->target && !P_MobjWasRemoved(mobj->target) && mobj->target->player
&& mobj->target->health > 0 && !mobj->target->player->spectator)
{
fixed_t rad = 32*mobj->target->scale;
@ -5293,14 +5424,14 @@ static void P_MobjSceneryThink(mobj_t *mobj)
angle_t ang, diff;
if (!((mobj->target->player-players) & 1))
ang = (FixedAngle(mobj->info->speed) * -1);
ang = -FixedAngle(mobj->info->speed);
else
ang = FixedAngle(mobj->info->speed);
if (mobj->target->player->kartstuff[k_bumper] <= 1)
if (mobj->target->player->bumpers <= 1)
diff = 0;
else
diff = FixedAngle(360*FRACUNIT/mobj->target->player->kartstuff[k_bumper]);
diff = FixedAngle(360*FRACUNIT/mobj->target->player->bumpers);
ang = (ang*leveltime) + (diff * (mobj->threshold-1));
@ -5319,51 +5450,66 @@ static void P_MobjSceneryThink(mobj_t *mobj)
mobj->drawflags = (mobj->target->drawflags & MFD_DONTDRAW);
if (mobj->target->eflags & MFE_VERTICALFLIP)
{
offz += 4*FRACUNIT;
}
else
{
offz -= 4*FRACUNIT;
}
if (mobj->tracer && mobj->tracer->player && mobj->tracer->player->mo
if (mobj->tracer && !P_MobjWasRemoved(mobj->tracer) && mobj->tracer->player
&& mobj->tracer->health > 0 && !mobj->tracer->player->spectator) // STOLEN
mobj->color = mobj->tracer->player->skincolor; // don't do star flashing for stolen bumpers
{
mobj->color = mobj->tracer->color;
}
else
mobj->color = mobj->target->color; // but do so if it belongs to you :B
{
mobj->color = mobj->target->color;
}
if (mobj->target->player->kartstuff[k_bumper] < 2)
if (mobj->target->player->bumpers < 2)
P_SetMobjState(mobj, S_BATTLEBUMPER3);
else if (mobj->target->player->kartstuff[k_bumper] < 3)
else if (mobj->target->player->bumpers < 3)
P_SetMobjState(mobj, S_BATTLEBUMPER2);
else
P_SetMobjState(mobj, S_BATTLEBUMPER1);
// Shrink your items if the player shrunk too.
mobj->scale = mobj->target->scale;
P_SetScale(mobj, mobj->target->scale);
P_UnsetThingPosition(mobj);
{
const angle_t fa = ang>>ANGLETOFINESHIFT;
const angle_t fa = ang >> ANGLETOFINESHIFT;
mobj->x = mobj->target->x + FixedMul(FINECOSINE(fa), rad);
mobj->y = mobj->target->y + FixedMul(FINESINE(fa), rad);
mobj->z = mobj->target->z + offz;
P_SetThingPosition(mobj);
}
// Was this so hard?
if (mobj->target->player->kartstuff[k_bumper] <= mobj->threshold)
if (mobj->target->player->bumpers <= mobj->threshold)
{
P_RemoveMobj(mobj);
return;
// Do bumper destruction
P_KillMobj(mobj, NULL, NULL, DMG_NORMAL);
break;
}
}
else if ((mobj->health > 0
&& (!mobj->target || !mobj->target->player || !mobj->target->player->mo || mobj->target->health <= 0 || mobj->target->player->spectator))
|| (mobj->health <= 0 && P_IsObjectOnGround(mobj))
|| P_CheckDeathPitCollide(mobj)) // When in death state
else
{
// Sliently remove
P_RemoveMobj(mobj);
return;
}
break;
case MT_BATTLEBUMPER_DEBRIS:
if (mobj->state == states + S_BATTLEBUMPER_EXDEBRIS2)
{
mobj->drawflags ^= MFD_DONTDRAW;
}
break;
case MT_PLAYERARROW:
if (mobj->target && mobj->target->health
&& mobj->target->player && !mobj->target->player->spectator
@ -5374,7 +5520,7 @@ static void P_MobjSceneryThink(mobj_t *mobj)
mobj->color = mobj->target->color;
K_MatchGenericExtraFlags(mobj, mobj->target);
if ((gametype == GT_RACE || mobj->target->player->kartstuff[k_bumper] <= 0)
if ((gametype == GT_RACE || mobj->target->player->bumpers <= 0)
#if 1 // Set to 0 to test without needing to host
|| (P_IsDisplayPlayer(mobj->target->player))
#endif
@ -6206,6 +6352,9 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
if (P_MobjTouchingSectorSpecial(mobj, 3, 1, true))
K_DoPogoSpring(mobj, 0, 1);
if (!(gametyperules & GTR_CIRCUIT))
mobj->friction = max(0, 3 * mobj->friction / 4);
break;
}
case MT_JAWZ_DUD:
@ -6357,7 +6506,8 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
ghost->colorized = true; // already has color!
}
if (P_IsObjectOnGround(mobj) && (mobj->state == &states[S_SSMINE_AIR1] || mobj->state == &states[S_SSMINE_AIR2]))
if (P_IsObjectOnGround(mobj) && (mobj->momz * P_MobjFlip(mobj)) <= 0
&& (mobj->state == &states[S_SSMINE_AIR1] || mobj->state == &states[S_SSMINE_AIR2]))
{
if (mobj->extravalue1 > 0)
mobj->extravalue1--;
@ -6426,6 +6576,37 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
S_StartSound(mobj, sfx_s3k4e);
mobj->health--;
break;
case MT_EMERALD:
{
if (battleovertime.enabled >= 10*TICRATE)
{
fixed_t distance = R_PointToDist2(mobj->x, mobj->y, battleovertime.x, battleovertime.y);
if (distance > battleovertime.radius)
{
// Delete emeralds to let them reappear
P_KillMobj(mobj, NULL, NULL, DMG_NORMAL);
}
}
if (leveltime % 3 == 0)
{
mobj_t *sparkle = P_SpawnMobjFromMobj(
mobj,
P_RandomRange(-48, 48) * FRACUNIT,
P_RandomRange(-48, 48) * FRACUNIT,
P_RandomRange(0, 64) * FRACUNIT,
MT_EMERALDSPARK
);
sparkle->color = mobj->color;
sparkle->momz += 8 * mobj->scale * P_MobjFlip(mobj);
}
if (mobj->threshold > 0)
mobj->threshold--;
}
break;
case MT_DRIFTEXPLODE:
if (!mobj->target || !mobj->target->health)
{
@ -6457,9 +6638,9 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
mobj->target->z);
}
P_SetScale(mobj, mobj->target->scale);
#ifdef HWRENDER
mobj->modeltilt = mobj->target->modeltilt;
#endif
mobj->roll = mobj->target->roll;
mobj->pitch = mobj->target->pitch;
if (mobj->fuse <= 16)
{
@ -6473,7 +6654,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
mobj->color = K_RainbowColor(
(SKINCOLOR_PURPLE - SKINCOLOR_PINK) // Smoothly transition into the other state
+ ((mobj->fuse - 32) * 2) // Make the color flashing slow down while it runs out
);
);
switch (mobj->extravalue1)
{
@ -6521,9 +6702,9 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
P_TeleportMove(mobj, mobj->target->x + P_ReturnThrustX(mobj, mobj->angle+ANGLE_180, mobj->target->radius),
mobj->target->y + P_ReturnThrustY(mobj, mobj->angle+ANGLE_180, mobj->target->radius), mobj->target->z);
P_SetScale(mobj, mobj->target->scale);
#ifdef HWRENDER
mobj->modeltilt = mobj->target->modeltilt;
#endif
mobj->roll = mobj->target->roll;
mobj->pitch = mobj->target->pitch;
{
player_t *p = NULL;
@ -7047,7 +7228,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
statenum_t state = (mobj->state-states);
if (!mobj->target || !mobj->target->health || !mobj->target->player || mobj->target->player->spectator
|| (gametype == GT_RACE || mobj->target->player->kartstuff[k_bumper]))
|| (gametype == GT_RACE || mobj->target->player->bumpers))
{
P_RemoveMobj(mobj);
return false;
@ -7068,11 +7249,11 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
mobj->radius = 24*mobj->target->scale;
mobj->height = 2*mobj->radius;
if (mobj->target->player->kartstuff[k_comebacktimer] > 0)
if (mobj->target->player->karmadelay > 0)
{
if (state < S_PLAYERBOMB1 || state > S_PLAYERBOMB20)
P_SetMobjState(mobj, S_PLAYERBOMB1);
if (mobj->target->player->kartstuff[k_comebacktimer] < TICRATE && (leveltime & 1))
if (mobj->target->player->karmadelay < TICRATE && (leveltime & 1))
mobj->drawflags &= ~MFD_DONTDRAW;
else
mobj->drawflags |= MFD_DONTDRAW;
@ -8379,6 +8560,7 @@ static boolean P_FuseThink(mobj_t *mobj)
if (mobj->threshold == 70)
newmobj->threshold = 70;
}
P_RemoveMobj(mobj); // make sure they disappear
return false;
case MT_SMK_ICEBLOCK:
@ -8425,12 +8607,6 @@ void P_MobjThinker(mobj_t *mobj)
I_Assert(mobj != NULL);
I_Assert(!P_MobjWasRemoved(mobj));
if (mobj->flags & MF_NOTHINK)
return;
if ((mobj->flags & MF_BOSS) && mobj->spawnpoint && (bossdisabled & (1<<mobj->spawnpoint->extrainfo)))
return;
// Remove dead target/tracer.
if (mobj->target && P_MobjWasRemoved(mobj->target))
P_SetTarget(&mobj->target, NULL);
@ -8441,6 +8617,12 @@ void P_MobjThinker(mobj_t *mobj)
if (mobj->hprev && P_MobjWasRemoved(mobj->hprev))
P_SetTarget(&mobj->hprev, NULL);
if (mobj->flags & MF_NOTHINK)
return;
if ((mobj->flags & MF_BOSS) && mobj->spawnpoint && (bossdisabled & (1<<mobj->spawnpoint->extrainfo)))
return;
// Don't run any thinker code while in hitlag
if (mobj->hitlag > 0)
{
@ -8610,7 +8792,7 @@ void P_MobjThinker(mobj_t *mobj)
|| mobj->type == MT_FLINGCOIN
|| mobj->type == MT_FLINGBLUESPHERE
|| mobj->type == MT_FLINGNIGHTSCHIP
|| mobj->type == MT_FLINGEMERALD
|| mobj->type == MT_EMERALD
|| mobj->type == MT_BIGTUMBLEWEED
|| mobj->type == MT_LITTLETUMBLEWEED
|| mobj->type == MT_CANNONBALLDECOR
@ -8943,6 +9125,8 @@ static void P_DefaultMobjShadowScale(mobj_t *thing)
break;
case MT_RING:
case MT_FLOATINGITEM:
case MT_BLUESPHERE:
case MT_EMERALD:
thing->shadowscale = FRACUNIT/2;
break;
case MT_DRIFTCLIP:
@ -9234,8 +9418,6 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
mobj->color = skincolor_blueteam;
break;
case MT_RING:
case MT_COIN:
case MT_NIGHTSSTAR:
if (nummaprings >= 0)
nummaprings++;
break;
@ -9593,10 +9775,7 @@ void P_RemoveMobj(mobj_t *mobj)
// Rings only, please!
if (mobj->spawnpoint &&
(mobj->type == MT_RING
|| mobj->type == MT_COIN
|| mobj->type == MT_NIGHTSSTAR
|| mobj->type == MT_REDTEAMRING
|| mobj->type == MT_BLUETEAMRING)
|| mobj->type == MT_BLUESPHERE)
&& !(mobj->flags2 & MF2_DONTRESPAWN))
{
itemrespawnque[iquehead] = mobj->spawnpoint;
@ -9995,11 +10174,11 @@ mobjtype_t P_GetMobjtype(UINT16 mthingtype)
void P_RespawnSpecials(void)
{
UINT8 p, pcount = 0;
tic_t time = 30*TICRATE; // Respawn things in empty dedicated servers
INT32 time = 30*TICRATE; // Respawn things in empty dedicated servers
mapthing_t *mthing = NULL;
if (!(gametyperules & GTR_CIRCUIT) && numgotboxes >= (4*nummapboxes/5)) // Battle Mode respawns all boxes in a different way
P_RespawnBattleBoxes();
//if (!(gametyperules & GTR_CIRCUIT) && numgotboxes >= (4*nummapboxes/5)) // Battle Mode respawns all boxes in a different way
//P_RespawnBattleBoxes();
// wait time depends on player count
for (p = 0; p < MAXPLAYERS; p++)
@ -10008,22 +10187,33 @@ void P_RespawnSpecials(void)
pcount++;
}
if (pcount == 1) // No respawn when alone
return;
else if (pcount > 1)
if (gametyperules & GTR_SPHERES)
{
time = (120 - ((pcount-2) * 10))*TICRATE;
if (pcount > 2)
time -= (5*TICRATE) * (pcount-2);
// If the map is longer or shorter than 3 laps, then adjust ring respawn to account for this.
// 5 lap courses would have more retreaded ground, while 2 lap courses would have less.
if ((mapheaderinfo[gamemap-1]->numlaps != 3)
&& !(mapheaderinfo[gamemap-1]->levelflags & LF_SECTIONRACE))
time = (time * 3) / max(1, mapheaderinfo[gamemap-1]->numlaps);
if (time < 10*TICRATE)
if (time < 5*TICRATE)
time = 5*TICRATE;
}
else
{
if (pcount == 1) // No respawn when alone
return;
else if (pcount > 1)
{
// Ensure it doesn't go into absurdly low values
time = 10*TICRATE;
time = (120 - ((pcount-2) * 10)) * TICRATE;
// If the map is longer or shorter than 3 laps, then adjust ring respawn to account for this.
// 5 lap courses would have more retreaded ground, while 2 lap courses would have less.
if ((mapheaderinfo[gamemap-1]->numlaps != 3)
&& !(mapheaderinfo[gamemap-1]->levelflags & LF_SECTIONRACE))
time = (time * 3) / max(1, mapheaderinfo[gamemap-1]->numlaps);
if (time < 10*TICRATE)
{
// Ensure it doesn't go into absurdly low values
time = 10*TICRATE;
}
}
}
@ -10032,7 +10222,7 @@ void P_RespawnSpecials(void)
return;
// the first item in the queue is the first to respawn
if (leveltime - itemrespawntime[iquetail] < time)
if (leveltime - itemrespawntime[iquetail] < (tic_t)time)
return;
mthing = itemrespawnque[iquetail];
@ -10084,7 +10274,7 @@ void P_SpawnPlayer(INT32 playernum)
/*
if (bonusgame || specialstage)
{
// Bots should avoid
// Bots should avoid
p->spectator = true;
}
*/
@ -10181,30 +10371,35 @@ void P_SpawnPlayer(INT32 playernum)
P_SetScale(mobj, mobj->destscale);
P_FlashPal(p, 0, 0); // Resets
if ((gametyperules & GTR_BUMPERS)) // SRB2kart
if (gametyperules & GTR_BUMPERS)
{
mobj_t *overheadarrow = P_SpawnMobj(mobj->x, mobj->y, mobj->z + mobj->height + 16*FRACUNIT, MT_PLAYERARROW);
P_SetTarget(&overheadarrow->target, mobj);
overheadarrow->drawflags |= MFD_DONTDRAW;
P_SetScale(overheadarrow, mobj->destscale);
if (p->spectator && pcount > 1) // HEY! No being cheap...
p->kartstuff[k_bumper] = 0;
else if (p->kartstuff[k_bumper] > 0 || leveltime < 1
|| (p->jointime <= 1 && pcount <= 1))
if (p->spectator)
{
if (leveltime < 1 || (p->jointime <= 1 && pcount <= 1)) // Start of the map?
p->kartstuff[k_bumper] = K_StartingBumperCount(); // Reset those bumpers!
if (p->kartstuff[k_bumper])
// HEY! No being cheap...
p->bumpers = 0;
}
else if ((p->bumpers > 0) || (leveltime < starttime) || (pcount <= 1))
{
if ((leveltime < starttime) || (pcount <= 1)) // Start of the map?
{
angle_t diff = FixedAngle(360*FRACUNIT/p->kartstuff[k_bumper]);
// Reset those bumpers!
p->bumpers = K_StartingBumperCount();
}
if (p->bumpers)
{
angle_t diff = FixedAngle(360*FRACUNIT/p->bumpers);
angle_t newangle = mobj->angle;
fixed_t newx = mobj->x + P_ReturnThrustX(mobj, newangle + ANGLE_180, 64*FRACUNIT);
fixed_t newy = mobj->y + P_ReturnThrustY(mobj, newangle + ANGLE_180, 64*FRACUNIT);
mobj_t *mo;
for (i = 0; i < p->kartstuff[k_bumper]; i++)
for (i = 0; i < p->bumpers; i++)
{
mo = P_SpawnMobj(newx, newy, mobj->z, MT_BATTLEBUMPER);
mo->threshold = i;
@ -10218,7 +10413,7 @@ void P_SpawnPlayer(INT32 playernum)
}
}
}
else if (p->kartstuff[k_bumper] <= 0)
else if (p->bumpers <= 0)
{
mobj_t *karmahitbox = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_KARMAHITBOX); // Player hitbox is too small!!
P_SetTarget(&karmahitbox->target, mobj);
@ -10439,6 +10634,7 @@ fixed_t P_GetMapThingSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* mt
case MT_SPIKEBALL:
case MT_EMBLEM:
case MT_RING:
case MT_BLUESPHERE:
offset += mthing->options & MTF_AMBUSH ? 24*mapobjectscale : 0;
break;
@ -10545,8 +10741,14 @@ static boolean P_AllowMobjSpawn(mapthing_t* mthing, mobjtype_t i)
static mobjtype_t P_GetMobjtypeSubstitute(mapthing_t *mthing, mobjtype_t i)
{
// Don't need this for Kart YET!
(void)mthing;
if ((gametyperules & GTR_SPHERES) && (i == MT_RING))
return MT_BLUESPHERE;
if ((gametyperules & GTR_PAPERITEMS) && (i == MT_RANDOMITEM))
return MT_PAPERITEMSPOT;
return i;
}

View file

@ -157,6 +157,8 @@ typedef enum
MF_RUNSPAWNFUNC = 1<<27,
// Don't remap in Encore mode. (Not a drawflag so that it's settable by mobjinfo.)
MF_DONTENCOREMAP = 1<<28,
// Hitbox extends just as far below as above.
MF_PICKUPFROMBELOW = 1<<29,
// free: to and including 1<<31
} mobjflag_t;
@ -408,9 +410,6 @@ typedef struct mobj_s
INT32 cvmem;
struct pslope_s *standingslope; // The slope that the object is standing on (shouldn't need synced in savegames, right?)
#ifdef HWRENDER
struct pslope_s *modeltilt; // Slope used for model tilting. Also is not synched, this is totally visual.
#endif
boolean colorized; // Whether the mobj uses the rainbow colormap
boolean mirrored; // The object's rotations will be mirrored left to right, e.g., see frame AL from the right and AR from the left
@ -532,7 +531,6 @@ boolean P_ZMovement(mobj_t *mo);
void P_RingZMovement(mobj_t *mo);
boolean P_SceneryZMovement(mobj_t *mo);
void P_PlayerZMovement(mobj_t *mo);
void P_EmeraldManager(void);
extern INT32 modulothing;

View file

@ -111,6 +111,7 @@ static void P_NetArchivePlayers(void)
WRITEANGLE(save_p, players[i].awayviewaiming);
WRITEINT32(save_p, players[i].awayviewtics);
WRITEINT16(save_p, players[i].rings);
WRITEINT16(save_p, players[i].spheres);
for (j = 0; j < NUMPOWERS; j++)
WRITEUINT16(save_p, players[i].powers[j]);
@ -234,7 +235,7 @@ static void P_NetArchivePlayers(void)
if (flags & FOLLOWITEM)
WRITEUINT32(save_p, players[i].followmobj->mobjnum);
WRITEUINT32(save_p, (UINT32)players[i].followitem);
WRITEUINT32(save_p, players[i].charflags);
@ -255,6 +256,15 @@ static void P_NetArchivePlayers(void)
WRITEUINT32(save_p, players[i].distancetofinish);
WRITEUINT32(save_p, K_GetWaypointHeapIndex(players[i].nextwaypoint));
WRITEUINT32(save_p, players[i].airtime);
WRITEUINT8(save_p, players[i].trickpanel);
WRITEUINT8(save_p, players[i].trickdelay);
WRITEUINT32(save_p, players[i].trickmomx);
WRITEUINT32(save_p, players[i].trickmomy);
WRITEUINT32(save_p, players[i].trickmomz);
WRITEUINT8(save_p, players[i].bumpers);
WRITEINT16(save_p, players[i].karmadelay);
WRITEUINT8(save_p, players[i].eliminated);
WRITEUINT8(save_p, players[i].tumbleBounces);
WRITEUINT16(save_p, players[i].tumbleHeight);
@ -308,6 +318,7 @@ static void P_NetUnArchivePlayers(void)
players[i].awayviewaiming = READANGLE(save_p);
players[i].awayviewtics = READINT32(save_p);
players[i].rings = READINT16(save_p);
players[i].spheres = READINT16(save_p);
for (j = 0; j < NUMPOWERS; j++)
players[i].powers[j] = READUINT16(save_p);
@ -422,7 +433,7 @@ static void P_NetUnArchivePlayers(void)
if (flags & FOLLOWITEM)
players[i].followmobj = (mobj_t *)(size_t)READUINT32(save_p);
players[i].followitem = (mobjtype_t)READUINT32(save_p);
//SetPlayerSkinByNum(i, players[i].skin);
@ -444,6 +455,15 @@ static void P_NetUnArchivePlayers(void)
players[i].distancetofinish = READUINT32(save_p);
players[i].nextwaypoint = (waypoint_t *)(size_t)READUINT32(save_p);
players[i].airtime = READUINT32(save_p);
players[i].trickpanel = READUINT8(save_p);
players[i].trickdelay = READUINT8(save_p);
players[i].trickmomx = READUINT32(save_p);
players[i].trickmomy = READUINT32(save_p);
players[i].trickmomz = READUINT32(save_p);
players[i].bumpers = READUINT8(save_p);
players[i].karmadelay = READINT16(save_p);
players[i].eliminated = (boolean)READUINT8(save_p);
players[i].tumbleBounces = READUINT8(save_p);
players[i].tumbleHeight = READUINT16(save_p);
@ -2808,12 +2828,7 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
if (diff2 & MD2_ITNEXT)
mobj->itnext = (mobj_t *)(size_t)READUINT32(save_p);
if (diff2 & MD2_SLOPE)
{
mobj->standingslope = P_SlopeById(READUINT16(save_p));
#ifdef HWRENDER
mobj->modeltilt = mobj->standingslope;
#endif
}
if (diff2 & MD2_COLORIZED)
mobj->colorized = READUINT8(save_p);
if (diff2 & MD2_MIRRORED)
@ -4132,7 +4147,6 @@ static void P_NetArchiveMisc(void)
// battleovertime_t
WRITEUINT16(save_p, battleovertime.enabled);
WRITEFIXED(save_p, battleovertime.radius);
WRITEFIXED(save_p, battleovertime.minradius);
WRITEFIXED(save_p, battleovertime.x);
WRITEFIXED(save_p, battleovertime.y);
WRITEFIXED(save_p, battleovertime.z);
@ -4266,7 +4280,6 @@ static inline boolean P_NetUnArchiveMisc(void)
// battleovertime_t
battleovertime.enabled = READUINT16(save_p);
battleovertime.radius = READFIXED(save_p);
battleovertime.minradius = READFIXED(save_p);
battleovertime.x = READFIXED(save_p);
battleovertime.y = READFIXED(save_p);
battleovertime.z = READFIXED(save_p);

View file

@ -3924,40 +3924,40 @@ boolean P_LoadLevel(boolean fromnetsave)
}
*/
// Make sure all sounds are stopped before Z_FreeTags.
S_StopSounds();
S_ClearSfx();
// Fade out music here. Deduct 2 tics so the fade volume actually reaches 0.
// But don't halt the music! S_Start will take care of that. This dodges a MIDI crash bug.
if (!titlemapinaction)
S_FadeMusic(0, FixedMul(
FixedDiv((F_GetWipeLength(wipedefs[wipe_level_toblack])-2)*NEWTICRATERATIO, NEWTICRATE), MUSICRATE));
// Reset the palette now all fades have been done
if (rendermode != render_none)
V_SetPaletteLump(GetPalette()); // Set the level palette
if (!titlemapinaction)
{
if (ranspecialwipe == 2)
{
pausedelay = -3; // preticker plus one
S_StartSound(NULL, sfx_s3k73);
}
// As oddly named as this is, this handles music only.
// We should be fine starting it here.
// Don't do this during titlemap, because the menu code handles music by itself.
S_Start();
}
levelfadecol = (encoremode ? 0 : 31);
// Let's fade to white here
// But only if we didn't do the encore startup wipe
if (!demo.rewinding)
{
// Make sure all sounds are stopped before Z_FreeTags.
S_StopSounds();
S_ClearSfx();
// Fade out music here. Deduct 2 tics so the fade volume actually reaches 0.
// But don't halt the music! S_Start will take care of that. This dodges a MIDI crash bug.
if (!titlemapinaction)
S_FadeMusic(0, FixedMul(
FixedDiv((F_GetWipeLength(wipedefs[wipe_level_toblack])-2)*NEWTICRATERATIO, NEWTICRATE), MUSICRATE));
// Reset the palette now all fades have been done
if (rendermode != render_none)
V_SetPaletteLump(GetPalette()); // Set the level palette
if (!titlemapinaction)
{
if (ranspecialwipe == 2)
{
pausedelay = -3; // preticker plus one
S_StartSound(NULL, sfx_s3k73);
}
// As oddly named as this is, this handles music only.
// We should be fine starting it here.
// Don't do this during titlemap, because the menu code handles music by itself.
S_Start();
}
levelfadecol = (encoremode ? 0 : 31);
if (rendermode != render_none)
{
F_WipeStartScreen();

View file

@ -498,3 +498,161 @@ boolean P_CheckSight(mobj_t *t1, mobj_t *t2)
// the head node is the last node output
return P_CrossBSPNode((INT32)numnodes - 1, &los);
}
//
// P_TraceBlockingLines
//
// Returns true if a straight line between t1 and t2 is unobstructed.
// Unlike P_CheckSight, simplifed down to only check for explicit blocking lines on the 2D plane.
// Intended for Kart waypoints.
// Might be better in it's own file?
//
typedef struct {
fixed_t t2x, t2y;
divline_t strace; // from t1 to t2
fixed_t bbox[4];
mobj_t *compareThing;
} traceblocking_t;
static boolean P_CrossBlockingSubsector(size_t num, register traceblocking_t *tb)
{
seg_t *seg;
INT32 count;
#ifdef RANGECHECK
if (num >= numsubsectors)
I_Error("P_CrossBlockingSubsector: ss %s with numss = %s\n", sizeu1(num), sizeu2(numsubsectors));
#endif
// haleyjd 02/23/06: this assignment should be after the above check
seg = segs + subsectors[num].firstline;
for (count = subsectors[num].numlines; --count >= 0; seg++) // check lines
{
line_t *line = seg->linedef;
divline_t divl;
const vertex_t *v1,*v2;
if (seg->glseg)
continue;
// already checked other side?
if (line->validcount == validcount)
continue;
line->validcount = validcount;
// OPTIMIZE: killough 4/20/98: Added quick bounding-box rejection test
if (line->bbox[BOXLEFT ] > tb->bbox[BOXRIGHT ] ||
line->bbox[BOXRIGHT ] < tb->bbox[BOXLEFT ] ||
line->bbox[BOXBOTTOM] > tb->bbox[BOXTOP ] ||
line->bbox[BOXTOP] < tb->bbox[BOXBOTTOM])
continue;
v1 = line->v1;
v2 = line->v2;
// line isn't crossed?
if (P_DivlineSide(v1->x, v1->y, &tb->strace) ==
P_DivlineSide(v2->x, v2->y, &tb->strace))
continue;
// stop because it is not two sided anyway
if (!(line->flags & ML_TWOSIDED))
return false;
divl.dx = v2->x - (divl.x = v1->x);
divl.dy = v2->y - (divl.y = v1->y);
// line isn't crossed?
if (P_DivlineSide(tb->strace.x, tb->strace.y, &divl) ==
P_DivlineSide(tb->t2x, tb->t2y, &divl))
continue;
if (P_IsLineBlocking(line, tb->compareThing) == true)
{
// This line will block us
return false;
}
}
// passed the subsector ok
return true;
}
static boolean P_CrossBSPNodeBlocking(INT32 bspnum, register traceblocking_t *tb)
{
while (!(bspnum & NF_SUBSECTOR))
{
register node_t *bsp = nodes + bspnum;
INT32 side = P_DivlineSide(tb->strace.x,tb->strace.y,(divline_t *)bsp)&1;
if (side == P_DivlineSide(tb->t2x, tb->t2y, (divline_t *) bsp))
bspnum = bsp->children[side]; // doesn't touch the other side
else // the partition plane is crossed here
{
if (!P_CrossBSPNodeBlocking(bsp->children[side], tb))
return false; // cross the starting side
else
bspnum = bsp->children[side^1]; // cross the ending side
}
}
return P_CrossBlockingSubsector((bspnum == -1 ? 0 : bspnum & ~NF_SUBSECTOR), tb);
}
boolean P_TraceBlockingLines(mobj_t *t1, mobj_t *t2)
{
const sector_t *s1, *s2;
size_t pnum;
traceblocking_t tb;
// First check for trivial rejection.
if (!t1 || !t2)
return false;
I_Assert(!P_MobjWasRemoved(t1));
I_Assert(!P_MobjWasRemoved(t2));
if (!t1->subsector || !t2->subsector
|| !t1->subsector->sector || !t2->subsector->sector)
return false;
s1 = t1->subsector->sector;
s2 = t2->subsector->sector;
pnum = (s1-sectors)*numsectors + (s2-sectors);
if (rejectmatrix != NULL)
{
// Check in REJECT table.
if (rejectmatrix[pnum>>3] & (1 << (pnum&7))) // can't possibly be connected
return false;
}
// killough 11/98: shortcut for melee situations
// same subsector? obviously visible
// haleyjd 02/23/06: can't do this if there are polyobjects in the subsec
if (!t1->subsector->polyList &&
t1->subsector == t2->subsector)
return true;
validcount++;
tb.strace.dx = (tb.t2x = t2->x) - (tb.strace.x = t1->x);
tb.strace.dy = (tb.t2y = t2->y) - (tb.strace.y = t1->y);
if (t1->x > t2->x)
tb.bbox[BOXRIGHT] = t1->x, tb.bbox[BOXLEFT] = t2->x;
else
tb.bbox[BOXRIGHT] = t2->x, tb.bbox[BOXLEFT] = t1->x;
if (t1->y > t2->y)
tb.bbox[BOXTOP] = t1->y, tb.bbox[BOXBOTTOM] = t2->y;
else
tb.bbox[BOXTOP] = t2->y, tb.bbox[BOXBOTTOM] = t1->y;
tb.compareThing = t1;
// the head node is the last node output
return P_CrossBSPNodeBlocking((INT32)numnodes - 1, &tb);
}

View file

@ -897,9 +897,8 @@ void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope)
if (P_MobjFlip(thing)*(thing->momz) < 0) // falling, land on slope
{
thing->standingslope = slope;
#ifdef HWRENDER
thing->modeltilt = thing->standingslope;
#endif
P_SetPitchRollFromSlope(thing, slope);
if (!thing->player || !(thing->player->pflags & PF_BOUNCING))
thing->momz = -P_MobjFlip(thing);
}
@ -916,9 +915,7 @@ void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope)
thing->momx = mom.x;
thing->momy = mom.y;
thing->standingslope = slope;
#ifdef HWRENDER
thing->modeltilt = thing->standingslope;
#endif
P_SetPitchRollFromSlope(thing, slope);
if (!thing->player || !(thing->player->pflags & PF_BOUNCING))
thing->momz = -P_MobjFlip(thing);
}

View file

@ -1612,7 +1612,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller
{
if (GETSECSPECIAL(caller->special, 2) == 6)
{
if (!(ALL7EMERALDS(emeralds)))
if (!(ALLCHAOSEMERALDS(emeralds)))
return false;
}
@ -2028,6 +2028,14 @@ static void K_HandleLapIncrement(player_t *player)
player->karthud[khud_laphand] = 0; // No hands in FREE PLAY
player->karthud[khud_lapanimation] = 80;
// save best lap for record attack
if (player == &players[consoleplayer])
{
if (curlap < bestlap || bestlap == 0)
bestlap = curlap;
curlap = 0;
}
}
if (rainbowstartavailable == true)
@ -2041,14 +2049,6 @@ static void K_HandleLapIncrement(player_t *player)
if (netgame && player->laps >= (UINT8)cv_numlaps.value)
CON_LogMessage(va(M_GetText("%s has finished the race.\n"), player_names[player-players]));
// SRB2Kart: save best lap for record attack
if (player == &players[consoleplayer])
{
if (curlap < bestlap || bestlap == 0)
bestlap = curlap;
curlap = 0;
}
player->starpostnum = 0;
if (P_IsDisplayPlayer(player))
@ -2133,6 +2133,7 @@ static void K_HandleLapDecrement(player_t *player)
{
player->starpostnum = numstarposts;
player->laps--;
curlap = UINT32_MAX;
}
}
}
@ -4598,47 +4599,43 @@ DoneSection2:
switch (special)
{
case 1: // SRB2kart: Spring Panel
case 3:
if (roversector || P_MobjReadyToTrigger(player->mo, sector))
{
const fixed_t hscale = mapobjectscale + (mapobjectscale - player->mo->scale);
const fixed_t minspeed = 24*hscale;
angle_t pushangle = K_MomentumAngle(player->mo);
fixed_t speed = FixedHypot(player->mo->momx, player->mo->momy);
fixed_t upwards = 32*FRACUNIT;
if (player->mo->eflags & MFE_SPRUNG)
{
break;
}
if (player->speed < minspeed) // Push forward to prevent getting stuck
P_InstaThrust(player->mo, pushangle, minspeed);
if (special == 3)
{
upwards /= 2;
}
player->kartstuff[k_pogospring] = 1;
K_DoPogoSpring(player->mo, 0, 1);
player->trickpanel = 1;
player->trickdelay = 1;
K_DoPogoSpring(player->mo, upwards, 1);
// Reduce speed
speed /= 2;
if (speed < minspeed)
{
speed = minspeed;
}
P_InstaThrust(player->mo, player->mo->angle, speed);
}
break;
case 2: // Wind/Current
break;
case 3: // SRB2kart: Spring Panel (capped speed)
if (roversector || P_MobjReadyToTrigger(player->mo, sector))
{
const fixed_t hscale = mapobjectscale + (mapobjectscale - player->mo->scale);
const fixed_t minspeed = 24*hscale;
const fixed_t maxspeed = 28*hscale;
angle_t pushangle = K_MomentumAngle(player->mo);
if (player->mo->eflags & MFE_SPRUNG)
break;
if (player->speed > maxspeed) // Prevent overshooting jumps
P_InstaThrust(player->mo, pushangle, maxspeed);
else if (player->speed < minspeed) // Push forward to prevent getting stuck
P_InstaThrust(player->mo, pushangle, minspeed);
player->kartstuff[k_pogospring] = 2;
K_DoPogoSpring(player->mo, 0, 1);
}
break;
case 4: // Conveyor Belt
break;
@ -4678,7 +4675,7 @@ DoneSection2:
P_InstaThrust(player->mo, lineangle, max(linespeed, 2*playerspeed));
player->kartstuff[k_dashpadcooldown] = TICRATE/3;
player->kartstuff[k_pogospring] = 0;
player->trickpanel = 0;
player->kartstuff[k_floorboost] = 2;
S_StartSound(player->mo, sfx_cdfm62);
}

View file

@ -332,6 +332,11 @@ static inline void P_RunThinkers(void)
ps_thlist_times[i] = I_GetTimeMicros() - ps_thlist_times[i];
}
if (gametyperules & GTR_PAPERITEMS)
K_RunPaperItemSpawners();
if ((gametyperules & GTR_BUMPERS) && battleovertime.enabled)
K_RunBattleOvertime();
}
//
@ -516,6 +521,8 @@ void P_Ticker(boolean run)
if (demo.rewinding && leveltime > 0)
{
leveltime = (leveltime-1) & ~3;
if (timeinmap > 0)
timeinmap = (timeinmap-1) & ~3;
G_PreviewRewind(leveltime);
}
else if (demo.freecam && democam.cam) // special case: allow freecam to MOVE during pause!
@ -592,9 +599,6 @@ void P_Ticker(boolean run)
if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
P_PlayerAfterThink(&players[i]);
if ((gametyperules & GTR_BUMPERS) && battleovertime.enabled)
K_RunBattleOvertime();
ps_lua_thinkframe_time = I_GetTimeMicros();
LUAh_ThinkFrame();
ps_lua_thinkframe_time = I_GetTimeMicros() - ps_lua_thinkframe_time;
@ -613,9 +617,7 @@ void P_Ticker(boolean run)
if (run)
leveltime++;
// as this is mostly used for HUD stuff, add the record attack specific hack to it as well!
if (!(modeattacking && !demo.playback) || leveltime >= starttime - TICRATE*4)
timeinmap++;
timeinmap++;
if (G_GametypeHasTeams())
P_DoTeamStuff();
@ -752,9 +754,6 @@ void P_PreTicker(INT32 frames)
if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
P_PlayerAfterThink(&players[i]);
if ((gametyperules & GTR_BUMPERS) && battleovertime.enabled)
K_RunBattleOvertime();
LUAh_ThinkFrame();
// Run shield positioning

View file

@ -461,18 +461,9 @@ UINT8 P_FindHighestLap(void)
//
boolean P_PlayerInPain(player_t *player)
{
if (player->respawn.state != RESPAWNST_NONE)
return true;
if (player->kartstuff[k_spinouttimer] || player->tumbleBounces > 0)
return true;
if (gametyperules & GTR_KARMA)
{
if (player->kartstuff[k_bumper] <= 0 && player->kartstuff[k_comebacktimer])
return true;
}
return false;
}
@ -488,7 +479,7 @@ void P_ResetPlayer(player_t *player)
player->onconveyor = 0;
//player->kartstuff[k_drift] = player->kartstuff[k_driftcharge] = 0;
player->kartstuff[k_pogospring] = 0;
player->trickpanel = 0;
}
//
@ -1293,6 +1284,8 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj)
ghost->colorized = mobj->colorized; // Kart: they should also be colorized if their origin is
ghost->angle = (mobj->player ? mobj->player->drawangle : mobj->angle);
ghost->roll = mobj->roll;
ghost->pitch = mobj->pitch;
ghost->sprite = mobj->sprite;
ghost->sprite2 = mobj->sprite2;
ghost->frame = mobj->frame;
@ -1301,13 +1294,11 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj)
ghost->fuse = ghost->info->damage;
ghost->skin = mobj->skin;
ghost->standingslope = mobj->standingslope;
#ifdef HWRENDER
ghost->modeltilt = mobj->modeltilt;
#endif
ghost->sprxoff = mobj->sprxoff;
ghost->spryoff = mobj->spryoff;
ghost->sprzoff = mobj->sprzoff;
ghost->rollangle = mobj->rollangle;
if (mobj->flags2 & MF2_OBJECTFLIP)
ghost->flags |= MF2_OBJECTFLIP;
@ -1927,8 +1918,7 @@ static void P_3dMovement(player_t *player)
//}
// Do not let the player control movement if not onground.
// SRB2Kart: pogo spring and speed bumps are supposed to control like you're on the ground
onground = (P_IsObjectOnGround(player->mo) || (player->kartstuff[k_pogospring]));
onground = P_IsObjectOnGround(player->mo);
K_AdjustPlayerFriction(player);
@ -1944,11 +1934,6 @@ static void P_3dMovement(player_t *player)
totalthrust.x += P_ReturnThrustX(player->mo, movepushangle, movepushforward);
totalthrust.y += P_ReturnThrustY(player->mo, movepushangle, movepushforward);
if (K_PlayerUsesBotMovement(player) == true)
{
K_MomentumToFacing(player);
}
}
if ((totalthrust.x || totalthrust.y)
@ -2220,10 +2205,14 @@ void P_MovePlayer(player_t *player)
{
K_KartMoveAnimation(player);
if (player->kartstuff[k_pogospring])
if (player->trickpanel == 2)
{
player->drawangle += ANGLE_22h;
}
else if (player->trickpanel == 3)
{
player->drawangle -= ANGLE_22h;
}
else
{
player->drawangle = player->mo->angle;
@ -2676,7 +2665,7 @@ static void P_DeathThink(player_t *player)
{
if (player->spectator || !circuitmap)
curlap = 0;
else
else if (curlap != UINT32_MAX)
curlap++; // This is too complicated to sync to realtime, just sorta hope for the best :V
}
}
@ -3221,17 +3210,40 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
}
// sets ideal cam pos
dist = camdist;
{
const fixed_t speedthreshold = 48*mapobjectscale;
const fixed_t olddist = P_AproxDistance(mo->x - thiscam->x, mo->y - thiscam->y);
/* player->speed subtracts conveyors, janks up the camera */
speed = R_PointToDist2(0, 0, player->mo->momx, player->mo->momy);
fixed_t lag, distoffset;
if (speed > K_GetKartSpeed(player, false))
dist += 4*(speed - K_GetKartSpeed(player, false));
dist += abs(thiscam->momz)/4;
dist = camdist;
if (player->karthud[khud_boostcam])
dist -= FixedMul(11*dist/16, player->karthud[khud_boostcam]);
if (player->karthud[khud_boostcam])
{
dist -= FixedMul(11*dist/16, player->karthud[khud_boostcam]);
}
speed = P_AproxDistance(P_AproxDistance(mo->momx, mo->momy), mo->momz / 16);
lag = FRACUNIT - ((FixedDiv(speed, speedthreshold) - FRACUNIT) * 2);
if (lag > FRACUNIT)
{
lag = FRACUNIT;
}
if (lag < camspeed)
{
lag = camspeed;
}
distoffset = dist - olddist;
dist = olddist + FixedMul(distoffset, lag);
if (dist < 0)
{
dist = 0;
}
}
if (mo->standingslope)
{
@ -3520,7 +3532,9 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
thiscam->momz = 0;
}
else if (player->exiting || timeover == 2)
{
thiscam->momx = thiscam->momy = thiscam->momz = 0;
}
else if (leveltime < introtime)
{
thiscam->momx = FixedMul(x - thiscam->x, camspeed);
@ -4418,7 +4432,7 @@ void P_PlayerThink(player_t *player)
{
if (player->spectator || !circuitmap)
curlap = 0;
else
else if (curlap != UINT32_MAX)
curlap++; // This is too complicated to sync to realtime, just sorta hope for the best :V
}
}
@ -4562,7 +4576,7 @@ void P_PlayerThink(player_t *player)
|| player->kartstuff[k_growshrinktimer] > 0 // Grow doesn't flash either.
|| (player->respawn.state != RESPAWNST_NONE) // Respawn timer (for drop dash effect)
|| (player->pflags & PF_GAMETYPEOVER) // NO CONTEST explosion
|| ((gametyperules & GTR_BUMPERS) && player->kartstuff[k_bumper] <= 0 && player->kartstuff[k_comebacktimer])
|| ((gametyperules & GTR_BUMPERS) && player->bumpers <= 0 && player->karmadelay)
|| leveltime < starttime)) // Level intro
{
if (player->powers[pw_flashing] > 0 && player->powers[pw_flashing] < K_GetKartFlashing(player)

View file

@ -23,6 +23,7 @@
#include "v_video.h"
#include "z_zone.h"
#include "w_wad.h"
#include "r_main.h" // R_PointToAngle
#ifdef HWRENDER
#include "hardware/hw_glob.h"
@ -1605,6 +1606,27 @@ void R_LoadSpriteInfoLumps(UINT16 wadnum, UINT16 numlumps)
}
#ifdef ROTSPRITE
//
// R_SpriteRotationAngle
//
// Gets the rollangle for the input object.
//
angle_t R_SpriteRotationAngle(mobj_t *mobj)
{
#if 0
angle_t viewingAngle = R_PointToAngle(mobj->x, mobj->y);
fixed_t pitchMul = -FINESINE(viewingAngle >> ANGLETOFINESHIFT);
fixed_t rollMul = FINECOSINE(viewingAngle >> ANGLETOFINESHIFT);
angle_t rollOrPitch = FixedMul(mobj->pitch, pitchMul) + FixedMul(mobj->roll, rollMul);
return (rollOrPitch + mobj->rollangle);
#else
return mobj->rollangle;
#endif
}
//
// R_GetRollAngle
//

View file

@ -122,6 +122,7 @@ void R_ParseSPRTINFOLump(UINT16 wadNum, UINT16 lumpNum);
// Sprite rotation
#ifdef ROTSPRITE
angle_t R_SpriteRotationAngle(mobj_t *mobj);
INT32 R_GetRollAngle(angle_t rollangle);
void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, spriteframe_t *sprframe, INT32 rot, UINT8 flip);
void R_FreeSingleRotSprite(spritedef_t *spritedef);

View file

@ -876,6 +876,11 @@ boolean SetPlayerFollower(INT32 playernum, const char *skinname)
INT32 i;
player_t *player = &players[playernum];
if (stricmp("None", skinname) == 0)
{
SetFollower(playernum, -1); // reminder that -1 is nothing
return true;
}
for (i = 0; i < numfollowers; i++)
{
// search in the skin list

View file

@ -1230,32 +1230,6 @@ fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope)
return groundz;
}
static void R_SetSpritePlaneHeights(vissprite_t *vis)
{
ffloor_t *rover;
fixed_t top;
fixed_t bot;
vis->pt = vis->sector->floorheight;
vis->pb = vis->sector->ceilingheight;
for (rover = vis->sector->ffloors; rover; rover = rover->next)
{
if (rover->flags & FF_EXISTS)
{
top = P_GetFFloorTopZAt (rover, vis->gx, vis->gy);
bot = P_GetFFloorBottomZAt (rover, vis->gx, vis->gy);
if (top <= vis->gzt && top > vis->pt)
vis->pt = top;
if (bot >= vis->gz && bot < vis->pb)
vis->pb = bot;
}
}
}
static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, fixed_t tx, fixed_t tz)
{
vissprite_t *shadow;
@ -1344,8 +1318,6 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale,
shadow->xscale = FixedMul(xscale, shadowxscale); //SoM: 4/17/2000
shadow->scale = FixedMul(yscale, shadowyscale);
shadow->sector = vis->sector;
shadow->pt = vis->pt;
shadow->pb = vis->pb;
shadow->szt = (INT16)((centeryfrac - FixedMul(shadow->gzt - viewz, yscale))>>FRACBITS);
shadow->sz = (INT16)((centeryfrac - FixedMul(shadow->gz - viewz, yscale))>>FRACBITS);
shadow->cut = SC_ISSCALED|SC_SHADOW; //check this
@ -1462,6 +1434,7 @@ static void R_ProjectSprite(mobj_t *thing)
#ifdef ROTSPRITE
patch_t *rotsprite = NULL;
INT32 rollangle = 0;
angle_t spriterotangle = 0;
#endif
// hitlag vibrating
@ -1602,9 +1575,11 @@ static void R_ProjectSprite(mobj_t *thing)
spr_topoffset = spritecachedinfo[lump].topoffset;
#ifdef ROTSPRITE
if (thing->rollangle)
spriterotangle = R_SpriteRotationAngle(thing);
if (spriterotangle != 0)
{
rollangle = R_GetRollAngle(thing->rollangle);
rollangle = R_GetRollAngle(spriterotangle);
if (!(sprframe->rotsprite.cached & (1<<rot)))
R_CacheRotSprite(thing->sprite, frame, sprinfo, sprframe, rot, flip);
rotsprite = sprframe->rotsprite.patch[rot][rollangle];
@ -1860,9 +1835,6 @@ static void R_ProjectSprite(mobj_t *thing)
vis->sector = thing->subsector->sector;
vis->szt = (INT16)((centeryfrac - FixedMul(vis->gzt - viewz, sortscale))>>FRACBITS);
vis->sz = (INT16)((centeryfrac - FixedMul(vis->gz - viewz, sortscale))>>FRACBITS);
R_SetSpritePlaneHeights(vis);
vis->cut = cut;
if (thing->subsector->sector->numlights)
vis->extra_colormap = *thing->subsector->sector->lightlist[light].extra_colormap;
@ -2077,8 +2049,6 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
vis->szt = (INT16)((centeryfrac - FixedMul(vis->gzt - viewz, yscale))>>FRACBITS);
vis->sz = (INT16)((centeryfrac - FixedMul(vis->gz - viewz, yscale))>>FRACBITS);
R_SetSpritePlaneHeights(vis);
iscale = FixedDiv(FRACUNIT, xscale);
vis->startfrac = 0;
@ -2458,12 +2428,12 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps
// bird: if any part of the sprite peeks in front the plane
if (planecameraz < viewz)
{
if (rover->pt >= planeobjectz && rover->gzt >= planeobjectz)
if (rover->gzt >= planeobjectz)
continue;
}
else if (planecameraz > viewz)
{
if (rover->pb <= planeobjectz && rover->gz <= planeobjectz)
if (rover->gz <= planeobjectz)
continue;
}
@ -2496,7 +2466,7 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps
}
else if (r2->thickseg)
{
fixed_t topplaneobjectz, topplanecameraz, botplaneobjectz, botplanecameraz;
//fixed_t topplaneobjectz, topplanecameraz, botplaneobjectz, botplanecameraz;
if (rover->x1 > r2->thickseg->x2 || rover->x2 < r2->thickseg->x1)
continue;
@ -2507,6 +2477,11 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps
if (scale <= rover->sortscale)
continue;
// bird: Always sort sprites behind segs. This helps the plane
// sorting above too. Basically if the sprite gets sorted behind
// the seg here, it will be behind the plane too, since planes
// are added after segs in the list.
#if 0
topplaneobjectz = P_GetFFloorTopZAt (r2->ffloor, rover->gx, rover->gy);
topplanecameraz = P_GetFFloorTopZAt (r2->ffloor, viewx, viewy);
botplaneobjectz = P_GetFFloorBottomZAt(r2->ffloor, rover->gx, rover->gy);
@ -2515,6 +2490,7 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps
if ((topplanecameraz > viewz && botplanecameraz < viewz) ||
(topplanecameraz < viewz && rover->gzt < topplaneobjectz) ||
(botplanecameraz > viewz && rover->gz > botplaneobjectz))
#endif
{
entry = R_CreateDrawNode(NULL);
(entry->prev = r2->prev)->next = entry;

View file

@ -171,7 +171,6 @@ typedef struct vissprite_s
// Precalculated top and bottom screen coords for the sprite.
sector_t *sector; // The sector containing the thing.
fixed_t pt, pb; // plane heights, also for sorting against 3D floors
INT16 sz, szt;
spritecut_e cut;

View file

@ -740,14 +740,14 @@ sfxinfo_t S_sfx[NUMSFX] =
{"cdfm61", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"cdfm62", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Speed boost"},
{"cdfm63", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"cdfm64", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"cdfm64", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"cdfm65", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"cdfm66", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"cdfm67", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"cdfm68", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"cdfm69", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"cdfm70", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"cdfm71", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"cdfm71", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"cdfm72", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"cdfm73", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"cdfm74", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
@ -808,7 +808,7 @@ sfxinfo_t S_sfx[NUMSFX] =
{"kc4f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"kc50", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"kc51", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"kc52", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"kc52", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"kc53", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"kc54", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"kc55", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},

View file

@ -673,10 +673,8 @@ void ST_preDrawTitleCard(void)
if (lt_ticker >= (lt_endtime + TICRATE))
return;
if (!lt_exitticker)
st_translucency = 0;
else
st_translucency = max(0, min((INT32)lt_exitticker-4, cv_translucenthud.value));
// Kart: nothing
st_translucency = cv_translucenthud.value;
}
//