mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Merge branch 'master' into waypoints-disable
This commit is contained in:
commit
1849f70359
37 changed files with 2189 additions and 278 deletions
|
|
@ -170,6 +170,7 @@ set(SRB2_CORE_GAME_SOURCES
|
|||
p_telept.c
|
||||
p_tick.c
|
||||
p_user.c
|
||||
k_race.c
|
||||
k_battle.c
|
||||
k_bheap.c
|
||||
k_collide.c
|
||||
|
|
@ -195,6 +196,7 @@ set(SRB2_CORE_GAME_SOURCES
|
|||
p_slopes.h
|
||||
p_spec.h
|
||||
p_tick.h
|
||||
k_race.h
|
||||
k_battle.h
|
||||
k_bheap.h
|
||||
k_collide.h
|
||||
|
|
|
|||
|
|
@ -558,6 +558,7 @@ OBJS:=$(i_main_o) \
|
|||
$(OBJDIR)/k_respawn.o\
|
||||
$(OBJDIR)/k_collide.o\
|
||||
$(OBJDIR)/k_color.o \
|
||||
$(OBJDIR)/k_race.o \
|
||||
$(OBJDIR)/k_battle.o \
|
||||
$(OBJDIR)/k_pwrlv.o \
|
||||
$(OBJDIR)/k_waypoint.o\
|
||||
|
|
|
|||
|
|
@ -616,6 +616,9 @@ 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->driftInput = players[i].driftInput;
|
||||
rsp->airFailsafe = players[i].airFailsafe;
|
||||
|
||||
rsp->trickpanel = (UINT8)players[i].trickpanel;
|
||||
rsp->trickdelay = (boolean)players[i].trickdelay;
|
||||
rsp->trickmomx = (fixed_t)LONG(players[i].trickmomx);
|
||||
|
|
@ -631,6 +634,8 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i)
|
|||
rsp->tumbleLastBounce = players[i].tumbleLastBounce;
|
||||
rsp->tumbleSound = players[i].tumbleSound;
|
||||
|
||||
rsp->glanceDir = players[i].glanceDir;
|
||||
|
||||
// respawnvars_t
|
||||
rsp->respawn_state = players[i].respawn.state;
|
||||
rsp->respawn_pointx = (fixed_t)LONG(players[i].respawn.pointx);
|
||||
|
|
@ -774,6 +779,9 @@ 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].driftInput = (boolean)rsp->driftInput;
|
||||
players[i].airFailsafe = (boolean)rsp->airFailsafe;
|
||||
|
||||
players[i].trickpanel = (UINT8)rsp->trickpanel;
|
||||
players[i].trickdelay = (boolean)rsp->trickdelay;
|
||||
players[i].trickmomx = (fixed_t)LONG(rsp->trickmomx);
|
||||
|
|
@ -789,6 +797,8 @@ static void resynch_read_player(resynch_pak *rsp)
|
|||
players[i].tumbleLastBounce = (boolean)rsp->tumbleLastBounce;
|
||||
players[i].tumbleSound = (boolean)rsp->tumbleSound;
|
||||
|
||||
players[i].glanceDir = (SINT8)rsp->glanceDir;
|
||||
|
||||
// respawnvars_t
|
||||
players[i].respawn.state = rsp->respawn_state;
|
||||
players[i].respawn.pointx = (fixed_t)LONG(rsp->respawn_pointx);
|
||||
|
|
|
|||
|
|
@ -280,6 +280,8 @@ typedef struct
|
|||
// SRB2kart
|
||||
INT32 kartstuff[NUMKARTSTUFF];
|
||||
tic_t airtime;
|
||||
boolean driftInput;
|
||||
boolean airFailsafe;
|
||||
UINT8 trickpanel;
|
||||
boolean trickdelay;
|
||||
fixed_t trickmomx;
|
||||
|
|
@ -295,6 +297,8 @@ typedef struct
|
|||
boolean tumbleLastBounce;
|
||||
boolean tumbleSound;
|
||||
|
||||
SINT8 glanceDir;
|
||||
|
||||
// respawnvars_t
|
||||
UINT8 respawn_state;
|
||||
fixed_t respawn_pointx;
|
||||
|
|
|
|||
|
|
@ -3555,12 +3555,16 @@ static void Command_Login_f(void)
|
|||
|
||||
boolean IsPlayerAdmin(INT32 playernum)
|
||||
{
|
||||
#ifdef DEVELOP
|
||||
return playernum != serverplayer;
|
||||
#else
|
||||
INT32 i;
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
if (playernum == adminplayers[i])
|
||||
return true;
|
||||
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void SetAdminPlayer(INT32 playernum)
|
||||
|
|
|
|||
|
|
@ -115,19 +115,11 @@ typedef enum
|
|||
{
|
||||
// Are animation frames playing?
|
||||
PA_ETC=0,
|
||||
PA_IDLE,
|
||||
PA_EDGE,
|
||||
PA_WALK,
|
||||
PA_RUN,
|
||||
PA_DASH,
|
||||
PA_PAIN,
|
||||
PA_ROLL,
|
||||
PA_JUMP,
|
||||
PA_SPRING,
|
||||
PA_FALL,
|
||||
PA_ABILITY,
|
||||
PA_ABILITY2,
|
||||
PA_RIDE
|
||||
PA_STILL,
|
||||
PA_SLOW,
|
||||
PA_FAST,
|
||||
PA_DRIFT,
|
||||
PA_HURT
|
||||
} panim_t;
|
||||
|
||||
//
|
||||
|
|
@ -454,6 +446,8 @@ typedef enum
|
|||
#define TRICKMOMZRAMP (30)
|
||||
#define TRICKLAG (9)
|
||||
|
||||
#define TUMBLEBOUNCES 3
|
||||
|
||||
//}
|
||||
|
||||
// player_t struct for all respawn variables
|
||||
|
|
@ -525,10 +519,13 @@ typedef struct player_s
|
|||
// SRB2kart stuff
|
||||
INT32 kartstuff[NUMKARTSTUFF];
|
||||
INT32 karthud[NUMKARTHUD];
|
||||
|
||||
UINT32 distancetofinish;
|
||||
waypoint_t *nextwaypoint;
|
||||
respawnvars_t respawn; // Respawn info
|
||||
tic_t airtime; // Keep track of how long you've been in the air
|
||||
boolean driftInput; // Whenever or not try drifting.
|
||||
boolean airFailsafe; // Whenever or not try the air boost
|
||||
|
||||
UINT8 trickpanel; // Trick panel state
|
||||
boolean trickdelay; // Prevent tricks until control stick is neutral
|
||||
|
|
@ -575,6 +572,8 @@ typedef struct player_s
|
|||
boolean tumbleLastBounce;
|
||||
boolean tumbleSound;
|
||||
|
||||
SINT8 glanceDir; // Direction the player is trying to look backwards in
|
||||
|
||||
//
|
||||
|
||||
UINT32 charflags; // Extra abilities/settings for skins (combinable stuff)
|
||||
|
|
|
|||
128
src/dehacked.c
128
src/dehacked.c
|
|
@ -2031,6 +2031,13 @@ static void readlevelheader(MYFILE *f, INT32 num)
|
|||
else
|
||||
mapheaderinfo[num-1]->levelflags &= ~LF_SECTIONRACE;
|
||||
}
|
||||
else if (fastcmp(word, "SUBTRACTNUM"))
|
||||
{
|
||||
if (i || word2[0] == 'T' || word2[0] == 'Y')
|
||||
mapheaderinfo[num-1]->levelflags |= LF_SUBTRACTNUM;
|
||||
else
|
||||
mapheaderinfo[num-1]->levelflags &= ~LF_SUBTRACTNUM;
|
||||
}
|
||||
|
||||
// Individual triggers for menu flags
|
||||
else if (fastcmp(word, "HIDDEN"))
|
||||
|
|
@ -5204,12 +5211,24 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
|
|||
"S_KART_STILL",
|
||||
"S_KART_STILL_L",
|
||||
"S_KART_STILL_R",
|
||||
"S_KART_STILL_GLANCE_L",
|
||||
"S_KART_STILL_GLANCE_R",
|
||||
"S_KART_STILL_LOOK_L",
|
||||
"S_KART_STILL_LOOK_R",
|
||||
"S_KART_SLOW",
|
||||
"S_KART_SLOW_L",
|
||||
"S_KART_SLOW_R",
|
||||
"S_KART_SLOW_GLANCE_L",
|
||||
"S_KART_SLOW_GLANCE_R",
|
||||
"S_KART_SLOW_LOOK_L",
|
||||
"S_KART_SLOW_LOOK_R",
|
||||
"S_KART_FAST",
|
||||
"S_KART_FAST_L",
|
||||
"S_KART_FAST_R",
|
||||
"S_KART_FAST_GLANCE_L",
|
||||
"S_KART_FAST_GLANCE_R",
|
||||
"S_KART_FAST_LOOK_L",
|
||||
"S_KART_FAST_LOOK_R",
|
||||
"S_KART_DRIFT_L",
|
||||
"S_KART_DRIFT_L_OUT",
|
||||
"S_KART_DRIFT_L_IN",
|
||||
|
|
@ -5217,12 +5236,18 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
|
|||
"S_KART_DRIFT_R_OUT",
|
||||
"S_KART_DRIFT_R_IN",
|
||||
"S_KART_SPINOUT",
|
||||
"S_KART_SQUISH",
|
||||
"S_KART_DEAD",
|
||||
"S_KART_SIGN",
|
||||
|
||||
// technically the player goes here but it's an infinite tic state
|
||||
"S_OBJPLACE_DUMMY",
|
||||
|
||||
"S_KART_LEFTOVER",
|
||||
"S_KART_LEFTOVER_NOTIRES",
|
||||
|
||||
"S_KART_TIRE1",
|
||||
"S_KART_TIRE2",
|
||||
|
||||
// Blue Crawla
|
||||
"S_POSS_STND",
|
||||
"S_POSS_RUN1",
|
||||
|
|
@ -9398,6 +9423,31 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
|
|||
"S_SPINDASHDUST",
|
||||
"S_SPINDASHWIND",
|
||||
|
||||
// Finish line beam
|
||||
"S_FINISHBEAM1",
|
||||
"S_FINISHBEAM2",
|
||||
"S_FINISHBEAM3",
|
||||
"S_FINISHBEAM4",
|
||||
"S_FINISHBEAM5",
|
||||
"S_FINISHBEAMEND1",
|
||||
"S_FINISHBEAMEND2",
|
||||
|
||||
// Funny Spike
|
||||
"S_DEBTSPIKE1",
|
||||
"S_DEBTSPIKE2",
|
||||
"S_DEBTSPIKE3",
|
||||
"S_DEBTSPIKE4",
|
||||
"S_DEBTSPIKE5",
|
||||
"S_DEBTSPIKE6",
|
||||
"S_DEBTSPIKE7",
|
||||
"S_DEBTSPIKE8",
|
||||
"S_DEBTSPIKE9",
|
||||
"S_DEBTSPIKEA",
|
||||
"S_DEBTSPIKEB",
|
||||
"S_DEBTSPIKEC",
|
||||
"S_DEBTSPIKED",
|
||||
"S_DEBTSPIKEE",
|
||||
|
||||
#ifdef SEENAMES
|
||||
"S_NAMECHECK",
|
||||
#endif
|
||||
|
|
@ -9412,6 +9462,8 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
|
|||
|
||||
"MT_THOK", // Thok! mobj
|
||||
"MT_PLAYER",
|
||||
"MT_KART_LEFTOVER",
|
||||
"MT_KART_TIRE",
|
||||
|
||||
// Enemies
|
||||
"MT_BLUECRAWLA", // Crawla (Blue)
|
||||
|
|
@ -9537,6 +9589,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
|
|||
// Collectible Items
|
||||
"MT_RING",
|
||||
"MT_FLINGRING", // Lost ring
|
||||
"MT_DEBTSPIKE", // Ring debt funny spike
|
||||
"MT_BLUESPHERE", // Blue sphere for special stages
|
||||
"MT_FLINGBLUESPHERE", // Lost blue sphere
|
||||
"MT_BOMBSPHERE",
|
||||
|
|
@ -10480,6 +10533,8 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
|
|||
|
||||
"MT_PAPERITEMSPOT",
|
||||
|
||||
"MT_BEAMPOINT",
|
||||
|
||||
#ifdef SEENAMES
|
||||
"MT_NAMECHECK",
|
||||
#endif
|
||||
|
|
@ -11002,6 +11057,32 @@ static const char *const KARTSTUFF_LIST[] = {
|
|||
"WRONGWAY"
|
||||
};
|
||||
|
||||
static const char *const KARTHUD_LIST[] = {
|
||||
"ITEMBLINK",
|
||||
"ITEMBLINKMODE",
|
||||
|
||||
"RINGFRAME",
|
||||
"RINGTICS",
|
||||
"RINGDELAY",
|
||||
"RINGSPBBLOCK",
|
||||
|
||||
"LAPANIMATION",
|
||||
"LAPHAND",
|
||||
|
||||
"FAULT",
|
||||
|
||||
"BOOSTCAM",
|
||||
"DESTBOOSTCAM",
|
||||
"TIMEOVERCAM",
|
||||
|
||||
"ENGINESND",
|
||||
"VOICES",
|
||||
"TAUNTVOICES",
|
||||
|
||||
"CARDANIMATION",
|
||||
"YOUGOTEM",
|
||||
};
|
||||
|
||||
static const char *const HUDITEMS_LIST[] = {
|
||||
"LIVES",
|
||||
|
||||
|
|
@ -11245,6 +11326,7 @@ struct {
|
|||
{"LF_SCRIPTISFILE",LF_SCRIPTISFILE},
|
||||
{"LF_NOZONE",LF_NOZONE},
|
||||
{"LF_SECTIONRACE",LF_SECTIONRACE},
|
||||
{"LF_SUBTRACTNUM",LF_SUBTRACTNUM},
|
||||
// And map flags
|
||||
{"LF2_HIDEINMENU",LF2_HIDEINMENU},
|
||||
{"LF2_HIDEINSTATS",LF2_HIDEINSTATS},
|
||||
|
|
@ -11405,19 +11487,11 @@ struct {
|
|||
|
||||
// Player animation (panim_t)
|
||||
{"PA_ETC",PA_ETC},
|
||||
{"PA_IDLE",PA_IDLE},
|
||||
{"PA_EDGE",PA_EDGE},
|
||||
{"PA_WALK",PA_WALK},
|
||||
{"PA_RUN",PA_RUN},
|
||||
{"PA_DASH",PA_DASH},
|
||||
{"PA_PAIN",PA_PAIN},
|
||||
{"PA_ROLL",PA_ROLL},
|
||||
{"PA_JUMP",PA_JUMP},
|
||||
{"PA_SPRING",PA_SPRING},
|
||||
{"PA_FALL",PA_FALL},
|
||||
{"PA_ABILITY",PA_ABILITY},
|
||||
{"PA_ABILITY2",PA_ABILITY2},
|
||||
{"PA_RIDE",PA_RIDE},
|
||||
{"PA_STILL",PA_STILL},
|
||||
{"PA_SLOW",PA_SLOW},
|
||||
{"PA_FAST",PA_FAST},
|
||||
{"PA_DRIFT",PA_DRIFT},
|
||||
{"PA_HURT",PA_HURT},
|
||||
|
||||
// Value for infinite lives
|
||||
{"INFLIVES",INFLIVES},
|
||||
|
|
@ -11644,6 +11718,8 @@ struct {
|
|||
{"V_70TRANS",V_70TRANS},
|
||||
{"V_80TRANS",V_80TRANS},
|
||||
{"V_90TRANS",V_90TRANS},
|
||||
{"V_ADDTRANS",V_ADDTRANS},
|
||||
{"V_SUBTRANS",V_SUBTRANS},
|
||||
{"V_HUDTRANSHALF",V_HUDTRANSHALF},
|
||||
{"V_HUDTRANS",V_HUDTRANS},
|
||||
{"V_RETURN8",V_RETURN8},
|
||||
|
|
@ -12244,6 +12320,7 @@ void DEH_Check(void)
|
|||
const size_t dehmobjs = sizeof(MOBJTYPE_LIST)/sizeof(const char*);
|
||||
const size_t dehpowers = sizeof(POWERS_LIST)/sizeof(const char*);
|
||||
const size_t dehkartstuff = sizeof(KARTSTUFF_LIST)/sizeof(const char*);
|
||||
const size_t dehkarthud = sizeof(KARTHUD_LIST)/sizeof(const char*);
|
||||
const size_t dehcolors = sizeof(COLOR_ENUMS)/sizeof(const char*);
|
||||
|
||||
if (dehstates != S_FIRSTFREESLOT)
|
||||
|
|
@ -12256,7 +12333,10 @@ void DEH_Check(void)
|
|||
I_Error("You forgot to update the Dehacked powers list, you dolt!\n(%d powers defined, versus %s in the Dehacked list)\n", NUMPOWERS, sizeu1(dehpowers));
|
||||
|
||||
if (dehkartstuff != NUMKARTSTUFF)
|
||||
I_Error("You forgot to update the Dehacked powers list, you dolt!\n(%d kartstuff defined, versus %s in the Dehacked list)\n", NUMKARTSTUFF, sizeu1(dehkartstuff));
|
||||
I_Error("You forgot to update the Dehacked kartstuff list, you dolt!\n(%d kartstuff defined, versus %s in the Dehacked list)\n", NUMKARTSTUFF, sizeu1(dehkartstuff));
|
||||
|
||||
if (dehkarthud != NUMKARTHUD)
|
||||
I_Error("You forgot to update the Dehacked karthud list, you dolt!\n(%d karthud defined, versus %s in the Dehacked list)\n", NUMKARTSTUFF, sizeu1(dehkartstuff));
|
||||
|
||||
if (dehcolors != SKINCOLOR_FIRSTFREESLOT)
|
||||
I_Error("You forgot to update the Dehacked colors list, you dolt!\n(%d colors defined, versus %s in the Dehacked list)\n", SKINCOLOR_FIRSTFREESLOT, sizeu1(dehcolors));
|
||||
|
|
@ -12718,6 +12798,15 @@ static inline int lib_getenum(lua_State *L)
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
else if (!mathlib && fastncmp("khud_",word,5)) {
|
||||
p = word+5;
|
||||
for (i = 0; i < NUMKARTHUD; i++)
|
||||
if (fasticmp(p, KARTHUD_LIST[i])) {
|
||||
lua_pushinteger(L, i);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else if (mathlib && fastncmp("K_",word,2)) { // SOCs are ALL CAPS!
|
||||
p = word+2;
|
||||
for (i = 0; i < NUMKARTSTUFF; i++)
|
||||
|
|
@ -12727,6 +12816,15 @@ static inline int lib_getenum(lua_State *L)
|
|||
}
|
||||
return luaL_error(L, "kartstuff '%s' could not be found.\n", word);
|
||||
}
|
||||
else if (mathlib && fastncmp("KHUD_",word,5)) { // SOCs are ALL CAPS!
|
||||
p = word+5;
|
||||
for (i = 0; i < NUMKARTHUD; i++)
|
||||
if (fastcmp(p, KARTHUD_LIST[i])) {
|
||||
lua_pushinteger(L, i);
|
||||
return 1;
|
||||
}
|
||||
return luaL_error(L, "karthud '%s' could not be found.\n", word);
|
||||
}
|
||||
else if (fastncmp("HUD_",word,4)) {
|
||||
p = word+4;
|
||||
for (i = 0; i < NUMHUDITEMS; i++)
|
||||
|
|
|
|||
|
|
@ -408,6 +408,7 @@ typedef struct
|
|||
#define LF_SCRIPTISFILE (1<<0) ///< True if the script is a file, not a lump.
|
||||
#define LF_NOZONE (1<<1) ///< Don't include "ZONE" on level title
|
||||
#define LF_SECTIONRACE (1<<2) ///< Section race level
|
||||
#define LF_SUBTRACTNUM (1<<3) ///< Use subtractive position number (for bright levels)
|
||||
|
||||
#define LF2_HIDEINMENU (1<<0) ///< Hide in the multiplayer menu
|
||||
#define LF2_HIDEINSTATS (1<<1) ///< Hide in the statistics screen
|
||||
|
|
|
|||
|
|
@ -1309,9 +1309,11 @@ void G_PreLevelTitleCard(void)
|
|||
//
|
||||
boolean G_IsTitleCardAvailable(void)
|
||||
{
|
||||
#if 0
|
||||
// The current level has no name.
|
||||
if (!mapheaderinfo[gamemap-1]->lvlttl[0])
|
||||
return false;
|
||||
#endif
|
||||
|
||||
// The title card is available.
|
||||
return true;
|
||||
|
|
@ -2261,7 +2263,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
p->pflags |= PF_JUMPDOWN;
|
||||
|
||||
p->playerstate = PST_LIVE;
|
||||
p->panim = PA_IDLE; // standing animation
|
||||
p->panim = PA_STILL; // standing animation
|
||||
|
||||
// Check to make sure their color didn't change somehow...
|
||||
if (G_GametypeHasTeams())
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t
|
|||
// 0--1
|
||||
float dupx, dupy, fscalew, fscaleh, fwidth, fheight;
|
||||
|
||||
if (alphalevel >= 10 && alphalevel < 13)
|
||||
if (alphalevel >= 12 && alphalevel < 13)
|
||||
return;
|
||||
|
||||
// make patch ready in hardware cache
|
||||
|
|
@ -268,7 +268,9 @@ void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t
|
|||
{
|
||||
FSurfaceInfo Surf;
|
||||
Surf.PolyColor.s.red = Surf.PolyColor.s.green = Surf.PolyColor.s.blue = 0xff;
|
||||
if (alphalevel == 13) Surf.PolyColor.s.alpha = softwaretranstogl_lo[st_translucency];
|
||||
if (alphalevel == 10) { flags &= ~PF_Translucent; flags |= PF_Additive; }
|
||||
else if (alphalevel == 11) { flags &= ~PF_Translucent; flags |= PF_Substractive; }
|
||||
else if (alphalevel == 13) Surf.PolyColor.s.alpha = softwaretranstogl_lo[st_translucency];
|
||||
else if (alphalevel == 14) Surf.PolyColor.s.alpha = softwaretranstogl[st_translucency];
|
||||
else if (alphalevel == 15) Surf.PolyColor.s.alpha = softwaretranstogl_hi[st_translucency];
|
||||
else Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel];
|
||||
|
|
@ -293,7 +295,7 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal
|
|||
// 0--1
|
||||
float dupx, dupy, fscale, fwidth, fheight;
|
||||
|
||||
if (alphalevel >= 10 && alphalevel < 13)
|
||||
if (alphalevel >= 12 && alphalevel < 13)
|
||||
return;
|
||||
|
||||
// make patch ready in hardware cache
|
||||
|
|
@ -426,7 +428,9 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal
|
|||
{
|
||||
FSurfaceInfo Surf;
|
||||
Surf.PolyColor.s.red = Surf.PolyColor.s.green = Surf.PolyColor.s.blue = 0xff;
|
||||
if (alphalevel == 13) Surf.PolyColor.s.alpha = softwaretranstogl_lo[st_translucency];
|
||||
if (alphalevel == 10) { flags &= ~PF_Translucent; flags |= PF_Additive; }
|
||||
else if (alphalevel == 11) { flags &= ~PF_Translucent; flags |= PF_Substractive; }
|
||||
else if (alphalevel == 13) Surf.PolyColor.s.alpha = softwaretranstogl_lo[st_translucency];
|
||||
else if (alphalevel == 14) Surf.PolyColor.s.alpha = softwaretranstogl[st_translucency];
|
||||
else if (alphalevel == 15) Surf.PolyColor.s.alpha = softwaretranstogl_hi[st_translucency];
|
||||
else Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel];
|
||||
|
|
|
|||
|
|
@ -150,8 +150,8 @@ FUNCPRINTF void GL_DBG_Printf(const char *format, ...)
|
|||
char str[4096] = "";
|
||||
va_list arglist;
|
||||
|
||||
if (gllogstream)
|
||||
{
|
||||
if (gllogstream)
|
||||
{
|
||||
va_start(arglist, format);
|
||||
vsnprintf(str, 4096, format, arglist);
|
||||
va_end(arglist);
|
||||
|
|
@ -698,7 +698,38 @@ static INT32 shader_leveltime = 0;
|
|||
"float fd = fe - fs;\n" \
|
||||
"darkness = clamp((darkness - fs) * (1.0 / fd), 0.0, 1.0);\n" \
|
||||
"}\n" \
|
||||
"final_color = mix(final_color, fade_color, darkness);\n"
|
||||
"float colorBrightness = sqrt((final_color.r * final_color.r) + (final_color.g * final_color.g) + (final_color.b * final_color.b));\n" \
|
||||
"float fogBrightness = sqrt((fade_color.r * fade_color.r) + (fade_color.g * fade_color.g) + (fade_color.b * fade_color.b));\n" \
|
||||
"float colorIntensity = 0.0;\n" \
|
||||
"if (fogBrightness > colorBrightness) {\n" \
|
||||
"colorIntensity = 1.0 - min(final_color.r, min(final_color.g, final_color.b));\n" \
|
||||
"colorIntensity = abs(colorIntensity - (1.0 - fogBrightness));\n" \
|
||||
"} else {\n" \
|
||||
"colorIntensity = max(final_color.r, max(final_color.g, final_color.b));\n" \
|
||||
"colorIntensity = abs(colorIntensity - (fogBrightness));\n" \
|
||||
"}\n" \
|
||||
"colorIntensity *= darkness;\n" \
|
||||
"if (abs(final_color.r - fade_color.r) <= colorIntensity) {\n" \
|
||||
"final_color.r = fade_color.r;\n" \
|
||||
"} else if (final_color.r < fade_color.r) {\n" \
|
||||
"final_color.r += colorIntensity;\n" \
|
||||
"} else {\n" \
|
||||
"final_color.r -= colorIntensity;\n" \
|
||||
"}\n" \
|
||||
"if (abs(final_color.g - fade_color.g) <= colorIntensity) {\n" \
|
||||
"final_color.g = fade_color.g;\n" \
|
||||
"} else if (final_color.g < fade_color.g) {\n" \
|
||||
"final_color.g += colorIntensity;\n" \
|
||||
"} else {\n" \
|
||||
"final_color.g -= colorIntensity;\n" \
|
||||
"}\n" \
|
||||
"if (abs(final_color.b - fade_color.b) <= colorIntensity) {\n" \
|
||||
"final_color.b = fade_color.b;\n" \
|
||||
"} else if (final_color.b < fade_color.b) {\n" \
|
||||
"final_color.b += colorIntensity;\n" \
|
||||
"} else {\n" \
|
||||
"final_color.b -= colorIntensity;\n" \
|
||||
"}\n" \
|
||||
|
||||
#define GLSL_SOFTWARE_FRAGMENT_SHADER \
|
||||
"uniform sampler2D tex;\n" \
|
||||
|
|
|
|||
194
src/info.c
194
src/info.c
|
|
@ -32,6 +32,8 @@ char sprnames[NUMSPRITES + 1][5] =
|
|||
|
||||
"THOK", // Thok! mobj
|
||||
"PLAY",
|
||||
"KART",
|
||||
"TIRE",
|
||||
|
||||
// Enemies
|
||||
"POSS", // Crawla (Blue)
|
||||
|
|
@ -131,6 +133,7 @@ char sprnames[NUMSPRITES + 1][5] =
|
|||
|
||||
// Collectible Items
|
||||
"RING",
|
||||
"DEBT",
|
||||
"TRNG", // Team Rings
|
||||
"TOKE", // Special Stage Token
|
||||
"RFLG", // Red CTF Flag
|
||||
|
|
@ -732,26 +735,39 @@ char sprnames[NUMSPRITES + 1][5] =
|
|||
"GCHA", // follower: generic chao
|
||||
"CHEZ", // follower: cheese
|
||||
|
||||
// First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw later
|
||||
"VIEW",
|
||||
|
||||
"DBCL", // Drift boost clip
|
||||
"DBNC", // Drift boost clip's sparks
|
||||
"DBST", // Drift boost plume
|
||||
|
||||
"SDDS", // Spindash dust
|
||||
"SDWN", // Spindash wind
|
||||
|
||||
"FLBM",
|
||||
|
||||
// First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw later
|
||||
"VIEW",
|
||||
};
|
||||
|
||||
char spr2names[NUMPLAYERSPRITES][5] =
|
||||
{
|
||||
"STIN", "STIL", "STIR", // Still
|
||||
"STGL", "STGR", // Still (glance back)
|
||||
"STLL", "STLR", // Still (look back)
|
||||
|
||||
"SLWN", "SLWL", "SLWR", // Slow driving
|
||||
"SLGL", "SLGR", // Slow (glance back)
|
||||
"SLLL", "SLLR", // Slow (look back)
|
||||
|
||||
"FSTN", "FSTL", "FSTR", // Fast driving
|
||||
"FSGL", "FSGR", // Fast (glance back)
|
||||
"FSLL", "FSLR", // Fast (look back)
|
||||
|
||||
"DRLN", "DRLO", "DRLI", // Drifting left
|
||||
"DRRN", "DRRO", "DRRI", // Drifting right
|
||||
|
||||
"SPIN", // Spinout
|
||||
"SQSH", // Squish
|
||||
"DEAD", // Dead
|
||||
|
||||
"SIGN", // Finish signpost
|
||||
"XTRA", // Three Faces of Darkness
|
||||
};
|
||||
|
|
@ -761,14 +777,26 @@ playersprite_t spr2defaults[NUMPLAYERSPRITES] = {
|
|||
0, // SPR2_STIN
|
||||
SPR2_STIN, // SPR2_STIL
|
||||
SPR2_STIN, // SPR2_STIR
|
||||
SPR2_STIN, // SPR2_STGL
|
||||
SPR2_STIN, // SPR2_STGR
|
||||
SPR2_STGL, // SPR2_STLL
|
||||
SPR2_STGR, // SPR2_STLR
|
||||
|
||||
0, // SPR2_SLWN
|
||||
SPR2_SLWN, // SPR2_SLWL
|
||||
SPR2_SLWN, // SPR2_SLWR
|
||||
SPR2_SLWN, // SPR2_SLGL
|
||||
SPR2_SLWN, // SPR2_SLGR
|
||||
SPR2_SLGL, // SPR2_SLLL
|
||||
SPR2_SLGR, // SPR2_SLLR
|
||||
|
||||
0, // SPR2_FSTN
|
||||
SPR2_FSTN, // SPR2_FSTL
|
||||
SPR2_FSTN, // SPR2_FSTR
|
||||
SPR2_FSTN, // SPR2_FSGL
|
||||
SPR2_FSTN, // SPR2_FSGR
|
||||
SPR2_FSGL, // SPR2_FSLL
|
||||
SPR2_FSGR, // SPR2_FSLR
|
||||
|
||||
0, // SPR2_DRLN
|
||||
SPR2_DRLN, // SPR2_DRLO
|
||||
|
|
@ -779,9 +807,10 @@ playersprite_t spr2defaults[NUMPLAYERSPRITES] = {
|
|||
SPR2_DRRN, // SPR2_DRRI
|
||||
|
||||
0, // SPR2_SPIN
|
||||
SPR2_SPIN, // SPR2_SQSH
|
||||
0, // SPR2_DEAD
|
||||
|
||||
0, // SPR2_SIGN
|
||||
0, // SPR2_XTRA
|
||||
};
|
||||
|
||||
// Doesn't work with g++, needs actionf_p1 (don't modify this comment)
|
||||
|
|
@ -812,12 +841,24 @@ state_t states[NUMSTATES] =
|
|||
{SPR_PLAY, SPR2_STIN, 1, {NULL}, 0, 0, S_KART_STILL}, // S_KART_STILL
|
||||
{SPR_PLAY, SPR2_STIL, 1, {NULL}, 0, 0, S_KART_STILL_L}, // S_KART_STILL_L
|
||||
{SPR_PLAY, SPR2_STIR, 1, {NULL}, 0, 0, S_KART_STILL_R}, // S_KART_STILL_R
|
||||
{SPR_PLAY, SPR2_STGL, 1, {NULL}, 0, 0, S_KART_STILL_GLANCE_L}, // S_KART_STILL_GLANCE_L
|
||||
{SPR_PLAY, SPR2_STGR, 1, {NULL}, 0, 0, S_KART_STILL_GLANCE_R}, // S_KART_STILL_GLANCE_R
|
||||
{SPR_PLAY, SPR2_STLL, 1, {NULL}, 0, 0, S_KART_STILL_LOOK_L}, // S_KART_STILL_LOOK_L
|
||||
{SPR_PLAY, SPR2_STLR, 1, {NULL}, 0, 0, S_KART_STILL_LOOK_R}, // S_KART_STILL_LOOK_R
|
||||
{SPR_PLAY, SPR2_SLWN, 1, {NULL}, 0, 0, S_KART_SLOW}, // S_KART_SLOW
|
||||
{SPR_PLAY, SPR2_SLWL, 1, {NULL}, 0, 0, S_KART_SLOW_L}, // S_KART_SLOW_L
|
||||
{SPR_PLAY, SPR2_SLWR, 1, {NULL}, 0, 0, S_KART_SLOW_R}, // S_KART_SLOW_R
|
||||
{SPR_PLAY, SPR2_SLGL, 1, {NULL}, 0, 0, S_KART_SLOW_GLANCE_L}, // S_KART_SLOW_GLANCE_L
|
||||
{SPR_PLAY, SPR2_SLGR, 1, {NULL}, 0, 0, S_KART_SLOW_GLANCE_R}, // S_KART_SLOW_GLANCE_R
|
||||
{SPR_PLAY, SPR2_SLLL, 1, {NULL}, 0, 0, S_KART_SLOW_LOOK_L}, // S_KART_SLOW_LOOK_L
|
||||
{SPR_PLAY, SPR2_SLLR, 1, {NULL}, 0, 0, S_KART_SLOW_LOOK_R}, // S_KART_SLOW_LOOK_R
|
||||
{SPR_PLAY, SPR2_FSTN, 1, {NULL}, 0, 0, S_KART_FAST}, // S_KART_FAST
|
||||
{SPR_PLAY, SPR2_FSTL, 1, {NULL}, 0, 0, S_KART_FAST_L}, // S_KART_FAST_L
|
||||
{SPR_PLAY, SPR2_FSTR, 1, {NULL}, 0, 0, S_KART_FAST_R}, // S_KART_FAST_R
|
||||
{SPR_PLAY, SPR2_FSGL, 1, {NULL}, 0, 0, S_KART_FAST_GLANCE_L}, // S_KART_FAST_GLANCE_L
|
||||
{SPR_PLAY, SPR2_FSGR, 1, {NULL}, 0, 0, S_KART_FAST_GLANCE_R}, // S_KART_FAST_GLANCE_R
|
||||
{SPR_PLAY, SPR2_FSLL, 1, {NULL}, 0, 0, S_KART_FAST_LOOK_L}, // S_KART_FAST_LOOK_L
|
||||
{SPR_PLAY, SPR2_FSLR, 1, {NULL}, 0, 0, S_KART_FAST_LOOK_R}, // S_KART_FAST_LOOK_R
|
||||
{SPR_PLAY, SPR2_DRLN, 1, {NULL}, 0, 0, S_KART_DRIFT_L}, // S_KART_DRIFT_L
|
||||
{SPR_PLAY, SPR2_DRLO, 1, {NULL}, 0, 0, S_KART_DRIFT_L_OUT}, // S_KART_DRIFT_L_OUT
|
||||
{SPR_PLAY, SPR2_DRLI, 1, {NULL}, 0, 0, S_KART_DRIFT_L_IN}, // S_KART_DRIFT_L_IN
|
||||
|
|
@ -825,11 +866,17 @@ state_t states[NUMSTATES] =
|
|||
{SPR_PLAY, SPR2_DRRO, 1, {NULL}, 0, 0, S_KART_DRIFT_R_OUT}, // S_KART_DRIFT_R_OUT
|
||||
{SPR_PLAY, SPR2_DRRI, 1, {NULL}, 0, 0, S_KART_DRIFT_R_IN}, // S_KART_DRIFT_R_IN
|
||||
{SPR_PLAY, SPR2_SPIN|FF_ANIMATE, 350, {NULL}, 0, 1, S_KART_STILL}, // S_KART_SPINOUT
|
||||
{SPR_PLAY, SPR2_SQSH|FF_ANIMATE, 350, {NULL}, 0, 1, S_KART_STILL}, // S_KART_SQUISH
|
||||
{SPR_PLAY, SPR2_DEAD, 3, {NULL}, 0, 0, S_KART_DEAD}, // S_KART_DEAD
|
||||
{SPR_PLAY, SPR2_SIGN|FF_PAPERSPRITE, 1, {NULL}, 0, 0, S_KART_SIGN}, // S_KART_SIGN
|
||||
|
||||
{SPR_NULL, 0, -1, {NULL}, 0, 0, S_OBJPLACE_DUMMY}, // S_OBJPLACE_DUMMY
|
||||
|
||||
{SPR_KART, 0, -1, {NULL}, 0, 0, S_NULL}, // S_KART_LEFTOVER
|
||||
{SPR_KART, 1, -1, {NULL}, 0, 0, S_NULL}, // S_KART_LEFTOVER_NOTIRES
|
||||
|
||||
{SPR_TIRE, 0, -1, {NULL}, 0, 0, S_NULL}, // S_KART_TIRE1
|
||||
{SPR_TIRE, 1, -1, {NULL}, 0, 0, S_NULL}, // S_KART_TIRE2
|
||||
|
||||
// Blue Crawla
|
||||
{SPR_POSS, 0, 5, {A_Look}, 0, 0, S_POSS_STND}, // S_POSS_STND
|
||||
{SPR_POSS, 0, 3, {A_Chase}, 0, 0, S_POSS_RUN2}, // S_POSS_RUN1
|
||||
|
|
@ -5115,6 +5162,31 @@ state_t states[NUMSTATES] =
|
|||
{SPR_SDDS, FF_ANIMATE, 9, {NULL}, 9, 1, S_NULL}, // S_SPINDASHDUST
|
||||
{SPR_SDWN, FF_ANIMATE|FF_PAPERSPRITE, 18, {NULL}, 9, 2, S_NULL}, // S_SPINDASHWIND
|
||||
|
||||
// Finish line beam
|
||||
{SPR_FLBM, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_NULL}, // S_FINISHBEAM1
|
||||
{SPR_FLBM, FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_NULL}, // S_FINISHBEAM2
|
||||
{SPR_FLBM, FF_FULLBRIGHT|2, 1, {NULL}, 0, 0, S_NULL}, // S_FINISHBEAM3
|
||||
{SPR_FLBM, FF_FULLBRIGHT|3, 1, {NULL}, 0, 0, S_NULL}, // S_FINISHBEAM4
|
||||
{SPR_FLBM, FF_FULLBRIGHT|4, 1, {NULL}, 0, 0, S_NULL}, // S_FINISHBEAM5
|
||||
{SPR_FLBM, FF_PAPERSPRITE|5, 1, {NULL}, 0, 0, S_NULL}, // S_FINISHBEAMEND1
|
||||
{SPR_FLBM, FF_PAPERSPRITE|6, 1, {NULL}, 0, 0, S_NULL}, // S_FINISHBEAMEND2
|
||||
|
||||
// Funny Spike
|
||||
{SPR_DEBT, 0|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_DEBTSPIKE2}, // S_DEBTSPIKE1
|
||||
{SPR_DEBT, 7|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_DEBTSPIKE3}, // S_DEBTSPIKE2
|
||||
{SPR_DEBT, 1|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_DEBTSPIKE4}, // S_DEBTSPIKE3
|
||||
{SPR_DEBT, 7|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_DEBTSPIKE5}, // S_DEBTSPIKE4
|
||||
{SPR_DEBT, 2|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_DEBTSPIKE6}, // S_DEBTSPIKE5
|
||||
{SPR_DEBT, 7|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_DEBTSPIKE7}, // S_DEBTSPIKE6
|
||||
{SPR_DEBT, 3|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_DEBTSPIKE8}, // S_DEBTSPIKE7
|
||||
{SPR_DEBT, 7|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_DEBTSPIKE9}, // S_DEBTSPIKE8
|
||||
{SPR_DEBT, 4|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_DEBTSPIKEA}, // S_DEBTSPIKE9
|
||||
{SPR_DEBT, 7|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_DEBTSPIKEB}, // S_DEBTSPIKEA
|
||||
{SPR_DEBT, 5|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_DEBTSPIKEC}, // S_DEBTSPIKEB
|
||||
{SPR_DEBT, 7|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_DEBTSPIKED}, // S_DEBTSPIKEC
|
||||
{SPR_DEBT, 6|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_DEBTSPIKEE}, // S_DEBTSPIKED
|
||||
{SPR_DEBT, 7|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_DEBTSPIKE1}, // S_DEBTSPIKEE
|
||||
|
||||
#ifdef SEENAMES
|
||||
{SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_NAMECHECK
|
||||
#endif
|
||||
|
|
@ -5216,7 +5288,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_KART_SPINOUT, // deathstate
|
||||
S_KART_DEAD, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
1, // speed
|
||||
|
|
@ -5230,6 +5302,60 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
(statenum_t)MT_THOK // raisestate
|
||||
},
|
||||
|
||||
{ // MT_KART_LEFTOVER
|
||||
4095, // doomednum
|
||||
S_KART_LEFTOVER, // spawnstate
|
||||
2, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
0, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
0, // painchance
|
||||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
1, // speed
|
||||
16*FRACUNIT, // radius
|
||||
48*FRACUNIT, // height
|
||||
-1, // display offset
|
||||
1000, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_SOLID|MF_DONTENCOREMAP, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_KART_TIRE
|
||||
-1, // doomednum
|
||||
S_KART_TIRE1, // spawnstate
|
||||
1, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
0, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
0, // painchance
|
||||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
1, // speed
|
||||
6*FRACUNIT, // radius
|
||||
12*FRACUNIT, // height
|
||||
-1, // display offset
|
||||
1000, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_DONTENCOREMAP, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_BLUECRAWLA
|
||||
100, // doomednum
|
||||
S_POSS_STND, // spawnstate
|
||||
|
|
@ -8011,6 +8137,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_DEBTSPIKE
|
||||
-1, // doomednum
|
||||
S_DEBTSPIKE1, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
MT_FLINGRING, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
MT_RING, // painchance
|
||||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_SPRK1, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_itemup, // deathsound
|
||||
38*FRACUNIT, // speed
|
||||
24*FRACUNIT, // radius
|
||||
48*FRACUNIT, // height
|
||||
0, // display offset
|
||||
100, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_DONTENCOREMAP, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_BLUESPHERE
|
||||
-1, // doomednum
|
||||
S_BLUESPHERE_SPAWN, // spawnstate
|
||||
|
|
@ -28743,6 +28896,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_BEAMPOINT
|
||||
2424, // 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_NOSECTOR|MF_NOCLIPTHING|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
// ============================================================================================================================//
|
||||
|
||||
#ifdef SEENAMES
|
||||
|
|
|
|||
64
src/info.h
64
src/info.h
|
|
@ -303,6 +303,8 @@ typedef enum sprite
|
|||
|
||||
SPR_THOK, // Thok! mobj
|
||||
SPR_PLAY,
|
||||
SPR_KART,
|
||||
SPR_TIRE,
|
||||
|
||||
// Enemies
|
||||
SPR_POSS, // Crawla (Blue)
|
||||
|
|
@ -402,6 +404,7 @@ typedef enum sprite
|
|||
|
||||
// Collectible Items
|
||||
SPR_RING,
|
||||
SPR_DEBT,
|
||||
SPR_TRNG, // Team Rings
|
||||
SPR_TOKE, // Special Stage Token
|
||||
SPR_RFLG, // Red CTF Flag
|
||||
|
|
@ -1003,9 +1006,6 @@ typedef enum sprite
|
|||
SPR_GCHA, // follower: generic chao
|
||||
SPR_CHEZ, // follower: cheese
|
||||
|
||||
// First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw later
|
||||
SPR_VIEW,
|
||||
|
||||
SPR_DBCL, // Drift boost clip
|
||||
SPR_DBNC, // Drift boost clip's sparks
|
||||
SPR_DBST, // Drift boost plume
|
||||
|
|
@ -1013,6 +1013,11 @@ typedef enum sprite
|
|||
SPR_SDDS, // Spindash dust
|
||||
SPR_SDWN, // Spindash wind
|
||||
|
||||
SPR_FLBM, // Finish line beam
|
||||
|
||||
// First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw later
|
||||
SPR_VIEW,
|
||||
|
||||
SPR_FIRSTFREESLOT,
|
||||
SPR_LASTFREESLOT = SPR_FIRSTFREESLOT + NUMSPRITEFREESLOTS - 1,
|
||||
NUMSPRITES
|
||||
|
|
@ -1024,12 +1029,15 @@ typedef enum sprite
|
|||
typedef enum playersprite
|
||||
{
|
||||
SPR2_STIN = 0, SPR2_STIL, SPR2_STIR,
|
||||
SPR2_STGL, SPR2_STGR, SPR2_STLL, SPR2_STLR,
|
||||
SPR2_SLWN, SPR2_SLWL, SPR2_SLWR,
|
||||
SPR2_SLGL, SPR2_SLGR, SPR2_SLLL, SPR2_SLLR,
|
||||
SPR2_FSTN, SPR2_FSTL, SPR2_FSTR,
|
||||
SPR2_FSGL, SPR2_FSGR, SPR2_FSLL, SPR2_FSLR,
|
||||
SPR2_DRLN, SPR2_DRLO, SPR2_DRLI,
|
||||
SPR2_DRRN, SPR2_DRRO, SPR2_DRRI,
|
||||
SPR2_SPIN,
|
||||
SPR2_SQSH,
|
||||
SPR2_DEAD,
|
||||
SPR2_SIGN,
|
||||
SPR2_XTRA,
|
||||
SPR2_FIRSTFREESLOT,
|
||||
|
|
@ -1057,12 +1065,24 @@ typedef enum state
|
|||
S_KART_STILL,
|
||||
S_KART_STILL_L,
|
||||
S_KART_STILL_R,
|
||||
S_KART_STILL_GLANCE_L,
|
||||
S_KART_STILL_GLANCE_R,
|
||||
S_KART_STILL_LOOK_L,
|
||||
S_KART_STILL_LOOK_R,
|
||||
S_KART_SLOW,
|
||||
S_KART_SLOW_L,
|
||||
S_KART_SLOW_R,
|
||||
S_KART_SLOW_GLANCE_L,
|
||||
S_KART_SLOW_GLANCE_R,
|
||||
S_KART_SLOW_LOOK_L,
|
||||
S_KART_SLOW_LOOK_R,
|
||||
S_KART_FAST,
|
||||
S_KART_FAST_L,
|
||||
S_KART_FAST_R,
|
||||
S_KART_FAST_GLANCE_L,
|
||||
S_KART_FAST_GLANCE_R,
|
||||
S_KART_FAST_LOOK_L,
|
||||
S_KART_FAST_LOOK_R,
|
||||
S_KART_DRIFT_L,
|
||||
S_KART_DRIFT_L_OUT,
|
||||
S_KART_DRIFT_L_IN,
|
||||
|
|
@ -1070,12 +1090,18 @@ typedef enum state
|
|||
S_KART_DRIFT_R_OUT,
|
||||
S_KART_DRIFT_R_IN,
|
||||
S_KART_SPINOUT,
|
||||
S_KART_SQUISH,
|
||||
S_KART_DEAD,
|
||||
S_KART_SIGN,
|
||||
|
||||
// technically the player goes here but it's an infinite tic state
|
||||
S_OBJPLACE_DUMMY,
|
||||
|
||||
S_KART_LEFTOVER,
|
||||
S_KART_LEFTOVER_NOTIRES,
|
||||
|
||||
S_KART_TIRE1,
|
||||
S_KART_TIRE2,
|
||||
|
||||
// Blue Crawla
|
||||
S_POSS_STND,
|
||||
S_POSS_RUN1,
|
||||
|
|
@ -5271,6 +5297,29 @@ typedef enum state
|
|||
S_SPINDASHDUST,
|
||||
S_SPINDASHWIND,
|
||||
|
||||
S_FINISHBEAM1,
|
||||
S_FINISHBEAM2,
|
||||
S_FINISHBEAM3,
|
||||
S_FINISHBEAM4,
|
||||
S_FINISHBEAM5,
|
||||
S_FINISHBEAMEND1,
|
||||
S_FINISHBEAMEND2,
|
||||
|
||||
S_DEBTSPIKE1,
|
||||
S_DEBTSPIKE2,
|
||||
S_DEBTSPIKE3,
|
||||
S_DEBTSPIKE4,
|
||||
S_DEBTSPIKE5,
|
||||
S_DEBTSPIKE6,
|
||||
S_DEBTSPIKE7,
|
||||
S_DEBTSPIKE8,
|
||||
S_DEBTSPIKE9,
|
||||
S_DEBTSPIKEA,
|
||||
S_DEBTSPIKEB,
|
||||
S_DEBTSPIKEC,
|
||||
S_DEBTSPIKED,
|
||||
S_DEBTSPIKEE,
|
||||
|
||||
#ifdef SEENAMES
|
||||
S_NAMECHECK,
|
||||
#endif
|
||||
|
|
@ -5305,6 +5354,8 @@ typedef enum mobj_type
|
|||
|
||||
MT_THOK, // Thok! mobj
|
||||
MT_PLAYER,
|
||||
MT_KART_LEFTOVER,
|
||||
MT_KART_TIRE,
|
||||
|
||||
// Enemies
|
||||
MT_BLUECRAWLA, // Crawla (Blue)
|
||||
|
|
@ -5430,6 +5481,7 @@ typedef enum mobj_type
|
|||
// Collectible Items
|
||||
MT_RING,
|
||||
MT_FLINGRING, // Lost ring
|
||||
MT_DEBTSPIKE, // Ring debt funny spike
|
||||
MT_BLUESPHERE, // Blue sphere for special stages
|
||||
MT_FLINGBLUESPHERE, // Lost blue sphere
|
||||
MT_BOMBSPHERE,
|
||||
|
|
@ -6373,6 +6425,8 @@ typedef enum mobj_type
|
|||
|
||||
MT_PAPERITEMSPOT,
|
||||
|
||||
MT_BEAMPOINT,
|
||||
|
||||
#ifdef SEENAMES
|
||||
MT_NAMECHECK,
|
||||
#endif
|
||||
|
|
|
|||
367
src/k_bot.c
367
src/k_bot.c
|
|
@ -26,6 +26,7 @@
|
|||
#include "d_ticcmd.h"
|
||||
#include "m_random.h"
|
||||
#include "r_things.h" // numskins
|
||||
#include "k_race.h" // finishBeamLine
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
|
|
@ -296,7 +297,7 @@ boolean K_BotCanTakeCut(player_t *player)
|
|||
--------------------------------------------------*/
|
||||
static UINT32 K_BotRubberbandDistance(player_t *player)
|
||||
{
|
||||
const UINT32 spacing = FixedDiv(512 * FRACUNIT, K_GetKartGameSpeedScalar(gamespeed)) / FRACUNIT;
|
||||
const UINT32 spacing = FixedDiv(640 * FRACUNIT, K_GetKartGameSpeedScalar(gamespeed)) / FRACUNIT;
|
||||
const UINT8 portpriority = player - players;
|
||||
UINT8 pos = 0;
|
||||
UINT8 i;
|
||||
|
|
@ -429,8 +430,8 @@ fixed_t K_BotTopSpeedRubberband(player_t *player)
|
|||
}
|
||||
else
|
||||
{
|
||||
// Max at +25% for level 9 bots
|
||||
rubberband = FRACUNIT + ((rubberband - FRACUNIT) / 4);
|
||||
// Max at +10% for level 9 bots
|
||||
rubberband = FRACUNIT + ((rubberband - FRACUNIT) / 10);
|
||||
}
|
||||
|
||||
// Only allow you to go faster than your regular top speed if you're facing the right direction
|
||||
|
|
@ -519,28 +520,35 @@ fixed_t K_BotFrictionRubberband(player_t *player, fixed_t frict)
|
|||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
fixed_t K_DistanceOfLineFromPoint(fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t v2y, fixed_t cx, fixed_t cy)
|
||||
fixed_t K_DistanceOfLineFromPoint(fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t v2y, fixed_t px, fixed_t py)
|
||||
{
|
||||
fixed_t v1toc[2] = {cx - v1x, cy - v1y};
|
||||
fixed_t v1tov2[2] = {v2x - v1x, v2y - v1y};
|
||||
|
||||
fixed_t mag = FixedMul(v1tov2[0], v1tov2[0]) + FixedMul(v1tov2[1], v1tov2[1]);
|
||||
fixed_t dot = FixedMul(v1toc[0], v1tov2[0]) + FixedMul(v1toc[1], v1tov2[1]);
|
||||
// Copy+paste from P_ClosestPointOnLine :pensive:
|
||||
fixed_t startx = v1x;
|
||||
fixed_t starty = v1y;
|
||||
fixed_t dx = v2x - v1x;
|
||||
fixed_t dy = v2y - v1y;
|
||||
|
||||
fixed_t cx, cy;
|
||||
fixed_t vx, vy;
|
||||
fixed_t magnitude;
|
||||
fixed_t t;
|
||||
fixed_t px, py;
|
||||
|
||||
if (mag == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
cx = px - startx;
|
||||
cy = py - starty;
|
||||
|
||||
t = FixedDiv(dot, mag);
|
||||
vx = dx;
|
||||
vy = dy;
|
||||
|
||||
px = v1x + FixedMul(v1tov2[0], t);
|
||||
py = v1y + FixedMul(v1tov2[1], t);
|
||||
magnitude = R_PointToDist2(v2x, v2y, startx, starty);
|
||||
vx = FixedDiv(vx, magnitude);
|
||||
vy = FixedDiv(vy, magnitude);
|
||||
|
||||
return P_AproxDistance(cx - px, cy - py);
|
||||
t = (FixedMul(vx, cx) + FixedMul(vy, cy));
|
||||
|
||||
vx = FixedMul(vx, t);
|
||||
vy = FixedMul(vy, t);
|
||||
|
||||
return R_PointToDist2(px, py, startx + vx, starty + vy);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
|
|
@ -690,6 +698,145 @@ static botprediction_t *K_CreateBotPrediction(player_t *player)
|
|||
return predict;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static UINT8 K_TrySpindash(player_t *player)
|
||||
|
||||
Determines conditions where the bot should attempt to spindash.
|
||||
|
||||
Input Arguments:-
|
||||
player - Bot player to check.
|
||||
|
||||
Return:-
|
||||
0 to make the bot drive normally, 1 to e-brake, 2 to e-brake & charge spindash.
|
||||
(TODO: make this an enum)
|
||||
--------------------------------------------------*/
|
||||
static UINT8 K_TrySpindash(player_t *player)
|
||||
{
|
||||
const tic_t difficultyModifier = (TICRATE/6);
|
||||
|
||||
if (player->kartstuff[k_spindashboost] || player->kartstuff[k_tiregrease])
|
||||
{
|
||||
// You just released a spindash, you don't need to try again yet, jeez.
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Try "start boosts" first
|
||||
if (leveltime == starttime)
|
||||
{
|
||||
// Forces them to release, even if they haven't fully charged.
|
||||
// Don't want them to keep charging if they didn't have time to.
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (leveltime < starttime)
|
||||
{
|
||||
INT32 boosthold = starttime - K_GetSpindashChargeTime(player);
|
||||
|
||||
boosthold -= (MAXBOTDIFFICULTY - player->botvars.difficulty) * difficultyModifier;
|
||||
|
||||
if (leveltime >= (unsigned)boosthold)
|
||||
{
|
||||
// Start charging...
|
||||
return 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Just hold your ground and e-brake.
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Logic for normal racing.
|
||||
if (player->powers[pw_flashing] > 0)
|
||||
{
|
||||
// Don't bother trying to spindash.
|
||||
// Trying to spindash while flashing is fine during POSITION, but not during the actual race.
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (player->speed < 10*mapobjectscale // Below the speed threshold
|
||||
&& player->kartstuff[k_speedboost] < (FRACUNIT/8)) // If you have other boosts, you can probably trust it.
|
||||
{
|
||||
INT32 chargingPoint = (K_GetSpindashChargeTime(player) + difficultyModifier);
|
||||
|
||||
// Release quicker the higher the difficulty is.
|
||||
// Sounds counter-productive, but that's actually the best strategy after the race has started.
|
||||
chargingPoint -= player->botvars.difficulty * difficultyModifier;
|
||||
|
||||
if (player->kartstuff[k_spindash] > chargingPoint)
|
||||
{
|
||||
// Time to release.
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
// We're doing just fine, we don't need to spindash, thanks.
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static INT16 K_FindBotController(mobj_t *mo)
|
||||
|
||||
Finds if any bot controller linedefs are tagged to the bot's sector.
|
||||
|
||||
Input Arguments:-
|
||||
mo - The bot player's mobj.
|
||||
|
||||
Return:-
|
||||
Line number of the bot controller. -1 if it doesn't exist.
|
||||
--------------------------------------------------*/
|
||||
static INT16 K_FindBotController(mobj_t *mo)
|
||||
{
|
||||
msecnode_t *node;
|
||||
ffloor_t *rover;
|
||||
INT16 lineNum = -1;
|
||||
|
||||
I_Assert(mo != NULL);
|
||||
I_Assert(!P_MobjWasRemoved(mo));
|
||||
|
||||
for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next)
|
||||
{
|
||||
if (!node->m_sector)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
lineNum = P_FindSpecialLineFromTag(2004, node->m_sector->tag, -1);
|
||||
|
||||
if (lineNum != -1)
|
||||
{
|
||||
return lineNum;
|
||||
}
|
||||
|
||||
for (rover = node->m_sector->ffloors; rover; rover = rover->next)
|
||||
{
|
||||
sector_t *rs = NULL;
|
||||
|
||||
if (!(rover->flags & FF_EXISTS))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mo->z > *rover->topheight || mo->z + mo->height < *rover->bottomheight)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
rs = §ors[rover->secnum];
|
||||
lineNum = P_FindSpecialLineFromTag(2004, rs->tag, -1);
|
||||
|
||||
if (lineNum != -1)
|
||||
{
|
||||
return lineNum;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
|
||||
|
||||
|
|
@ -698,7 +845,10 @@ static botprediction_t *K_CreateBotPrediction(player_t *player)
|
|||
void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
|
||||
{
|
||||
botprediction_t *predict = NULL;
|
||||
boolean trySpindash = true;
|
||||
UINT8 spindash = 0;
|
||||
INT32 turnamt = 0;
|
||||
INT16 botController = -1;
|
||||
|
||||
// Can't build a ticcmd if we aren't spawned...
|
||||
if (!player->mo)
|
||||
|
|
@ -709,53 +859,87 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
|
|||
// Remove any existing controls
|
||||
memset(cmd, 0, sizeof(ticcmd_t));
|
||||
|
||||
if (gamestate != GS_LEVEL
|
||||
|| player->mo->scale <= 1) // funny post-finish death
|
||||
if (
|
||||
gamestate != GS_LEVEL
|
||||
|| player->mo->scale <= 1
|
||||
|| player->playerstate == PST_DEAD
|
||||
)
|
||||
{
|
||||
// No need to do anything else.
|
||||
return;
|
||||
}
|
||||
|
||||
if (player->playerstate == PST_DEAD)
|
||||
{
|
||||
cmd->buttons |= BT_ACCELERATE;
|
||||
return;
|
||||
}
|
||||
|
||||
// Complete override of all ticcmd functionality
|
||||
if (LUAh_BotTiccmd(player, cmd))
|
||||
return;
|
||||
|
||||
// Start boost handler
|
||||
if (leveltime <= starttime)
|
||||
{
|
||||
tic_t length = (TICRATE/6);
|
||||
tic_t boosthold = starttime - K_GetSpindashChargeTime(player);
|
||||
|
||||
cmd->buttons |= BT_EBRAKEMASK;
|
||||
|
||||
boosthold -= (MAXBOTDIFFICULTY - player->botvars.difficulty) * length;
|
||||
|
||||
if (leveltime >= boosthold)
|
||||
{
|
||||
cmd->buttons |= BT_DRIFT;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle steering towards waypoints!
|
||||
if (player->nextwaypoint != NULL && player->nextwaypoint->mobj != NULL && !P_MobjWasRemoved(player->nextwaypoint->mobj))
|
||||
botController = K_FindBotController(player->mo);
|
||||
|
||||
if (player->trickpanel != 0)
|
||||
{
|
||||
// Trick panel state -- do nothing until a controller line is found, in which case do a trick.
|
||||
|
||||
if (player->trickpanel == 1 && botController != -1)
|
||||
{
|
||||
line_t *controllerLine = &lines[botController];
|
||||
INT32 type = (sides[controllerLine->sidenum[0]].rowoffset / FRACUNIT);
|
||||
|
||||
// Y Offset: Trick type
|
||||
switch (type)
|
||||
{
|
||||
case 1:
|
||||
cmd->turning = KART_FULLTURN;
|
||||
break;
|
||||
case 2:
|
||||
cmd->turning = -KART_FULLTURN;
|
||||
break;
|
||||
case 3:
|
||||
cmd->buttons |= BT_FORWARD;
|
||||
break;
|
||||
case 4:
|
||||
cmd->buttons |= BT_BACKWARD;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Don't do anything else.
|
||||
return;
|
||||
}
|
||||
|
||||
if ((player->nextwaypoint != NULL
|
||||
&& player->nextwaypoint->mobj != NULL
|
||||
&& !P_MobjWasRemoved(player->nextwaypoint->mobj))
|
||||
|| (botController != -1))
|
||||
{
|
||||
// Handle steering towards waypoints!
|
||||
SINT8 turnsign = 0;
|
||||
angle_t destangle, moveangle, angle;
|
||||
INT16 anglediff;
|
||||
|
||||
predict = K_CreateBotPrediction(player);
|
||||
if (botController != -1)
|
||||
{
|
||||
const fixed_t dist = (player->mo->radius * 4);
|
||||
line_t *controllerLine = &lines[botController];
|
||||
|
||||
// X Offset: Movement direction
|
||||
destangle = FixedAngle(sides[controllerLine->sidenum[0]].textureoffset);
|
||||
|
||||
// Overwritten prediction
|
||||
predict = Z_Calloc(sizeof(botprediction_t), PU_LEVEL, NULL);
|
||||
|
||||
predict->x = player->mo->x + FixedMul(dist, FINECOSINE(destangle >> ANGLETOFINESHIFT));
|
||||
predict->y = player->mo->y + FixedMul(dist, FINESINE(destangle >> ANGLETOFINESHIFT));
|
||||
predict->radius = (DEFAULT_WAYPOINT_RADIUS / 4) * mapobjectscale;
|
||||
}
|
||||
else
|
||||
{
|
||||
predict = K_CreateBotPrediction(player);
|
||||
destangle = R_PointToAngle2(player->mo->x, player->mo->y, predict->x, predict->y);
|
||||
}
|
||||
|
||||
destangle = R_PointToAngle2(player->mo->x, player->mo->y, predict->x, predict->y);
|
||||
moveangle = player->mo->angle;
|
||||
|
||||
angle = (moveangle - destangle);
|
||||
|
||||
if (angle < ANGLE_180)
|
||||
|
|
@ -781,7 +965,7 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
|
|||
else
|
||||
{
|
||||
const fixed_t playerwidth = (player->mo->radius * 2);
|
||||
const fixed_t realrad = predict->radius - (playerwidth * 4); // Remove a "safe" distance away from the edges of the road
|
||||
fixed_t realrad = predict->radius - (playerwidth * 4); // Remove a "safe" distance away from the edges of the road
|
||||
fixed_t rad = realrad;
|
||||
fixed_t dirdist = K_DistanceOfLineFromPoint(
|
||||
player->mo->x, player->mo->y,
|
||||
|
|
@ -857,8 +1041,77 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
|
|||
}
|
||||
}
|
||||
|
||||
// Handle item usage
|
||||
K_BotItemUsage(player, cmd, turnamt);
|
||||
if (leveltime <= starttime && finishBeamLine != NULL)
|
||||
{
|
||||
const fixed_t distBase = 384*mapobjectscale;
|
||||
const fixed_t distAdjust = 64*mapobjectscale;
|
||||
|
||||
const fixed_t closeDist = distBase + (distAdjust * (9 - player->kartweight));
|
||||
const fixed_t farDist = closeDist + (distAdjust * 2);
|
||||
|
||||
fixed_t distToFinish = K_DistanceOfLineFromPoint(
|
||||
finishBeamLine->v1->x, finishBeamLine->v1->y,
|
||||
finishBeamLine->v2->x, finishBeamLine->v2->y,
|
||||
player->mo->x, player->mo->y
|
||||
);
|
||||
|
||||
// Don't run the spindash code at all until we're in the right place
|
||||
trySpindash = false;
|
||||
|
||||
// If you're too far, enable spindash & stay still.
|
||||
// If you're too close, start backing up.
|
||||
|
||||
if (distToFinish < closeDist)
|
||||
{
|
||||
// Silly way of getting us to reverse, but it respects the above code
|
||||
// where we figure out what the shape of the track looks like.
|
||||
UINT16 oldButtons = cmd->buttons;
|
||||
|
||||
cmd->buttons &= ~(BT_ACCELERATE|BT_BRAKE);
|
||||
|
||||
if (oldButtons & BT_ACCELERATE)
|
||||
{
|
||||
cmd->buttons |= BT_BRAKE;
|
||||
}
|
||||
|
||||
if (oldButtons & BT_BRAKE)
|
||||
{
|
||||
cmd->buttons |= BT_ACCELERATE;
|
||||
}
|
||||
|
||||
cmd->forwardmove = -cmd->forwardmove;
|
||||
}
|
||||
else if (distToFinish < farDist)
|
||||
{
|
||||
// We're in about the right place, spindash now.
|
||||
cmd->forwardmove = 0;
|
||||
trySpindash = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (trySpindash == true)
|
||||
{
|
||||
// Spindashing
|
||||
spindash = K_TrySpindash(player);
|
||||
|
||||
if (spindash > 0)
|
||||
{
|
||||
cmd->buttons |= BT_EBRAKEMASK;
|
||||
cmd->forwardmove = 0;
|
||||
|
||||
if (spindash == 2 && player->speed < 6*mapobjectscale)
|
||||
{
|
||||
cmd->buttons |= BT_DRIFT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (spindash == 0)
|
||||
{
|
||||
// Don't pointlessly try to use rings/sneakers while charging a spindash.
|
||||
// TODO: Allowing projectile items like orbinaut while e-braking would be nice, maybe just pass in the spindash variable?
|
||||
K_BotItemUsage(player, cmd, turnamt);
|
||||
}
|
||||
|
||||
if (turnamt != 0)
|
||||
{
|
||||
|
|
@ -873,6 +1126,7 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
|
|||
|
||||
if (turnamt > 0)
|
||||
{
|
||||
// Count up
|
||||
if (player->botvars.turnconfirm < BOTTURNCONFIRM)
|
||||
{
|
||||
player->botvars.turnconfirm++;
|
||||
|
|
@ -880,11 +1134,24 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
|
|||
}
|
||||
else if (turnamt < 0)
|
||||
{
|
||||
// Count down
|
||||
if (player->botvars.turnconfirm > -BOTTURNCONFIRM)
|
||||
{
|
||||
player->botvars.turnconfirm--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Back to neutral
|
||||
if (player->botvars.turnconfirm < 0)
|
||||
{
|
||||
player->botvars.turnconfirm++;
|
||||
}
|
||||
else if (player->botvars.turnconfirm > 0)
|
||||
{
|
||||
player->botvars.turnconfirm--;
|
||||
}
|
||||
}
|
||||
|
||||
if (abs(player->botvars.turnconfirm) >= BOTTURNCONFIRM)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -167,9 +167,9 @@ void K_InitGrandPrixBots(void)
|
|||
difficultylevels[10] = max(1, startingdifficulty-5);
|
||||
difficultylevels[11] = max(1, startingdifficulty-6);
|
||||
difficultylevels[12] = max(1, startingdifficulty-6);
|
||||
difficultylevels[13] = max(1, startingdifficulty-6);
|
||||
difficultylevels[13] = max(1, startingdifficulty-7);
|
||||
difficultylevels[14] = max(1, startingdifficulty-7);
|
||||
difficultylevels[15] = max(1, startingdifficulty-7);
|
||||
difficultylevels[15] = max(1, startingdifficulty-8);
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
|
|
|
|||
59
src/k_hud.c
59
src/k_hud.c
|
|
@ -1415,17 +1415,26 @@ static void K_DrawKartPositionNum(INT32 num)
|
|||
fixed_t scale = FRACUNIT;
|
||||
patch_t *localpatch = kp_positionnum[0][0];
|
||||
INT32 fx = 0, fy = 0, fflags = 0;
|
||||
INT32 addOrSub = V_ADDTRANS;
|
||||
boolean flipdraw = false; // flip the order we draw it in for MORE splitscreen bs. fun.
|
||||
boolean flipvdraw = false; // used only for 2p splitscreen so overtaking doesn't make 1P's position fly off the screen.
|
||||
boolean overtake = false;
|
||||
|
||||
if ((mapheaderinfo[gamemap - 1]->levelflags & LF_SUBTRACTNUM) == LF_SUBTRACTNUM)
|
||||
{
|
||||
addOrSub = V_SUBTRANS;
|
||||
}
|
||||
|
||||
if (stplyr->kartstuff[k_positiondelay] || stplyr->exiting)
|
||||
{
|
||||
scale *= 2;
|
||||
overtake = true; // this is used for splitscreen stuff in conjunction with flipdraw.
|
||||
}
|
||||
|
||||
if (r_splitscreen)
|
||||
{
|
||||
scale /= 2;
|
||||
}
|
||||
|
||||
W = FixedMul(W<<FRACBITS, scale)>>FRACBITS;
|
||||
|
||||
|
|
@ -1472,38 +1481,46 @@ static void K_DrawKartPositionNum(INT32 num)
|
|||
}
|
||||
|
||||
// Special case for 0
|
||||
if (!num)
|
||||
if (num <= 0)
|
||||
{
|
||||
V_DrawFixedPatch(fx<<FRACBITS, fy<<FRACBITS, scale, V_HUDTRANSHALF|V_SLIDEIN|fflags, kp_positionnum[0][0], NULL);
|
||||
V_DrawFixedPatch(fx<<FRACBITS, fy<<FRACBITS, scale, addOrSub|V_SLIDEIN|fflags, kp_positionnum[0][0], NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
I_Assert(num >= 0); // This function does not draw negative numbers
|
||||
|
||||
// Draw the number
|
||||
while (num)
|
||||
{
|
||||
if (win) // 1st place winner? You get rainbows!!
|
||||
{
|
||||
localpatch = kp_winnernum[(leveltime % (NUMWINFRAMES*3)) / 3];
|
||||
}
|
||||
else if (stplyr->laps >= cv_numlaps.value || stplyr->exiting) // Check for the final lap, or won
|
||||
{
|
||||
// Alternate frame every three frames
|
||||
switch (leveltime % 9)
|
||||
boolean useRedNums = K_IsPlayerLosing(stplyr);
|
||||
|
||||
if (addOrSub == V_SUBTRANS)
|
||||
{
|
||||
case 1: case 2: case 3:
|
||||
if (K_IsPlayerLosing(stplyr))
|
||||
// Subtracting RED will look BLUE, and vice versa.
|
||||
useRedNums = !useRedNums;
|
||||
}
|
||||
|
||||
// Alternate frame every three frames
|
||||
switch ((leveltime % 9) / 3)
|
||||
{
|
||||
case 0:
|
||||
if (useRedNums == true)
|
||||
localpatch = kp_positionnum[num % 10][4];
|
||||
else
|
||||
localpatch = kp_positionnum[num % 10][1];
|
||||
break;
|
||||
case 4: case 5: case 6:
|
||||
if (K_IsPlayerLosing(stplyr))
|
||||
case 1:
|
||||
if (useRedNums == true)
|
||||
localpatch = kp_positionnum[num % 10][5];
|
||||
else
|
||||
localpatch = kp_positionnum[num % 10][2];
|
||||
break;
|
||||
case 7: case 8: case 9:
|
||||
if (K_IsPlayerLosing(stplyr))
|
||||
case 2:
|
||||
if (useRedNums == true)
|
||||
localpatch = kp_positionnum[num % 10][6];
|
||||
else
|
||||
localpatch = kp_positionnum[num % 10][3];
|
||||
|
|
@ -1514,9 +1531,15 @@ static void K_DrawKartPositionNum(INT32 num)
|
|||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
localpatch = kp_positionnum[num % 10][0];
|
||||
}
|
||||
|
||||
V_DrawFixedPatch((fx<<FRACBITS) + ((overtake && flipdraw) ? (SHORT(localpatch->width)*scale/2) : 0), (fy<<FRACBITS) + ((overtake && flipvdraw) ? (SHORT(localpatch->height)*scale/2) : 0), scale, V_HUDTRANSHALF|V_SLIDEIN|fflags, localpatch, NULL);
|
||||
V_DrawFixedPatch(
|
||||
(fx<<FRACBITS) + ((overtake && flipdraw) ? (SHORT(localpatch->width)*scale/2) : 0),
|
||||
(fy<<FRACBITS) + ((overtake && flipvdraw) ? (SHORT(localpatch->height)*scale/2) : 0),
|
||||
scale, addOrSub|V_SLIDEIN|fflags, localpatch, NULL
|
||||
);
|
||||
// ^ if we overtake as p1 or p3 in splitscren, we shift it so that it doesn't go off screen.
|
||||
// ^ if we overtake as p1 in 2p splits, shift vertically so that this doesn't happen either.
|
||||
|
||||
|
|
@ -2043,7 +2066,7 @@ static void K_drawKartSpeedometer(void)
|
|||
{
|
||||
case 1: // Sonic Drift 2 style percentage
|
||||
default:
|
||||
convSpeed = (((25*stplyr->speed)/24) * 100) / K_GetKartSpeed(stplyr, false); // Based on top speed! (cheats with the numbers due to some weird discrepancy)
|
||||
convSpeed = (stplyr->speed * 100) / K_GetKartSpeed(stplyr, false); // Based on top speed!
|
||||
labeln = 0;
|
||||
break;
|
||||
case 2: // Kilometers
|
||||
|
|
@ -2062,7 +2085,8 @@ static void K_drawKartSpeedometer(void)
|
|||
}
|
||||
|
||||
// Don't overflow
|
||||
if (convSpeed > 999)
|
||||
// (negative speed IS really high speed :V)
|
||||
if (convSpeed > 999 || convSpeed < 0)
|
||||
convSpeed = 999;
|
||||
|
||||
numbers[0] = ((convSpeed / 100) % 10);
|
||||
|
|
@ -2402,6 +2426,7 @@ static void K_drawKartPlayerCheck(void)
|
|||
UINT8 cnum = 0;
|
||||
UINT8 i;
|
||||
INT32 splitflags = V_SNAPTOBOTTOM|V_SPLITSCREEN;
|
||||
fixed_t y = CHEK_Y * FRACUNIT;
|
||||
|
||||
if (stplyr == NULL || stplyr->mo == NULL || P_MobjWasRemoved(stplyr->mo))
|
||||
{
|
||||
|
|
@ -2420,6 +2445,8 @@ static void K_drawKartPlayerCheck(void)
|
|||
|
||||
if (r_splitscreen)
|
||||
{
|
||||
y /= 2;
|
||||
|
||||
for (i = 1; i <= r_splitscreen; i++)
|
||||
{
|
||||
if (stplyr == &players[displayplayers[i]])
|
||||
|
|
@ -2492,7 +2519,7 @@ static void K_drawKartPlayerCheck(void)
|
|||
K_ObjectTracking(&x, NULL, &c, thiscam->angle + ANGLE_180, 0, &v, cnum);
|
||||
|
||||
colormap = R_GetTranslationColormap(TC_DEFAULT, checkplayer->mo->color, GTC_CACHE);
|
||||
V_DrawFixedPatch(x, CHEK_Y * FRACUNIT, FRACUNIT, V_HUDTRANS|V_SPLITSCREEN|splitflags, kp_check[pnum], colormap);
|
||||
V_DrawFixedPatch(x, y, FRACUNIT, V_HUDTRANS|V_SPLITSCREEN|splitflags, kp_check[pnum], colormap);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
435
src/k_kart.c
435
src/k_kart.c
|
|
@ -1010,6 +1010,14 @@ fixed_t K_GetMobjWeight(mobj_t *mobj, mobj_t *against)
|
|||
break;
|
||||
weight = K_PlayerWeight(mobj, against);
|
||||
break;
|
||||
case MT_KART_LEFTOVER:
|
||||
weight = 5*FRACUNIT/2;
|
||||
|
||||
if (mobj->extravalue1 > 0)
|
||||
{
|
||||
weight = mobj->extravalue1 * (FRACUNIT >> 1);
|
||||
}
|
||||
break;
|
||||
case MT_BUBBLESHIELD:
|
||||
weight = K_PlayerWeight(mobj->target, against);
|
||||
break;
|
||||
|
|
@ -1726,6 +1734,102 @@ void K_SpawnDriftBoostClipSpark(mobj_t *clip)
|
|||
spark->momy = clip->momx/2;
|
||||
}
|
||||
|
||||
static SINT8 K_GlanceAtPlayers(player_t *glancePlayer)
|
||||
{
|
||||
const fixed_t maxdistance = FixedMul(1280 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed));
|
||||
const angle_t blindSpotSize = ANG10; // ANG5
|
||||
UINT8 i;
|
||||
SINT8 glanceDir = 0;
|
||||
SINT8 lastValidGlance = 0;
|
||||
|
||||
// See if there's any players coming up behind us.
|
||||
// If so, your character will glance at 'em.
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
player_t *p;
|
||||
angle_t back;
|
||||
angle_t diff;
|
||||
fixed_t distance;
|
||||
SINT8 dir = -1;
|
||||
|
||||
if (!playeringame[i])
|
||||
{
|
||||
// Invalid player
|
||||
continue;
|
||||
}
|
||||
|
||||
p = &players[i];
|
||||
|
||||
if (p == glancePlayer)
|
||||
{
|
||||
// FOOL! Don't glance at yerself!
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!p->mo || P_MobjWasRemoved(p->mo))
|
||||
{
|
||||
// Invalid mobj
|
||||
continue;
|
||||
}
|
||||
|
||||
if (p->spectator || p->kartstuff[k_hyudorotimer] > 0)
|
||||
{
|
||||
// Not playing / invisible
|
||||
continue;
|
||||
}
|
||||
|
||||
distance = R_PointToDist2(glancePlayer->mo->x, glancePlayer->mo->y, p->mo->x, p->mo->y);
|
||||
|
||||
if (distance > maxdistance)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
back = glancePlayer->mo->angle + ANGLE_180;
|
||||
diff = R_PointToAngle2(glancePlayer->mo->x, glancePlayer->mo->y, p->mo->x, p->mo->y) - back;
|
||||
|
||||
if (diff > ANGLE_180)
|
||||
{
|
||||
diff = InvAngle(diff);
|
||||
dir = -dir;
|
||||
}
|
||||
|
||||
if (diff > ANGLE_90)
|
||||
{
|
||||
// Not behind the player
|
||||
continue;
|
||||
}
|
||||
|
||||
if (diff < blindSpotSize)
|
||||
{
|
||||
// Small blindspot directly behind your back, gives the impression of smoothly turning.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (P_CheckSight(glancePlayer->mo, p->mo) == true)
|
||||
{
|
||||
// Not blocked by a wall, we can glance at 'em!
|
||||
// Adds, so that if there's more targets on one of your sides, it'll glance on that side.
|
||||
glanceDir += dir;
|
||||
|
||||
// That poses a limitation if there's an equal number of targets on both sides...
|
||||
// In that case, we'll pick the last chosen glance direction.
|
||||
lastValidGlance = dir;
|
||||
}
|
||||
}
|
||||
|
||||
if (glanceDir > 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else if (glanceDir < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return lastValidGlance;
|
||||
}
|
||||
|
||||
/** \brief Handles the state changing for moving players, moved here to eliminate duplicate code
|
||||
|
||||
\param player player data
|
||||
|
|
@ -1735,7 +1839,6 @@ void K_SpawnDriftBoostClipSpark(mobj_t *clip)
|
|||
void K_KartMoveAnimation(player_t *player)
|
||||
{
|
||||
const INT16 minturn = KART_FULLTURN/8;
|
||||
SINT8 turndir = 0;
|
||||
|
||||
const fixed_t fastspeed = (K_GetKartSpeed(player, false) * 17) / 20; // 85%
|
||||
const fixed_t speedthreshold = player->mo->scale / 8;
|
||||
|
|
@ -1743,7 +1846,12 @@ void K_KartMoveAnimation(player_t *player)
|
|||
const boolean onground = P_IsObjectOnGround(player->mo);
|
||||
|
||||
ticcmd_t *cmd = &player->cmd;
|
||||
const boolean spinningwheels = ((cmd->buttons & BT_ACCELERATE) || (onground && player->speed > 0));
|
||||
const boolean spinningwheels = (((cmd->buttons & BT_ACCELERATE) == BT_ACCELERATE) || (onground && player->speed > 0));
|
||||
const boolean lookback = ((cmd->buttons & BT_LOOKBACK) == BT_LOOKBACK);
|
||||
|
||||
SINT8 turndir = 0;
|
||||
SINT8 destGlanceDir = 0;
|
||||
SINT8 drift = player->kartstuff[k_drift];
|
||||
|
||||
if (cmd->turning < -minturn)
|
||||
{
|
||||
|
|
@ -1754,20 +1862,89 @@ void K_KartMoveAnimation(player_t *player)
|
|||
turndir = 1;
|
||||
}
|
||||
|
||||
if (lookback == true && drift == 0)
|
||||
{
|
||||
// Prioritize looking back frames over turning
|
||||
turndir = 0;
|
||||
}
|
||||
|
||||
if (turndir == 0 && drift == 0)
|
||||
{
|
||||
// Only try glancing if you're driving straight.
|
||||
// This avoids all-players loops when we don't need it.
|
||||
destGlanceDir = K_GlanceAtPlayers(player);
|
||||
|
||||
if (lookback == true)
|
||||
{
|
||||
if (destGlanceDir == 0)
|
||||
{
|
||||
if (player->glanceDir != 0)
|
||||
{
|
||||
// Keep to the side you were already on.
|
||||
if (player->glanceDir < 0)
|
||||
{
|
||||
destGlanceDir = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
destGlanceDir = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Look to your right by default
|
||||
destGlanceDir = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Looking back AND glancing? Amplify the look!
|
||||
destGlanceDir *= 2;
|
||||
}
|
||||
}
|
||||
else if (K_GetForwardMove(player) < 0 && destGlanceDir == 0)
|
||||
{
|
||||
// Reversing -- like looking back, but doesn't stack on the other glances.
|
||||
if (player->glanceDir != 0)
|
||||
{
|
||||
// Keep to the side you were already on.
|
||||
if (player->glanceDir < 0)
|
||||
{
|
||||
destGlanceDir = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
destGlanceDir = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Look to your right by default
|
||||
destGlanceDir = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not glancing
|
||||
destGlanceDir = 0;
|
||||
player->glanceDir = 0;
|
||||
}
|
||||
|
||||
#define SetState(sn) \
|
||||
if (player->mo->state != &states[sn]) \
|
||||
P_SetPlayerMobjState(player->mo, sn)
|
||||
|
||||
if (!onground)
|
||||
if (onground == false)
|
||||
{
|
||||
// Only use certain frames in the air, to make it look like your tires are spinning fruitlessly!
|
||||
|
||||
if (player->kartstuff[k_drift] > 0)
|
||||
if (drift > 0)
|
||||
{
|
||||
// Neutral drift
|
||||
SetState(S_KART_DRIFT_L);
|
||||
}
|
||||
else if (player->kartstuff[k_drift] > 0)
|
||||
else if (drift < 0)
|
||||
{
|
||||
// Neutral drift
|
||||
SetState(S_KART_DRIFT_R);
|
||||
|
|
@ -1782,22 +1959,41 @@ void K_KartMoveAnimation(player_t *player)
|
|||
{
|
||||
SetState(S_KART_FAST_L);
|
||||
}
|
||||
else if (turndir == 0)
|
||||
else
|
||||
{
|
||||
SetState(S_KART_FAST);
|
||||
switch (player->glanceDir)
|
||||
{
|
||||
case -2:
|
||||
SetState(S_KART_FAST_LOOK_R);
|
||||
break;
|
||||
case 2:
|
||||
SetState(S_KART_FAST_LOOK_L);
|
||||
break;
|
||||
case -1:
|
||||
SetState(S_KART_FAST_GLANCE_R);
|
||||
break;
|
||||
case 1:
|
||||
SetState(S_KART_FAST_GLANCE_L);
|
||||
break;
|
||||
default:
|
||||
SetState(S_KART_FAST);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!spinningwheels)
|
||||
{
|
||||
// TODO: These should prooobably be different SPR2s
|
||||
// Just a quick hack to prevent needing to do that :V
|
||||
// TODO: The "tires still in the air" states should have it's own SPR2s.
|
||||
// This was a quick hack to get the same functionality with less work,
|
||||
// but it's really dunderheaded & isn't customizable at all.
|
||||
player->mo->frame = (player->mo->frame & ~FF_FRAMEMASK);
|
||||
player->mo->tics++; // Makes it properly use frame 0
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (player->kartstuff[k_drift] > 0)
|
||||
if (drift > 0)
|
||||
{
|
||||
// Drifting LEFT!
|
||||
|
||||
|
|
@ -1817,7 +2013,7 @@ void K_KartMoveAnimation(player_t *player)
|
|||
SetState(S_KART_DRIFT_L);
|
||||
}
|
||||
}
|
||||
else if (player->kartstuff[k_drift] < 0)
|
||||
else if (drift < 0)
|
||||
{
|
||||
// Drifting RIGHT!
|
||||
|
||||
|
|
@ -1853,7 +2049,24 @@ void K_KartMoveAnimation(player_t *player)
|
|||
}
|
||||
else
|
||||
{
|
||||
SetState(S_KART_FAST);
|
||||
switch (player->glanceDir)
|
||||
{
|
||||
case -2:
|
||||
SetState(S_KART_FAST_LOOK_R);
|
||||
break;
|
||||
case 2:
|
||||
SetState(S_KART_FAST_LOOK_L);
|
||||
break;
|
||||
case -1:
|
||||
SetState(S_KART_FAST_GLANCE_R);
|
||||
break;
|
||||
case 1:
|
||||
SetState(S_KART_FAST_GLANCE_L);
|
||||
break;
|
||||
default:
|
||||
SetState(S_KART_FAST);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -1872,7 +2085,24 @@ void K_KartMoveAnimation(player_t *player)
|
|||
}
|
||||
else
|
||||
{
|
||||
SetState(S_KART_SLOW);
|
||||
switch (player->glanceDir)
|
||||
{
|
||||
case -2:
|
||||
SetState(S_KART_SLOW_LOOK_R);
|
||||
break;
|
||||
case 2:
|
||||
SetState(S_KART_SLOW_LOOK_L);
|
||||
break;
|
||||
case -1:
|
||||
SetState(S_KART_SLOW_GLANCE_R);
|
||||
break;
|
||||
case 1:
|
||||
SetState(S_KART_SLOW_GLANCE_L);
|
||||
break;
|
||||
default:
|
||||
SetState(S_KART_SLOW);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -1889,7 +2119,24 @@ void K_KartMoveAnimation(player_t *player)
|
|||
}
|
||||
else
|
||||
{
|
||||
SetState(S_KART_STILL);
|
||||
switch (player->glanceDir)
|
||||
{
|
||||
case -2:
|
||||
SetState(S_KART_STILL_LOOK_R);
|
||||
break;
|
||||
case 2:
|
||||
SetState(S_KART_STILL_LOOK_L);
|
||||
break;
|
||||
case -1:
|
||||
SetState(S_KART_STILL_GLANCE_R);
|
||||
break;
|
||||
case 1:
|
||||
SetState(S_KART_STILL_GLANCE_L);
|
||||
break;
|
||||
default:
|
||||
SetState(S_KART_STILL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1898,6 +2145,16 @@ void K_KartMoveAnimation(player_t *player)
|
|||
|
||||
#undef SetState
|
||||
|
||||
// Update your glance value to smooth it out.
|
||||
if (player->glanceDir > destGlanceDir)
|
||||
{
|
||||
player->glanceDir--;
|
||||
}
|
||||
else if (player->glanceDir < destGlanceDir)
|
||||
{
|
||||
player->glanceDir++;
|
||||
}
|
||||
|
||||
// Update lastspeed value -- we use to display slow driving frames instead of fast driving when slowing down.
|
||||
player->lastspeed = player->speed;
|
||||
}
|
||||
|
|
@ -2030,6 +2287,13 @@ boolean K_ApplyOffroad(player_t *player)
|
|||
return true;
|
||||
}
|
||||
|
||||
boolean K_SlopeResistance(player_t *player)
|
||||
{
|
||||
if (player->kartstuff[k_invincibilitytimer] || player->kartstuff[k_sneakertimer] || player->kartstuff[k_tiregrease])
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static fixed_t K_FlameShieldDashVar(INT32 val)
|
||||
{
|
||||
// 1 second = 75% + 50% top speed
|
||||
|
|
@ -2048,7 +2312,7 @@ fixed_t K_GetSpindashChargeSpeed(player_t *player)
|
|||
// more speed for higher weight & speed
|
||||
// Tails = +6.25%, Fang = +20.31%, Mighty = +20.31%, Metal = +25%
|
||||
// (can be higher than this value when overcharged)
|
||||
return (player->kartspeed + player->kartweight) * (FRACUNIT/64);
|
||||
return (player->kartspeed + player->kartweight) * (FRACUNIT/32);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -2124,11 +2388,12 @@ static void K_GetKartBoostPower(player_t *player)
|
|||
if (player->kartstuff[k_spindashboost]) // Spindash boost
|
||||
{
|
||||
const fixed_t MAXCHARGESPEED = K_GetSpindashChargeSpeed(player);
|
||||
const fixed_t exponent = FixedMul(player->kartstuff[k_spindashspeed], player->kartstuff[k_spindashspeed]);
|
||||
|
||||
// character & charge dependent
|
||||
ADDBOOST(
|
||||
FixedMul(MAXCHARGESPEED, player->kartstuff[k_spindashspeed]), // + 0 to K_GetSpindashChargeSpeed()% top speed
|
||||
(4*FRACUNIT) + (36*player->kartstuff[k_spindashspeed]), // + 400% to 4000% acceleration
|
||||
FixedMul(MAXCHARGESPEED, exponent), // + 0 to K_GetSpindashChargeSpeed()% top speed
|
||||
(40 * exponent), // + 0% to 4000% acceleration
|
||||
0 // + 0% handling
|
||||
);
|
||||
}
|
||||
|
|
@ -2205,10 +2470,17 @@ fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower)
|
|||
finalspeed = FixedMul(finalspeed, FRACUNIT + (sphereAdd * player->spheres));
|
||||
}
|
||||
|
||||
if (K_PlayerUsesBotMovement(player) && player->botvars.rival == true)
|
||||
if (K_PlayerUsesBotMovement(player))
|
||||
{
|
||||
// +10% top speed for the rival
|
||||
finalspeed = FixedMul(finalspeed, 11*FRACUNIT/10);
|
||||
// Increase bot speed by 1-10% depending on difficulty
|
||||
fixed_t add = (player->botvars.difficulty * (FRACUNIT/10)) / MAXBOTDIFFICULTY;
|
||||
finalspeed = FixedMul(finalspeed, FRACUNIT + add);
|
||||
|
||||
if (player->botvars.rival == true)
|
||||
{
|
||||
// +10% top speed for the rival
|
||||
finalspeed = FixedMul(finalspeed, 11*FRACUNIT/10);
|
||||
}
|
||||
}
|
||||
|
||||
if (player->mo && !P_MobjWasRemoved(player->mo))
|
||||
|
|
@ -2546,7 +2818,7 @@ void K_TumblePlayer(player_t *player, mobj_t *inflictor, mobj_t *source)
|
|||
|
||||
static boolean K_LastTumbleBounceCondition(player_t *player)
|
||||
{
|
||||
return (player->tumbleBounces > 4 && player->tumbleHeight < 40);
|
||||
return (player->tumbleBounces > TUMBLEBOUNCES && player->tumbleHeight < 40);
|
||||
}
|
||||
|
||||
static void K_HandleTumbleBounce(player_t *player)
|
||||
|
|
@ -2616,8 +2888,10 @@ static void K_HandleTumbleSound(player_t *player)
|
|||
}
|
||||
}
|
||||
|
||||
void K_ExplodePlayer(player_t *player, mobj_t *inflictor, mobj_t *source) // A bit of a hack, we just throw the player up higher here and extend their spinout timer
|
||||
INT32 K_ExplodePlayer(player_t *player, mobj_t *inflictor, mobj_t *source) // A bit of a hack, we just throw the player up higher here and extend their spinout timer
|
||||
{
|
||||
INT32 ringburst = 10;
|
||||
|
||||
(void)source;
|
||||
|
||||
player->mo->momz = 18*mapobjectscale*P_MobjFlip(player->mo); // please stop forgetting mobjflip checks!!!!
|
||||
|
|
@ -2632,6 +2906,7 @@ void K_ExplodePlayer(player_t *player, mobj_t *inflictor, mobj_t *source) // A b
|
|||
{
|
||||
player->kartstuff[k_spinouttimer] = ((5*player->kartstuff[k_spinouttimer])/2)+1;
|
||||
player->mo->momz *= 2;
|
||||
ringburst = 20;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2642,6 +2917,8 @@ void K_ExplodePlayer(player_t *player, mobj_t *inflictor, mobj_t *source) // A b
|
|||
|
||||
if (P_IsDisplayPlayer(player))
|
||||
P_StartQuake(64<<FRACBITS, 5);
|
||||
|
||||
return ringburst;
|
||||
}
|
||||
|
||||
// This kind of wipeout happens with no rings -- doesn't remove a bumper, has no invulnerability, and is much shorter.
|
||||
|
|
@ -6135,9 +6412,18 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
|
|||
}
|
||||
|
||||
if (cmd->buttons & BT_DRIFT)
|
||||
player->kartstuff[k_jmp] = 1;
|
||||
{
|
||||
// Only allow drifting while NOT trying to do an spindash input.
|
||||
if ((cmd->buttons & BT_EBRAKEMASK) != BT_EBRAKEMASK)
|
||||
{
|
||||
player->driftInput = true;
|
||||
}
|
||||
// else, keep the previous value, because it might be brake-drifting.
|
||||
}
|
||||
else
|
||||
player->kartstuff[k_jmp] = 0;
|
||||
{
|
||||
player->driftInput = false;
|
||||
}
|
||||
|
||||
// Roulette Code
|
||||
K_KartItemRoulette(player, cmd);
|
||||
|
|
@ -6569,7 +6855,15 @@ void K_UpdateDistanceFromFinishLine(player_t *const player)
|
|||
|
||||
INT32 K_GetKartRingPower(player_t *player)
|
||||
{
|
||||
return (((9 - player->kartspeed) + (9 - player->kartweight)) / 2);
|
||||
INT32 ringPower = ((9 - player->kartspeed) + (9 - player->kartweight)) / 2;
|
||||
|
||||
if (K_PlayerUsesBotMovement(player))
|
||||
{
|
||||
// Double for Lv. 9
|
||||
ringPower += (player->botvars.difficulty * ringPower) / MAXBOTDIFFICULTY;
|
||||
}
|
||||
|
||||
return ringPower;
|
||||
}
|
||||
|
||||
// Returns false if this player being placed here causes them to collide with any other player
|
||||
|
|
@ -6715,6 +7009,7 @@ INT32 K_GetKartDriftSparkValue(player_t *player)
|
|||
Stage 1: red sparks
|
||||
Stage 2: blue sparks
|
||||
Stage 3: big large rainbow sparks
|
||||
Stage 0: air failsafe
|
||||
*/
|
||||
void K_SpawnDriftBoostExplosion(player_t *player, int stage)
|
||||
{
|
||||
|
|
@ -6745,6 +7040,11 @@ void K_SpawnDriftBoostExplosion(player_t *player, int stage)
|
|||
S_StartSound(player->mo, sfx_kc5b);
|
||||
S_StartSound(player->mo, sfx_s3kc4l);
|
||||
break;
|
||||
|
||||
case 0:
|
||||
overlay->color = SKINCOLOR_SILVER;
|
||||
overlay->fuse = 16;
|
||||
break;
|
||||
}
|
||||
|
||||
overlay->extravalue1 = stage;
|
||||
|
|
@ -6752,13 +7052,15 @@ void K_SpawnDriftBoostExplosion(player_t *player, int stage)
|
|||
|
||||
static void K_KartDrift(player_t *player, boolean onground)
|
||||
{
|
||||
fixed_t minspeed = (10 * player->mo->scale);
|
||||
INT32 dsone = K_GetKartDriftSparkValue(player);
|
||||
INT32 dstwo = dsone*2;
|
||||
INT32 dsthree = dstwo*2;
|
||||
const fixed_t minspeed = (10 * player->mo->scale);
|
||||
|
||||
const INT32 dsone = K_GetKartDriftSparkValue(player);
|
||||
const INT32 dstwo = dsone*2;
|
||||
const INT32 dsthree = dstwo*2;
|
||||
|
||||
// Drifting is actually straffing + automatic turning.
|
||||
// Holding the Jump button will enable drifting.
|
||||
// (This comment is extremely funny)
|
||||
|
||||
// Drift Release (Moved here so you can't "chain" drifts)
|
||||
if (player->kartstuff[k_drift] != -5 && player->kartstuff[k_drift] != 5)
|
||||
|
|
@ -6819,21 +7121,21 @@ static void K_KartDrift(player_t *player, boolean onground)
|
|||
}
|
||||
|
||||
// Drifting: left or right?
|
||||
if ((player->cmd.turning > 0) && player->speed > minspeed && player->kartstuff[k_jmp] == 1
|
||||
if ((player->cmd.turning > 0) && player->speed > minspeed && player->driftInput == true
|
||||
&& (player->kartstuff[k_drift] == 0 || player->kartstuff[k_driftend] == 1)) // && player->kartstuff[k_drift] != 1)
|
||||
{
|
||||
// Starting left drift
|
||||
player->kartstuff[k_drift] = 1;
|
||||
player->kartstuff[k_driftend] = player->kartstuff[k_driftcharge] = 0;
|
||||
}
|
||||
else if ((player->cmd.turning < 0) && player->speed > minspeed && player->kartstuff[k_jmp] == 1
|
||||
else if ((player->cmd.turning < 0) && player->speed > minspeed && player->driftInput == true
|
||||
&& (player->kartstuff[k_drift] == 0 || player->kartstuff[k_driftend] == 1)) // && player->kartstuff[k_drift] != -1)
|
||||
{
|
||||
// Starting right drift
|
||||
player->kartstuff[k_drift] = -1;
|
||||
player->kartstuff[k_driftend] = player->kartstuff[k_driftcharge] = 0;
|
||||
}
|
||||
else if (player->kartstuff[k_jmp] == 0) // || player->kartstuff[k_turndir] == 0)
|
||||
else if (player->driftInput == false) // || player->kartstuff[k_turndir] == 0)
|
||||
{
|
||||
// drift is not being performed so if we're just finishing set driftend and decrement counters
|
||||
if (player->kartstuff[k_drift] > 0)
|
||||
|
|
@ -6857,7 +7159,7 @@ static void K_KartDrift(player_t *player, boolean onground)
|
|||
player->kartstuff[k_aizdriftstrat] = player->kartstuff[k_brakedrift] = 0;
|
||||
player->kartstuff[k_getsparks] = 0;
|
||||
}
|
||||
else if (player->kartstuff[k_jmp] == 1 && player->kartstuff[k_drift] != 0)
|
||||
else if (player->driftInput == true && player->kartstuff[k_drift] != 0)
|
||||
{
|
||||
// Incease/decrease the drift value to continue drifting in that direction
|
||||
fixed_t driftadditive = 24;
|
||||
|
|
@ -7209,6 +7511,11 @@ static void K_KartSpindash(player_t *player)
|
|||
ticcmd_t *cmd = &player->cmd;
|
||||
boolean spawnWind = (leveltime % 2 == 0);
|
||||
|
||||
if (player->mo->hitlag > 0 || P_PlayerInPain(player))
|
||||
{
|
||||
player->kartstuff[k_spindash] = 0;
|
||||
}
|
||||
|
||||
if (player->kartstuff[k_spindash] > 0 && (cmd->buttons & (BT_DRIFT|BT_BRAKE)) != (BT_DRIFT|BT_BRAKE))
|
||||
{
|
||||
player->kartstuff[k_spindashspeed] = (player->kartstuff[k_spindash] * FRACUNIT) / MAXCHARGETIME;
|
||||
|
|
@ -7250,11 +7557,14 @@ static void K_KartSpindash(player_t *player)
|
|||
return;
|
||||
}
|
||||
|
||||
if (player->speed < 6*mapobjectscale && player->powers[pw_flashing] == 0)
|
||||
if (player->speed == 0 && cmd->turning != 0 && leveltime % 8 == 0)
|
||||
{
|
||||
if (cmd->turning != 0 && leveltime % 8 == 0)
|
||||
S_StartSound(player->mo, sfx_ruburn);
|
||||
// Rubber burn turn sfx
|
||||
S_StartSound(player->mo, sfx_ruburn);
|
||||
}
|
||||
|
||||
if (player->speed < 6*player->mo->scale)
|
||||
{
|
||||
if ((cmd->buttons & (BT_DRIFT|BT_BRAKE)) == (BT_DRIFT|BT_BRAKE))
|
||||
{
|
||||
INT16 chargetime = MAXCHARGETIME - ++player->kartstuff[k_spindash];
|
||||
|
|
@ -7271,6 +7581,15 @@ static void K_KartSpindash(player_t *player)
|
|||
K_KartSpindashWind(player->mo);
|
||||
}
|
||||
|
||||
if (player->powers[pw_flashing] > 0 && (leveltime & 1) && player->kartstuff[k_hyudorotimer] == 0)
|
||||
{
|
||||
// Every frame that you're invisible from flashing, spill a ring.
|
||||
// Intentionally a lop-sided trade-off, so the game doesn't become
|
||||
// Funky Kong's Ring Racers.
|
||||
|
||||
P_PlayerRingBurst(player, 1);
|
||||
}
|
||||
|
||||
if (chargetime > 0)
|
||||
{
|
||||
UINT16 soundcharge = 0;
|
||||
|
|
@ -7298,6 +7617,39 @@ static void K_KartSpindash(player_t *player)
|
|||
}
|
||||
}
|
||||
|
||||
static void K_AirFailsafe(player_t *player)
|
||||
{
|
||||
const fixed_t maxSpeed = 6*player->mo->scale;
|
||||
const fixed_t thrustSpeed = 6*player->mo->scale; // 10*player->mo->scale
|
||||
|
||||
ticcmd_t *cmd = &player->cmd;
|
||||
|
||||
if (player->speed > maxSpeed // Above the max speed that you're allowed to use this technique.
|
||||
|| player->respawn.state != RESPAWNST_NONE) // Respawning, you don't need this AND drop dash :V
|
||||
{
|
||||
player->airFailsafe = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((cmd->buttons & BT_ACCELERATE) || K_GetForwardMove(player) != 0)
|
||||
{
|
||||
// Queue up later
|
||||
player->airFailsafe = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (player->airFailsafe == true)
|
||||
{
|
||||
// Push the player forward
|
||||
P_Thrust(player->mo, K_MomentumAngle(player->mo), thrustSpeed);
|
||||
|
||||
S_StartSound(player->mo, sfx_s23c);
|
||||
K_SpawnDriftBoostExplosion(player, 0);
|
||||
|
||||
player->airFailsafe = false;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// K_AdjustPlayerFriction
|
||||
//
|
||||
|
|
@ -8171,9 +8523,18 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
|
|||
}
|
||||
}
|
||||
|
||||
K_KartDrift(player, P_IsObjectOnGround(player->mo)); // Not using onground, since we don't want this affected by spring pads
|
||||
K_KartDrift(player, onground);
|
||||
K_KartSpindash(player);
|
||||
|
||||
if (onground == false)
|
||||
{
|
||||
K_AirFailsafe(player);
|
||||
}
|
||||
else
|
||||
{
|
||||
player->airFailsafe = false;
|
||||
}
|
||||
|
||||
// Play the starting countdown sounds
|
||||
if (player == &players[g_localplayers[0]]) // Don't play louder in splitscreen
|
||||
{
|
||||
|
|
|
|||
|
|
@ -45,13 +45,14 @@ void K_DoInstashield(player_t *player);
|
|||
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);
|
||||
INT32 K_ExplodePlayer(player_t *player, mobj_t *inflictor, mobj_t *source);
|
||||
void K_DebtStingPlayer(player_t *player, mobj_t *source);
|
||||
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);
|
||||
void K_RunFinishLineBeam(void);
|
||||
UINT16 K_DriftSparkColor(player_t *player, INT32 charge);
|
||||
void K_SpawnBoostTrail(player_t *player);
|
||||
void K_SpawnSparkleTrail(mobj_t *mo);
|
||||
|
|
@ -81,6 +82,7 @@ void K_StripItems(player_t *player);
|
|||
void K_StripOther(player_t *player);
|
||||
void K_MomentumToFacing(player_t *player);
|
||||
boolean K_ApplyOffroad(player_t *player);
|
||||
boolean K_SlopeResistance(player_t *player);
|
||||
INT16 K_GetSpindashChargeTime(player_t *player);
|
||||
fixed_t K_GetSpindashChargeSpeed(player_t *player);
|
||||
fixed_t K_GetKartSpeedFromStat(UINT8 kartspeed);
|
||||
|
|
|
|||
421
src/k_race.c
Normal file
421
src/k_race.c
Normal file
|
|
@ -0,0 +1,421 @@
|
|||
// SONIC ROBO BLAST 2 KART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2018-2020 by Kart Krew
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file k_race.c
|
||||
/// \brief Race Mode specific code.
|
||||
|
||||
#include "k_race.h"
|
||||
|
||||
#include "k_kart.h"
|
||||
#include "k_battle.h"
|
||||
#include "k_pwrlv.h"
|
||||
#include "k_color.h"
|
||||
#include "k_respawn.h"
|
||||
#include "doomdef.h"
|
||||
#include "hu_stuff.h"
|
||||
#include "g_game.h"
|
||||
#include "m_random.h"
|
||||
#include "p_local.h"
|
||||
#include "p_slopes.h"
|
||||
#include "p_setup.h"
|
||||
#include "r_draw.h"
|
||||
#include "r_local.h"
|
||||
#include "s_sound.h"
|
||||
#include "st_stuff.h"
|
||||
#include "v_video.h"
|
||||
#include "z_zone.h"
|
||||
#include "m_misc.h"
|
||||
#include "m_cond.h"
|
||||
#include "f_finale.h"
|
||||
#include "lua_hud.h" // For Lua hud checks
|
||||
#include "lua_hook.h" // For MobjDamage and ShouldDamage
|
||||
#include "m_cheat.h" // objectplacing
|
||||
#include "p_spec.h"
|
||||
|
||||
#include "k_waypoint.h"
|
||||
#include "k_bot.h"
|
||||
#include "k_hud.h"
|
||||
|
||||
line_t *finishBeamLine = NULL;
|
||||
|
||||
static mobj_t *beamPoints[2];
|
||||
static UINT8 numBeamPoints = 0;
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_ClearFinishBeamLine(void)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
void K_ClearFinishBeamLine(void)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
finishBeamLine = NULL;
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
beamPoints[i] = NULL;
|
||||
}
|
||||
|
||||
numBeamPoints = 0;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static void K_FreeFinishBeamLine(void)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
static void K_FreeFinishBeamLine(void)
|
||||
{
|
||||
if (finishBeamLine != NULL)
|
||||
{
|
||||
if (finishBeamLine->v1 != NULL)
|
||||
{
|
||||
Z_Free(finishBeamLine->v1);
|
||||
}
|
||||
|
||||
if (finishBeamLine->v2 != NULL)
|
||||
{
|
||||
Z_Free(finishBeamLine->v2);
|
||||
}
|
||||
|
||||
Z_Free(finishBeamLine);
|
||||
}
|
||||
|
||||
K_ClearFinishBeamLine();
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static void K_CreateFinishLineFromPoints(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
static void K_CreateFinishLineFromPoints(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2)
|
||||
{
|
||||
I_Assert(finishBeamLine == NULL); // Needs to be NULL
|
||||
|
||||
finishBeamLine = Z_Calloc(sizeof (*finishBeamLine), PU_LEVEL, NULL);
|
||||
|
||||
finishBeamLine->v1 = Z_Calloc(sizeof (*finishBeamLine->v1), PU_LEVEL, NULL);
|
||||
finishBeamLine->v1->x = x1;
|
||||
finishBeamLine->v1->y = y1;
|
||||
|
||||
finishBeamLine->v2 = Z_Calloc(sizeof (*finishBeamLine->v2), PU_LEVEL, NULL);
|
||||
finishBeamLine->v2->x = x2;
|
||||
finishBeamLine->v2->y = y2;
|
||||
|
||||
finishBeamLine->dx = x2 - x1;
|
||||
finishBeamLine->dy = y2 - y1;
|
||||
|
||||
finishBeamLine->flags = 0;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
boolean K_GenerateFinishBeamLine(void)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
boolean K_GenerateFinishBeamLine(void)
|
||||
{
|
||||
mapthing_t *mt;
|
||||
|
||||
INT64 bounds[4];
|
||||
angle_t angle;
|
||||
|
||||
boolean valid = false;
|
||||
size_t i;
|
||||
|
||||
// Ensure everything's freed by this time.
|
||||
K_FreeFinishBeamLine();
|
||||
|
||||
// First: attempt to create from beam point objects
|
||||
for (i = 0, mt = mapthings; i < nummapthings; i++, mt++)
|
||||
{
|
||||
if (numBeamPoints >= 2)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (mt->type == mobjinfo[MT_BEAMPOINT].doomednum)
|
||||
{
|
||||
beamPoints[numBeamPoints] = mt->mobj;
|
||||
numBeamPoints++;
|
||||
}
|
||||
}
|
||||
|
||||
if (numBeamPoints == 2)
|
||||
{
|
||||
// Found 'em! Really easy to generate a line out of these :)
|
||||
|
||||
K_CreateFinishLineFromPoints(
|
||||
beamPoints[0]->x, beamPoints[0]->y,
|
||||
beamPoints[1]->x, beamPoints[1]->y
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bounds[0] = INT64_MAX; // min x
|
||||
bounds[1] = INT64_MIN; // max x
|
||||
bounds[2] = INT64_MAX; // min y
|
||||
bounds[3] = INT64_MIN; // max y
|
||||
|
||||
for (i = 0; i < numlines; i++)
|
||||
{
|
||||
angle_t thisAngle;
|
||||
|
||||
if (lines[i].special != 2001)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
thisAngle = R_PointToAngle2(0, 0, lines[i].dx, lines[i].dy);
|
||||
|
||||
bounds[0] = min(bounds[0], min(lines[i].v1->x, lines[i].v2->x)); // min x
|
||||
bounds[1] = max(bounds[1], max(lines[i].v1->x, lines[i].v2->x)); // max x
|
||||
bounds[2] = min(bounds[2], min(lines[i].v1->y, lines[i].v2->y)); // min y
|
||||
bounds[3] = max(bounds[3], max(lines[i].v1->y, lines[i].v2->y)); // max y
|
||||
|
||||
if (valid == false)
|
||||
{
|
||||
angle = thisAngle;
|
||||
valid = true;
|
||||
}
|
||||
else if (angle != thisAngle)
|
||||
{
|
||||
// Do not even attempt to bother with curved finish lines.
|
||||
// Will likely just crash.
|
||||
valid = false;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (valid == true)
|
||||
{
|
||||
fixed_t span = P_AproxDistance(bounds[1] - bounds[0], bounds[3] - bounds[2]) / 2;
|
||||
|
||||
fixed_t cx = (bounds[0] + bounds[1]) / 2;
|
||||
fixed_t cy = (bounds[2] + bounds[3]) / 2;
|
||||
|
||||
fixed_t spanC = FixedMul(span, FINECOSINE(angle >> ANGLETOFINESHIFT));
|
||||
fixed_t spanS = FixedMul(span, FINESINE(angle >> ANGLETOFINESHIFT));
|
||||
|
||||
K_CreateFinishLineFromPoints(
|
||||
cx - spanC, cy - spanS,
|
||||
cx + spanC, cy + spanS
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static void K_DrawFinishLineBeamForLine(fixed_t offset, angle_t aiming, line_t *line, boolean reverse)
|
||||
|
||||
Draws a helix out of rainbow colored orbs along a line, unique for each display player.
|
||||
Called twice for the finish line beam effect.
|
||||
|
||||
Input Arguments:-
|
||||
offset - Offset value for positioning. Changed every tick to make it animate.
|
||||
aiming - Starting vertical angle value. Changed every tick to make it animate.
|
||||
line - Linedef to draw along.
|
||||
reverse - Draw in reverse. Call twice with this toggled to make a double helix.
|
||||
|
||||
Return:-
|
||||
None
|
||||
--------------------------------------------------*/
|
||||
|
||||
static void K_DrawFinishLineBeamForLine(fixed_t offset, angle_t aiming, line_t *line, boolean reverse)
|
||||
{
|
||||
const fixed_t linelength = P_AproxDistance(line->dx, line->dy);
|
||||
const fixed_t xstep = FixedDiv(line->dx, linelength);
|
||||
const fixed_t ystep = FixedDiv(line->dy, linelength);
|
||||
|
||||
fixed_t linex = line->v1->x;
|
||||
fixed_t liney = line->v1->y;
|
||||
angle_t lineangle = R_PointToAngle2(0, 0, line->dx, line->dy) + ANGLE_90;
|
||||
|
||||
UINT8 i;
|
||||
|
||||
if (line->flags & ML_NOCLIMB)
|
||||
{
|
||||
// Line is flipped
|
||||
lineangle += ANGLE_180;
|
||||
}
|
||||
|
||||
linex += FixedMul(offset, xstep);
|
||||
liney += FixedMul(offset, ystep);
|
||||
|
||||
while (offset < linelength)
|
||||
{
|
||||
#define COLORCYCLELEN 10
|
||||
const UINT8 colorcycle[COLORCYCLELEN] = {
|
||||
SKINCOLOR_PERIWINKLE,
|
||||
SKINCOLOR_SLATE,
|
||||
SKINCOLOR_BLOSSOM,
|
||||
SKINCOLOR_RASPBERRY,
|
||||
SKINCOLOR_ORANGE,
|
||||
SKINCOLOR_YELLOW,
|
||||
SKINCOLOR_LIME,
|
||||
SKINCOLOR_TURTLE,
|
||||
SKINCOLOR_ROBIN,
|
||||
SKINCOLOR_JAWZ
|
||||
};
|
||||
|
||||
const UINT8 numframes = 5;
|
||||
const angle_t framethreshold = ANGLE_180 / (numframes-1);
|
||||
const angle_t frameaim = aiming + (framethreshold / 2);
|
||||
|
||||
fixed_t x, y, z;
|
||||
UINT8 spriteframe = 0;
|
||||
|
||||
x = linex + FixedMul(FixedMul(FINISHLINEBEAM_SPACING, FINECOSINE(lineangle >> ANGLETOFINESHIFT)), FINECOSINE(aiming >> ANGLETOFINESHIFT));
|
||||
y = liney + FixedMul(FixedMul(FINISHLINEBEAM_SPACING, FINESINE(lineangle >> ANGLETOFINESHIFT)), FINECOSINE(aiming >> ANGLETOFINESHIFT));
|
||||
z = FINISHLINEBEAM_SPACING + FixedMul(FINISHLINEBEAM_SPACING, FINESINE(aiming >> ANGLETOFINESHIFT));
|
||||
|
||||
if (leveltime >= starttime)
|
||||
{
|
||||
spriteframe = 4; // Weakest sprite when passable
|
||||
}
|
||||
else if (frameaim > ANGLE_180)
|
||||
{
|
||||
spriteframe = (ANGLE_MAX - frameaim) / framethreshold;
|
||||
}
|
||||
else
|
||||
{
|
||||
spriteframe = frameaim / framethreshold;
|
||||
}
|
||||
|
||||
for (i = 0; i <= r_splitscreen; i++)
|
||||
{
|
||||
if (playeringame[displayplayers[i]] && players[displayplayers[i]].mo && !P_MobjWasRemoved(players[displayplayers[i]].mo))
|
||||
{
|
||||
mobj_t *beam;
|
||||
|
||||
beam = P_SpawnMobj(x, y, players[displayplayers[i]].mo->z + z, MT_THOK);
|
||||
P_SetMobjState(beam, S_FINISHBEAM1 + spriteframe);
|
||||
|
||||
beam->colorized = true;
|
||||
beam->drawflags = MFD_DONTDRAW & ~K_GetPlayerDontDrawFlag(&players[displayplayers[i]]);
|
||||
|
||||
if (reverse)
|
||||
{
|
||||
beam->color = colorcycle[((leveltime / 4) + (COLORCYCLELEN/2)) % COLORCYCLELEN];
|
||||
}
|
||||
else
|
||||
{
|
||||
beam->color = colorcycle[(leveltime / 4) % COLORCYCLELEN];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
offset += FINISHLINEBEAM_SPACING;
|
||||
linex += FixedMul(FINISHLINEBEAM_SPACING, xstep);
|
||||
liney += FixedMul(FINISHLINEBEAM_SPACING, ystep);
|
||||
|
||||
if (reverse)
|
||||
{
|
||||
aiming -= ANGLE_45;
|
||||
}
|
||||
else
|
||||
{
|
||||
aiming += ANGLE_45;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i <= r_splitscreen; i++)
|
||||
{
|
||||
if (playeringame[displayplayers[i]] && players[displayplayers[i]].mo && !P_MobjWasRemoved(players[displayplayers[i]].mo))
|
||||
{
|
||||
UINT8 j;
|
||||
for (j = 0; j < 2; j++)
|
||||
{
|
||||
vertex_t *v = line->v1;
|
||||
mobj_t *end1, *end2;
|
||||
angle_t a = R_PointToAngle2(0, 0, line->dx, line->dy);
|
||||
fixed_t sx;
|
||||
fixed_t sy;
|
||||
|
||||
/*
|
||||
if (line->flags & ML_NOCLIMB)
|
||||
{
|
||||
a += ANGLE_180;
|
||||
}
|
||||
*/
|
||||
|
||||
sx = FixedMul(3*mapobjectscale, FINECOSINE(a >> ANGLETOFINESHIFT));
|
||||
sy = FixedMul(3*mapobjectscale, FINESINE(a >> ANGLETOFINESHIFT));
|
||||
|
||||
if (j == 1)
|
||||
{
|
||||
v = line->v2;
|
||||
sx = -sx;
|
||||
sy = -sy;
|
||||
}
|
||||
|
||||
end1 = P_SpawnMobj(
|
||||
v->x + sx,
|
||||
v->y + sy,
|
||||
players[displayplayers[i]].mo->z + FINISHLINEBEAM_SPACING,
|
||||
MT_THOK
|
||||
);
|
||||
|
||||
P_SetMobjState(end1, S_FINISHBEAMEND1);
|
||||
end1->drawflags = MFD_DONTDRAW & ~K_GetPlayerDontDrawFlag(&players[displayplayers[i]]);
|
||||
end1->angle = lineangle;
|
||||
|
||||
end2 = P_SpawnMobj(
|
||||
v->x + (8*sx),
|
||||
v->y + (8*sy),
|
||||
players[displayplayers[i]].mo->z + FINISHLINEBEAM_SPACING,
|
||||
MT_THOK
|
||||
);
|
||||
|
||||
P_SetMobjState(end2, S_FINISHBEAMEND2);
|
||||
end2->drawflags = MFD_DONTDRAW & ~K_GetPlayerDontDrawFlag(&players[displayplayers[i]]);
|
||||
end2->angle = lineangle;
|
||||
|
||||
P_SetTarget(&end2->tracer, end1);
|
||||
end2->flags2 |= MF2_LINKDRAW;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_RunFinishLineBeam(void)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
|
||||
void K_RunFinishLineBeam(void)
|
||||
{
|
||||
if (!(leveltime < starttime || rainbowstartavailable == true))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (finishBeamLine != NULL)
|
||||
{
|
||||
const angle_t angoffset = ANGLE_45;
|
||||
const angle_t angadd = ANGLE_11hh;
|
||||
const fixed_t speed = 6 * mapobjectscale;
|
||||
|
||||
fixed_t offseta = (leveltime * speed) % FINISHLINEBEAM_SPACING;
|
||||
angle_t aiminga = (angoffset * -((leveltime * speed) / FINISHLINEBEAM_SPACING)) + (angadd * leveltime);
|
||||
|
||||
fixed_t offsetb = FINISHLINEBEAM_SPACING - offseta;
|
||||
angle_t aimingb = (angoffset * -((leveltime * speed) / FINISHLINEBEAM_SPACING)) - (angadd * leveltime);
|
||||
|
||||
K_DrawFinishLineBeamForLine(offseta, aiminga, finishBeamLine, false);
|
||||
K_DrawFinishLineBeamForLine(offsetb, aimingb, finishBeamLine, true);
|
||||
}
|
||||
}
|
||||
69
src/k_race.h
Normal file
69
src/k_race.h
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
// SONIC ROBO BLAST 2 KART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2018-2020 by Kart Krew
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file k_race.h
|
||||
/// \brief Race Mode specific code.
|
||||
|
||||
#ifndef __K_RACE__
|
||||
#define __K_RACE__
|
||||
|
||||
#include "r_defs.h"
|
||||
|
||||
extern line_t *finishBeamLine;
|
||||
|
||||
#define FINISHLINEBEAM_SPACING (48*mapobjectscale)
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_ClearFinishBeamLine(void);
|
||||
|
||||
Clears variables for finishBeamLine.
|
||||
Separate from K_FreeFinishBeamLine since this
|
||||
needs called when PU_LEVEL is freed.
|
||||
|
||||
Input Arguments:-
|
||||
None
|
||||
|
||||
Return:-
|
||||
None
|
||||
--------------------------------------------------*/
|
||||
|
||||
void K_ClearFinishBeamLine(void);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
boolean K_GenerateFinishBeamLine(void);
|
||||
|
||||
Finds pre-placed "beam points" to create a finish line out of,
|
||||
or tries to automatically create it from a finish linedef in the map.
|
||||
The result is stored in the "finishBeamLine" variable.
|
||||
|
||||
Input Arguments:-
|
||||
None
|
||||
|
||||
Return:-
|
||||
True if successful, otherwise false.
|
||||
--------------------------------------------------*/
|
||||
|
||||
boolean K_GenerateFinishBeamLine(void);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_RunFinishLineBeam(void);
|
||||
|
||||
Updates the finish line beam effect.
|
||||
|
||||
Input Arguments:-
|
||||
None
|
||||
|
||||
Return:-
|
||||
None
|
||||
--------------------------------------------------*/
|
||||
|
||||
void K_RunFinishLineBeam(void);
|
||||
|
||||
#endif
|
||||
|
|
@ -122,9 +122,9 @@ void K_DoIngameRespawn(player_t *player)
|
|||
// If player was tumbling, set variables so that they don't tumble like crazy after they're done respawning
|
||||
if (player->tumbleBounces > 0)
|
||||
{
|
||||
player->tumbleBounces = 3; // Max # of bounces-1 (so you still tumble once)
|
||||
player->tumbleLastBounce = 0; // Still force them to bounce at least once for the funny
|
||||
players->tumbleHeight = 20; // force tumble height
|
||||
player->tumbleBounces = TUMBLEBOUNCES-1; // Max # of bounces-1 (so you still tumble once)
|
||||
player->tumbleLastBounce = false; // Still force them to bounce at least once for the funny
|
||||
players->tumbleHeight = 20; // force tumble height
|
||||
}
|
||||
|
||||
P_ResetPlayer(player);
|
||||
|
|
|
|||
|
|
@ -3440,8 +3440,8 @@ static int lib_kExplodePlayer(lua_State *L)
|
|||
inflictor = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
|
||||
if (!lua_isnone(L, 3) && lua_isuserdata(L, 3))
|
||||
source = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
|
||||
K_ExplodePlayer(player, inflictor, source);
|
||||
return 0;
|
||||
lua_pushinteger(L, K_ExplodePlayer(player, inflictor, source));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_kTakeBumpersFromPlayer(lua_State *L)
|
||||
|
|
|
|||
|
|
@ -34,6 +34,8 @@ extern lua_State *gL;
|
|||
#define META_SKIN "SKIN_T*"
|
||||
#define META_POWERS "PLAYER_T*POWERS"
|
||||
#define META_KARTSTUFF "PLAYER_T*KARTSTUFF"
|
||||
#define META_KARTHUD "PLAYER_T*KARTHUD"
|
||||
#define META_RESPAWN "PLAYER_T*RESPAWN"
|
||||
#define META_COLLIDE "PLAYER_T*COLLIDE"
|
||||
#define META_SOUNDSID "SKIN_T*SOUNDSID"
|
||||
|
||||
|
|
|
|||
|
|
@ -192,6 +192,8 @@ static int player_get(lua_State *L)
|
|||
LUA_PushUserdata(L, plr->mo, META_MOBJ);
|
||||
else if (fastcmp(field,"cmd"))
|
||||
LUA_PushUserdata(L, &plr->cmd, META_TICCMD);
|
||||
else if (fastcmp(field,"respawn"))
|
||||
LUA_PushUserdata(L, &plr->respawn, META_RESPAWN);
|
||||
else if (fastcmp(field,"playerstate"))
|
||||
lua_pushinteger(L, plr->playerstate);
|
||||
else if (fastcmp(field,"viewz"))
|
||||
|
|
@ -212,8 +214,14 @@ static int player_get(lua_State *L)
|
|||
LUA_PushUserdata(L, plr->powers, META_POWERS);
|
||||
else if (fastcmp(field,"kartstuff"))
|
||||
LUA_PushUserdata(L, plr->kartstuff, META_KARTSTUFF);
|
||||
else if (fastcmp(field,"karthud"))
|
||||
LUA_PushUserdata(L, plr->karthud, META_KARTHUD);
|
||||
else if (fastcmp(field,"airtime"))
|
||||
lua_pushinteger(L, plr->airtime);
|
||||
else if (fastcmp(field,"driftInput"))
|
||||
lua_pushboolean(L, plr->driftInput);
|
||||
else if (fastcmp(field,"airFailsafe"))
|
||||
lua_pushboolean(L, plr->airFailsafe);
|
||||
else if (fastcmp(field,"tumbleBounces"))
|
||||
lua_pushinteger(L, plr->tumbleBounces);
|
||||
else if (fastcmp(field,"tumbleHeight"))
|
||||
|
|
@ -222,6 +230,8 @@ static int player_get(lua_State *L)
|
|||
lua_pushboolean(L, plr->tumbleLastBounce);
|
||||
else if (fastcmp(field,"tumbleSound"))
|
||||
lua_pushboolean(L, plr->tumbleSound);
|
||||
else if (fastcmp(field,"glanceDir"))
|
||||
lua_pushinteger(L, plr->glanceDir);
|
||||
else if (fastcmp(field,"trickpanel"))
|
||||
lua_pushinteger(L, plr->trickpanel);
|
||||
else if (fastcmp(field,"trickdelay"))
|
||||
|
|
@ -471,6 +481,8 @@ static int player_set(lua_State *L)
|
|||
}
|
||||
else if (fastcmp(field,"cmd"))
|
||||
return NOSET;
|
||||
else if (fastcmp(field,"respawn"))
|
||||
return NOSET;
|
||||
else if (fastcmp(field,"playerstate"))
|
||||
plr->playerstate = luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"viewz"))
|
||||
|
|
@ -521,6 +533,10 @@ static int player_set(lua_State *L)
|
|||
return NOSET;
|
||||
else if (fastcmp(field,"airtime"))
|
||||
plr->airtime = (tic_t)luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"driftInput"))
|
||||
plr->driftInput = luaL_checkboolean(L, 3);
|
||||
else if (fastcmp(field,"airFailsafe"))
|
||||
plr->airFailsafe = luaL_checkboolean(L, 3);
|
||||
else if (fastcmp(field,"tumbleBounces"))
|
||||
plr->tumbleBounces = (UINT8)luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"tumbleHeight"))
|
||||
|
|
@ -529,6 +545,8 @@ static int player_set(lua_State *L)
|
|||
plr->tumbleLastBounce = luaL_checkboolean(L, 3);
|
||||
else if (fastcmp(field,"tumbleSound"))
|
||||
plr->tumbleSound = luaL_checkboolean(L, 3);
|
||||
else if (fastcmp(field,"glanceDir"))
|
||||
plr->glanceDir = (SINT8)luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"trickpanel"))
|
||||
plr->trickpanel = luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"trickdelay"))
|
||||
|
|
@ -848,13 +866,48 @@ static int kartstuff_set(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
// #kartstuff -> NUMKARTSTUFF
|
||||
// #karthud -> NUMKARTSTUFF
|
||||
static int kartstuff_len(lua_State *L)
|
||||
{
|
||||
lua_pushinteger(L, NUMKARTSTUFF);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// karthud, ks -> karthud[ks]
|
||||
static int karthud_get(lua_State *L)
|
||||
{
|
||||
INT32 *karthud = *((INT32 **)luaL_checkudata(L, 1, META_KARTHUD));
|
||||
karthudtype_t ks = luaL_checkinteger(L, 2);
|
||||
if (ks >= NUMKARTHUD)
|
||||
return luaL_error(L, LUA_QL("karthudtype_t") " cannot be %u", ks);
|
||||
lua_pushinteger(L, karthud[ks]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// karthud, ks, value -> kartstuff[ks] = value
|
||||
static int karthud_set(lua_State *L)
|
||||
{
|
||||
INT32 *karthud = *((INT32 **)luaL_checkudata(L, 1, META_KARTHUD));
|
||||
karthudtype_t ks = luaL_checkinteger(L, 2);
|
||||
INT32 i = (INT32)luaL_checkinteger(L, 3);
|
||||
if (ks >= NUMKARTHUD)
|
||||
return luaL_error(L, LUA_QL("karthudtype_t") " cannot be %u", ks);
|
||||
if (hud_running)
|
||||
return luaL_error(L, "Do not alter player_t in HUD rendering code!");
|
||||
if (hook_cmd_running)
|
||||
return luaL_error(L, "Do not alter player_t in BuildCMD code!");
|
||||
karthud[ks] = i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// #karthud -> NUMKARTHUD
|
||||
static int karthud_len(lua_State *L)
|
||||
{
|
||||
lua_pushinteger(L, NUMKARTHUD);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// player.cmd get/set
|
||||
#define NOFIELD luaL_error(L, LUA_QL("ticcmd_t") " has no field named " LUA_QS, field)
|
||||
#define NOSET luaL_error(L, LUA_QL("ticcmd_t") " field " LUA_QS " cannot be set.", field)
|
||||
|
||||
|
|
@ -913,6 +966,82 @@ static int ticcmd_set(lua_State *L)
|
|||
|
||||
#undef NOFIELD
|
||||
|
||||
// Same shit for player.respawn variable... Why is everything in different sub-variables again now???
|
||||
#define RNOFIELD luaL_error(L, LUA_QL("respawnvars_t") " has no field named " LUA_QS, field)
|
||||
#define RUNIMPLEMENTED luaL_error(L, LUA_QL("respawnvars_t") " unimplemented field " LUA_QS " cannot be read or set.", field)
|
||||
// @TODO: Waypoints in Lua possibly maybe? No don't count on me to do it...
|
||||
|
||||
static int respawn_get(lua_State *L)
|
||||
{
|
||||
respawnvars_t *rsp = *((respawnvars_t **)luaL_checkudata(L, 1, META_RESPAWN));
|
||||
const char *field = luaL_checkstring(L, 2);
|
||||
if (!rsp)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
|
||||
if (fastcmp(field,"state"))
|
||||
lua_pushinteger(L, rsp->state);
|
||||
else if (fastcmp(field,"waypoint"))
|
||||
return RUNIMPLEMENTED;
|
||||
else if (fastcmp(field,"pointx"))
|
||||
lua_pushfixed(L, rsp->pointx);
|
||||
else if (fastcmp(field,"pointy"))
|
||||
lua_pushfixed(L, rsp->pointy);
|
||||
else if (fastcmp(field,"pointz"))
|
||||
lua_pushfixed(L, rsp->pointz);
|
||||
else if (fastcmp(field,"flip"))
|
||||
lua_pushboolean(L, rsp->flip);
|
||||
else if (fastcmp(field,"timer"))
|
||||
lua_pushinteger(L, rsp->timer);
|
||||
else if (fastcmp(field,"distanceleft"))
|
||||
lua_pushinteger(L, rsp->distanceleft); // Can't possibly foresee any problem when pushing UINT32 to Lua's INT32 hahahahaha, get ready for dumb hacky shit on high distances.
|
||||
else if (fastcmp(field,"dropdash"))
|
||||
lua_pushinteger(L, rsp->dropdash);
|
||||
else
|
||||
return RNOFIELD;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int respawn_set(lua_State *L)
|
||||
{
|
||||
respawnvars_t *rsp = *((respawnvars_t **)luaL_checkudata(L, 1, META_RESPAWN));
|
||||
const char *field = luaL_checkstring(L, 2);
|
||||
if (!rsp)
|
||||
return LUA_ErrInvalid(L, "respawnvars_t");
|
||||
|
||||
if (hud_running)
|
||||
return luaL_error(L, "Do not alter player_t in HUD rendering code!");
|
||||
if (hook_cmd_running)
|
||||
return luaL_error(L, "Do not alter player_t in CMD building code!");
|
||||
|
||||
if (fastcmp(field,"state"))
|
||||
rsp->state = (UINT8)luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"waypoint"))
|
||||
return RUNIMPLEMENTED;
|
||||
else if (fastcmp(field,"pointx"))
|
||||
rsp->pointx = luaL_checkfixed(L, 3);
|
||||
else if (fastcmp(field,"pointy"))
|
||||
rsp->pointy = luaL_checkfixed(L, 3);
|
||||
else if (fastcmp(field,"pointz"))
|
||||
rsp->pointz = luaL_checkfixed(L, 3);
|
||||
else if (fastcmp(field,"flip"))
|
||||
rsp->flip = luaL_checkboolean(L, 3);
|
||||
else if (fastcmp(field,"timer"))
|
||||
rsp->timer = (tic_t)luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"distanceleft"))
|
||||
rsp->distanceleft = (UINT32)luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"dropdash"))
|
||||
rsp->dropdash = (tic_t)luaL_checkinteger(L, 3);
|
||||
else
|
||||
return RNOFIELD;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#undef RNOFIELD
|
||||
#undef RUNIMPLEMENTED
|
||||
|
||||
|
||||
int LUA_PlayerLib(lua_State *L)
|
||||
{
|
||||
luaL_newmetatable(L, META_PLAYER);
|
||||
|
|
@ -948,6 +1077,25 @@ int LUA_PlayerLib(lua_State *L)
|
|||
lua_setfield(L, -2, "__len");
|
||||
lua_pop(L,1);
|
||||
|
||||
luaL_newmetatable(L, META_KARTHUD);
|
||||
lua_pushcfunction(L, karthud_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, karthud_set);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
|
||||
lua_pushcfunction(L, karthud_len);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_pop(L,1);
|
||||
|
||||
luaL_newmetatable(L, META_RESPAWN);
|
||||
lua_pushcfunction(L, respawn_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, respawn_set);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
lua_pop(L,1);
|
||||
|
||||
luaL_newmetatable(L, META_TICCMD);
|
||||
lua_pushcfunction(L, ticcmd_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
|
|
|||
|
|
@ -4229,7 +4229,7 @@ void A_AttractChase(mobj_t *actor)
|
|||
else
|
||||
actor->drawflags &= ~MFD_DONTDRAW;
|
||||
|
||||
// spilled rings have ghost trails and get capped to a certain speed
|
||||
// spilled rings get capped to a certain speed
|
||||
if (actor->type == (mobjtype_t)actor->info->reactiontime)
|
||||
{
|
||||
const fixed_t maxspeed = 4<<FRACBITS;
|
||||
|
|
@ -4241,9 +4241,6 @@ void A_AttractChase(mobj_t *actor)
|
|||
actor->momx = FixedMul(FixedDiv(actor->momx, oldspeed), newspeed);
|
||||
actor->momy = FixedMul(FixedDiv(actor->momy, oldspeed), newspeed);
|
||||
}
|
||||
|
||||
if (!P_IsObjectOnGround(actor))
|
||||
P_SpawnGhostMobj(actor)->tics = 3;
|
||||
}
|
||||
|
||||
if (actor->tracer && actor->tracer->player && actor->tracer->health
|
||||
|
|
|
|||
147
src/p_inter.c
147
src/p_inter.c
|
|
@ -1371,13 +1371,47 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
|
|||
|
||||
case MT_PLAYER:
|
||||
{
|
||||
angle_t flingAngle;
|
||||
mobj_t *kart;
|
||||
|
||||
target->fuse = TICRATE*3; // timer before mobj disappears from view (even if not an actual player)
|
||||
target->momx = target->momy = target->momz = 0;
|
||||
|
||||
if (target->player && target->player->pflags & PF_GAMETYPEOVER)
|
||||
break;
|
||||
kart = P_SpawnMobjFromMobj(target, 0, 0, 0, MT_KART_LEFTOVER);
|
||||
|
||||
if (kart && !P_MobjWasRemoved(kart))
|
||||
{
|
||||
kart->angle = target->angle;
|
||||
kart->color = target->color;
|
||||
kart->hitlag = target->hitlag;
|
||||
P_SetObjectMomZ(kart, 6*FRACUNIT, false);
|
||||
kart->extravalue1 = target->player->kartweight;
|
||||
}
|
||||
|
||||
if (source && !P_MobjWasRemoved(source))
|
||||
{
|
||||
flingAngle = R_PointToAngle2(
|
||||
source->x - source->momx, source->y - source->momy,
|
||||
target->x, target->y
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
flingAngle = target->angle + ANGLE_180;
|
||||
|
||||
if (P_RandomByte() & 1)
|
||||
{
|
||||
flingAngle -= ANGLE_45;
|
||||
}
|
||||
else
|
||||
{
|
||||
flingAngle += ANGLE_45;
|
||||
}
|
||||
}
|
||||
|
||||
P_InstaThrust(target, flingAngle, 14 * target->scale);
|
||||
P_SetObjectMomZ(target, 14*FRACUNIT, false);
|
||||
|
||||
P_PlayDeathSound(target);
|
||||
}
|
||||
break;
|
||||
|
|
@ -2012,10 +2046,11 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
break;
|
||||
case DMG_TUMBLE:
|
||||
K_TumblePlayer(player, inflictor, source);
|
||||
ringburst = 10;
|
||||
break;
|
||||
case DMG_EXPLODE:
|
||||
case DMG_KARMA:
|
||||
K_ExplodePlayer(player, inflictor, source);
|
||||
ringburst = K_ExplodePlayer(player, inflictor, source);
|
||||
break;
|
||||
case DMG_WIPEOUT:
|
||||
if (P_IsDisplayPlayer(player))
|
||||
|
|
@ -2100,6 +2135,56 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
return true;
|
||||
}
|
||||
|
||||
static void P_FlingBurst
|
||||
( player_t *player,
|
||||
angle_t fa,
|
||||
fixed_t z,
|
||||
mobjtype_t objType,
|
||||
tic_t objFuse,
|
||||
fixed_t objScale,
|
||||
INT32 i)
|
||||
{
|
||||
mobj_t *mo;
|
||||
fixed_t ns;
|
||||
fixed_t momxy = 5<<FRACBITS, momz = 12<<FRACBITS; // base horizonal/vertical thrusts
|
||||
INT32 mx = (i + 1) >> 1;
|
||||
|
||||
z = player->mo->z;
|
||||
if (player->mo->eflags & MFE_VERTICALFLIP)
|
||||
z += player->mo->height - mobjinfo[objType].height;
|
||||
|
||||
mo = P_SpawnMobj(player->mo->x, player->mo->y, z, objType);
|
||||
|
||||
mo->threshold = 10; // not useful for spikes
|
||||
mo->fuse = objFuse;
|
||||
P_SetTarget(&mo->target, player->mo);
|
||||
|
||||
mo->destscale = objScale;
|
||||
P_SetScale(mo, objScale);
|
||||
|
||||
/*
|
||||
0: 0
|
||||
1: 1 = (1+1)/2 = 1
|
||||
2: 1 = (2+1)/2 = 1
|
||||
3: 2 = (3+1)/2 = 2
|
||||
4: 2 = (4+1)/2 = 2
|
||||
5: 3 = (4+1)/2 = 2
|
||||
*/
|
||||
// Angle / height offset changes every other ring
|
||||
momxy -= mx * FRACUNIT;
|
||||
momz += mx * (2<<FRACBITS);
|
||||
|
||||
if (i & 1)
|
||||
fa += ANGLE_180;
|
||||
|
||||
ns = FixedMul(momxy, player->mo->scale);
|
||||
mo->momx = (mo->target->momx/2) + FixedMul(FINECOSINE(fa>>ANGLETOFINESHIFT), ns);
|
||||
mo->momy = (mo->target->momy/2) + FixedMul(FINESINE(fa>>ANGLETOFINESHIFT), ns);
|
||||
|
||||
ns = FixedMul(momz, player->mo->scale);
|
||||
mo->momz = (mo->target->momz/2) + ((ns) * P_MobjFlip(mo));
|
||||
}
|
||||
|
||||
/** Spills an injured player's rings.
|
||||
*
|
||||
* \param player The player who is losing rings.
|
||||
|
|
@ -2109,12 +2194,10 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
*/
|
||||
void P_PlayerRingBurst(player_t *player, INT32 num_rings)
|
||||
{
|
||||
INT32 num_fling_rings;
|
||||
INT32 i;
|
||||
mobj_t *mo;
|
||||
angle_t fa;
|
||||
fixed_t ns;
|
||||
fixed_t z;
|
||||
fixed_t momxy = 5<<FRACBITS, momz = 12<<FRACBITS; // base horizonal/vertical thrusts
|
||||
|
||||
// Rings shouldn't be in Battle!
|
||||
if (gametyperules & GTR_SPHERES)
|
||||
|
|
@ -2134,52 +2217,26 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings)
|
|||
else if (num_rings <= 0)
|
||||
return;
|
||||
|
||||
// Cap the maximum loss automatically to 2 in ring debt
|
||||
if (player->rings <= 0 && num_rings > 2)
|
||||
num_rings = 2;
|
||||
num_fling_rings = min(num_rings, player->rings);
|
||||
|
||||
P_GivePlayerRings(player, -num_rings);
|
||||
|
||||
// determine first angle
|
||||
fa = player->mo->angle + ((P_RandomByte() & 1) ? -ANGLE_90 : ANGLE_90);
|
||||
|
||||
for (i = 0; i < num_rings; i++)
|
||||
z = player->mo->z;
|
||||
if (player->mo->eflags & MFE_VERTICALFLIP)
|
||||
z += player->mo->height - mobjinfo[MT_RING].height;
|
||||
|
||||
for (i = 0; i < num_fling_rings; i++)
|
||||
{
|
||||
INT32 objType = mobjinfo[MT_RING].reactiontime;
|
||||
P_FlingBurst(player, fa, z,
|
||||
MT_FLINGRING, 60*TICRATE, player->mo->scale, i);
|
||||
}
|
||||
|
||||
z = player->mo->z;
|
||||
if (player->mo->eflags & MFE_VERTICALFLIP)
|
||||
z += player->mo->height - mobjinfo[objType].height;
|
||||
|
||||
mo = P_SpawnMobj(player->mo->x, player->mo->y, z, objType);
|
||||
|
||||
mo->threshold = 10;
|
||||
mo->fuse = 60*TICRATE;
|
||||
P_SetTarget(&mo->target, player->mo);
|
||||
|
||||
mo->destscale = player->mo->scale;
|
||||
P_SetScale(mo, player->mo->scale);
|
||||
|
||||
// Angle / height offset changes every other ring
|
||||
if (i != 0)
|
||||
{
|
||||
if (i & 1)
|
||||
{
|
||||
momxy -= FRACUNIT;
|
||||
momz += 2<<FRACBITS;
|
||||
}
|
||||
|
||||
fa += ANGLE_180;
|
||||
}
|
||||
|
||||
ns = FixedMul(momxy, mo->scale);
|
||||
mo->momx = (mo->target->momx/2) + FixedMul(FINECOSINE(fa>>ANGLETOFINESHIFT), ns);
|
||||
mo->momy = (mo->target->momy/2) + FixedMul(FINESINE(fa>>ANGLETOFINESHIFT), ns);
|
||||
|
||||
ns = FixedMul(momz, mo->scale);
|
||||
P_SetObjectMomZ(mo, (mo->target->momz/2) + ns, false);
|
||||
|
||||
if (player->mo->eflags & MFE_VERTICALFLIP)
|
||||
mo->momz *= -1;
|
||||
while (i < num_rings)
|
||||
{
|
||||
P_FlingBurst(player, fa, z,
|
||||
MT_DEBTSPIKE, 0, 3 * player->mo->scale / 2, i++);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
16
src/p_map.c
16
src/p_map.c
|
|
@ -213,6 +213,7 @@ static boolean P_SpecialIsLinedefCrossType(UINT16 ldspecial)
|
|||
switch (ldspecial)
|
||||
{
|
||||
case 2001: // Finish line
|
||||
case 2003: // Respawn line
|
||||
{
|
||||
linedefcrossspecial = true;
|
||||
}
|
||||
|
|
@ -1398,6 +1399,21 @@ static boolean PIT_CheckThing(mobj_t *thing)
|
|||
|
||||
return false;
|
||||
}
|
||||
else if (thing->type == MT_KART_LEFTOVER)
|
||||
{
|
||||
// see if it went over / under
|
||||
if (tmthing->z > thing->z + thing->height)
|
||||
return true; // overhead
|
||||
if (tmthing->z + tmthing->height < thing->z)
|
||||
return true; // underneath
|
||||
|
||||
if (P_IsObjectOnGround(thing) && tmthing->momz < 0)
|
||||
K_KartBouncing(tmthing, thing, true, false);
|
||||
else
|
||||
K_KartBouncing(tmthing, thing, false, false);
|
||||
|
||||
return false;
|
||||
}
|
||||
else if (thing->flags & MF_SOLID)
|
||||
{
|
||||
// see if it went over / under
|
||||
|
|
|
|||
133
src/p_mobj.c
133
src/p_mobj.c
|
|
@ -221,17 +221,29 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
|
|||
case S_KART_STILL:
|
||||
case S_KART_STILL_L:
|
||||
case S_KART_STILL_R:
|
||||
player->panim = PA_IDLE;
|
||||
case S_KART_STILL_GLANCE_L:
|
||||
case S_KART_STILL_GLANCE_R:
|
||||
case S_KART_STILL_LOOK_L:
|
||||
case S_KART_STILL_LOOK_R:
|
||||
player->panim = PA_STILL;
|
||||
break;
|
||||
case S_KART_SLOW:
|
||||
case S_KART_SLOW_L:
|
||||
case S_KART_SLOW_R:
|
||||
player->panim = PA_WALK;
|
||||
case S_KART_SLOW_GLANCE_L:
|
||||
case S_KART_SLOW_GLANCE_R:
|
||||
case S_KART_SLOW_LOOK_L:
|
||||
case S_KART_SLOW_LOOK_R:
|
||||
player->panim = PA_SLOW;
|
||||
break;
|
||||
case S_KART_FAST:
|
||||
case S_KART_FAST_L:
|
||||
case S_KART_FAST_R:
|
||||
player->panim = PA_RUN;
|
||||
case S_KART_FAST_GLANCE_L:
|
||||
case S_KART_FAST_GLANCE_R:
|
||||
case S_KART_FAST_LOOK_L:
|
||||
case S_KART_FAST_LOOK_R:
|
||||
player->panim = PA_FAST;
|
||||
break;
|
||||
case S_KART_DRIFT_L:
|
||||
case S_KART_DRIFT_L_OUT:
|
||||
|
|
@ -239,11 +251,11 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
|
|||
case S_KART_DRIFT_R:
|
||||
case S_KART_DRIFT_R_OUT:
|
||||
case S_KART_DRIFT_R_IN:
|
||||
player->panim = PA_DASH;
|
||||
player->panim = PA_DRIFT;
|
||||
break;
|
||||
case S_KART_SPINOUT:
|
||||
case S_KART_SQUISH:
|
||||
player->panim = PA_PAIN;
|
||||
case S_KART_DEAD:
|
||||
player->panim = PA_HURT;
|
||||
break;
|
||||
default:
|
||||
player->panim = PA_ETC;
|
||||
|
|
@ -1300,7 +1312,7 @@ static void P_XYFriction(mobj_t *mo, fixed_t oldx, fixed_t oldy)
|
|||
&& !(player->mo->standingslope && (!(player->mo->standingslope->flags & SL_NOPHYSICS)) /*&& (abs(player->mo->standingslope->zdelta) >= FRACUNIT/2)*/))
|
||||
{
|
||||
// if in a walking frame, stop moving
|
||||
if (player->panim == PA_WALK)
|
||||
if (player->panim == PA_SLOW)
|
||||
{
|
||||
P_SetPlayerMobjState(mo, S_KART_STILL);
|
||||
}
|
||||
|
|
@ -2280,6 +2292,16 @@ boolean P_ZMovement(mobj_t *mo)
|
|||
else
|
||||
mo->flags2 ^= MFD_DONTDRAW;
|
||||
}
|
||||
else if (mo->type == MT_DEBTSPIKE)
|
||||
{
|
||||
mom.x = mom.y = 0;
|
||||
mom.z = -mom.z/2;
|
||||
|
||||
if (mo->fuse == 0)
|
||||
{
|
||||
mo->fuse = 90;
|
||||
}
|
||||
}
|
||||
else if (mo->flags & MF_MISSILE)
|
||||
{
|
||||
if (!(mo->flags & MF_NOCLIP))
|
||||
|
|
@ -2334,6 +2356,68 @@ boolean P_ZMovement(mobj_t *mo)
|
|||
|
||||
if (mo->flags2 & MF2_SKULLFLY) // the skull slammed into something
|
||||
mom.z = -mom.z;
|
||||
else if (mo->type == MT_KART_LEFTOVER)
|
||||
{
|
||||
if (mo->health > 1)
|
||||
{
|
||||
const fixed_t tireOffset = 32;
|
||||
const angle_t aOffset = ANGLE_22h;
|
||||
|
||||
UINT8 i;
|
||||
angle_t tireAngle;
|
||||
mobj_t *tire;
|
||||
|
||||
// Spawn tires!
|
||||
mo->health = 1;
|
||||
P_SetMobjState(mo, S_KART_LEFTOVER_NOTIRES);
|
||||
|
||||
// Front tires
|
||||
tireAngle = mo->angle - aOffset;
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
tire = P_SpawnMobjFromMobj(
|
||||
mo,
|
||||
tireOffset * FINECOSINE(tireAngle >> ANGLETOFINESHIFT),
|
||||
tireOffset * FINESINE(tireAngle >> ANGLETOFINESHIFT),
|
||||
0,
|
||||
MT_KART_TIRE
|
||||
);
|
||||
|
||||
tire->angle = mo->angle;
|
||||
tire->fuse = 3*TICRATE;
|
||||
P_InstaThrust(tire, tireAngle, 4 * mo->scale);
|
||||
P_SetObjectMomZ(tire, 4*FRACUNIT, false);
|
||||
|
||||
tireAngle += (aOffset * 2);
|
||||
}
|
||||
|
||||
// Back tires
|
||||
tireAngle = (mo->angle + ANGLE_180) - aOffset;
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
tire = P_SpawnMobjFromMobj(
|
||||
mo,
|
||||
tireOffset * FINECOSINE(tireAngle >> ANGLETOFINESHIFT),
|
||||
tireOffset * FINESINE(tireAngle >> ANGLETOFINESHIFT),
|
||||
0,
|
||||
MT_KART_TIRE
|
||||
);
|
||||
|
||||
tire->angle = mo->angle;
|
||||
tire->fuse = 3*TICRATE;
|
||||
P_InstaThrust(tire, tireAngle, 4 * mo->scale);
|
||||
P_SetObjectMomZ(tire, 4*FRACUNIT, false);
|
||||
|
||||
P_SetMobjState(tire, S_KART_TIRE2);
|
||||
|
||||
tireAngle += (aOffset * 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (mo->type == MT_KART_TIRE)
|
||||
{
|
||||
mom.z = -mom.z;
|
||||
}
|
||||
else if (mo->type == MT_BIGTUMBLEWEED
|
||||
|| mo->type == MT_LITTLETUMBLEWEED
|
||||
|| mo->type == MT_CANNONBALLDECOR
|
||||
|
|
@ -2633,7 +2717,7 @@ void P_PlayerZMovement(mobj_t *mo)
|
|||
mo->z = mo->floorz;
|
||||
|
||||
// Get up if you fell.
|
||||
if (mo->player->panim == PA_PAIN && mo->player->kartstuff[k_spinouttimer] == 0 && mo->player->tumbleBounces == 0)
|
||||
if (mo->player->panim == PA_HURT && mo->player->kartstuff[k_spinouttimer] == 0 && mo->player->tumbleBounces == 0)
|
||||
P_SetPlayerMobjState(mo, S_KART_STILL);
|
||||
|
||||
if (!mo->standingslope && (mo->eflags & MFE_VERTICALFLIP ? tmceilingslope : tmfloorslope)) {
|
||||
|
|
@ -5867,8 +5951,11 @@ static boolean P_MobjDeadThink(mobj_t *mobj)
|
|||
{ // Go away.
|
||||
/// \todo Actually go ahead and remove mobj completely, and fix any bugs and crashes doing this creates. Chasecam should stop moving, and F12 should never return to it.
|
||||
mobj->momz = 0;
|
||||
|
||||
if (mobj->player)
|
||||
{
|
||||
mobj->drawflags |= MFD_DONTDRAW;
|
||||
}
|
||||
else // safe to remove, nobody's going to complain!
|
||||
{
|
||||
P_RemoveMobj(mobj);
|
||||
|
|
@ -5877,16 +5964,6 @@ static boolean P_MobjDeadThink(mobj_t *mobj)
|
|||
}
|
||||
else // Apply gravity to fall downwards.
|
||||
{
|
||||
if (mobj->player && !(mobj->fuse % 8) && (mobj->player->charflags & SF_MACHINE))
|
||||
{
|
||||
fixed_t r = mobj->radius >> FRACBITS;
|
||||
mobj_t *explosion = P_SpawnMobj(
|
||||
mobj->x + (P_RandomRange(r, -r) << FRACBITS),
|
||||
mobj->y + (P_RandomRange(r, -r) << FRACBITS),
|
||||
mobj->z + (P_RandomKey(mobj->height >> FRACBITS) << FRACBITS),
|
||||
MT_SONIC3KBOSSEXPLODE);
|
||||
S_StartSound(explosion, sfx_s3kb4);
|
||||
}
|
||||
P_SetObjectMomZ(mobj, -2*FRACUNIT/3, true);
|
||||
}
|
||||
break;
|
||||
|
|
@ -6671,6 +6748,10 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
|||
if (mobj->fuse == 16)/* to red*/
|
||||
K_SpawnDriftBoostClip(mobj->target->player);
|
||||
break;
|
||||
|
||||
case 0:/* air failsafe boost */
|
||||
mobj->color = SKINCOLOR_SILVER; // force white
|
||||
break;
|
||||
}
|
||||
|
||||
{
|
||||
|
|
@ -9079,6 +9160,7 @@ static void P_DefaultMobjShadowScale(mobj_t *thing)
|
|||
switch (thing->type)
|
||||
{
|
||||
case MT_PLAYER:
|
||||
case MT_KART_LEFTOVER:
|
||||
case MT_SMALLMACE:
|
||||
case MT_BIGMACE:
|
||||
case MT_PUMA:
|
||||
|
|
@ -9124,6 +9206,8 @@ static void P_DefaultMobjShadowScale(mobj_t *thing)
|
|||
thing->shadowscale = FRACUNIT;
|
||||
break;
|
||||
case MT_RING:
|
||||
case MT_FLINGRING:
|
||||
case MT_DEBTSPIKE:
|
||||
case MT_FLOATINGITEM:
|
||||
case MT_BLUESPHERE:
|
||||
case MT_EMERALD:
|
||||
|
|
@ -9371,6 +9455,19 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
|
|||
mobj->color = (P_RandomChance(FRACUNIT/2) ? SKINCOLOR_RED : SKINCOLOR_AQUAMARINE);
|
||||
break;
|
||||
case MT_BALLOON:
|
||||
{
|
||||
static const UINT8 BALLOONCOLORS[] = {
|
||||
// Carnival Night balloon colors
|
||||
SKINCOLOR_KETCHUP,
|
||||
SKINCOLOR_SAPPHIRE,
|
||||
SKINCOLOR_TANGERINE,
|
||||
SKINCOLOR_JET
|
||||
};
|
||||
|
||||
mobj->color = BALLOONCOLORS[P_RandomKey(sizeof(BALLOONCOLORS))];
|
||||
}
|
||||
break;
|
||||
case MT_KART_LEFTOVER:
|
||||
mobj->color = SKINCOLOR_RED;
|
||||
break;
|
||||
case MT_EGGROBO1:
|
||||
|
|
|
|||
|
|
@ -255,7 +255,11 @@ 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].driftInput);
|
||||
WRITEUINT8(save_p, players[i].airFailsafe);
|
||||
|
||||
WRITEUINT8(save_p, players[i].trickpanel);
|
||||
WRITEUINT8(save_p, players[i].trickdelay);
|
||||
WRITEUINT32(save_p, players[i].trickmomx);
|
||||
|
|
@ -271,6 +275,8 @@ static void P_NetArchivePlayers(void)
|
|||
WRITEUINT8(save_p, players[i].tumbleLastBounce);
|
||||
WRITEUINT8(save_p, players[i].tumbleSound);
|
||||
|
||||
WRITESINT8(save_p, players[i].glanceDir);
|
||||
|
||||
// respawnvars_t
|
||||
WRITEUINT8(save_p, players[i].respawn.state);
|
||||
WRITEUINT32(save_p, K_GetWaypointHeapIndex(players[i].respawn.wp));
|
||||
|
|
@ -455,7 +461,11 @@ 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].driftInput = (boolean)READUINT8(save_p);
|
||||
players[i].airFailsafe = (boolean)READUINT8(save_p);
|
||||
|
||||
players[i].trickpanel = READUINT8(save_p);
|
||||
players[i].trickdelay = READUINT8(save_p);
|
||||
players[i].trickmomx = READUINT32(save_p);
|
||||
|
|
@ -471,6 +481,8 @@ static void P_NetUnArchivePlayers(void)
|
|||
players[i].tumbleLastBounce = (boolean)READUINT8(save_p);
|
||||
players[i].tumbleSound = (boolean)READUINT8(save_p);
|
||||
|
||||
players[i].glanceDir = READSINT8(save_p);
|
||||
|
||||
// respawnvars_t
|
||||
players[i].respawn.state = READUINT8(save_p);
|
||||
players[i].respawn.wp = (waypoint_t *)(size_t)READUINT32(save_p);
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@
|
|||
|
||||
// SRB2Kart
|
||||
#include "k_kart.h"
|
||||
#include "k_race.h"
|
||||
#include "k_battle.h" // K_SpawnBattleCapsules
|
||||
#include "k_pwrlv.h"
|
||||
#include "k_waypoint.h"
|
||||
|
|
@ -4059,6 +4060,8 @@ boolean P_LoadLevel(boolean fromnetsave)
|
|||
|
||||
// The waypoint data that's in PU_LEVEL needs to be reset back to 0/NULL now since PU_LEVEL was cleared
|
||||
K_ClearWaypoints();
|
||||
K_ClearFinishBeamLine();
|
||||
|
||||
// Load the waypoints please!
|
||||
if (gametyperules & GTR_CIRCUIT)
|
||||
{
|
||||
|
|
@ -4066,6 +4069,11 @@ boolean P_LoadLevel(boolean fromnetsave)
|
|||
{
|
||||
CONS_Alert(CONS_ERROR, "Waypoints were not able to be setup! Player positions will not work correctly.\n");
|
||||
}
|
||||
|
||||
if (K_GenerateFinishBeamLine() == false)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "No valid finish line beam setup could be found.\n");
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HWRENDER // not win32 only 19990829 by Kin
|
||||
|
|
|
|||
19
src/p_spec.c
19
src/p_spec.c
|
|
@ -2182,6 +2182,20 @@ void P_CrossSpecialLine(line_t *line, INT32 side, mobj_t *thing)
|
|||
}
|
||||
break;
|
||||
|
||||
case 2003: // Respawn Line
|
||||
{
|
||||
/* No Climb: only trigger from front side */
|
||||
if
|
||||
(
|
||||
player->respawn.state == RESPAWNST_NONE &&
|
||||
(!(line->flags & ML_NOCLIMB) || side == 0)
|
||||
)
|
||||
{
|
||||
P_DamageMobj(player->mo, NULL, NULL, 1, DMG_DEATHPIT);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
// Do nothing
|
||||
|
|
@ -6973,6 +6987,11 @@ void P_SpawnSpecials(boolean fromnetsave)
|
|||
break;
|
||||
case 2002: // Linedef Trigger: Race Lap
|
||||
break;
|
||||
case 2003: // Respawn Line
|
||||
break;
|
||||
case 2004: // Bot controller
|
||||
break;
|
||||
|
||||
case 499: // Linedef Executor: Enable/Disable Waypoints
|
||||
break;
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
// SRB2Kart
|
||||
#include "k_kart.h"
|
||||
#include "k_race.h"
|
||||
#include "k_battle.h"
|
||||
#include "k_waypoint.h"
|
||||
|
||||
|
|
@ -332,6 +333,9 @@ static inline void P_RunThinkers(void)
|
|||
ps_thlist_times[i] = I_GetTimeMicros() - ps_thlist_times[i];
|
||||
}
|
||||
|
||||
if (gametyperules & GTR_CIRCUIT)
|
||||
K_RunFinishLineBeam();
|
||||
|
||||
if (gametyperules & GTR_PAPERITEMS)
|
||||
K_RunPaperItemSpawners();
|
||||
|
||||
|
|
|
|||
14
src/p_user.c
14
src/p_user.c
|
|
@ -1851,7 +1851,7 @@ static void P_3dMovement(player_t *player)
|
|||
totalthrust.x = totalthrust.y = 0; // I forget if this is needed
|
||||
totalthrust.z = FRACUNIT*P_MobjFlip(player->mo)/3; // A bit of extra push-back on slopes
|
||||
|
||||
if (player->kartstuff[k_sneakertimer] > 0)
|
||||
if (K_SlopeResistance(player) == true)
|
||||
{
|
||||
totalthrust.z = -(totalthrust.z);
|
||||
}
|
||||
|
|
@ -2632,9 +2632,6 @@ static void P_DeathThink(player_t *player)
|
|||
if (player->deadtimer < INT32_MAX)
|
||||
player->deadtimer++;
|
||||
|
||||
if (player->bot) // don't allow bots to do any of the below, B_CheckRespawn does all they need for respawning already
|
||||
goto notrealplayer;
|
||||
|
||||
if ((player->pflags & PF_GAMETYPEOVER) && (gametyperules & GTR_CIRCUIT))
|
||||
{
|
||||
player->karthud[khud_timeovercam]++;
|
||||
|
|
@ -2677,8 +2674,6 @@ static void P_DeathThink(player_t *player)
|
|||
}
|
||||
}
|
||||
|
||||
notrealplayer:
|
||||
|
||||
if (!player->mo)
|
||||
return;
|
||||
|
||||
|
|
@ -3075,6 +3070,13 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
|
|||
|
||||
mo = player->mo;
|
||||
|
||||
if (mo->hitlag > 0 || player->playerstate == PST_DEAD)
|
||||
{
|
||||
// Do not move the camera while in hitlag!
|
||||
// The camera zooming out after you got hit makes it hard to focus on the vibration.
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifndef NOCLIPCAM
|
||||
cameranoclip = ((player->pflags & PF_NOCLIP)
|
||||
|| (mo->flags & (MF_NOCLIP|MF_NOCLIPHEIGHT)) // Noclipping player camera noclips too!!
|
||||
|
|
|
|||
59
src/r_data.c
59
src/r_data.c
|
|
@ -623,13 +623,13 @@ extracolormap_t *R_ColormapForName(char *name)
|
|||
// custom colormaps at runtime. NOTE: For GL mode, we only need to color
|
||||
// data and not the colormap data.
|
||||
//
|
||||
static double deltas[256][3], map[256][3];
|
||||
static double brightChange[256], map[256][3];
|
||||
|
||||
static int RoundUp(double number);
|
||||
|
||||
lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap)
|
||||
{
|
||||
double cmaskr, cmaskg, cmaskb, cdestr, cdestg, cdestb;
|
||||
double cmaskr, cmaskg, cmaskb, cdestr, cdestg, cdestb, cdestbright;
|
||||
double maskamt = 0, othermask = 0;
|
||||
|
||||
UINT8 cr = R_GetRgbaR(extra_colormap->rgba),
|
||||
|
|
@ -668,6 +668,7 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap)
|
|||
cdestr = cfr;
|
||||
cdestg = cfg;
|
||||
cdestb = cfb;
|
||||
cdestbright = sqrt((cfr*cfr) + (cfg*cfg) + (cfb*cfb));
|
||||
|
||||
// fade alpha unused in software
|
||||
// maskamt = (double)(cfa/24.0l);
|
||||
|
|
@ -682,15 +683,15 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap)
|
|||
// This code creates the colormap array used by software renderer
|
||||
/////////////////////
|
||||
{
|
||||
double r, g, b, cbrightness;
|
||||
double r, g, b, cbrightness, cbest, cdist;
|
||||
int p;
|
||||
lighttable_t *colormap_p;
|
||||
|
||||
// Initialise the map and delta arrays
|
||||
// map[i] stores an RGB color (as double) for index i,
|
||||
// which is then converted to SRB2's palette later
|
||||
// deltas[i] stores a corresponding fade delta between the RGB color and the final fade color;
|
||||
// map[i]'s values are decremented by after each use
|
||||
// brightChange[i] is the value added/subtracted every step for the fade;
|
||||
// map[i]'s values are in/decremented by it after each use
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
r = pMasterPalette[i].s.red;
|
||||
|
|
@ -701,17 +702,31 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap)
|
|||
map[i][0] = (cbrightness * cmaskr) + (r * othermask);
|
||||
if (map[i][0] > 255.0l)
|
||||
map[i][0] = 255.0l;
|
||||
deltas[i][0] = (map[i][0] - cdestr) / (double)fadedist;
|
||||
|
||||
map[i][1] = (cbrightness * cmaskg) + (g * othermask);
|
||||
if (map[i][1] > 255.0l)
|
||||
map[i][1] = 255.0l;
|
||||
deltas[i][1] = (map[i][1] - cdestg) / (double)fadedist;
|
||||
|
||||
map[i][2] = (cbrightness * cmaskb) + (b * othermask);
|
||||
if (map[i][2] > 255.0l)
|
||||
map[i][2] = 255.0l;
|
||||
deltas[i][2] = (map[i][2] - cdestb) / (double)fadedist;
|
||||
|
||||
// Get the "best" color.
|
||||
// Our brightest color's value, if we're fading to a darker color,
|
||||
// or our (inverted) darkest color's value, if we're fading to a brighter color.
|
||||
if (cbrightness < cdestbright)
|
||||
{
|
||||
cbest = 255.0l - min(r, min(g, b));
|
||||
cdist = 255.0l - cdestbright;
|
||||
}
|
||||
else
|
||||
{
|
||||
cbest = max(r, max(g, b));
|
||||
cdist = cdestbright;
|
||||
}
|
||||
|
||||
// Add/subtract this value during fading.
|
||||
brightChange[i] = fabs(cbest - cdist) / (double)fadedist;
|
||||
}
|
||||
|
||||
// Now allocate memory for the actual colormap array itself!
|
||||
|
|
@ -732,22 +747,28 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap)
|
|||
|
||||
if ((UINT32)p < fadestart)
|
||||
continue;
|
||||
#define ABS2(x) ((x) < 0 ? -(x) : (x))
|
||||
if (ABS2(map[i][0] - cdestr) > ABS2(deltas[i][0]))
|
||||
map[i][0] -= deltas[i][0];
|
||||
else
|
||||
|
||||
// Add/subtract towards the destination color.
|
||||
if (fabs(map[i][0] - cdestr) <= brightChange[i])
|
||||
map[i][0] = cdestr;
|
||||
|
||||
if (ABS2(map[i][1] - cdestg) > ABS2(deltas[i][1]))
|
||||
map[i][1] -= deltas[i][1];
|
||||
else if (map[i][0] > cdestr)
|
||||
map[i][0] -= brightChange[i];
|
||||
else
|
||||
map[i][0] += brightChange[i];
|
||||
|
||||
if (fabs(map[i][1] - cdestg) <= brightChange[i])
|
||||
map[i][1] = cdestg;
|
||||
|
||||
if (ABS2(map[i][2] - cdestb) > ABS2(deltas[i][1]))
|
||||
map[i][2] -= deltas[i][2];
|
||||
else if (map[i][1] > cdestg)
|
||||
map[i][1] -= brightChange[i];
|
||||
else
|
||||
map[i][1] += brightChange[i];
|
||||
|
||||
if (fabs(map[i][2] - cdestb) <= brightChange[i])
|
||||
map[i][2] = cdestb;
|
||||
#undef ABS2
|
||||
else if (map[i][2] > cdestb)
|
||||
map[i][2] -= brightChange[i];
|
||||
else
|
||||
map[i][2] += brightChange[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1236,28 +1236,24 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale,
|
|||
patch_t *patch;
|
||||
fixed_t xscale, yscale, shadowxscale, shadowyscale, shadowskew, x1, x2;
|
||||
INT32 light = 0;
|
||||
fixed_t scalemul; UINT8 trans;
|
||||
fixed_t floordiff;
|
||||
UINT8 trans = tr_transsub;
|
||||
fixed_t groundz;
|
||||
pslope_t *groundslope;
|
||||
boolean isflipped = thing->eflags & MFE_VERTICALFLIP;
|
||||
|
||||
groundz = R_GetShadowZ(thing, &groundslope);
|
||||
|
||||
if (abs(groundz-viewz)/tz > 4) return; // Prevent stretchy shadows and possible crashes
|
||||
|
||||
floordiff = abs((isflipped ? thing->height : 0) + thing->z - groundz);
|
||||
if (thing->whiteshadow == true)
|
||||
{
|
||||
trans = tr_transadd;
|
||||
}
|
||||
|
||||
trans = floordiff / (100*FRACUNIT) + 3;
|
||||
if (trans >= 9) return;
|
||||
|
||||
scalemul = FixedMul(FRACUNIT - floordiff/640, scale);
|
||||
|
||||
patch = W_CachePatchName((thing->whiteshadow == true ? "LSHADOW" : "DSHADOW"), PU_CACHE);
|
||||
patch = W_CachePatchName("DSHADOW", PU_CACHE);
|
||||
xscale = FixedDiv(projection[viewssnum], tz);
|
||||
yscale = FixedDiv(projectiony[viewssnum], tz);
|
||||
shadowxscale = FixedMul(thing->radius*2, scalemul);
|
||||
shadowyscale = FixedMul(FixedMul(thing->radius*2, scalemul), FixedDiv(abs(groundz - viewz), tz));
|
||||
shadowxscale = FixedMul(thing->radius*2, scale);
|
||||
shadowyscale = FixedMul(FixedMul(thing->radius*2, scale), FixedDiv(abs(groundz - viewz), tz));
|
||||
shadowyscale = min(shadowyscale, shadowxscale) / SHORT(patch->height);
|
||||
shadowxscale /= SHORT(patch->width);
|
||||
shadowskew = 0;
|
||||
|
|
@ -1274,9 +1270,9 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale,
|
|||
//CONS_Printf("Shadow is sloped by %d %d\n", xslope, zslope);
|
||||
|
||||
if (viewz < groundz)
|
||||
shadowyscale += FixedMul(FixedMul(thing->radius*2 / SHORT(patch->height), scalemul), zslope);
|
||||
shadowyscale += FixedMul(FixedMul(thing->radius*2 / SHORT(patch->height), scale), zslope);
|
||||
else
|
||||
shadowyscale -= FixedMul(FixedMul(thing->radius*2 / SHORT(patch->height), scalemul), zslope);
|
||||
shadowyscale -= FixedMul(FixedMul(thing->radius*2 / SHORT(patch->height), scale), zslope);
|
||||
|
||||
shadowyscale = abs(shadowyscale);
|
||||
|
||||
|
|
@ -1354,16 +1350,9 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale,
|
|||
else
|
||||
shadow->extra_colormap = thing->subsector->sector->extra_colormap;
|
||||
|
||||
shadow->transmap = transtables + (trans<<FF_TRANSSHIFT);
|
||||
shadow->transmap = transtables + ((trans-1) << FF_TRANSSHIFT);
|
||||
|
||||
if (thing->whiteshadow == true)
|
||||
{
|
||||
shadow->colormap = scalelight[LIGHTLEVELS - 1][0]; // full bright!
|
||||
}
|
||||
else
|
||||
{
|
||||
shadow->colormap = scalelight[0][0]; // full dark!
|
||||
}
|
||||
shadow->colormap = colormaps;
|
||||
|
||||
objectsdrawn++;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -551,7 +551,7 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca
|
|||
else if (alphalevel == 15)
|
||||
alphalevel = hudplusalpha[st_translucency];
|
||||
|
||||
if (alphalevel >= 10)
|
||||
if (alphalevel >= 12)
|
||||
return; // invis
|
||||
|
||||
if (alphalevel)
|
||||
|
|
@ -744,7 +744,7 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_
|
|||
else if (alphalevel == 15)
|
||||
alphalevel = hudplusalpha[st_translucency];
|
||||
|
||||
if (alphalevel >= 10)
|
||||
if (alphalevel >= 12)
|
||||
return; // invis
|
||||
|
||||
if (alphalevel)
|
||||
|
|
@ -997,7 +997,7 @@ void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
|
|||
else if (alphalevel == 15)
|
||||
alphalevel = hudplusalpha[st_translucency];
|
||||
|
||||
if (alphalevel >= 10)
|
||||
if (alphalevel >= 12)
|
||||
return; // invis
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -120,6 +120,8 @@ void V_CubeApply(UINT8 *red, UINT8 *green, UINT8 *blue);
|
|||
#define V_70TRANS 0x00070000
|
||||
#define V_80TRANS 0x00080000 // used to be V_8020TRANS
|
||||
#define V_90TRANS 0x00090000
|
||||
#define V_ADDTRANS 0x000A0000
|
||||
#define V_SUBTRANS 0x000B0000
|
||||
#define V_HUDTRANSHALF 0x000D0000
|
||||
#define V_HUDTRANS 0x000E0000 // draw the hud translucent
|
||||
#define V_HUDTRANSDOUBLE 0x000F0000
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue