mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-12-24 00:42:32 +00:00
Merge remote-tracking branch 'origin/master' into parties
This commit is contained in:
commit
abcba53781
35 changed files with 2002 additions and 1211 deletions
|
|
@ -495,6 +495,8 @@ OBJS:=$(i_main_o) \
|
|||
$(OBJDIR)/y_inter.o \
|
||||
$(OBJDIR)/st_stuff.o \
|
||||
$(OBJDIR)/k_kart.o \
|
||||
$(OBJDIR)/k_collide.o\
|
||||
$(OBJDIR)/k_battle.o \
|
||||
$(OBJDIR)/k_pwrlv.o \
|
||||
$(OBJDIR)/k_waypoint.o\
|
||||
$(OBJDIR)/k_pathfind.o\
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@
|
|||
#include "lua_script.h"
|
||||
#include "lua_hook.h"
|
||||
#include "k_kart.h"
|
||||
#include "k_battle.h"
|
||||
#include "k_pwrlv.h"
|
||||
|
||||
#ifdef CLIENT_LOADINGSCREEN
|
||||
|
|
@ -3516,7 +3517,7 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
|
|||
splitscreenplayer = (UINT8)READUINT8(*p);
|
||||
|
||||
CONS_Debug(DBG_NETPLAY, "addplayer: %d %d %d\n", node, newplayernum, splitscreenplayer);
|
||||
|
||||
|
||||
// Clear player before joining, lest some things get set incorrectly
|
||||
CL_ClearPlayer(newplayernum);
|
||||
|
||||
|
|
@ -3767,7 +3768,11 @@ void SV_StartSinglePlayerServer(void)
|
|||
server = true;
|
||||
netgame = false;
|
||||
multiplayer = false;
|
||||
gametype = GT_RACE; //srb2kart
|
||||
|
||||
if (modeattacking == ATTACKING_CAPSULES)
|
||||
gametype = GT_MATCH; //srb2kart
|
||||
else
|
||||
gametype = GT_RACE; //srb2kart
|
||||
|
||||
// no more tic the game with this settings!
|
||||
SV_StopServer();
|
||||
|
|
|
|||
|
|
@ -468,7 +468,7 @@ static void D_Display(void)
|
|||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@
|
|||
#include "m_cond.h"
|
||||
#include "m_anigif.h"
|
||||
#include "k_kart.h" // SRB2kart
|
||||
#include "k_battle.h"
|
||||
#include "k_pwrlv.h"
|
||||
#include "y_inter.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -2473,10 +2473,10 @@ static void readunlockable(MYFILE *f, INT32 num)
|
|||
unlockables[num].type = SECRET_PANDORA;
|
||||
else if (fastcmp(word2, "CREDITS"))
|
||||
unlockables[num].type = SECRET_CREDITS;
|
||||
else if (fastcmp(word2, "RECORDATTACK"))
|
||||
unlockables[num].type = SECRET_RECORDATTACK;
|
||||
else if (fastcmp(word2, "NIGHTSMODE"))
|
||||
unlockables[num].type = SECRET_NIGHTSMODE;
|
||||
else if (fastcmp(word2, "TIMEATTACK"))
|
||||
unlockables[num].type = SECRET_TIMEATTACK;
|
||||
else if (fastcmp(word2, "BREAKTHECAPSULES"))
|
||||
unlockables[num].type = SECRET_BREAKTHECAPSULES;
|
||||
else if (fastcmp(word2, "HEADER"))
|
||||
unlockables[num].type = SECRET_HEADER;
|
||||
else if (fastcmp(word2, "LEVELSELECT"))
|
||||
|
|
@ -7219,6 +7219,13 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
|
|||
"S_OVERTIMEORB",
|
||||
"S_OVERTIMEBEAM",
|
||||
|
||||
"S_BATTLECAPSULE_SIDE1",
|
||||
"S_BATTLECAPSULE_SIDE2",
|
||||
"S_BATTLECAPSULE_TOP",
|
||||
"S_BATTLECAPSULE_BUTTON",
|
||||
"S_BATTLECAPSULE_SUPPORT",
|
||||
"S_BATTLECAPSULE_SUPPORTFLY",
|
||||
|
||||
#ifdef SEENAMES
|
||||
"S_NAMECHECK",
|
||||
#endif
|
||||
|
|
@ -8018,6 +8025,9 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
|
|||
"MT_OVERTIMEORB",
|
||||
"MT_OVERTIMEBEAM",
|
||||
|
||||
"MT_BATTLECAPSULE",
|
||||
"MT_BATTLECAPSULE_PIECE",
|
||||
|
||||
#ifdef SEENAMES
|
||||
"MT_NAMECHECK",
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* ______ ___ ___
|
||||
* /\ _ \ /\_ \ /\_ \
|
||||
* \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
|
||||
/* ______ ___ ___
|
||||
* /\ _ \ /\_ \ /\_ \
|
||||
* \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
|
||||
* \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
|
||||
* \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
|
||||
* \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
|
||||
|
|
@ -22,9 +22,9 @@
|
|||
|
||||
#include "allegro.h"
|
||||
|
||||
/* ______ ___ ___
|
||||
* /\ _ \ /\_ \ /\_ \
|
||||
* \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
|
||||
/* ______ ___ ___
|
||||
* /\ _ \ /\_ \ /\_ \
|
||||
* \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
|
||||
* \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
|
||||
* \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
|
||||
* \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
|
||||
|
|
@ -57,7 +57,7 @@
|
|||
#define FILE_CREATE(filename, handle) handle = open(filename, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)
|
||||
#define FILE_CLOSE(handle) close(handle)
|
||||
#define FILE_READ(handle, buf, size, sz) sz = read(handle, buf, size)
|
||||
#define FILE_WRITE(handle, buf, size, sz) sz = write(handle, buf, size)
|
||||
#define FILE_WRITE(handle, buf, size, sz) sz = write(handle, buf, size)
|
||||
#define FILE_SEARCH_STRUCT struct ffblk
|
||||
#define FILE_FINDFIRST(filename, attrib, dta) findfirst(filename, dta, attrib)
|
||||
#define FILE_FINDNEXT(dta) findnext(dta)
|
||||
|
|
@ -73,11 +73,11 @@
|
|||
#define ENABLE() asm volatile ("sti")
|
||||
|
||||
|
||||
__INLINE__ void enter_critical(void)
|
||||
__INLINE__ void enter_critical(void)
|
||||
{
|
||||
if (windows_version >= 3) {
|
||||
__dpmi_regs r;
|
||||
r.x.ax = 0x1681;
|
||||
r.x.ax = 0x1681;
|
||||
__dpmi_int(0x2F, &r);
|
||||
}
|
||||
|
||||
|
|
@ -85,11 +85,11 @@ __INLINE__ void enter_critical(void)
|
|||
}
|
||||
|
||||
|
||||
__INLINE__ void exit_critical(void)
|
||||
__INLINE__ void exit_critical(void)
|
||||
{
|
||||
if (windows_version >= 3) {
|
||||
__dpmi_regs r;
|
||||
r.x.ax = 0x1682;
|
||||
r.x.ax = 0x1682;
|
||||
__dpmi_int(0x2F, &r);
|
||||
}
|
||||
|
||||
|
|
@ -176,9 +176,9 @@ extern int _fm_port;
|
|||
extern int _mpu_port;
|
||||
extern int _mpu_irq;
|
||||
extern int _sb_freq;
|
||||
extern int _sb_port;
|
||||
extern int _sb_dma;
|
||||
extern int _sb_irq;
|
||||
extern int _sb_port;
|
||||
extern int _sb_dma;
|
||||
extern int _sb_irq;
|
||||
|
||||
int _sb_read_dsp_version(void);
|
||||
int _sb_reset_dsp(int data);
|
||||
|
|
@ -238,8 +238,8 @@ extern volatile int _retrace_hpp_value;
|
|||
|
||||
|
||||
/* caches and tables for svga bank switching */
|
||||
extern int _last_bank_1, _last_bank_2;
|
||||
extern int *_gfx_bank;
|
||||
extern int _last_bank_1, _last_bank_2;
|
||||
extern int *_gfx_bank;
|
||||
|
||||
|
||||
/* bank switching routines */
|
||||
|
|
@ -282,7 +282,7 @@ extern int _crtc;
|
|||
__INLINE__ int _read_vga_register(int port, int index)
|
||||
{
|
||||
if (port==0x3C0)
|
||||
inportb(_crtc+6);
|
||||
inportb(_crtc+6);
|
||||
|
||||
outportb(port, index);
|
||||
return inportb(port+1);
|
||||
|
|
@ -292,7 +292,7 @@ __INLINE__ int _read_vga_register(int port, int index)
|
|||
/* _write_vga_register:
|
||||
* Writes a byte to a VGA register.
|
||||
*/
|
||||
__INLINE__ void _write_vga_register(int port, int index, int v)
|
||||
__INLINE__ void _write_vga_register(int port, int index, int v)
|
||||
{
|
||||
if (port==0x3C0) {
|
||||
inportb(_crtc+6);
|
||||
|
|
@ -345,7 +345,7 @@ __INLINE__ void _vsync_out_v(void)
|
|||
__INLINE__ void _vsync_in(void)
|
||||
{
|
||||
if (_timer_use_retrace) {
|
||||
int t = retrace_count;
|
||||
int t = retrace_count;
|
||||
|
||||
do {
|
||||
} while (t == retrace_count);
|
||||
|
|
@ -555,7 +555,7 @@ typedef struct POLYGON_SEGMENT
|
|||
|
||||
|
||||
/* an active polygon edge */
|
||||
typedef struct POLYGON_EDGE
|
||||
typedef struct POLYGON_EDGE
|
||||
{
|
||||
int top; /* top y position */
|
||||
int bottom; /* bottom y position */
|
||||
|
|
@ -673,7 +673,7 @@ void _poly_scanline_ptex_mask_lit32d(unsigned long addr, int w, POLYGON_SEGMENT
|
|||
/* sound lib stuff */
|
||||
extern int _digi_volume;
|
||||
extern int _midi_volume;
|
||||
extern int _flip_pan;
|
||||
extern int _flip_pan;
|
||||
extern int _sound_hq;
|
||||
|
||||
extern int (*_midi_init)(void);
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ extern boolean metalrecording;
|
|||
|
||||
#define ATTACKING_NONE 0
|
||||
#define ATTACKING_RECORD 1
|
||||
//#define ATTACKING_NIGHTS 2
|
||||
#define ATTACKING_CAPSULES 2
|
||||
extern UINT8 modeattacking;
|
||||
|
||||
// menu demo things
|
||||
|
|
@ -385,7 +385,7 @@ extern UINT16 emeralds;
|
|||
#define EMERALD7 64
|
||||
#define ALL7EMERALDS(v) ((v & (EMERALD1|EMERALD2|EMERALD3|EMERALD4|EMERALD5|EMERALD6|EMERALD7)) == (EMERALD1|EMERALD2|EMERALD3|EMERALD4|EMERALD5|EMERALD6|EMERALD7))
|
||||
|
||||
extern INT32 nummaprings, nummapboxes, numgotboxes; //keep track of spawned rings/coins/battle mode items
|
||||
extern INT32 nummaprings; // keep track of spawned rings/coins
|
||||
|
||||
/** Time attack information, currently a very small structure.
|
||||
*/
|
||||
|
|
@ -518,15 +518,6 @@ extern INT16 votelevels[5][2];
|
|||
extern SINT8 votes[MAXPLAYERS];
|
||||
extern SINT8 pickedvote;
|
||||
|
||||
/** Battle overtime information
|
||||
*/
|
||||
extern struct battleovertime
|
||||
{
|
||||
UINT16 enabled; ///< Has this been initalized yet?
|
||||
fixed_t radius, minradius; ///< Radius of kill field
|
||||
fixed_t x, y, z; ///< Position to center on
|
||||
} battleovertime;
|
||||
|
||||
extern tic_t hidetime;
|
||||
|
||||
extern UINT32 timesBeaten; // # of times the game has been beaten.
|
||||
|
|
|
|||
|
|
@ -204,7 +204,7 @@ static void F_DoWipe(fademask_t *fademask, lighttable_t *fadecolormap, boolean r
|
|||
// ---
|
||||
// Sal: I kinda destroyed some of this code by introducing Genesis-style fades.
|
||||
// A colormap can be provided in F_RunWipe, which the white/black values will be
|
||||
// remapped to the appropriate entry in the fade colormap.
|
||||
// remapped to the appropriate entry in the fade colormap.
|
||||
{
|
||||
// wipe screen, start, end
|
||||
UINT8 *w = wipe_scr;
|
||||
|
|
@ -434,7 +434,7 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu, const char *colormap, boolean r
|
|||
reverse = false;
|
||||
}
|
||||
|
||||
paldiv = FixedDiv(257<<FRACBITS, pallen<<FRACBITS);
|
||||
paldiv = FixedDiv(257<<FRACBITS, pallen<<FRACBITS);
|
||||
|
||||
// Init the wipe
|
||||
WipeInAction = true;
|
||||
|
|
|
|||
157
src/g_game.c
157
src/g_game.c
|
|
@ -48,6 +48,7 @@
|
|||
#include "m_cond.h" // condition sets
|
||||
#include "md5.h" // demo checksums
|
||||
#include "k_kart.h" // SRB2kart
|
||||
#include "k_battle.h"
|
||||
#include "k_pwrlv.h"
|
||||
|
||||
gameaction_t gameaction;
|
||||
|
|
@ -199,10 +200,6 @@ UINT32 bluescore, redscore; // CTF and Team Match team scores
|
|||
// ring count... for PERFECT!
|
||||
INT32 nummaprings = 0;
|
||||
|
||||
// box respawning in battle mode
|
||||
INT32 nummapboxes = 0;
|
||||
INT32 numgotboxes = 0;
|
||||
|
||||
// Elminates unnecessary searching.
|
||||
boolean CheckForBustableBlocks;
|
||||
boolean CheckForBouncySector;
|
||||
|
|
@ -276,9 +273,6 @@ INT16 votelevels[5][2]; // Levels that were rolled by the host
|
|||
SINT8 votes[MAXPLAYERS]; // Each player's vote
|
||||
SINT8 pickedvote; // What vote the host rolls
|
||||
|
||||
// Battle overtime system
|
||||
struct battleovertime battleovertime;
|
||||
|
||||
// Server-sided, synched variables
|
||||
SINT8 battlewanted[4]; // WANTED players in battle, worth x2 points
|
||||
tic_t wantedcalcdelay; // Time before it recalculates WANTED
|
||||
|
|
@ -2639,7 +2633,7 @@ void G_PlayerReborn(INT32 player)
|
|||
itemtype = 0;
|
||||
itemamount = 0;
|
||||
growshrinktimer = 0;
|
||||
bumper = (G_BattleGametype() ? cv_kartbumpers.value : 0);
|
||||
bumper = (G_BattleGametype() ? K_StartingBumperCount() : 0);
|
||||
rings = (G_BattleGametype() ? 0 : 5);
|
||||
comebackpoints = 0;
|
||||
wanted = 0;
|
||||
|
|
@ -2864,9 +2858,13 @@ void G_SpawnPlayer(INT32 playernum, boolean starpost)
|
|||
return;
|
||||
}
|
||||
|
||||
// -- Record Attack --
|
||||
if (modeattacking || battlecapsules)
|
||||
spawnpoint = playerstarts[0];
|
||||
|
||||
// -- CTF --
|
||||
// Order: CTF->DM->Coop
|
||||
if (gametype == GT_CTF && players[playernum].ctfteam)
|
||||
else if (gametype == GT_CTF && players[playernum].ctfteam)
|
||||
{
|
||||
if (!(spawnpoint = G_FindCTFStart(playernum)) // find a CTF start
|
||||
&& !(spawnpoint = G_FindMatchStart(playernum))) // find a DM start
|
||||
|
|
@ -4805,8 +4803,8 @@ char *G_BuildMapTitle(INT32 mapnum)
|
|||
#define DEMOHEADER "\xF0" "KartReplay" "\x0F"
|
||||
|
||||
#define DF_GHOST 0x01 // This demo contains ghost data too!
|
||||
#define DF_RECORDATTACK 0x02 // This demo is from record attack and contains its final completion time!
|
||||
#define DF_NIGHTSATTACK 0x04 // This demo is from NiGHTS attack and contains its time left, score, and mares!
|
||||
#define DF_TIMEATTACK 0x02 // This demo is from Time Attack and contains its final completion time & best lap!
|
||||
#define DF_BREAKTHECAPSULES 0x04 // This demo is from Break the Capsules and contains its final completion time!
|
||||
#define DF_ATTACKMASK 0x06 // This demo is from ??? attack and contains ???
|
||||
#define DF_ATTACKSHIFT 1
|
||||
#define DF_ENCORE 0x40
|
||||
|
|
@ -4844,7 +4842,6 @@ static ticcmd_t oldcmd[MAXPLAYERS];
|
|||
// Not used for Metal Sonic
|
||||
#define GZT_SPRITE 0x10 // Animation frame
|
||||
#define GZT_EXTRA 0x20
|
||||
#define GZT_NIGHTS 0x40 // NiGHTS Mode stuff!
|
||||
|
||||
// GZT_EXTRA flags
|
||||
#define EZT_THOK 0x01 // Spawned a thok object
|
||||
|
|
@ -5350,13 +5347,6 @@ void G_WriteGhostTic(mobj_t *ghost, INT32 playernum)
|
|||
if (!(demoflags & DF_GHOST))
|
||||
return; // No ghost data to write.
|
||||
|
||||
if (ghost->player && ghost->player->pflags & PF_NIGHTSMODE && ghost->tracer)
|
||||
{
|
||||
// We're talking about the NiGHTS thing, not the normal platforming thing!
|
||||
ziptic |= GZT_NIGHTS;
|
||||
ghost = ghost->tracer;
|
||||
}
|
||||
|
||||
ziptic_p = demo_p++; // the ziptic, written at the end of this function
|
||||
|
||||
#define MAXMOM (0x7FFF<<8)
|
||||
|
|
@ -5573,12 +5563,6 @@ void G_ConsGhostTic(INT32 playernum)
|
|||
demo_p++;
|
||||
if (ziptic & GZT_SPRITE)
|
||||
demo_p++;
|
||||
if(ziptic & GZT_NIGHTS) {
|
||||
if (!testmo || !testmo->player || !(testmo->player->pflags & PF_NIGHTSMODE) || !testmo->tracer)
|
||||
nightsfail = true;
|
||||
else
|
||||
testmo = testmo->tracer;
|
||||
}
|
||||
|
||||
if (ziptic & GZT_EXTRA)
|
||||
{ // But wait, there's more!
|
||||
|
|
@ -6409,6 +6393,10 @@ void G_BeginRecording(void)
|
|||
WRITEUINT32(demo_p,UINT32_MAX); // time
|
||||
WRITEUINT32(demo_p,UINT32_MAX); // lap
|
||||
break;
|
||||
case ATTACKING_CAPSULES: // 2
|
||||
demotime_p = demo_p;
|
||||
WRITEUINT32(demo_p,UINT32_MAX); // time
|
||||
break;
|
||||
default: // 3
|
||||
break;
|
||||
}
|
||||
|
|
@ -6551,13 +6539,18 @@ void G_SetDemoTime(UINT32 ptime, UINT32 plap)
|
|||
{
|
||||
if (!demo.recording || !demotime_p)
|
||||
return;
|
||||
|
||||
if (demoflags & DF_RECORDATTACK)
|
||||
if (demoflags & DF_TIMEATTACK)
|
||||
{
|
||||
WRITEUINT32(demotime_p, ptime);
|
||||
WRITEUINT32(demotime_p, plap);
|
||||
demotime_p = NULL;
|
||||
}
|
||||
else if (demoflags & DF_BREAKTHECAPSULES)
|
||||
{
|
||||
WRITEUINT32(demotime_p, ptime);
|
||||
(void)plap;
|
||||
demotime_p = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void G_LoadDemoExtraFiles(UINT8 **pp)
|
||||
|
|
@ -6733,6 +6726,7 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname)
|
|||
UINT8 c;
|
||||
UINT16 s ATTRUNUSED;
|
||||
UINT8 aflags = 0;
|
||||
boolean uselaps = false;
|
||||
|
||||
// load the new file
|
||||
FIL_DefaultExtension(newname, ".lmp");
|
||||
|
|
@ -6759,20 +6753,17 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname)
|
|||
p++; // gametype
|
||||
G_SkipDemoExtraFiles(&p);
|
||||
|
||||
aflags = flags & (DF_RECORDATTACK|DF_NIGHTSATTACK);
|
||||
aflags = flags & (DF_TIMEATTACK|DF_BREAKTHECAPSULES);
|
||||
I_Assert(aflags);
|
||||
if (flags & DF_RECORDATTACK)
|
||||
{
|
||||
newtime = READUINT32(p);
|
||||
|
||||
if (flags & DF_TIMEATTACK)
|
||||
uselaps = true; // get around uninitalized error
|
||||
|
||||
newtime = READUINT32(p);
|
||||
if (uselaps)
|
||||
newlap = READUINT32(p);
|
||||
}
|
||||
/*else if (flags & DF_NIGHTSATTACK)
|
||||
{
|
||||
newtime = READUINT32(p);
|
||||
newscore = READUINT32(p);
|
||||
}*/
|
||||
else // appease compiler
|
||||
return 0;
|
||||
else
|
||||
newlap = UINT32_MAX;
|
||||
|
||||
Z_Free(buffer);
|
||||
|
||||
|
|
@ -6824,28 +6815,32 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname)
|
|||
Z_Free(buffer);
|
||||
return UINT8_MAX;
|
||||
}
|
||||
if (flags & DF_RECORDATTACK)
|
||||
{
|
||||
oldtime = READUINT32(p);
|
||||
|
||||
oldtime = READUINT32(p);
|
||||
if (uselaps)
|
||||
oldlap = READUINT32(p);
|
||||
}
|
||||
/*else if (flags & DF_NIGHTSATTACK)
|
||||
{
|
||||
oldtime = READUINT32(p);
|
||||
oldscore = READUINT32(p);
|
||||
}*/
|
||||
else // appease compiler
|
||||
return UINT8_MAX;
|
||||
else
|
||||
oldlap = 0;
|
||||
|
||||
Z_Free(buffer);
|
||||
|
||||
c = 0;
|
||||
if (newtime < oldtime
|
||||
|| (newtime == oldtime && (newlap < oldlap)))
|
||||
c |= 1; // Better time
|
||||
if (newlap < oldlap
|
||||
|| (newlap == oldlap && newtime < oldtime))
|
||||
c |= 1<<1; // Better lap time
|
||||
|
||||
if (uselaps)
|
||||
{
|
||||
if (newtime < oldtime
|
||||
|| (newtime == oldtime && (newlap < oldlap)))
|
||||
c |= 1; // Better time
|
||||
if (newlap < oldlap
|
||||
|| (newlap == oldlap && newtime < oldtime))
|
||||
c |= 1<<1; // Better lap time
|
||||
}
|
||||
else
|
||||
{
|
||||
if (newtime < oldtime)
|
||||
c |= 1; // Better time
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
|
@ -7220,19 +7215,18 @@ void G_DoPlayDemo(char *defdemoname)
|
|||
|
||||
switch (modeattacking)
|
||||
{
|
||||
case ATTACKING_NONE: // 0
|
||||
break;
|
||||
case ATTACKING_RECORD: // 1
|
||||
hu_demotime = READUINT32(demo_p);
|
||||
hu_demolap = READUINT32(demo_p);
|
||||
break;
|
||||
/*case ATTACKING_NIGHTS: // 2
|
||||
hu_demotime = READUINT32(demo_p);
|
||||
hu_demoscore = READUINT32(demo_p);
|
||||
break;*/
|
||||
default: // 3
|
||||
modeattacking = ATTACKING_NONE;
|
||||
break;
|
||||
case ATTACKING_NONE: // 0
|
||||
break;
|
||||
case ATTACKING_RECORD: // 1
|
||||
hu_demotime = READUINT32(demo_p);
|
||||
hu_demolap = READUINT32(demo_p);
|
||||
break;
|
||||
case ATTACKING_CAPSULES: // 2
|
||||
hu_demotime = READUINT32(demo_p);
|
||||
break;
|
||||
default: // 3
|
||||
modeattacking = ATTACKING_NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
// Random seed
|
||||
|
|
@ -7527,16 +7521,16 @@ void G_AddGhost(char *defdemoname)
|
|||
|
||||
switch ((flags & DF_ATTACKMASK)>>DF_ATTACKSHIFT)
|
||||
{
|
||||
case ATTACKING_NONE: // 0
|
||||
break;
|
||||
case ATTACKING_RECORD: // 1
|
||||
p += 8; // demo time, lap
|
||||
break;
|
||||
/*case ATTACKING_NIGHTS: // 2
|
||||
p += 8; // demo time left, score
|
||||
break;*/
|
||||
default: // 3
|
||||
break;
|
||||
case ATTACKING_NONE: // 0
|
||||
break;
|
||||
case ATTACKING_RECORD: // 1
|
||||
p += 8; // demo time, lap
|
||||
break;
|
||||
case ATTACKING_CAPSULES: // 2
|
||||
p += 4; // demo time
|
||||
break;
|
||||
default: // 3
|
||||
break;
|
||||
}
|
||||
|
||||
p += 4; // random seed
|
||||
|
|
@ -7728,6 +7722,9 @@ void G_UpdateStaffGhostName(lumpnum_t l)
|
|||
case ATTACKING_RECORD: // 1
|
||||
p += 8; // demo time, lap
|
||||
break;
|
||||
case ATTACKING_CAPSULES: // 2
|
||||
p += 4; // demo time
|
||||
break;
|
||||
default: // 3
|
||||
break;
|
||||
}
|
||||
|
|
@ -8059,7 +8056,7 @@ void G_SaveDemo(void)
|
|||
free(demobuffer);
|
||||
demo.recording = false;
|
||||
|
||||
if (modeattacking != ATTACKING_RECORD)
|
||||
if (!modeattacking)
|
||||
{
|
||||
if (demo.savemode == DSM_SAVED)
|
||||
CONS_Printf(M_GetText("Demo %s recorded\n"), demoname);
|
||||
|
|
|
|||
61
src/info.c
61
src/info.c
|
|
@ -3460,6 +3460,13 @@ state_t states[NUMSTATES] =
|
|||
{SPR_OTFG, 2|FF_FULLBRIGHT|FF_PAPERSPRITE, 1, {NULL}, 0, 0, S_NULL}, // S_OVERTIMEORB
|
||||
{SPR_OTFG, 1|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_NULL}, // S_OVERTIMEBEAM
|
||||
|
||||
{SPR_CAPS, FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_BATTLECAPSULE_SIDE1
|
||||
{SPR_CAPS, FF_PAPERSPRITE|1, -1, {NULL}, 0, 0, S_NULL}, // S_BATTLECAPSULE_SIDE2
|
||||
{SPR_CAPS, 2, -1, {NULL}, 0, 0, S_NULL}, // S_BATTLECAPSULE_TOP
|
||||
{SPR_CAPS, 3, -1, {NULL}, 0, 0, S_NULL}, // S_BATTLECAPSULE_BUTTON
|
||||
{SPR_CAPS, 4, -1, {NULL}, 0, 0, S_NULL}, // S_BATTLECAPSULE_SUPPORT
|
||||
{SPR_CAPS, FF_ANIMATE|5, -1, {NULL}, 3, 1, S_NULL}, // S_BATTLECAPSULE_SUPPORTFLY
|
||||
|
||||
#ifdef SEENAMES
|
||||
{SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_NAMECHECK
|
||||
#endif
|
||||
|
|
@ -20441,6 +20448,60 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_BATTLECAPSULE
|
||||
2333, // doomednum
|
||||
S_INVISIBLE, // spawnstate
|
||||
1, // 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_INVISIBLE, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
0, // speed
|
||||
28<<FRACBITS, // radius
|
||||
112<<FRACBITS, // height
|
||||
0, // display offset
|
||||
100, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_SOLID|MF_SHOOTABLE|MF_DONTENCOREMAP, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_BATTLECAPSULE_PIECE
|
||||
-1, // doomednum
|
||||
S_INVISIBLE, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
8, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
0, // painchance
|
||||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
0, // speed
|
||||
8<<FRACBITS, // radius
|
||||
8<<FRACBITS, // height
|
||||
0, // display offset
|
||||
100, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_SCENERY|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOBLOCKMAP|MF_DONTENCOREMAP, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
// ============================================================================================================================//
|
||||
|
||||
#ifdef SEENAMES
|
||||
|
|
|
|||
10
src/info.h
10
src/info.h
|
|
@ -4126,6 +4126,13 @@ typedef enum state
|
|||
S_OVERTIMEORB,
|
||||
S_OVERTIMEBEAM,
|
||||
|
||||
S_BATTLECAPSULE_SIDE1,
|
||||
S_BATTLECAPSULE_SIDE2,
|
||||
S_BATTLECAPSULE_TOP,
|
||||
S_BATTLECAPSULE_BUTTON,
|
||||
S_BATTLECAPSULE_SUPPORT,
|
||||
S_BATTLECAPSULE_SUPPORTFLY,
|
||||
|
||||
#ifdef SEENAMES
|
||||
S_NAMECHECK,
|
||||
#endif
|
||||
|
|
@ -4942,6 +4949,9 @@ typedef enum mobj_type
|
|||
MT_OVERTIMEORB,
|
||||
MT_OVERTIMEBEAM,
|
||||
|
||||
MT_BATTLECAPSULE,
|
||||
MT_BATTLECAPSULE_PIECE,
|
||||
|
||||
#ifdef SEENAMES
|
||||
MT_NAMECHECK,
|
||||
#endif
|
||||
|
|
|
|||
764
src/k_battle.c
Normal file
764
src/k_battle.c
Normal file
|
|
@ -0,0 +1,764 @@
|
|||
/// \file k_battle.c
|
||||
/// \brief SRB2Kart Battle Mode specific code
|
||||
|
||||
#include "k_battle.h"
|
||||
#include "k_kart.h"
|
||||
#include "doomtype.h"
|
||||
#include "doomdata.h"
|
||||
#include "g_game.h"
|
||||
#include "p_mobj.h"
|
||||
#include "p_local.h"
|
||||
#include "p_setup.h"
|
||||
#include "p_slopes.h" // P_GetZAt
|
||||
#include "r_main.h"
|
||||
#include "r_defs.h" // MAXFFLOORS
|
||||
#include "info.h"
|
||||
#include "s_sound.h"
|
||||
#include "m_random.h"
|
||||
#include "r_sky.h" // skyflatnum
|
||||
|
||||
// Battle overtime info
|
||||
struct battleovertime battleovertime;
|
||||
|
||||
// Capsules mode enabled for this map?
|
||||
boolean battlecapsules = false;
|
||||
|
||||
// box respawning in battle mode
|
||||
INT32 nummapboxes = 0;
|
||||
INT32 numgotboxes = 0;
|
||||
|
||||
// Capsule counters
|
||||
UINT8 maptargets = 0; // Capsules in map
|
||||
UINT8 numtargets = 0; // Capsules busted
|
||||
|
||||
INT32 K_StartingBumperCount(void)
|
||||
{
|
||||
if (battlecapsules)
|
||||
return 1; // always 1 hit in Break the Capsules
|
||||
|
||||
return cv_kartbumpers.value;
|
||||
}
|
||||
|
||||
boolean K_IsPlayerWanted(player_t *player)
|
||||
{
|
||||
UINT8 i;
|
||||
if (!(G_BattleGametype()))
|
||||
return false;
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
if (battlewanted[i] == -1)
|
||||
break;
|
||||
if (player == &players[battlewanted[i]])
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void K_CalculateBattleWanted(void)
|
||||
{
|
||||
UINT8 numingame = 0, numplaying = 0, numwanted = 0;
|
||||
SINT8 bestbumperplayer = -1, bestbumper = -1;
|
||||
SINT8 camppos[MAXPLAYERS]; // who is the biggest camper
|
||||
UINT8 ties = 0, nextcamppos = 0;
|
||||
boolean setbumper = false;
|
||||
UINT8 i, j;
|
||||
|
||||
if (!G_BattleGametype())
|
||||
{
|
||||
for (i = 0; i < 4; i++)
|
||||
battlewanted[i] = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
wantedcalcdelay = wantedfrequency;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
camppos[i] = -1; // initialize
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
UINT8 position = 1;
|
||||
|
||||
if (!playeringame[i] || players[i].spectator) // Not playing
|
||||
continue;
|
||||
|
||||
if (players[i].exiting) // We're done, don't calculate.
|
||||
return;
|
||||
|
||||
numplaying++;
|
||||
|
||||
if (players[i].kartstuff[k_bumper] <= 0) // Not alive, so don't do anything else
|
||||
continue;
|
||||
|
||||
numingame++;
|
||||
|
||||
if (bestbumper == -1 || players[i].kartstuff[k_bumper] > bestbumper)
|
||||
{
|
||||
bestbumper = players[i].kartstuff[k_bumper];
|
||||
bestbumperplayer = i;
|
||||
}
|
||||
else if (players[i].kartstuff[k_bumper] == bestbumper)
|
||||
bestbumperplayer = -1; // Tie, no one has best bumper.
|
||||
|
||||
for (j = 0; j < MAXPLAYERS; j++)
|
||||
{
|
||||
if (!playeringame[j] || players[j].spectator)
|
||||
continue;
|
||||
if (players[j].kartstuff[k_bumper] <= 0)
|
||||
continue;
|
||||
if (j == i)
|
||||
continue;
|
||||
if (players[j].kartstuff[k_wanted] == players[i].kartstuff[k_wanted] && players[j].marescore > players[i].marescore)
|
||||
position++;
|
||||
else if (players[j].kartstuff[k_wanted] > players[i].kartstuff[k_wanted])
|
||||
position++;
|
||||
}
|
||||
|
||||
position--; // Make zero based
|
||||
|
||||
while (camppos[position] != -1) // Port priority!
|
||||
position++;
|
||||
|
||||
camppos[position] = i;
|
||||
}
|
||||
|
||||
if (numplaying <= 2 || (numingame <= 2 && bestbumper == 1)) // In 1v1s then there's no need for WANTED. In bigger netgames, don't show anyone as WANTED when they're equally matched.
|
||||
numwanted = 0;
|
||||
else
|
||||
numwanted = min(4, 1 + ((numingame-2) / 4));
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
if (i+1 > numwanted) // Not enough players for this slot to be wanted!
|
||||
battlewanted[i] = -1;
|
||||
else if (bestbumperplayer != -1 && !setbumper) // If there's a player who has an untied bumper lead over everyone else, they are the first to be wanted.
|
||||
{
|
||||
battlewanted[i] = bestbumperplayer;
|
||||
setbumper = true; // Don't set twice
|
||||
}
|
||||
else
|
||||
{
|
||||
// Don't accidentally set the same player, if the bestbumperplayer is also a huge camper.
|
||||
while (bestbumperplayer != -1 && camppos[nextcamppos] != -1
|
||||
&& bestbumperplayer == camppos[nextcamppos])
|
||||
nextcamppos++;
|
||||
|
||||
// Do not add *any* more people if there's too many times that are tied with others.
|
||||
// This could theoretically happen very easily if people don't hit each other for a while after the start of a match.
|
||||
// (I will be sincerely impressed if more than 2 people tie after people start hitting each other though)
|
||||
|
||||
if (camppos[nextcamppos] == -1 // Out of entries
|
||||
|| ties >= (numwanted-i)) // Already counted ties
|
||||
{
|
||||
battlewanted[i] = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ties < (numwanted-i))
|
||||
{
|
||||
ties = 0; // Reset
|
||||
for (j = 0; j < 2; j++)
|
||||
{
|
||||
if (camppos[nextcamppos+(j+1)] == -1) // Nothing beyond, cancel
|
||||
break;
|
||||
if (players[camppos[nextcamppos]].kartstuff[k_wanted] == players[camppos[nextcamppos+(j+1)]].kartstuff[k_wanted])
|
||||
ties++;
|
||||
}
|
||||
}
|
||||
|
||||
if (ties < (numwanted-i)) // Is it still low enough after counting?
|
||||
{
|
||||
battlewanted[i] = camppos[nextcamppos];
|
||||
nextcamppos++;
|
||||
}
|
||||
else
|
||||
battlewanted[i] = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void K_SpawnBattlePoints(player_t *source, player_t *victim, UINT8 amount)
|
||||
{
|
||||
statenum_t st;
|
||||
mobj_t *pt;
|
||||
|
||||
if (!source || !source->mo)
|
||||
return;
|
||||
|
||||
if (amount == 1)
|
||||
st = S_BATTLEPOINT1A;
|
||||
else if (amount == 2)
|
||||
st = S_BATTLEPOINT2A;
|
||||
else if (amount == 3)
|
||||
st = S_BATTLEPOINT3A;
|
||||
else
|
||||
return; // NO STATE!
|
||||
|
||||
pt = P_SpawnMobj(source->mo->x, source->mo->y, source->mo->z, MT_BATTLEPOINT);
|
||||
P_SetTarget(&pt->target, source->mo);
|
||||
P_SetMobjState(pt, st);
|
||||
if (victim && victim->skincolor)
|
||||
pt->color = victim->skincolor;
|
||||
else
|
||||
pt->color = source->skincolor;
|
||||
}
|
||||
|
||||
void K_CheckBumpers(void)
|
||||
{
|
||||
UINT8 i;
|
||||
UINT8 numingame = 0;
|
||||
SINT8 winnernum = -1;
|
||||
INT32 winnerscoreadd = 0;
|
||||
boolean nobumpers = false;
|
||||
|
||||
if (!G_BattleGametype())
|
||||
return;
|
||||
|
||||
if (gameaction == ga_completed)
|
||||
return;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i] || players[i].spectator) // not even in-game
|
||||
continue;
|
||||
|
||||
if (players[i].exiting) // we're already exiting! stop!
|
||||
return;
|
||||
|
||||
numingame++;
|
||||
winnerscoreadd += players[i].marescore;
|
||||
|
||||
if (players[i].kartstuff[k_bumper] <= 0) // if you don't have any bumpers, you're probably not a winner
|
||||
{
|
||||
nobumpers = true;
|
||||
continue;
|
||||
}
|
||||
else if (winnernum != -1) // TWO winners? that's dumb :V
|
||||
return;
|
||||
|
||||
winnernum = i;
|
||||
winnerscoreadd -= players[i].marescore;
|
||||
}
|
||||
|
||||
if (numingame <= 1)
|
||||
{
|
||||
if (!battlecapsules)
|
||||
{
|
||||
// Reset map to turn on battle capsules
|
||||
D_MapChange(gamemap, gametype, encoremode, true, 0, false, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nobumpers)
|
||||
{
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
players[i].pflags |= PF_TIMEOVER;
|
||||
//players[i].lives = 0;
|
||||
P_DoPlayerExit(&players[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (winnernum > -1 && playeringame[winnernum])
|
||||
{
|
||||
players[winnernum].marescore += winnerscoreadd;
|
||||
CONS_Printf(M_GetText("%s recieved %d point%s for winning!\n"), player_names[winnernum], winnerscoreadd, (winnerscoreadd == 1 ? "" : "s"));
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++) // This can't go in the earlier loop because winning adds points
|
||||
K_KartUpdatePosition(&players[i]);
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++) // and it can't be merged with this loop because it needs to be all updated before exiting... multi-loops suck...
|
||||
P_DoPlayerExit(&players[i]);
|
||||
}
|
||||
|
||||
#define MAXPLANESPERSECTOR (MAXFFLOORS+1)*2
|
||||
|
||||
static void K_SpawnOvertimeParticles(fixed_t x, fixed_t y, fixed_t scale, mobjtype_t type, boolean ceiling)
|
||||
{
|
||||
UINT8 i;
|
||||
fixed_t flatz[MAXPLANESPERSECTOR];
|
||||
boolean flip[MAXPLANESPERSECTOR];
|
||||
UINT8 numflats = 0;
|
||||
mobj_t *mo;
|
||||
subsector_t *ss = R_IsPointInSubsector(x, y);
|
||||
sector_t *sec;
|
||||
|
||||
if (!ss)
|
||||
return;
|
||||
sec = ss->sector;
|
||||
|
||||
// convoluted stuff JUST to get all of the planes we need to draw orbs on :V
|
||||
|
||||
for (i = 0; i < MAXPLANESPERSECTOR; i++)
|
||||
flip[i] = false;
|
||||
|
||||
if (sec->floorpic != skyflatnum)
|
||||
{
|
||||
#ifdef ESLOPE
|
||||
flatz[numflats] = (sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : sec->floorheight);
|
||||
#else
|
||||
flatz[numflats] = (sec->floorheight);
|
||||
#endif
|
||||
numflats++;
|
||||
}
|
||||
if (sec->ceilingpic != skyflatnum && ceiling)
|
||||
{
|
||||
#ifdef ESLOPE
|
||||
flatz[numflats] = (sec->c_slope ? P_GetZAt(sec->c_slope, x, y) : sec->ceilingheight) - FixedMul(mobjinfo[type].height, scale);
|
||||
#else
|
||||
flatz[numflats] = (sec->ceilingheight) - FixedMul(mobjinfo[type].height, scale);
|
||||
#endif
|
||||
flip[numflats] = true;
|
||||
numflats++;
|
||||
}
|
||||
|
||||
if (sec->ffloors)
|
||||
{
|
||||
ffloor_t *rover;
|
||||
for (rover = sec->ffloors; rover; rover = rover->next)
|
||||
{
|
||||
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER))
|
||||
continue;
|
||||
if (*rover->toppic != skyflatnum)
|
||||
{
|
||||
#ifdef ESLOPE
|
||||
flatz[numflats] = (*rover->t_slope ? P_GetZAt(*rover->t_slope, x, y) : *rover->topheight);
|
||||
#else
|
||||
flatz[numflats] = (*rover->topheight);
|
||||
#endif
|
||||
numflats++;
|
||||
}
|
||||
if (*rover->bottompic != skyflatnum && ceiling)
|
||||
{
|
||||
#ifdef ESLOPE
|
||||
flatz[numflats] = (*rover->b_slope ? P_GetZAt(*rover->b_slope, x, y) : *rover->bottomheight) - FixedMul(mobjinfo[type].height, scale);
|
||||
#else
|
||||
flatz[numflats] = (*rover->bottomheight) - FixedMul(mobjinfo[type].height, scale);
|
||||
#endif
|
||||
flip[numflats] = true;
|
||||
numflats++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (numflats <= 0) // no flats
|
||||
return;
|
||||
|
||||
for (i = 0; i < numflats; i++)
|
||||
{
|
||||
mo = P_SpawnMobj(x, y, flatz[i], type);
|
||||
|
||||
// Lastly, if this can see the skybox mobj, then... we just wasted our time :V
|
||||
if (skyboxmo[0] && !P_MobjWasRemoved(skyboxmo[0]))
|
||||
{
|
||||
const fixed_t sbz = skyboxmo[0]->z;
|
||||
fixed_t checkz = sec->floorheight;
|
||||
|
||||
while (checkz < sec->ceilingheight)
|
||||
{
|
||||
P_TeleportMove(skyboxmo[0], skyboxmo[0]->x, skyboxmo[0]->y, checkz);
|
||||
if (P_CheckSight(skyboxmo[0], mo))
|
||||
{
|
||||
P_RemoveMobj(mo);
|
||||
break;
|
||||
}
|
||||
else
|
||||
checkz += 32*mapobjectscale;
|
||||
}
|
||||
|
||||
P_TeleportMove(skyboxmo[0], skyboxmo[0]->x, skyboxmo[0]->y, sbz);
|
||||
|
||||
if (P_MobjWasRemoved(mo))
|
||||
continue;
|
||||
}
|
||||
|
||||
P_SetScale(mo, scale);
|
||||
|
||||
if (flip[i])
|
||||
{
|
||||
mo->flags2 |= MF2_OBJECTFLIP;
|
||||
mo->eflags |= MFE_VERTICALFLIP;
|
||||
}
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case MT_OVERTIMEFOG:
|
||||
mo->destscale = 8*mo->scale;
|
||||
mo->momz = P_RandomRange(1,8)*mo->scale;
|
||||
break;
|
||||
case MT_OVERTIMEORB:
|
||||
//mo->destscale = mo->scale/4;
|
||||
mo->frame += ((leveltime/4) % 8);
|
||||
/*if (battleovertime.enabled < 10*TICRATE)
|
||||
mo->flags2 |= MF2_SHADOW;*/
|
||||
mo->angle = R_PointToAngle2(mo->x, mo->y, battleovertime.x, battleovertime.y) + ANGLE_90;
|
||||
mo->z += P_RandomRange(0,48) * mo->scale;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#undef MAXPLANESPERSECTOR
|
||||
|
||||
void K_RunBattleOvertime(void)
|
||||
{
|
||||
UINT16 i, j;
|
||||
|
||||
if (battleovertime.enabled < 10*TICRATE)
|
||||
{
|
||||
battleovertime.enabled++;
|
||||
if (battleovertime.enabled == TICRATE)
|
||||
S_StartSound(NULL, sfx_bhurry);
|
||||
if (battleovertime.enabled == 10*TICRATE)
|
||||
S_StartSound(NULL, sfx_kc40);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (battleovertime.radius > battleovertime.minradius)
|
||||
battleovertime.radius -= mapobjectscale;
|
||||
else
|
||||
battleovertime.radius = battleovertime.minradius;
|
||||
}
|
||||
|
||||
if (leveltime & 1)
|
||||
{
|
||||
UINT8 transparency = tr_trans50;
|
||||
|
||||
if (!splitscreen && players[displayplayers[0]].mo)
|
||||
{
|
||||
INT32 dist = P_AproxDistance(battleovertime.x-players[displayplayers[0]].mo->x, battleovertime.y-players[displayplayers[0]].mo->y);
|
||||
transparency = max(0, NUMTRANSMAPS - ((256 + (dist>>FRACBITS)) / 256));
|
||||
}
|
||||
|
||||
if (transparency < NUMTRANSMAPS)
|
||||
{
|
||||
mobj_t *beam = P_SpawnMobj(battleovertime.x, battleovertime.y, battleovertime.z + (mobjinfo[MT_RANDOMITEM].height/2), MT_OVERTIMEBEAM);
|
||||
P_SetScale(beam, beam->scale*2);
|
||||
if (transparency > 0)
|
||||
beam->frame |= transparency<<FF_TRANSSHIFT;
|
||||
}
|
||||
}
|
||||
|
||||
// 16 orbs at the normal minimum size of 512
|
||||
{
|
||||
const fixed_t pi = (22<<FRACBITS) / 7; // loose approximation, this doesn't need to be incredibly precise
|
||||
fixed_t scale = mapobjectscale + (battleovertime.radius/2048);
|
||||
fixed_t sprwidth = 32*scale;
|
||||
fixed_t circumference = FixedMul(pi, battleovertime.radius<<1);
|
||||
UINT16 orbs = circumference / sprwidth;
|
||||
angle_t angoff = ANGLE_MAX / orbs;
|
||||
|
||||
for (i = 0; i < orbs; i++)
|
||||
{
|
||||
angle_t ang = (i * angoff) + FixedAngle((leveltime/2)<<FRACBITS);
|
||||
fixed_t x = battleovertime.x + P_ReturnThrustX(NULL, ang, battleovertime.radius - FixedMul(mobjinfo[MT_OVERTIMEORB].radius, scale));
|
||||
fixed_t y = battleovertime.y + P_ReturnThrustY(NULL, ang, battleovertime.radius - FixedMul(mobjinfo[MT_OVERTIMEORB].radius, scale));
|
||||
K_SpawnOvertimeParticles(x, y, scale, MT_OVERTIMEORB, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (battleovertime.enabled < 10*TICRATE)
|
||||
return;
|
||||
|
||||
/*if (!S_IdPlaying(sfx_s3kd4s)) // global ambience
|
||||
S_StartSoundAtVolume(NULL, sfx_s3kd4s, min(255, ((4096*mapobjectscale) - battleovertime.radius)>>FRACBITS / 2));*/
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
j = 0;
|
||||
while (j < 32) // max attempts
|
||||
{
|
||||
fixed_t x = battleovertime.x + ((P_RandomRange(-64,64) * 128)<<FRACBITS);
|
||||
fixed_t y = battleovertime.y + ((P_RandomRange(-64,64) * 128)<<FRACBITS);
|
||||
fixed_t closestdist = battleovertime.radius + (8*mobjinfo[MT_OVERTIMEFOG].radius);
|
||||
j++;
|
||||
if (P_AproxDistance(x-battleovertime.x, y-battleovertime.y) < closestdist)
|
||||
continue;
|
||||
K_SpawnOvertimeParticles(x, y, 4*mapobjectscale, MT_OVERTIMEFOG, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void K_SetupMovingCapsule(mapthing_t *mt, mobj_t *mobj)
|
||||
{
|
||||
UINT8 sequence = mt->extrainfo-1;
|
||||
fixed_t speed = (FRACUNIT >> 3) * mt->angle;
|
||||
boolean backandforth = (mt->options & MTF_AMBUSH);
|
||||
boolean reverse = (mt->options & MTF_OBJECTSPECIAL);
|
||||
mobj_t *mo2;
|
||||
mobj_t *target = NULL;
|
||||
thinker_t *th;
|
||||
|
||||
// Find the inital target
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
|
||||
if (mo2->type != MT_TUBEWAYPOINT)
|
||||
continue;
|
||||
|
||||
if (mo2->threshold == sequence)
|
||||
{
|
||||
if (reverse) // Use the highest waypoint number as first
|
||||
{
|
||||
if (mo2->health != 0)
|
||||
{
|
||||
if (target == NULL)
|
||||
target = mo2;
|
||||
else if (mo2->health > target->health)
|
||||
target = mo2;
|
||||
}
|
||||
}
|
||||
else // Use the lowest waypoint number as first
|
||||
{
|
||||
if (mo2->health == 0)
|
||||
target = mo2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!target)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, "No target waypoint found for moving capsule (seq: #%d)\n", sequence);
|
||||
return;
|
||||
}
|
||||
|
||||
P_SetTarget(&mobj->target, target);
|
||||
mobj->lastlook = sequence;
|
||||
mobj->movecount = target->health;
|
||||
mobj->movefactor = speed;
|
||||
|
||||
if (backandforth) {
|
||||
mobj->flags2 |= MF2_AMBUSH;
|
||||
} else {
|
||||
mobj->flags2 &= ~MF2_AMBUSH;
|
||||
}
|
||||
|
||||
if (reverse) {
|
||||
mobj->cvmem = -1;
|
||||
} else {
|
||||
mobj->cvmem = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void K_SpawnBattleCapsules(void)
|
||||
{
|
||||
mapthing_t *mt;
|
||||
size_t i;
|
||||
|
||||
if (battlecapsules)
|
||||
return;
|
||||
|
||||
if (!G_BattleGametype())
|
||||
return;
|
||||
|
||||
if (modeattacking != ATTACKING_CAPSULES)
|
||||
{
|
||||
UINT8 n = 0;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i] && !players[i].spectator)
|
||||
n++;
|
||||
if (players[i].exiting)
|
||||
return;
|
||||
if (n > 1)
|
||||
break;
|
||||
}
|
||||
|
||||
if (n > 1)
|
||||
return;
|
||||
}
|
||||
|
||||
mt = mapthings;
|
||||
for (i = 0; i < nummapthings; i++, mt++)
|
||||
{
|
||||
if (mt->type == mobjinfo[MT_BATTLECAPSULE].doomednum)
|
||||
{
|
||||
sector_t *mtsector, *sec;
|
||||
fixed_t x, y, z;
|
||||
fixed_t floorheights[MAXFFLOORS+1];
|
||||
UINT8 numfloors = 1;
|
||||
mobj_t *mobj = NULL;
|
||||
boolean fly = true;
|
||||
UINT8 j;
|
||||
|
||||
mt->mobj = NULL;
|
||||
|
||||
mtsector = R_PointInSubsector(mt->x << FRACBITS, mt->y << FRACBITS)->sector;
|
||||
mt->z = (INT16)(
|
||||
#ifdef ESLOPE
|
||||
mtsector->f_slope ? P_GetZAt(mtsector->f_slope, mt->x << FRACBITS, mt->y << FRACBITS) :
|
||||
#endif
|
||||
mtsector->floorheight)>>FRACBITS;
|
||||
|
||||
x = mt->x << FRACBITS;
|
||||
y = mt->y << FRACBITS;
|
||||
|
||||
sec = R_PointInSubsector(x, y)->sector;
|
||||
|
||||
if (mt->options & MTF_OBJECTFLIP)
|
||||
{
|
||||
z = (
|
||||
#ifdef ESLOPE
|
||||
sec->c_slope ? P_GetZAt(sec->c_slope, x, y) :
|
||||
#endif
|
||||
sec->ceilingheight) - mobjinfo[MT_BATTLECAPSULE].height;
|
||||
|
||||
floorheights[0] = z;
|
||||
|
||||
if (mt->options >> ZSHIFT)
|
||||
z -= ((mt->options >> ZSHIFT) << FRACBITS);
|
||||
}
|
||||
else
|
||||
{
|
||||
z =
|
||||
#ifdef ESLOPE
|
||||
sec->f_slope ? P_GetZAt(sec->f_slope, x, y) :
|
||||
#endif
|
||||
sec->floorheight;
|
||||
|
||||
floorheights[0] = z;
|
||||
|
||||
if (mt->options >> ZSHIFT)
|
||||
z += ((mt->options >> ZSHIFT) << FRACBITS);
|
||||
}
|
||||
|
||||
|
||||
if (sec->ffloors)
|
||||
{
|
||||
ffloor_t *rover;
|
||||
for (rover = sec->ffloors; rover; rover = rover->next)
|
||||
{
|
||||
if ((rover->flags & FF_EXISTS) && (rover->flags & FF_BLOCKOTHERS))
|
||||
{
|
||||
if (mt->options & MTF_OBJECTFLIP)
|
||||
{
|
||||
floorheights[numfloors] = (
|
||||
#ifdef ESLOPE
|
||||
*rover->b_slope ? P_GetZAt(*rover->b_slope, x, y) :
|
||||
#endif
|
||||
*rover->bottomheight) - mobjinfo[MT_BATTLECAPSULE].height;
|
||||
}
|
||||
else
|
||||
{
|
||||
floorheights[numfloors] = (
|
||||
#ifdef ESLOPE
|
||||
*rover->t_slope ? P_GetZAt(*rover->t_slope, x, y) :
|
||||
#endif
|
||||
*rover->topheight);
|
||||
}
|
||||
|
||||
numfloors++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mt->z = (INT16)(z>>FRACBITS);
|
||||
|
||||
mobj = P_SpawnMobj(x, y, z, MT_BATTLECAPSULE);
|
||||
mobj->spawnpoint = mt;
|
||||
|
||||
if (mt->options & MTF_OBJECTFLIP)
|
||||
{
|
||||
mobj->eflags |= MFE_VERTICALFLIP;
|
||||
mobj->flags2 |= MF2_OBJECTFLIP;
|
||||
}
|
||||
|
||||
for (j = 0; j < numfloors; j++)
|
||||
{
|
||||
if (z == floorheights[j])
|
||||
{
|
||||
fly = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Flying capsules
|
||||
if (fly)
|
||||
{
|
||||
mobj->flags |= MF_NOGRAVITY;
|
||||
mobj->extravalue1 = 1; // Set extravalue1 for later reference
|
||||
}
|
||||
|
||||
// Moving capsules!
|
||||
if (mt->extrainfo && mt->angle)
|
||||
K_SetupMovingCapsule(mt, mobj);
|
||||
|
||||
// Moved from P_SpawnMobj due to order of operations mumbo jumbo
|
||||
{
|
||||
mobj_t *cur, *prev = mobj;
|
||||
|
||||
// Init hnext list
|
||||
// Spherical top
|
||||
cur = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_BATTLECAPSULE_PIECE);
|
||||
P_SetMobjState(cur, S_BATTLECAPSULE_TOP);
|
||||
|
||||
P_SetTarget(&cur->target, mobj);
|
||||
P_SetTarget(&cur->hprev, prev);
|
||||
P_SetTarget(&prev->hnext, cur);
|
||||
prev = cur;
|
||||
|
||||
// Tippity-top decorational button
|
||||
cur = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_BATTLECAPSULE_PIECE);
|
||||
P_SetMobjState(cur, S_BATTLECAPSULE_BUTTON);
|
||||
|
||||
P_SetTarget(&cur->target, mobj);
|
||||
P_SetTarget(&cur->hprev, prev);
|
||||
P_SetTarget(&prev->hnext, cur);
|
||||
prev = cur;
|
||||
|
||||
// Supports on the bottom
|
||||
for (j = 0; j < 4; j++)
|
||||
{
|
||||
cur = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_BATTLECAPSULE_PIECE);
|
||||
cur->extravalue1 = j;
|
||||
|
||||
if (mobj->extravalue1) // Flying capsule, moving or not
|
||||
P_SetMobjState(cur, S_BATTLECAPSULE_SUPPORTFLY);
|
||||
else if (mobj->target && !P_MobjWasRemoved(mobj->target)) // Grounded, moving capsule
|
||||
P_SetMobjState(cur, S_KARMAWHEEL);
|
||||
else
|
||||
P_SetMobjState(cur, S_BATTLECAPSULE_SUPPORT); // Grounded, stationary capsule
|
||||
|
||||
P_SetTarget(&cur->target, mobj);
|
||||
P_SetTarget(&cur->hprev, prev);
|
||||
P_SetTarget(&prev->hnext, cur);
|
||||
prev = cur;
|
||||
}
|
||||
|
||||
// Side paneling
|
||||
for (j = 0; j < 8; j++)
|
||||
{
|
||||
cur = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_BATTLECAPSULE_PIECE);
|
||||
cur->extravalue1 = j;
|
||||
|
||||
if (j & 1)
|
||||
P_SetMobjState(cur, S_BATTLECAPSULE_SIDE2);
|
||||
else
|
||||
P_SetMobjState(cur, S_BATTLECAPSULE_SIDE1);
|
||||
|
||||
P_SetTarget(&cur->target, mobj);
|
||||
P_SetTarget(&cur->hprev, prev);
|
||||
P_SetTarget(&prev->hnext, cur);
|
||||
prev = cur;
|
||||
}
|
||||
}
|
||||
|
||||
mt->mobj = mobj;
|
||||
}
|
||||
}
|
||||
|
||||
battlecapsules = true;
|
||||
}
|
||||
26
src/k_battle.h
Normal file
26
src/k_battle.h
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
#ifndef __K_BATTLE__
|
||||
#define __K_BATTLE__
|
||||
|
||||
#include "doomtype.h"
|
||||
#include "d_player.h"
|
||||
|
||||
extern struct battleovertime
|
||||
{
|
||||
UINT16 enabled; ///< Has this been initalized yet?
|
||||
fixed_t radius, minradius; ///< Radius of kill field
|
||||
fixed_t x, y, z; ///< Position to center on
|
||||
} battleovertime;
|
||||
|
||||
extern boolean battlecapsules;
|
||||
extern INT32 nummapboxes, numgotboxes; // keep track of spawned battle mode items
|
||||
extern UINT8 maptargets, numtargets;
|
||||
|
||||
INT32 K_StartingBumperCount(void);
|
||||
boolean K_IsPlayerWanted(player_t *player);
|
||||
void K_CalculateBattleWanted(void);
|
||||
void K_SpawnBattlePoints(player_t *source, player_t *victim, UINT8 amount);
|
||||
void K_CheckBumpers(void);
|
||||
void K_RunBattleOvertime(void);
|
||||
void K_SpawnBattleCapsules(void);
|
||||
|
||||
#endif
|
||||
319
src/k_collide.c
Normal file
319
src/k_collide.c
Normal file
|
|
@ -0,0 +1,319 @@
|
|||
/// \file k_collide.c
|
||||
/// \brief SRB2Kart item collision hooks
|
||||
|
||||
#include "k_collide.h"
|
||||
#include "doomtype.h"
|
||||
#include "p_mobj.h"
|
||||
#include "k_kart.h"
|
||||
#include "p_local.h"
|
||||
#include "s_sound.h"
|
||||
#include "r_main.h" // R_PointToAngle2, R_PointToDist2
|
||||
#include "hu_stuff.h" // Sink snipe print
|
||||
#include "doomdef.h" // Sink snipe print
|
||||
#include "g_game.h" // Sink snipe print
|
||||
|
||||
boolean K_OrbinautJawzCollide(mobj_t *t1, mobj_t *t2)
|
||||
{
|
||||
boolean damageitem = false;
|
||||
|
||||
if (((t1->target == t2) || (t1->target == t2->target)) && (t1->threshold > 0 || (t2->type != MT_PLAYER && t2->threshold > 0)))
|
||||
return true;
|
||||
|
||||
if (t1->health <= 0 || t2->health <= 0)
|
||||
return true;
|
||||
|
||||
if ((t1->type == MT_ORBINAUT_SHIELD || t1->type == MT_JAWZ_SHIELD) && t1->lastlook
|
||||
&& (t2->type == MT_ORBINAUT_SHIELD || t2->type == MT_JAWZ_SHIELD) && t2->lastlook
|
||||
&& (t1->target == t2->target)) // Don't hit each other if you have the same target
|
||||
return true;
|
||||
|
||||
if (t2->player)
|
||||
{
|
||||
if (t2->player->powers[pw_flashing]
|
||||
&& !(t1->type == MT_ORBINAUT || t1->type == MT_JAWZ || t1->type == MT_JAWZ_DUD))
|
||||
return true;
|
||||
|
||||
if (t2->player->kartstuff[k_hyudorotimer])
|
||||
return true; // no interaction
|
||||
|
||||
// Player Damage
|
||||
P_DamageMobj(t2, t1, t1->target, 1);
|
||||
K_KartBouncing(t2, t1, false, false);
|
||||
S_StartSound(t2, sfx_s3k7b);
|
||||
|
||||
damageitem = true;
|
||||
}
|
||||
else if (t2->type == MT_ORBINAUT || t2->type == MT_JAWZ || t2->type == MT_JAWZ_DUD
|
||||
|| t2->type == MT_ORBINAUT_SHIELD || t2->type == MT_JAWZ_SHIELD
|
||||
|| t2->type == MT_BANANA || t2->type == MT_BANANA_SHIELD
|
||||
|| t2->type == MT_BALLHOG)
|
||||
{
|
||||
// Other Item Damage
|
||||
if (t2->eflags & MFE_VERTICALFLIP)
|
||||
t2->z -= t2->height;
|
||||
else
|
||||
t2->z += t2->height;
|
||||
|
||||
S_StartSound(t2, t2->info->deathsound);
|
||||
P_KillMobj(t2, t1, t1);
|
||||
|
||||
P_SetObjectMomZ(t2, 8*FRACUNIT, false);
|
||||
P_InstaThrust(t2, R_PointToAngle2(t1->x, t1->y, t2->x, t2->y)+ANGLE_90, 16*FRACUNIT);
|
||||
|
||||
P_SpawnMobj(t2->x/2 + t1->x/2, t2->y/2 + t1->y/2, t2->z/2 + t1->z/2, MT_ITEMCLASH);
|
||||
|
||||
damageitem = true;
|
||||
}
|
||||
else if (t2->type == MT_SSMINE_SHIELD || t2->type == MT_SSMINE)
|
||||
{
|
||||
damageitem = true;
|
||||
// Bomb death
|
||||
P_KillMobj(t2, t1, t1);
|
||||
}
|
||||
else if (t2->flags & MF_SPRING && (t1->type != MT_ORBINAUT_SHIELD && t1->type != MT_JAWZ_SHIELD))
|
||||
{
|
||||
// Let thrown items hit springs!
|
||||
P_DoSpring(t2, t1);
|
||||
}
|
||||
else if (t2->flags & MF_SHOOTABLE)
|
||||
{
|
||||
// Shootable damage
|
||||
P_DamageMobj(t2, t2, t1->target, 1);
|
||||
damageitem = true;
|
||||
}
|
||||
|
||||
if (damageitem)
|
||||
{
|
||||
// This Item Damage
|
||||
if (t1->eflags & MFE_VERTICALFLIP)
|
||||
t1->z -= t1->height;
|
||||
else
|
||||
t1->z += t1->height;
|
||||
|
||||
S_StartSound(t1, t1->info->deathsound);
|
||||
P_KillMobj(t1, t2, t2);
|
||||
|
||||
P_SetObjectMomZ(t1, 8*FRACUNIT, false);
|
||||
P_InstaThrust(t1, R_PointToAngle2(t2->x, t2->y, t1->x, t1->y)+ANGLE_90, 16*FRACUNIT);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean K_BananaBallhogCollide(mobj_t *t1, mobj_t *t2)
|
||||
{
|
||||
boolean damageitem = false;
|
||||
|
||||
if (((t1->target == t2) || (t1->target == t2->target)) && (t1->threshold > 0 || (t2->type != MT_PLAYER && t2->threshold > 0)))
|
||||
return true;
|
||||
|
||||
if (t1->health <= 0 || t2->health <= 0)
|
||||
return true;
|
||||
|
||||
if (((t1->type == MT_BANANA_SHIELD) && (t2->type == MT_BANANA_SHIELD))
|
||||
&& (t1->target == t2->target)) // Don't hit each other if you have the same target
|
||||
return true;
|
||||
|
||||
if (t1->type == MT_BALLHOG && t2->type == MT_BALLHOG)
|
||||
return true; // Ballhogs don't collide with eachother
|
||||
|
||||
if (t2->player)
|
||||
{
|
||||
if (t2->player->powers[pw_flashing])
|
||||
return true;
|
||||
|
||||
// Banana snipe!
|
||||
if (t1->type == MT_BANANA && t1->health > 1)
|
||||
S_StartSound(t2, sfx_bsnipe);
|
||||
|
||||
// Player Damage
|
||||
K_SpinPlayer(t2->player, t1->target, 0, t1, (t1->type == MT_BANANA || t1->type == MT_BANANA_SHIELD));
|
||||
|
||||
damageitem = true;
|
||||
}
|
||||
else if (t2->type == MT_BANANA || t2->type == MT_BANANA_SHIELD
|
||||
|| t2->type == MT_ORBINAUT || t2->type == MT_ORBINAUT_SHIELD
|
||||
|| t2->type == MT_JAWZ || t2->type == MT_JAWZ_DUD || t2->type == MT_JAWZ_SHIELD
|
||||
|| t2->type == MT_BALLHOG)
|
||||
{
|
||||
// Other Item Damage
|
||||
if (t2->eflags & MFE_VERTICALFLIP)
|
||||
t2->z -= t2->height;
|
||||
else
|
||||
t2->z += t2->height;
|
||||
|
||||
S_StartSound(t2, t2->info->deathsound);
|
||||
P_KillMobj(t2, t1, t1);
|
||||
|
||||
P_SetObjectMomZ(t2, 8*FRACUNIT, false);
|
||||
P_InstaThrust(t2, R_PointToAngle2(t1->x, t1->y, t2->x, t2->y)+ANGLE_90, 16*FRACUNIT);
|
||||
|
||||
P_SpawnMobj(t2->x/2 + t1->x/2, t2->y/2 + t1->y/2, t2->z/2 + t1->z/2, MT_ITEMCLASH);
|
||||
|
||||
damageitem = true;
|
||||
}
|
||||
else if (t2->flags & MF_SHOOTABLE)
|
||||
{
|
||||
// Shootable damage
|
||||
P_DamageMobj(t2, t2, t1->target, 1);
|
||||
damageitem = true;
|
||||
}
|
||||
|
||||
if (damageitem)
|
||||
{
|
||||
// This Item Damage
|
||||
if (t1->eflags & MFE_VERTICALFLIP)
|
||||
t1->z -= t1->height;
|
||||
else
|
||||
t1->z += t1->height;
|
||||
|
||||
S_StartSound(t1, t1->info->deathsound);
|
||||
P_KillMobj(t1, t2, t2);
|
||||
|
||||
P_SetObjectMomZ(t1, 8*FRACUNIT, false);
|
||||
P_InstaThrust(t1, R_PointToAngle2(t2->x, t2->y, t1->x, t1->y)+ANGLE_90, 16*FRACUNIT);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean K_EggItemCollide(mobj_t *t1, mobj_t *t2)
|
||||
{
|
||||
// Push fakes out of other item boxes
|
||||
if (t2->type == MT_RANDOMITEM || t2->type == MT_EGGMANITEM)
|
||||
P_InstaThrust(t1, R_PointToAngle2(t2->x, t2->y, t1->x, t1->y), t2->radius/4);
|
||||
|
||||
// Player collision is handled by TouchSpecial
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean K_MineCollide(mobj_t *t1, mobj_t *t2)
|
||||
{
|
||||
if (((t1->target == t2) || (t1->target == t2->target)) && (t1->threshold > 0 || (t2->type != MT_PLAYER && t2->threshold > 0)))
|
||||
return true;
|
||||
|
||||
if (t1->health <= 0 || t2->health <= 0)
|
||||
return true;
|
||||
|
||||
if (t2->player)
|
||||
{
|
||||
if (t2->player->powers[pw_flashing])
|
||||
return true;
|
||||
|
||||
// Bomb punting
|
||||
if ((t1->state >= &states[S_SSMINE1] && t1->state <= &states[S_SSMINE4])
|
||||
|| (t1->state >= &states[S_SSMINE_DEPLOY8] && t1->state <= &states[S_SSMINE_DEPLOY13]))
|
||||
P_KillMobj(t1, t2, t2);
|
||||
else
|
||||
K_PuntMine(t1, t2);
|
||||
}
|
||||
else if (t2->type == MT_ORBINAUT || t2->type == MT_JAWZ || t2->type == MT_JAWZ_DUD
|
||||
|| t2->type == MT_ORBINAUT_SHIELD || t2->type == MT_JAWZ_SHIELD)
|
||||
{
|
||||
// Bomb death
|
||||
P_KillMobj(t1, t2, t2);
|
||||
|
||||
// Other Item Damage
|
||||
if (t2->eflags & MFE_VERTICALFLIP)
|
||||
t2->z -= t2->height;
|
||||
else
|
||||
t2->z += t2->height;
|
||||
|
||||
S_StartSound(t2, t2->info->deathsound);
|
||||
P_KillMobj(t2, t1, t1);
|
||||
|
||||
P_SetObjectMomZ(t2, 8*FRACUNIT, false);
|
||||
P_InstaThrust(t2, R_PointToAngle2(t1->x, t1->y, t2->x, t2->y)+ANGLE_90, 16*FRACUNIT);
|
||||
}
|
||||
else if (t2->flags & MF_SHOOTABLE)
|
||||
{
|
||||
// Bomb death
|
||||
P_KillMobj(t1, t2, t2);
|
||||
// Shootable damage
|
||||
P_DamageMobj(t2, t2, t1->target, 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean K_MineExplosionCollide(mobj_t *t1, mobj_t *t2)
|
||||
{
|
||||
if (t2->player)
|
||||
{
|
||||
if (t2->player->powers[pw_flashing])
|
||||
return true;
|
||||
|
||||
if (t1->state == &states[S_MINEEXPLOSION1])
|
||||
K_ExplodePlayer(t2->player, t1->target, t1);
|
||||
else
|
||||
K_SpinPlayer(t2->player, t1->target, 0, t1, false);
|
||||
}
|
||||
else if (t2->flags & MF_SHOOTABLE)
|
||||
{
|
||||
// Shootable damage
|
||||
P_DamageMobj(t2, t2, t1->target, 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean K_KitchenSinkCollide(mobj_t *t1, mobj_t *t2)
|
||||
{
|
||||
if (((t1->target == t2) || (t1->target == t2->target)) && (t1->threshold > 0 || (t2->type != MT_PLAYER && t2->threshold > 0)))
|
||||
return true;
|
||||
|
||||
if (t2->player)
|
||||
{
|
||||
if (t2->player->powers[pw_flashing])
|
||||
return true;
|
||||
|
||||
S_StartSound(NULL, sfx_bsnipe); // let all players hear it.
|
||||
HU_SetCEchoFlags(0);
|
||||
HU_SetCEchoDuration(5);
|
||||
HU_DoCEcho(va("%s\\was hit by a kitchen sink.\\\\\\\\", player_names[t2->player-players]));
|
||||
I_OutputMsg("%s was hit by a kitchen sink.\n", player_names[t2->player-players]);
|
||||
P_DamageMobj(t2, t1, t1->target, 10000);
|
||||
P_KillMobj(t1, t2, t2);
|
||||
}
|
||||
else if (t2->flags & MF_SHOOTABLE)
|
||||
{
|
||||
// Shootable damage
|
||||
P_KillMobj(t2, t2, t1->target);
|
||||
// This item damage
|
||||
P_KillMobj(t1, t2, t2);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean K_FallingRockCollide(mobj_t *t1, mobj_t *t2)
|
||||
{
|
||||
if (t2->player || t2->type == MT_FALLINGROCK)
|
||||
K_KartBouncing(t2, t1, false, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean K_SMKIceBlockCollide(mobj_t *t1, mobj_t *t2)
|
||||
{
|
||||
if (!(t2->flags & MF_SOLID || t2->flags & MF_SHOOTABLE || t2->flags & MF_BOUNCE))
|
||||
return true;
|
||||
|
||||
if (!(t2->health))
|
||||
return true;
|
||||
|
||||
if (t2->type == MT_BANANA || t2->type == MT_BANANA_SHIELD
|
||||
|| t2->type == MT_EGGMANITEM || t2->type == MT_EGGMANITEM_SHIELD
|
||||
|| t2->type == MT_SSMINE || t2->type == MT_SSMINE_SHIELD
|
||||
|| t2->type == MT_ORBINAUT_SHIELD || t2->type == MT_JAWZ_SHIELD)
|
||||
return false;
|
||||
|
||||
if (t1->health)
|
||||
P_KillMobj(t1, t2, t2);
|
||||
|
||||
/*if (t2->player && (t2->player->kartstuff[k_invincibilitytimer] > 0
|
||||
|| t2->player->kartstuff[k_growshrinktimer] > 0))
|
||||
return true;*/
|
||||
|
||||
K_KartBouncing(t2, t1, false, true);
|
||||
return false;
|
||||
}
|
||||
16
src/k_collide.h
Normal file
16
src/k_collide.h
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
#ifndef __K_COLLIDE__
|
||||
#define __K_COLLIDE__
|
||||
|
||||
#include "doomtype.h"
|
||||
#include "p_mobj.h"
|
||||
|
||||
boolean K_OrbinautJawzCollide(mobj_t *t1, mobj_t *t2);
|
||||
boolean K_BananaBallhogCollide(mobj_t *t1, mobj_t *t2);
|
||||
boolean K_EggItemCollide(mobj_t *t1, mobj_t *t2);
|
||||
boolean K_MineCollide(mobj_t *t1, mobj_t *t2);
|
||||
boolean K_MineExplosionCollide(mobj_t *t1, mobj_t *t2);
|
||||
boolean K_KitchenSinkCollide(mobj_t *t1, mobj_t *t2);
|
||||
boolean K_FallingRockCollide(mobj_t *t1, mobj_t *t2);
|
||||
boolean K_SMKIceBlockCollide(mobj_t *t1, mobj_t *t2);
|
||||
|
||||
#endif
|
||||
335
src/k_kart.c
335
src/k_kart.c
|
|
@ -5,6 +5,7 @@
|
|||
/// All of the SRB2kart-unique stuff.
|
||||
|
||||
#include "k_kart.h"
|
||||
#include "k_battle.h"
|
||||
#include "k_pwrlv.h"
|
||||
#include "doomdef.h"
|
||||
#include "hu_stuff.h"
|
||||
|
|
@ -604,6 +605,9 @@ boolean K_IsPlayerLosing(player_t *player)
|
|||
INT32 winningpos = 1;
|
||||
UINT8 i, pcount = 0;
|
||||
|
||||
if (battlecapsules && player->kartstuff[k_bumper] <= 0)
|
||||
return true; // DNF in break the capsules
|
||||
|
||||
if (player->kartstuff[k_position] == 1)
|
||||
return false;
|
||||
|
||||
|
|
@ -625,21 +629,6 @@ boolean K_IsPlayerLosing(player_t *player)
|
|||
return (player->kartstuff[k_position] > winningpos);
|
||||
}
|
||||
|
||||
boolean K_IsPlayerWanted(player_t *player)
|
||||
{
|
||||
UINT8 i;
|
||||
if (!(G_BattleGametype()))
|
||||
return false;
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
if (battlewanted[i] == -1)
|
||||
break;
|
||||
if (player == &players[battlewanted[i]])
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
fixed_t K_GetKartGameSpeedScalar(SINT8 value)
|
||||
{
|
||||
// Easy = 81.25%
|
||||
|
|
@ -1179,8 +1168,8 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (modeattacking || cv_orbinaut.value) // Waited patiently? You get an orbinaut!
|
||||
K_KartGetItemResult(player, KITEM_ORBINAUT);
|
||||
if (modeattacking || cv_tripleorbinaut.value) // Waited patiently? You get Orbinaut x3!
|
||||
K_KartGetItemResult(player, KRITEM_TRIPLEORBINAUT);
|
||||
else // Default to sad if nothing's enabled...
|
||||
K_KartGetItemResult(player, KITEM_SAD);
|
||||
player->karthud[khud_itemblinkmode] = 0;
|
||||
|
|
@ -2630,32 +2619,6 @@ void K_DoInstashield(player_t *player)
|
|||
P_SetTarget(&layerb->target, player->mo);
|
||||
}
|
||||
|
||||
void K_SpawnBattlePoints(player_t *source, player_t *victim, UINT8 amount)
|
||||
{
|
||||
statenum_t st;
|
||||
mobj_t *pt;
|
||||
|
||||
if (!source || !source->mo)
|
||||
return;
|
||||
|
||||
if (amount == 1)
|
||||
st = S_BATTLEPOINT1A;
|
||||
else if (amount == 2)
|
||||
st = S_BATTLEPOINT2A;
|
||||
else if (amount == 3)
|
||||
st = S_BATTLEPOINT3A;
|
||||
else
|
||||
return; // NO STATE!
|
||||
|
||||
pt = P_SpawnMobj(source->mo->x, source->mo->y, source->mo->z, MT_BATTLEPOINT);
|
||||
P_SetTarget(&pt->target, source->mo);
|
||||
P_SetMobjState(pt, st);
|
||||
if (victim && victim->skincolor)
|
||||
pt->color = victim->skincolor;
|
||||
else
|
||||
pt->color = source->skincolor;
|
||||
}
|
||||
|
||||
void K_SpinPlayer(player_t *player, mobj_t *source, INT32 type, mobj_t *inflictor, boolean trapitem)
|
||||
{
|
||||
UINT8 scoremultiply = 1;
|
||||
|
|
@ -3076,7 +3039,7 @@ void K_StealBumper(player_t *player, player_t *victim, boolean force)
|
|||
|
||||
if (!force)
|
||||
{
|
||||
if (victim->kartstuff[k_bumper] <= 0) // || player->kartstuff[k_bumper] >= cv_kartbumpers.value+2
|
||||
if (victim->kartstuff[k_bumper] <= 0) // || player->kartstuff[k_bumper] >= K_StartingBumperCount()+2
|
||||
return;
|
||||
|
||||
if (player->kartstuff[k_squishedtimer] > 0 || player->kartstuff[k_spinouttimer] > 0)
|
||||
|
|
@ -7665,181 +7628,6 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
|
|||
}
|
||||
}
|
||||
|
||||
void K_CalculateBattleWanted(void)
|
||||
{
|
||||
UINT8 numingame = 0, numplaying = 0, numwanted = 0;
|
||||
SINT8 bestbumperplayer = -1, bestbumper = -1;
|
||||
SINT8 camppos[MAXPLAYERS]; // who is the biggest camper
|
||||
UINT8 ties = 0, nextcamppos = 0;
|
||||
boolean setbumper = false;
|
||||
UINT8 i, j;
|
||||
|
||||
if (!G_BattleGametype())
|
||||
{
|
||||
for (i = 0; i < 4; i++)
|
||||
battlewanted[i] = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
wantedcalcdelay = wantedfrequency;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
camppos[i] = -1; // initialize
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
UINT8 position = 1;
|
||||
|
||||
if (!playeringame[i] || players[i].spectator) // Not playing
|
||||
continue;
|
||||
|
||||
if (players[i].exiting) // We're done, don't calculate.
|
||||
return;
|
||||
|
||||
numplaying++;
|
||||
|
||||
if (players[i].kartstuff[k_bumper] <= 0) // Not alive, so don't do anything else
|
||||
continue;
|
||||
|
||||
numingame++;
|
||||
|
||||
if (bestbumper == -1 || players[i].kartstuff[k_bumper] > bestbumper)
|
||||
{
|
||||
bestbumper = players[i].kartstuff[k_bumper];
|
||||
bestbumperplayer = i;
|
||||
}
|
||||
else if (players[i].kartstuff[k_bumper] == bestbumper)
|
||||
bestbumperplayer = -1; // Tie, no one has best bumper.
|
||||
|
||||
for (j = 0; j < MAXPLAYERS; j++)
|
||||
{
|
||||
if (!playeringame[j] || players[j].spectator)
|
||||
continue;
|
||||
if (players[j].kartstuff[k_bumper] <= 0)
|
||||
continue;
|
||||
if (j == i)
|
||||
continue;
|
||||
if (players[j].kartstuff[k_wanted] == players[i].kartstuff[k_wanted] && players[j].marescore > players[i].marescore)
|
||||
position++;
|
||||
else if (players[j].kartstuff[k_wanted] > players[i].kartstuff[k_wanted])
|
||||
position++;
|
||||
}
|
||||
|
||||
position--; // Make zero based
|
||||
|
||||
while (camppos[position] != -1) // Port priority!
|
||||
position++;
|
||||
|
||||
camppos[position] = i;
|
||||
}
|
||||
|
||||
if (numplaying <= 2 || (numingame <= 2 && bestbumper == 1)) // In 1v1s then there's no need for WANTED. In bigger netgames, don't show anyone as WANTED when they're equally matched.
|
||||
numwanted = 0;
|
||||
else
|
||||
numwanted = min(4, 1 + ((numingame-2) / 4));
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
if (i+1 > numwanted) // Not enough players for this slot to be wanted!
|
||||
battlewanted[i] = -1;
|
||||
else if (bestbumperplayer != -1 && !setbumper) // If there's a player who has an untied bumper lead over everyone else, they are the first to be wanted.
|
||||
{
|
||||
battlewanted[i] = bestbumperplayer;
|
||||
setbumper = true; // Don't set twice
|
||||
}
|
||||
else
|
||||
{
|
||||
// Don't accidentally set the same player, if the bestbumperplayer is also a huge camper.
|
||||
while (bestbumperplayer != -1 && camppos[nextcamppos] != -1
|
||||
&& bestbumperplayer == camppos[nextcamppos])
|
||||
nextcamppos++;
|
||||
|
||||
// Do not add *any* more people if there's too many times that are tied with others.
|
||||
// This could theoretically happen very easily if people don't hit each other for a while after the start of a match.
|
||||
// (I will be sincerely impressed if more than 2 people tie after people start hitting each other though)
|
||||
|
||||
if (camppos[nextcamppos] == -1 // Out of entries
|
||||
|| ties >= (numwanted-i)) // Already counted ties
|
||||
{
|
||||
battlewanted[i] = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ties < (numwanted-i))
|
||||
{
|
||||
ties = 0; // Reset
|
||||
for (j = 0; j < 2; j++)
|
||||
{
|
||||
if (camppos[nextcamppos+(j+1)] == -1) // Nothing beyond, cancel
|
||||
break;
|
||||
if (players[camppos[nextcamppos]].kartstuff[k_wanted] == players[camppos[nextcamppos+(j+1)]].kartstuff[k_wanted])
|
||||
ties++;
|
||||
}
|
||||
}
|
||||
|
||||
if (ties < (numwanted-i)) // Is it still low enough after counting?
|
||||
{
|
||||
battlewanted[i] = camppos[nextcamppos];
|
||||
nextcamppos++;
|
||||
}
|
||||
else
|
||||
battlewanted[i] = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void K_CheckBumpers(void)
|
||||
{
|
||||
UINT8 i;
|
||||
UINT8 numingame = 0;
|
||||
SINT8 winnernum = -1;
|
||||
INT32 winnerscoreadd = 0;
|
||||
|
||||
if (!multiplayer)
|
||||
return;
|
||||
|
||||
if (!G_BattleGametype())
|
||||
return;
|
||||
|
||||
if (gameaction == ga_completed)
|
||||
return;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i] || players[i].spectator) // not even in-game
|
||||
continue;
|
||||
|
||||
if (players[i].exiting) // we're already exiting! stop!
|
||||
return;
|
||||
|
||||
numingame++;
|
||||
winnerscoreadd += players[i].marescore;
|
||||
|
||||
if (players[i].kartstuff[k_bumper] <= 0) // if you don't have any bumpers, you're probably not a winner
|
||||
continue;
|
||||
else if (winnernum > -1) // TWO winners? that's dumb :V
|
||||
return;
|
||||
|
||||
winnernum = i;
|
||||
winnerscoreadd -= players[i].marescore;
|
||||
}
|
||||
|
||||
if (numingame <= 1)
|
||||
return;
|
||||
|
||||
if (winnernum > -1 && playeringame[winnernum])
|
||||
{
|
||||
players[winnernum].marescore += winnerscoreadd;
|
||||
CONS_Printf(M_GetText("%s recieved %d point%s for winning!\n"), player_names[winnernum], winnerscoreadd, (winnerscoreadd == 1 ? "" : "s"));
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++) // This can't go in the earlier loop because winning adds points
|
||||
K_KartUpdatePosition(&players[i]);
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++) // and it can't be merged with this loop because it needs to be all updated before exiting... multi-loops suck...
|
||||
P_DoPlayerExit(&players[i]);
|
||||
}
|
||||
|
||||
void K_CheckSpectateStatus(void)
|
||||
{
|
||||
UINT8 respawnlist[MAXPLAYERS];
|
||||
|
|
@ -7953,6 +7741,8 @@ static patch_t *kp_lapstickernarrow;
|
|||
static patch_t *kp_splitlapflag;
|
||||
static patch_t *kp_bumpersticker;
|
||||
static patch_t *kp_bumperstickerwide;
|
||||
static patch_t *kp_capsulesticker;
|
||||
static patch_t *kp_capsulestickerwide;
|
||||
static patch_t *kp_karmasticker;
|
||||
static patch_t *kp_splitkarmabomb;
|
||||
static patch_t *kp_timeoutsticker;
|
||||
|
|
@ -7983,6 +7773,7 @@ static patch_t *kp_speedometerlabel[4];
|
|||
static patch_t *kp_rankbumper;
|
||||
static patch_t *kp_tinybumper[2];
|
||||
static patch_t *kp_ranknobumpers;
|
||||
static patch_t *kp_rankcapsule;
|
||||
|
||||
static patch_t *kp_battlewin;
|
||||
static patch_t *kp_battlecool;
|
||||
|
|
@ -8055,6 +7846,8 @@ void K_LoadKartHUDGraphics(void)
|
|||
kp_splitlapflag = W_CachePatchName("K_SPTLAP", PU_HUDGFX);
|
||||
kp_bumpersticker = W_CachePatchName("K_STBALN", PU_HUDGFX);
|
||||
kp_bumperstickerwide = W_CachePatchName("K_STBALW", PU_HUDGFX);
|
||||
kp_capsulesticker = W_CachePatchName("K_STCAPN", PU_HUDGFX);
|
||||
kp_capsulestickerwide = W_CachePatchName("K_STCAPW", PU_HUDGFX);
|
||||
kp_karmasticker = W_CachePatchName("K_STKARM", PU_HUDGFX);
|
||||
kp_splitkarmabomb = W_CachePatchName("K_SPTKRM", PU_HUDGFX);
|
||||
kp_timeoutsticker = W_CachePatchName("K_STTOUT", PU_HUDGFX);
|
||||
|
|
@ -8181,6 +7974,7 @@ void K_LoadKartHUDGraphics(void)
|
|||
kp_tinybumper[0] = W_CachePatchName("K_BLNA", PU_HUDGFX);
|
||||
kp_tinybumper[1] = W_CachePatchName("K_BLNB", PU_HUDGFX);
|
||||
kp_ranknobumpers = W_CachePatchName("K_NOBLNS", PU_HUDGFX);
|
||||
kp_rankcapsule = W_CachePatchName("K_CAPICO", PU_HUDGFX);
|
||||
|
||||
// Battle graphics
|
||||
kp_battlewin = W_CachePatchName("K_BWIN", PU_HUDGFX);
|
||||
|
|
@ -9524,8 +9318,8 @@ static void K_drawKartLapsAndRings(void)
|
|||
if (cv_numlaps.value >= 10)
|
||||
{
|
||||
UINT8 ln[2];
|
||||
ln[0] = ((abs(stplyr->laps) / 10) % 10);
|
||||
ln[1] = (abs(stplyr->laps) % 10);
|
||||
ln[0] = ((stplyr->laps / 10) % 10);
|
||||
ln[1] = (stplyr->laps % 10);
|
||||
|
||||
V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|splitflags, pingnum[ln[0]]);
|
||||
V_DrawScaledPatch(fx+17, fy, V_HUDTRANS|splitflags, pingnum[ln[1]]);
|
||||
|
|
@ -9705,52 +9499,95 @@ static void K_drawKartBumpersOrKarma(void)
|
|||
V_DrawScaledPatch(fx-2 + (flipflag ? (SHORT(kp_ringstickersplit[1]->width) - 3) : 0), fy, V_HUDTRANS|splitflags|flipflag, kp_ringstickersplit[0]);
|
||||
V_DrawScaledPatch(fx+22, fy, V_HUDTRANS|splitflags, frameslash);
|
||||
|
||||
if (stplyr->kartstuff[k_bumper] <= 0)
|
||||
if (battlecapsules)
|
||||
{
|
||||
V_DrawMappedPatch(fx+1, fy-2, V_HUDTRANS|splitflags, kp_splitkarmabomb, colormap);
|
||||
V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|splitflags, kp_facenum[(stplyr->kartstuff[k_comebackpoints]) % 10]);
|
||||
V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|splitflags, kp_facenum[2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
V_DrawMappedPatch(fx+1, fy-2, V_HUDTRANS|splitflags, kp_rankbumper, colormap);
|
||||
V_DrawMappedPatch(fx+1, fy-2, V_HUDTRANS|splitflags, kp_rankcapsule, NULL);
|
||||
|
||||
if (stplyr->kartstuff[k_bumper] > 9 || cv_kartbumpers.value > 9)
|
||||
if (numtargets > 9 || maptargets > 9)
|
||||
{
|
||||
UINT8 ln[2];
|
||||
ln[0] = ((abs(stplyr->kartstuff[k_bumper]) / 10) % 10);
|
||||
ln[1] = (abs(stplyr->kartstuff[k_bumper]) % 10);
|
||||
ln[0] = ((numtargets / 10) % 10);
|
||||
ln[1] = (numtargets % 10);
|
||||
|
||||
V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|splitflags, pingnum[ln[0]]);
|
||||
V_DrawScaledPatch(fx+17, fy, V_HUDTRANS|splitflags, pingnum[ln[1]]);
|
||||
|
||||
ln[0] = ((abs(cv_kartbumpers.value) / 10) % 10);
|
||||
ln[1] = (abs(cv_kartbumpers.value) % 10);
|
||||
ln[0] = ((maptargets / 10) % 10);
|
||||
ln[1] = (maptargets % 10);
|
||||
|
||||
V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|splitflags, pingnum[ln[0]]);
|
||||
V_DrawScaledPatch(fx+31, fy, V_HUDTRANS|splitflags, pingnum[ln[1]]);
|
||||
}
|
||||
else
|
||||
{
|
||||
V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|splitflags, kp_facenum[(stplyr->kartstuff[k_bumper]) % 10]);
|
||||
V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|splitflags, kp_facenum[(cv_kartbumpers.value) % 10]);
|
||||
V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|splitflags, kp_facenum[numtargets % 10]);
|
||||
V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|splitflags, kp_facenum[maptargets % 10]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (stplyr->kartstuff[k_bumper] <= 0)
|
||||
{
|
||||
V_DrawMappedPatch(fx+1, fy-2, V_HUDTRANS|splitflags, kp_splitkarmabomb, colormap);
|
||||
V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|splitflags, kp_facenum[(stplyr->kartstuff[k_comebackpoints]) % 10]);
|
||||
V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|splitflags, kp_facenum[2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
INT32 maxbumper = K_StartingBumperCount();
|
||||
V_DrawMappedPatch(fx+1, fy-2, V_HUDTRANS|splitflags, kp_rankbumper, colormap);
|
||||
|
||||
if (stplyr->kartstuff[k_bumper] > 9 || maxbumper > 9)
|
||||
{
|
||||
UINT8 ln[2];
|
||||
ln[0] = ((abs(stplyr->kartstuff[k_bumper]) / 10) % 10);
|
||||
ln[1] = (abs(stplyr->kartstuff[k_bumper]) % 10);
|
||||
|
||||
V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|splitflags, pingnum[ln[0]]);
|
||||
V_DrawScaledPatch(fx+17, fy, V_HUDTRANS|splitflags, pingnum[ln[1]]);
|
||||
|
||||
ln[0] = ((abs(maxbumper) / 10) % 10);
|
||||
ln[1] = (abs(maxbumper) % 10);
|
||||
|
||||
V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|splitflags, pingnum[ln[0]]);
|
||||
V_DrawScaledPatch(fx+31, fy, V_HUDTRANS|splitflags, pingnum[ln[1]]);
|
||||
}
|
||||
else
|
||||
{
|
||||
V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|splitflags, kp_facenum[(stplyr->kartstuff[k_bumper]) % 10]);
|
||||
V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|splitflags, kp_facenum[(maxbumper) % 10]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (stplyr->kartstuff[k_bumper] <= 0)
|
||||
if (battlecapsules)
|
||||
{
|
||||
V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|splitflags, kp_karmasticker, colormap);
|
||||
V_DrawKartString(LAPS_X+47, LAPS_Y+3, V_HUDTRANS|splitflags, va("%d/2", stplyr->kartstuff[k_comebackpoints]));
|
||||
if (numtargets > 9 && maptargets > 9)
|
||||
V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|splitflags, kp_capsulestickerwide, NULL);
|
||||
else
|
||||
V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|splitflags, kp_capsulesticker, NULL);
|
||||
V_DrawKartString(LAPS_X+47, LAPS_Y+3, V_HUDTRANS|splitflags, va("%d/%d", numtargets, maptargets));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (stplyr->kartstuff[k_bumper] > 9 && cv_kartbumpers.value > 9)
|
||||
V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|splitflags, kp_bumperstickerwide, colormap);
|
||||
if (stplyr->kartstuff[k_bumper] <= 0)
|
||||
{
|
||||
V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|splitflags, kp_karmasticker, colormap);
|
||||
V_DrawKartString(LAPS_X+47, LAPS_Y+3, V_HUDTRANS|splitflags, va("%d/2", stplyr->kartstuff[k_comebackpoints]));
|
||||
}
|
||||
else
|
||||
V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|splitflags, kp_bumpersticker, colormap);
|
||||
V_DrawKartString(LAPS_X+47, LAPS_Y+3, V_HUDTRANS|splitflags, va("%d/%d", stplyr->kartstuff[k_bumper], cv_kartbumpers.value));
|
||||
{
|
||||
INT32 maxbumper = K_StartingBumperCount();
|
||||
|
||||
if (stplyr->kartstuff[k_bumper] > 9 && maxbumper > 9)
|
||||
V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|splitflags, kp_bumperstickerwide, colormap);
|
||||
else
|
||||
V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|splitflags, kp_bumpersticker, colormap);
|
||||
|
||||
V_DrawKartString(LAPS_X+47, LAPS_Y+3, V_HUDTRANS|splitflags, va("%d/%d", stplyr->kartstuff[k_bumper], maxbumper));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -10308,10 +10145,14 @@ static void K_drawBattleFullscreen(void)
|
|||
V_DrawFadeScreen(0xFF00, 16);
|
||||
if (stplyr->exiting < 6*TICRATE && !stplyr->spectator)
|
||||
{
|
||||
if (stplyr->kartstuff[k_position] == 1)
|
||||
V_DrawFixedPatch(x<<FRACBITS, y<<FRACBITS, scale, splitflags, kp_battlewin, NULL);
|
||||
else
|
||||
V_DrawFixedPatch(x<<FRACBITS, y<<FRACBITS, scale, splitflags, (K_IsPlayerLosing(stplyr) ? kp_battlelose : kp_battlecool), NULL);
|
||||
patch_t *p = kp_battlecool;
|
||||
|
||||
if (K_IsPlayerLosing(stplyr))
|
||||
p = kp_battlelose;
|
||||
else if (stplyr->kartstuff[k_position] == 1)
|
||||
p = kp_battlewin;
|
||||
|
||||
V_DrawFixedPatch(x<<FRACBITS, y<<FRACBITS, scale, splitflags, p, NULL);
|
||||
}
|
||||
else
|
||||
K_drawKartFinish();
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ UINT8 K_GetKartColorByName(const char *name);
|
|||
void K_RegisterKartStuff(void);
|
||||
|
||||
boolean K_IsPlayerLosing(player_t *player);
|
||||
boolean K_IsPlayerWanted(player_t *player);
|
||||
fixed_t K_GetKartGameSpeedScalar(SINT8 value);
|
||||
void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid);
|
||||
void K_KartPainEnergyFling(player_t *player);
|
||||
|
|
@ -34,7 +33,6 @@ void K_KartPlayerHUDUpdate(player_t *player);
|
|||
void K_KartPlayerThink(player_t *player, ticcmd_t *cmd);
|
||||
void K_KartPlayerAfterThink(player_t *player);
|
||||
void K_DoInstashield(player_t *player);
|
||||
void K_SpawnBattlePoints(player_t *source, player_t *victim, UINT8 amount);
|
||||
void K_SpinPlayer(player_t *player, mobj_t *source, INT32 type, mobj_t *inflictor, boolean trapitem);
|
||||
void K_SquishPlayer(player_t *player, mobj_t *source, mobj_t *inflictor);
|
||||
void K_ExplodePlayer(player_t *player, mobj_t *source, mobj_t *inflictor);
|
||||
|
|
@ -68,8 +66,6 @@ fixed_t K_GetKartAccel(player_t *player);
|
|||
UINT16 K_GetKartFlashing(player_t *player);
|
||||
fixed_t K_3dKartMovement(player_t *player, boolean onground, fixed_t forwardmove);
|
||||
void K_MoveKartPlayer(player_t *player, boolean onground);
|
||||
void K_CalculateBattleWanted(void);
|
||||
void K_CheckBumpers(void);
|
||||
void K_CheckSpectateStatus(void);
|
||||
|
||||
// sound stuff for lua
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ UINT16 clientpowerlevels[MAXPLAYERS][PWRLV_NUMTYPES];
|
|||
|
||||
// Which players spec-scummed, and their power level before scumming.
|
||||
// On race finish, everyone is considered to have "won" against these people.
|
||||
INT16 nospectategrief[MAXPLAYERS];
|
||||
INT16 nospectategrief[MAXPLAYERS];
|
||||
|
||||
// Game setting scrambles based on server Power Level
|
||||
SINT8 speedscramble = -1;
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include "hu_stuff.h" // HU_AddChatText
|
||||
#include "console.h"
|
||||
#include "k_kart.h" // SRB2Kart
|
||||
#include "k_battle.h"
|
||||
#include "d_netcmd.h" // IsPlayerAdmin
|
||||
|
||||
#include "lua_script.h"
|
||||
|
|
|
|||
|
|
@ -172,7 +172,8 @@ unlockable_t unlockables[MAXUNLOCKABLES] =
|
|||
/* 05 */ {"Encore Mode", "", 4, 5, SECRET_ENCORE, 0, false, false, 0},
|
||||
/* 06 */ {"Hell Attack", "", 6, 6, SECRET_HELLATTACK, 0, false, false, 0},
|
||||
|
||||
/* 07 */ {"Record Attack", "", -1, -1, SECRET_RECORDATTACK, 0, true, true, 0},
|
||||
/* 07 */ {"Time Attack", "", -1, -1, SECRET_TIMEATTACK, 0, true, true, 0},
|
||||
/* 08 */ {"Break the Capsules", "", -1, -1, SECRET_BREAKTHECAPSULES, 0, true, true, 0},
|
||||
};
|
||||
|
||||
// Default number of emblems and extra emblems
|
||||
|
|
|
|||
|
|
@ -118,8 +118,8 @@ typedef struct
|
|||
#define SECRET_ITEMFINDER -5 // Enables Item Finder/Emblem Radar
|
||||
#define SECRET_EMBLEMHINTS -4 // Enables Emblem Hints
|
||||
#define SECRET_PANDORA -3 // Enables Pandora's Box
|
||||
#define SECRET_RECORDATTACK -2 // Enables Record Attack on the main menu
|
||||
#define SECRET_NIGHTSMODE -1 // Enables NiGHTS Mode on the main menu
|
||||
#define SECRET_TIMEATTACK -2 // Enables Time Attack on the main menu
|
||||
#define SECRET_BREAKTHECAPSULES -1 // Enables Break the Capsules on the main menu
|
||||
#define SECRET_HEADER 0 // Does nothing on its own, just serves as a header for the menu
|
||||
#define SECRET_LEVELSELECT 1 // Selectable level select
|
||||
#define SECRET_WARP 2 // Selectable warp
|
||||
|
|
|
|||
188
src/m_menu.c
188
src/m_menu.c
|
|
@ -138,8 +138,8 @@ typedef enum
|
|||
{
|
||||
LLM_CREATESERVER,
|
||||
LLM_LEVELSELECT,
|
||||
LLM_RECORDATTACK,
|
||||
LLM_NIGHTSATTACK
|
||||
LLM_TIMEATTACK,
|
||||
LLM_BREAKTHECAPSULES
|
||||
} levellist_mode_t;
|
||||
|
||||
levellist_mode_t levellistmode = LLM_CREATESERVER;
|
||||
|
|
@ -205,9 +205,7 @@ static char *M_GetConditionString(condition_t cond);
|
|||
menu_t SR_MainDef, SR_UnlockChecklistDef;
|
||||
|
||||
// Misc. Main Menu
|
||||
#if 0 // Bring this back when we have actual single-player
|
||||
static void M_SinglePlayerMenu(INT32 choice);
|
||||
#endif
|
||||
static void M_Options(INT32 choice);
|
||||
static void M_Manual(INT32 choice);
|
||||
static void M_SelectableClearMenus(INT32 choice);
|
||||
|
|
@ -230,7 +228,7 @@ menu_t MISC_ScrambleTeamDef, MISC_ChangeTeamDef, MISC_ChangeSpectateDef;
|
|||
//static void M_LoadGame(INT32 choice);
|
||||
static void M_TimeAttack(INT32 choice);
|
||||
static boolean M_QuitTimeAttackMenu(void);
|
||||
//static void M_NightsAttack(INT32 choice);
|
||||
static void M_BreakTheCapsules(INT32 choice);
|
||||
static void M_Statistics(INT32 choice);
|
||||
static void M_HandleStaffReplay(INT32 choice);
|
||||
static void M_ReplayTimeAttack(INT32 choice);
|
||||
|
|
@ -482,11 +480,10 @@ static consvar_t cv_dummystaff = {"dummystaff", "0", CV_HIDEN|CV_CALL, dummystaf
|
|||
static menuitem_t MainMenu[] =
|
||||
{
|
||||
{IT_SUBMENU|IT_STRING, NULL, "Extras", &SR_MainDef, 76},
|
||||
//{IT_CALL |IT_STRING, NULL, "1 Player", M_SinglePlayerMenu, 84},
|
||||
#ifdef TESTERS
|
||||
{IT_GRAYEDOUT, NULL, "Time Attack", NULL, 84},
|
||||
{IT_GRAYEDOUT, NULL, "1 Player", NULL, 84},
|
||||
#else
|
||||
{IT_CALL |IT_STRING, NULL, "Time Attack", M_TimeAttack, 84},
|
||||
{IT_CALL |IT_STRING, NULL, "1 Player", M_SinglePlayerMenu, 84},
|
||||
#endif
|
||||
{IT_SUBMENU|IT_STRING, NULL, "Multiplayer", &MP_MainDef, 92},
|
||||
{IT_CALL |IT_STRING, NULL, "Options", M_Options, 100},
|
||||
|
|
@ -806,18 +803,16 @@ static menuitem_t SR_EmblemHintMenu[] =
|
|||
// Single Player Main
|
||||
static menuitem_t SP_MainMenu[] =
|
||||
{
|
||||
//{IT_CALL | IT_STRING, NULL, "Start Game", M_LoadGame, 92},
|
||||
{IT_SECRET, NULL, "Record Attack", M_TimeAttack, 100},
|
||||
//{IT_SECRET, NULL, "NiGHTS Mode", M_NightsAttack, 108},
|
||||
{IT_CALL | IT_STRING | IT_CALL_NOTMODIFIED, NULL, "Statistics", M_Statistics, 108},
|
||||
//{IT_CALL | IT_STRING, NULL, "Grand Prix", M_LoadGame, 92},
|
||||
{IT_SECRET, NULL, "Time Attack", M_TimeAttack, 100},
|
||||
{IT_SECRET, NULL, "Break the Capsules", M_BreakTheCapsules, 108},
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
//sploadgame,
|
||||
sprecordattack,
|
||||
//spnightsmode,
|
||||
spstatistics
|
||||
//spgrandprix,
|
||||
sptimeattack,
|
||||
spbreakthecapsules
|
||||
};
|
||||
|
||||
// Single Player Load Game
|
||||
|
|
@ -1879,52 +1874,6 @@ static menu_t SP_GhostDef =
|
|||
NULL
|
||||
};
|
||||
|
||||
/*static menu_t SP_NightsAttackDef =
|
||||
{
|
||||
"M_NIGHTS",
|
||||
sizeof (SP_NightsAttackMenu)/sizeof (menuitem_t),
|
||||
&MainDef, // Doesn't matter.
|
||||
SP_NightsAttackMenu,
|
||||
M_DrawNightsAttackMenu,
|
||||
32, 40,
|
||||
0,
|
||||
NULL
|
||||
};
|
||||
static menu_t SP_NightsReplayDef =
|
||||
{
|
||||
"M_NIGHTS",
|
||||
sizeof(SP_NightsReplayMenu)/sizeof(menuitem_t),
|
||||
&SP_NightsAttackDef,
|
||||
SP_NightsReplayMenu,
|
||||
M_DrawNightsAttackMenu,
|
||||
32, 120,
|
||||
0,
|
||||
NULL
|
||||
};
|
||||
static menu_t SP_NightsGuestReplayDef =
|
||||
{
|
||||
"M_NIGHTS",
|
||||
sizeof(SP_NightsGuestReplayMenu)/sizeof(menuitem_t),
|
||||
&SP_NightsAttackDef,
|
||||
SP_NightsGuestReplayMenu,
|
||||
M_DrawNightsAttackMenu,
|
||||
32, 120,
|
||||
0,
|
||||
NULL
|
||||
};
|
||||
static menu_t SP_NightsGhostDef =
|
||||
{
|
||||
"M_NIGHTS",
|
||||
sizeof(SP_NightsGhostMenu)/sizeof(menuitem_t),
|
||||
&SP_NightsAttackDef,
|
||||
SP_NightsGhostMenu,
|
||||
M_DrawNightsAttackMenu,
|
||||
32, 120,
|
||||
0,
|
||||
NULL
|
||||
};*/
|
||||
|
||||
|
||||
/*menu_t SP_PlayerDef =
|
||||
{
|
||||
"M_PICKP",
|
||||
|
|
@ -2163,7 +2112,7 @@ static void Nextmap_OnChange(void)
|
|||
|
||||
CV_StealthSetValue(&cv_dummystaff, 0);
|
||||
|
||||
active = false;
|
||||
active = 0;
|
||||
SP_TimeAttackMenu[taguest].status = IT_DISABLED;
|
||||
SP_TimeAttackMenu[tareplay].status = IT_DISABLED;
|
||||
//SP_TimeAttackMenu[taghost].status = IT_DISABLED;
|
||||
|
|
@ -2184,11 +2133,15 @@ static void Nextmap_OnChange(void)
|
|||
SP_GuestReplayMenu[0].status = IT_WHITESTRING|IT_CALL;
|
||||
active |= 3;
|
||||
}
|
||||
if (FIL_FileExists(va("%s-%s-lap-best.lmp", gpath, cv_chooseskin.string))) {
|
||||
SP_ReplayMenu[1].status = IT_WHITESTRING|IT_CALL;
|
||||
SP_GuestReplayMenu[1].status = IT_WHITESTRING|IT_CALL;
|
||||
active |= 3;
|
||||
|
||||
if (levellistmode != LLM_BREAKTHECAPSULES) {
|
||||
if (FIL_FileExists(va("%s-%s-lap-best.lmp", gpath, cv_chooseskin.string))) {
|
||||
SP_ReplayMenu[1].status = IT_WHITESTRING|IT_CALL;
|
||||
SP_GuestReplayMenu[1].status = IT_WHITESTRING|IT_CALL;
|
||||
active |= 3;
|
||||
}
|
||||
}
|
||||
|
||||
if (FIL_FileExists(va("%s-%s-last.lmp", gpath, cv_chooseskin.string))) {
|
||||
SP_ReplayMenu[2].status = IT_WHITESTRING|IT_CALL;
|
||||
SP_GuestReplayMenu[2].status = IT_WHITESTRING|IT_CALL;
|
||||
|
|
@ -4263,11 +4216,13 @@ boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt)
|
|||
return false; // not unlocked
|
||||
|
||||
return true;*/
|
||||
case LLM_RECORDATTACK:
|
||||
case LLM_TIMEATTACK:
|
||||
case LLM_BREAKTHECAPSULES:
|
||||
/*if (!(mapheaderinfo[mapnum]->menuflags & LF2_RECORDATTACK))
|
||||
return false;*/
|
||||
|
||||
if (!(mapheaderinfo[mapnum]->typeoflevel & TOL_RACE))
|
||||
if ((levellistmode == LLM_TIMEATTACK && !(mapheaderinfo[mapnum]->typeoflevel & TOL_RACE))
|
||||
|| (levellistmode == LLM_BREAKTHECAPSULES && !(mapheaderinfo[mapnum]->typeoflevel & TOL_MATCH)))
|
||||
return false;
|
||||
|
||||
if (M_MapLocked(mapnum+1))
|
||||
|
|
@ -4286,20 +4241,6 @@ boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt)
|
|||
return false;*/
|
||||
|
||||
return true;
|
||||
/*case LLM_NIGHTSATTACK:
|
||||
if (!(mapheaderinfo[mapnum]->menuflags & LF2_NIGHTSATTACK))
|
||||
return false;
|
||||
|
||||
if (M_MapLocked(mapnum+1))
|
||||
return false; // not unlocked
|
||||
|
||||
if (mapheaderinfo[mapnum]->menuflags & LF2_NOVISITNEEDED)
|
||||
return true;
|
||||
|
||||
if (!mapvisited[mapnum])
|
||||
return false;
|
||||
|
||||
return true;*/
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
|
@ -6627,18 +6568,16 @@ static void M_Credits(INT32 choice)
|
|||
// SINGLE PLAYER MENU
|
||||
// ==================
|
||||
|
||||
#if 0 // Bring this back when we have actual single-player
|
||||
static void M_SinglePlayerMenu(INT32 choice)
|
||||
{
|
||||
(void)choice;
|
||||
SP_MainMenu[sprecordattack].status =
|
||||
(M_SecretUnlocked(SECRET_RECORDATTACK)) ? IT_CALL|IT_STRING : IT_SECRET;
|
||||
/*SP_MainMenu[spnightsmode].status =
|
||||
(M_SecretUnlocked(SECRET_NIGHTSMODE)) ? IT_CALL|IT_STRING : IT_SECRET;*/
|
||||
SP_MainMenu[sptimeattack].status =
|
||||
(M_SecretUnlocked(SECRET_TIMEATTACK)) ? IT_CALL|IT_STRING : IT_SECRET;
|
||||
SP_MainMenu[spbreakthecapsules].status =
|
||||
(M_SecretUnlocked(SECRET_BREAKTHECAPSULES)) ? IT_CALL|IT_STRING : IT_SECRET;
|
||||
|
||||
M_SetupNextMenu(&SP_MainDef);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*static void M_LoadGameLevelSelect(INT32 choice)
|
||||
{
|
||||
|
|
@ -7624,8 +7563,11 @@ void M_DrawTimeAttackMenu(void)
|
|||
|
||||
V_DrawFill((BASEVIDWIDTH - dupadjust)>>1, 78, dupadjust, 36, 159);
|
||||
|
||||
V_DrawRightAlignedString(149, 80, highlightflags, "BEST LAP:");
|
||||
K_drawKartTimestamp(lap, 19, 86, 0, 2);
|
||||
if (levellistmode != LLM_BREAKTHECAPSULES)
|
||||
{
|
||||
V_DrawRightAlignedString(149, 80, highlightflags, "BEST LAP:");
|
||||
K_drawKartTimestamp(lap, 19, 86, 0, 2);
|
||||
}
|
||||
|
||||
V_DrawRightAlignedString(292, 80, highlightflags, "BEST TIME:");
|
||||
K_drawKartTimestamp(time, 162, 86, cv_nextmap.value, 1);
|
||||
|
|
@ -7714,11 +7656,43 @@ static void M_TimeAttack(INT32 choice)
|
|||
|
||||
memset(skins_cons_t, 0, sizeof (skins_cons_t));
|
||||
|
||||
levellistmode = LLM_RECORDATTACK; // Don't be dependent on cv_newgametype
|
||||
levellistmode = LLM_TIMEATTACK; // Don't be dependent on cv_newgametype
|
||||
|
||||
if (M_CountLevelsToShowInList() == 0)
|
||||
{
|
||||
M_StartMessage(M_GetText("No record-attackable levels found.\n"),NULL,MM_NOTHING);
|
||||
M_StartMessage(M_GetText("No levels found for Time Attack.\n"),NULL,MM_NOTHING);
|
||||
return;
|
||||
}
|
||||
|
||||
M_PatchSkinNameTable();
|
||||
|
||||
M_PrepareLevelSelect();
|
||||
M_SetupNextMenu(&SP_TimeAttackDef);
|
||||
|
||||
G_SetGamestate(GS_TIMEATTACK);
|
||||
|
||||
if (cv_nextmap.value)
|
||||
Nextmap_OnChange();
|
||||
else
|
||||
CV_AddValue(&cv_nextmap, 1);
|
||||
|
||||
itemOn = tastart; // "Start" is selected.
|
||||
|
||||
S_ChangeMusicInternal("racent", true);
|
||||
}
|
||||
|
||||
// Same as above, but sets a different levellistmode. Should probably be merged...
|
||||
static void M_BreakTheCapsules(INT32 choice)
|
||||
{
|
||||
(void)choice;
|
||||
|
||||
memset(skins_cons_t, 0, sizeof (skins_cons_t));
|
||||
|
||||
levellistmode = LLM_BREAKTHECAPSULES; // Don't be dependent on cv_newgametype
|
||||
|
||||
if (M_CountLevelsToShowInList() == 0)
|
||||
{
|
||||
M_StartMessage(M_GetText("No levels found for Break the Capsules.\n"),NULL,MM_NOTHING);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -7852,13 +7826,13 @@ static boolean M_QuitTimeAttackMenu(void)
|
|||
}*/
|
||||
|
||||
// Going to Nights Attack menu...
|
||||
/*static void M_NightsAttack(INT32 choice)
|
||||
/*static void M_BreakTheCapsules(INT32 choice)
|
||||
{
|
||||
(void)choice;
|
||||
|
||||
memset(skins_cons_t, 0, sizeof (skins_cons_t));
|
||||
|
||||
levellistmode = LLM_NIGHTSATTACK; // Don't be dependent on cv_newgametype
|
||||
levellistmode = LLM_BREAKTHECAPSULES; // Don't be dependent on cv_newgametype
|
||||
|
||||
if (M_CountLevelsToShowInList() == 0)
|
||||
{
|
||||
|
|
@ -7886,7 +7860,7 @@ static boolean M_QuitTimeAttackMenu(void)
|
|||
(void)choice;
|
||||
emeralds = 0;
|
||||
M_ClearMenus(true);
|
||||
modeattacking = ATTACKING_NIGHTS;
|
||||
modeattacking = ATTACKING_CAPSULES;
|
||||
|
||||
I_mkdir(va("%s"PATHSEP"replay", srb2home), 0755);
|
||||
I_mkdir(va("%s"PATHSEP"replay"PATHSEP"%s", srb2home, timeattackfolder), 0755);
|
||||
|
|
@ -7910,7 +7884,7 @@ static void M_ChooseTimeAttack(INT32 choice)
|
|||
(void)choice;
|
||||
emeralds = 0;
|
||||
M_ClearMenus(true);
|
||||
modeattacking = ATTACKING_RECORD;
|
||||
modeattacking = (levellistmode == LLM_BREAKTHECAPSULES ? ATTACKING_CAPSULES : ATTACKING_RECORD);
|
||||
|
||||
I_mkdir(va("%s"PATHSEP"replay", srb2home), 0755);
|
||||
I_mkdir(va("%s"PATHSEP"replay"PATHSEP"%s", srb2home, timeattackfolder), 0755);
|
||||
|
|
@ -7960,7 +7934,7 @@ static void M_HandleStaffReplay(INT32 choice)
|
|||
if (l == LUMPERROR)
|
||||
break;
|
||||
M_ClearMenus(true);
|
||||
modeattacking = ATTACKING_RECORD;
|
||||
modeattacking = (levellistmode == LLM_BREAKTHECAPSULES ? ATTACKING_CAPSULES : ATTACKING_RECORD);
|
||||
demo.loadfiles = false; demo.ignorefiles = true; // Just assume that record attack replays have the files needed
|
||||
G_DoPlayDemo(va("%sS%02u",G_BuildMapName(cv_nextmap.value),cv_dummystaff.value));
|
||||
break;
|
||||
|
|
@ -7981,7 +7955,7 @@ static void M_ReplayTimeAttack(INT32 choice)
|
|||
{
|
||||
const char *which;
|
||||
M_ClearMenus(true);
|
||||
modeattacking = ATTACKING_RECORD; // set modeattacking before G_DoPlayDemo so the map loader knows
|
||||
modeattacking = (levellistmode == LLM_BREAKTHECAPSULES ? ATTACKING_CAPSULES : ATTACKING_RECORD); // set modeattacking before G_DoPlayDemo so the map loader knows
|
||||
demo.loadfiles = false; demo.ignorefiles = true; // Just assume that record attack replays have the files needed
|
||||
|
||||
if (currentMenu == &SP_ReplayDef)
|
||||
|
|
@ -8128,10 +8102,8 @@ static void M_ModeAttackRetry(INT32 choice)
|
|||
{
|
||||
(void)choice;
|
||||
G_CheckDemoStatus(); // Cancel recording
|
||||
if (modeattacking == ATTACKING_RECORD)
|
||||
if (modeattacking)
|
||||
M_ChooseTimeAttack(0);
|
||||
/*else if (modeattacking == ATTACKING_NIGHTS)
|
||||
M_ChooseNightsAttack(0);*/
|
||||
}
|
||||
|
||||
static void M_ModeAttackEndGame(INT32 choice)
|
||||
|
|
@ -8143,16 +8115,10 @@ static void M_ModeAttackEndGame(INT32 choice)
|
|||
Command_ExitGame_f();
|
||||
|
||||
M_StartControlPanel();
|
||||
switch(modeattacking)
|
||||
{
|
||||
default:
|
||||
case ATTACKING_RECORD:
|
||||
|
||||
if (modeattacking)
|
||||
currentMenu = &SP_TimeAttackDef;
|
||||
break;
|
||||
/*case ATTACKING_NIGHTS:
|
||||
currentMenu = &SP_NightsAttackDef;
|
||||
break;*/
|
||||
}
|
||||
|
||||
itemOn = currentMenu->lastOn;
|
||||
G_SetGamestate(GS_TIMEATTACK);
|
||||
modeattacking = ATTACKING_NONE;
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include "lua_hook.h"
|
||||
#include "k_kart.h" // SRB2kart
|
||||
#include "k_waypoint.h"
|
||||
#include "k_battle.h"
|
||||
|
||||
#ifdef HW3SOUND
|
||||
#include "hardware/hw3sound.h"
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "m_misc.h"
|
||||
#include "v_video.h" // video flags for CEchos
|
||||
#include "k_kart.h" // SRB2kart
|
||||
#include "k_battle.h"
|
||||
#include "k_pwrlv.h"
|
||||
|
||||
// CTF player names
|
||||
|
|
@ -1785,7 +1786,7 @@ void P_CheckTimeLimit(void)
|
|||
if (!(multiplayer || netgame))
|
||||
return;
|
||||
|
||||
if (G_RaceGametype())
|
||||
if (G_RaceGametype() || battlecapsules)
|
||||
return;
|
||||
|
||||
if (leveltime < (timelimitintics + starttime))
|
||||
|
|
@ -2516,6 +2517,45 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source)
|
|||
S_StartSound(target, sfx_s3k80);
|
||||
}
|
||||
break;
|
||||
case MT_BATTLECAPSULE:
|
||||
{
|
||||
mobj_t *cur;
|
||||
|
||||
numtargets++;
|
||||
target->fuse = 16;
|
||||
target->flags |= MF_NOCLIP|MF_NOCLIPTHING;
|
||||
|
||||
cur = target->hnext;
|
||||
|
||||
while (cur && !P_MobjWasRemoved(cur))
|
||||
{
|
||||
// Shoot every piece outward
|
||||
if (!(cur->x == target->x && cur->y == target->y))
|
||||
{
|
||||
P_InstaThrust(cur,
|
||||
R_PointToAngle2(target->x, target->y, cur->x, cur->y),
|
||||
R_PointToDist2(target->x, target->y, cur->x, cur->y) / 12
|
||||
);
|
||||
}
|
||||
|
||||
cur->momz = 8 * target->scale * P_MobjFlip(target);
|
||||
|
||||
cur->flags &= ~MF_NOGRAVITY;
|
||||
cur->tics = TICRATE;
|
||||
cur->frame &= ~FF_ANIMATE; // Stop animating the propellers
|
||||
|
||||
cur = cur->hnext;
|
||||
}
|
||||
|
||||
// All targets busted!
|
||||
if (numtargets >= maptargets)
|
||||
{
|
||||
UINT8 i;
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
P_DoPlayerExit(&players[i]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -227,7 +227,6 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state);
|
|||
boolean P_SetMobjState(mobj_t *mobj, statenum_t state);
|
||||
//void P_RunShields(void);
|
||||
void P_RunOverlays(void);
|
||||
void P_RunBattleOvertime(void);
|
||||
void P_MobjThinker(mobj_t *mobj);
|
||||
boolean P_RailThinker(mobj_t *mobj);
|
||||
void P_PushableThinker(mobj_t *mobj);
|
||||
|
|
|
|||
474
src/p_map.c
474
src/p_map.c
|
|
@ -25,6 +25,7 @@
|
|||
#include "s_sound.h"
|
||||
#include "w_wad.h"
|
||||
#include "k_kart.h" // SRB2kart 011617
|
||||
#include "k_collide.h"
|
||||
|
||||
#include "hu_stuff.h" // SRB2kart
|
||||
#include "i_system.h" // SRB2kart
|
||||
|
|
@ -819,7 +820,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
|
|||
|
||||
// SRB2kart 011617 - Colission[sic] code for kart items //{
|
||||
|
||||
if (thing->type == MT_SMK_ICEBLOCK)
|
||||
if (tmthing->type == MT_SMK_ICEBLOCK)
|
||||
{
|
||||
// see if it went over / under
|
||||
if (tmthing->z > thing->z + thing->height)
|
||||
|
|
@ -827,31 +828,20 @@ static boolean PIT_CheckThing(mobj_t *thing)
|
|||
if (tmthing->z + tmthing->height < thing->z)
|
||||
return true; // underneath
|
||||
|
||||
if (!(tmthing->flags & MF_SOLID || tmthing->flags & MF_SHOOTABLE || tmthing->flags & MF_BOUNCE))
|
||||
return true;
|
||||
return K_SMKIceBlockCollide(tmthing, thing);
|
||||
}
|
||||
else if (thing->type == MT_SMK_ICEBLOCK)
|
||||
{
|
||||
// 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 (!(tmthing->health))
|
||||
return true;
|
||||
|
||||
if (tmthing->type == MT_BANANA || tmthing->type == MT_BANANA_SHIELD
|
||||
|| tmthing->type == MT_EGGMANITEM || tmthing->type == MT_EGGMANITEM_SHIELD
|
||||
|| tmthing->type == MT_SSMINE || tmthing->type == MT_SSMINE_SHIELD
|
||||
|| tmthing->type == MT_ORBINAUT_SHIELD || tmthing->type == MT_JAWZ_SHIELD)
|
||||
return false;
|
||||
|
||||
if (thing->health)
|
||||
P_KillMobj(thing, tmthing, tmthing);
|
||||
|
||||
/*if (tmthing->player && (tmthing->player->kartstuff[k_invincibilitytimer] > 0
|
||||
|| tmthing->player->kartstuff[k_growshrinktimer] > 0))
|
||||
return true;*/
|
||||
|
||||
K_KartBouncing(tmthing, thing, false, true);
|
||||
return false;
|
||||
return K_SMKIceBlockCollide(thing, tmthing);
|
||||
}
|
||||
|
||||
// Push fakes out of other items
|
||||
if (tmthing->type == MT_EGGMANITEM && (thing->type == MT_RANDOMITEM || thing->type == MT_EGGMANITEM))
|
||||
if (tmthing->type == MT_EGGMANITEM)
|
||||
{
|
||||
// see if it went over / under
|
||||
if (tmthing->z > thing->z + thing->height)
|
||||
|
|
@ -859,10 +849,10 @@ static boolean PIT_CheckThing(mobj_t *thing)
|
|||
if (tmthing->z + tmthing->height < thing->z)
|
||||
return true; // underneath
|
||||
|
||||
P_InstaThrust(tmthing, R_PointToAngle2(thing->x, thing->y, tmthing->x, tmthing->y), thing->radius/4);
|
||||
K_EggItemCollide(tmthing, thing);
|
||||
return true;
|
||||
}
|
||||
else if (thing->type == MT_EGGMANITEM && (tmthing->type == MT_RANDOMITEM || tmthing->type == MT_EGGMANITEM))
|
||||
else if (thing->type == MT_EGGMANITEM)
|
||||
{
|
||||
// see if it went over / under
|
||||
if (tmthing->z > thing->z + thing->height)
|
||||
|
|
@ -870,7 +860,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
|
|||
if (tmthing->z + tmthing->height < thing->z)
|
||||
return true; // underneath
|
||||
|
||||
P_InstaThrust(thing, R_PointToAngle2(tmthing->x, tmthing->y, thing->x, thing->y), tmthing->radius/4);
|
||||
K_EggItemCollide(thing, tmthing);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -886,97 +876,10 @@ static boolean PIT_CheckThing(mobj_t *thing)
|
|||
if (tmthing->z + tmthing->height < thing->z)
|
||||
return true; // underneath
|
||||
|
||||
if (((tmthing->target == thing) || (tmthing->target == thing->target)) && (tmthing->threshold > 0 || (thing->type != MT_PLAYER && thing->threshold > 0)))
|
||||
return true;
|
||||
|
||||
if (tmthing->health <= 0 || thing->health <= 0)
|
||||
return true;
|
||||
|
||||
if ((tmthing->type == MT_ORBINAUT_SHIELD || tmthing->type == MT_JAWZ_SHIELD) && tmthing->lastlook
|
||||
&& (thing->type == MT_ORBINAUT_SHIELD || thing->type == MT_JAWZ_SHIELD) && thing->lastlook
|
||||
&& (tmthing->target == thing->target)) // Don't hit each other if you have the same target
|
||||
return true;
|
||||
|
||||
if (thing->player && thing->player->powers[pw_flashing]
|
||||
&& !(tmthing->type == MT_ORBINAUT || tmthing->type == MT_JAWZ || tmthing->type == MT_JAWZ_DUD))
|
||||
return true;
|
||||
|
||||
if (thing->player && thing->player->kartstuff[k_hyudorotimer])
|
||||
return true; // no interaction
|
||||
|
||||
if (thing->type == MT_PLAYER)
|
||||
{
|
||||
// Player Damage
|
||||
P_DamageMobj(thing, tmthing, tmthing->target, 1);
|
||||
K_KartBouncing(thing, tmthing, false, false);
|
||||
S_StartSound(thing, sfx_s3k7b);
|
||||
|
||||
// This Item Damage
|
||||
if (tmthing->eflags & MFE_VERTICALFLIP)
|
||||
tmthing->z -= tmthing->height;
|
||||
else
|
||||
tmthing->z += tmthing->height;
|
||||
|
||||
S_StartSound(tmthing, tmthing->info->deathsound);
|
||||
P_KillMobj(tmthing, thing, thing);
|
||||
|
||||
P_SetObjectMomZ(tmthing, 12*FRACUNIT, false);
|
||||
P_InstaThrust(tmthing, R_PointToAngle2(thing->x, thing->y, tmthing->x, tmthing->y)+ANGLE_90, 16*FRACUNIT);
|
||||
}
|
||||
else if (thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD
|
||||
|| thing->type == MT_ORBINAUT_SHIELD || thing->type == MT_JAWZ_SHIELD
|
||||
|| thing->type == MT_BANANA || thing->type == MT_BANANA_SHIELD
|
||||
|| thing->type == MT_BALLHOG)
|
||||
{
|
||||
// Other Item Damage
|
||||
if (thing->eflags & MFE_VERTICALFLIP)
|
||||
thing->z -= thing->height;
|
||||
else
|
||||
thing->z += thing->height;
|
||||
|
||||
S_StartSound(thing, thing->info->deathsound);
|
||||
P_KillMobj(thing, tmthing, tmthing);
|
||||
|
||||
P_SetObjectMomZ(thing, 12*FRACUNIT, false);
|
||||
P_InstaThrust(thing, R_PointToAngle2(tmthing->x, tmthing->y, thing->x, thing->y)+ANGLE_90, 16*FRACUNIT);
|
||||
|
||||
P_SpawnMobj(thing->x/2 + tmthing->x/2, thing->y/2 + tmthing->y/2, thing->z/2 + tmthing->z/2, MT_ITEMCLASH);
|
||||
|
||||
// This Item Damage
|
||||
if (tmthing->eflags & MFE_VERTICALFLIP)
|
||||
tmthing->z -= tmthing->height;
|
||||
else
|
||||
tmthing->z += tmthing->height;
|
||||
|
||||
S_StartSound(tmthing, tmthing->info->deathsound);
|
||||
P_KillMobj(tmthing, thing, thing);
|
||||
|
||||
P_SetObjectMomZ(tmthing, 12*FRACUNIT, false);
|
||||
P_InstaThrust(tmthing, R_PointToAngle2(thing->x, thing->y, tmthing->x, tmthing->y)+ANGLE_90, 16*FRACUNIT);
|
||||
}
|
||||
else if (thing->type == MT_SSMINE_SHIELD || thing->type == MT_SSMINE)
|
||||
{
|
||||
// This Item Damage
|
||||
if (tmthing->eflags & MFE_VERTICALFLIP)
|
||||
tmthing->z -= tmthing->height;
|
||||
else
|
||||
tmthing->z += tmthing->height;
|
||||
|
||||
S_StartSound(tmthing, tmthing->info->deathsound);
|
||||
P_KillMobj(tmthing, thing, thing);
|
||||
|
||||
P_SetObjectMomZ(tmthing, 12*FRACUNIT, false);
|
||||
P_InstaThrust(tmthing, R_PointToAngle2(thing->x, thing->y, tmthing->x, tmthing->y)+ANGLE_90, 16*FRACUNIT);
|
||||
|
||||
// Bomb death
|
||||
P_KillMobj(thing, tmthing, tmthing);
|
||||
}
|
||||
else if (thing->flags & MF_SPRING && (tmthing->type == MT_JAWZ || tmthing->type == MT_JAWZ_DUD || tmthing->type == MT_ORBINAUT))
|
||||
P_DoSpring(thing, tmthing);
|
||||
|
||||
return true;
|
||||
return K_OrbinautJawzCollide(tmthing, thing);
|
||||
}
|
||||
else if (tmthing->flags & MF_SPRING && (thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD || thing->type == MT_ORBINAUT))
|
||||
else if (thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD
|
||||
|| thing->type == MT_ORBINAUT_SHIELD || thing->type == MT_JAWZ_SHIELD)
|
||||
{
|
||||
// see if it went over / under
|
||||
if (tmthing->z > thing->z + thing->height)
|
||||
|
|
@ -984,14 +887,10 @@ static boolean PIT_CheckThing(mobj_t *thing)
|
|||
if (tmthing->z + tmthing->height < thing->z)
|
||||
return true; // underneath
|
||||
|
||||
if (thing->health <= 0)
|
||||
return true;
|
||||
|
||||
P_DoSpring(tmthing, thing);
|
||||
|
||||
return true;
|
||||
return K_OrbinautJawzCollide(thing, tmthing);
|
||||
}
|
||||
else if (tmthing->type == MT_SINK)
|
||||
|
||||
if (tmthing->type == MT_BANANA || tmthing->type == MT_BANANA_SHIELD || tmthing->type == MT_BALLHOG)
|
||||
{
|
||||
// see if it went over / under
|
||||
if (tmthing->z > thing->z + thing->height)
|
||||
|
|
@ -999,34 +898,9 @@ static boolean PIT_CheckThing(mobj_t *thing)
|
|||
if (tmthing->z + tmthing->height < thing->z)
|
||||
return true; // underneath
|
||||
|
||||
if (((tmthing->target == thing) || (tmthing->target == thing->target)) && (tmthing->threshold > 0 || (thing->type != MT_PLAYER && thing->threshold > 0)))
|
||||
return true;
|
||||
|
||||
if (thing->player && thing->player->powers[pw_flashing])
|
||||
return true;
|
||||
|
||||
if (thing->type == MT_PLAYER)
|
||||
{
|
||||
mobj_t *explosion;
|
||||
|
||||
S_StartSound(NULL, sfx_bsnipe); // let all players hear it.
|
||||
|
||||
HU_SetCEchoFlags(0);
|
||||
HU_SetCEchoDuration(5);
|
||||
HU_DoCEcho(va("%s\\was hit by a kitchen sink.\\\\\\\\", player_names[thing->player-players]));
|
||||
I_OutputMsg("%s was hit by a kitchen sink.\n", player_names[thing->player-players]);
|
||||
|
||||
explosion = P_SpawnMobj(thing->x, thing->y, thing->z, MT_SPBEXPLOSION);
|
||||
explosion->extravalue1 = 1; // Tell K_ExplodePlayer to use extra knockback
|
||||
if (tmthing->target && !P_MobjWasRemoved(tmthing->target))
|
||||
P_SetTarget(&explosion->target, tmthing->target);
|
||||
|
||||
P_KillMobj(tmthing, thing, thing);
|
||||
}
|
||||
|
||||
return true;
|
||||
return K_BananaBallhogCollide(tmthing, thing);
|
||||
}
|
||||
else if (tmthing->type == MT_MINEEXPLOSION)
|
||||
else if (thing->type == MT_BANANA || thing->type == MT_BANANA_SHIELD || thing->type == MT_BALLHOG)
|
||||
{
|
||||
// see if it went over / under
|
||||
if (tmthing->z > thing->z + thing->height)
|
||||
|
|
@ -1034,24 +908,10 @@ static boolean PIT_CheckThing(mobj_t *thing)
|
|||
if (tmthing->z + tmthing->height < thing->z)
|
||||
return true; // underneath
|
||||
|
||||
if (!(thing->type == MT_PLAYER))
|
||||
return true;
|
||||
|
||||
if (thing->player && thing->player->powers[pw_flashing])
|
||||
return true;
|
||||
|
||||
if (thing->type == MT_PLAYER && thing->player)
|
||||
{
|
||||
if (tmthing->state == &states[S_MINEEXPLOSION1])
|
||||
K_ExplodePlayer(thing->player, tmthing->target, tmthing);
|
||||
else
|
||||
K_SpinPlayer(thing->player, tmthing->target, 0, tmthing, false);
|
||||
}
|
||||
|
||||
return true; // This doesn't collide with anything, but we want it to effect the player anyway.
|
||||
return K_BananaBallhogCollide(thing, tmthing);
|
||||
}
|
||||
else if (tmthing->type == MT_BANANA_SHIELD || tmthing->type == MT_BANANA
|
||||
|| tmthing->type == MT_BALLHOG)
|
||||
|
||||
if (tmthing->type == MT_SSMINE || tmthing->type == MT_SSMINE_SHIELD)
|
||||
{
|
||||
// see if it went over / under
|
||||
if (tmthing->z > thing->z + thing->height)
|
||||
|
|
@ -1059,78 +919,9 @@ static boolean PIT_CheckThing(mobj_t *thing)
|
|||
if (tmthing->z + tmthing->height < thing->z)
|
||||
return true; // underneath
|
||||
|
||||
if (((tmthing->target == thing) || (tmthing->target == thing->target)) && (tmthing->threshold > 0 || (thing->type != MT_PLAYER && thing->threshold > 0)))
|
||||
return true;
|
||||
|
||||
if (tmthing->health <= 0 || thing->health <= 0)
|
||||
return true;
|
||||
|
||||
if (((tmthing->type == MT_BANANA_SHIELD) && (thing->type == MT_BANANA_SHIELD))
|
||||
&& (tmthing->target == thing->target)) // Don't hit each other if you have the same target
|
||||
return true;
|
||||
|
||||
if (tmthing->type == MT_BALLHOG && thing->type == MT_BALLHOG)
|
||||
return true; // Ballhogs don't collide with eachother
|
||||
|
||||
if (thing->player && thing->player->powers[pw_flashing])
|
||||
return true;
|
||||
|
||||
if (thing->type == MT_PLAYER)
|
||||
{
|
||||
// Banana snipe!
|
||||
if (tmthing->type == MT_BANANA && tmthing->health > 1)
|
||||
S_StartSound(thing, sfx_bsnipe);
|
||||
|
||||
// Player Damage
|
||||
K_SpinPlayer(thing->player, tmthing->target, 0, tmthing, (tmthing->type == MT_BANANA || tmthing->type == MT_BANANA_SHIELD));
|
||||
|
||||
// This Item Damage
|
||||
if (tmthing->eflags & MFE_VERTICALFLIP)
|
||||
tmthing->z -= tmthing->height;
|
||||
else
|
||||
tmthing->z += tmthing->height;
|
||||
|
||||
S_StartSound(tmthing, tmthing->info->deathsound);
|
||||
P_KillMobj(tmthing, thing, thing);
|
||||
|
||||
P_SetObjectMomZ(tmthing, 12*FRACUNIT, false);
|
||||
P_InstaThrust(tmthing, R_PointToAngle2(thing->x, thing->y, tmthing->x, tmthing->y)+ANGLE_90, 16*FRACUNIT);
|
||||
}
|
||||
else if (thing->type == MT_BANANA || thing->type == MT_BANANA_SHIELD
|
||||
|| thing->type == MT_ORBINAUT || thing->type == MT_ORBINAUT_SHIELD
|
||||
|| thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD || thing->type == MT_JAWZ_SHIELD
|
||||
|| thing->type == MT_BALLHOG)
|
||||
{
|
||||
// Other Item Damage
|
||||
if (thing->eflags & MFE_VERTICALFLIP)
|
||||
thing->z -= thing->height;
|
||||
else
|
||||
thing->z += thing->height;
|
||||
|
||||
S_StartSound(thing, thing->info->deathsound);
|
||||
P_KillMobj(thing, tmthing, tmthing);
|
||||
|
||||
P_SetObjectMomZ(thing, 12*FRACUNIT, false);
|
||||
P_InstaThrust(thing, R_PointToAngle2(tmthing->x, tmthing->y, thing->x, thing->y)+ANGLE_90, 16*FRACUNIT);
|
||||
|
||||
P_SpawnMobj(thing->x/2 + tmthing->x/2, thing->y/2 + tmthing->y/2, thing->z/2 + tmthing->z/2, MT_ITEMCLASH);
|
||||
|
||||
// This Item Damage
|
||||
if (tmthing->eflags & MFE_VERTICALFLIP)
|
||||
tmthing->z -= tmthing->height;
|
||||
else
|
||||
tmthing->z += tmthing->height;
|
||||
|
||||
S_StartSound(tmthing, tmthing->info->deathsound);
|
||||
P_KillMobj(tmthing, thing, thing);
|
||||
|
||||
P_SetObjectMomZ(tmthing, 12*FRACUNIT, false);
|
||||
P_InstaThrust(tmthing, R_PointToAngle2(thing->x, thing->y, tmthing->x, tmthing->y)+ANGLE_90, 16*FRACUNIT);
|
||||
}
|
||||
|
||||
return true;
|
||||
return K_MineCollide(tmthing, thing);
|
||||
}
|
||||
else if (tmthing->type == MT_SSMINE_SHIELD || tmthing->type == MT_SSMINE)
|
||||
else if (thing->type == MT_SSMINE || thing->type == MT_SSMINE_SHIELD)
|
||||
{
|
||||
// see if it went over / under
|
||||
if (tmthing->z > thing->z + thing->height)
|
||||
|
|
@ -1138,52 +929,10 @@ static boolean PIT_CheckThing(mobj_t *thing)
|
|||
if (tmthing->z + tmthing->height < thing->z)
|
||||
return true; // underneath
|
||||
|
||||
if (((tmthing->target == thing) || (tmthing->target == thing->target)) && (tmthing->threshold > 0 || (thing->type != MT_PLAYER && thing->threshold > 0)))
|
||||
return true;
|
||||
|
||||
if (tmthing->health <= 0 || thing->health <= 0)
|
||||
return true;
|
||||
|
||||
if (thing->player && thing->player->powers[pw_flashing])
|
||||
return true;
|
||||
|
||||
if (thing->type == MT_PLAYER)
|
||||
{
|
||||
// Bomb punting
|
||||
if ((tmthing->state >= &states[S_SSMINE1] && tmthing->state <= &states[S_SSMINE4])
|
||||
|| (tmthing->state >= &states[S_SSMINE_DEPLOY8] && tmthing->state <= &states[S_SSMINE_DEPLOY13]))
|
||||
P_KillMobj(tmthing, thing, thing);
|
||||
else
|
||||
K_PuntMine(tmthing, thing);
|
||||
}
|
||||
else if (thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD
|
||||
|| thing->type == MT_ORBINAUT_SHIELD || thing->type == MT_JAWZ_SHIELD)
|
||||
{
|
||||
P_KillMobj(tmthing, thing, thing);
|
||||
|
||||
// Other Item Damage
|
||||
if (thing->eflags & MFE_VERTICALFLIP)
|
||||
thing->z -= thing->height;
|
||||
else
|
||||
thing->z += thing->height;
|
||||
|
||||
S_StartSound(thing, thing->info->deathsound);
|
||||
P_KillMobj(thing, tmthing, tmthing);
|
||||
|
||||
P_SetObjectMomZ(thing, 12*FRACUNIT, false);
|
||||
P_InstaThrust(thing, R_PointToAngle2(tmthing->x, tmthing->y, thing->x, thing->y)+ANGLE_90, 16*FRACUNIT);
|
||||
}
|
||||
|
||||
return true;
|
||||
return K_MineCollide(thing, tmthing);
|
||||
}
|
||||
else if (tmthing->type == MT_PLAYER &&
|
||||
(thing->type == MT_ORBINAUT_SHIELD || thing->type == MT_ORBINAUT
|
||||
|| thing->type == MT_JAWZ_SHIELD || thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD
|
||||
|| thing->type == MT_BANANA_SHIELD || thing->type == MT_BANANA
|
||||
|| thing->type == MT_SSMINE_SHIELD || thing->type == MT_SSMINE
|
||||
|| thing->type == MT_MINEEXPLOSION
|
||||
|| thing->type == MT_SINK || thing->type == MT_BALLHOG
|
||||
))
|
||||
|
||||
if (tmthing->type == MT_MINEEXPLOSION)
|
||||
{
|
||||
// see if it went over / under
|
||||
if (tmthing->z > thing->z + thing->height)
|
||||
|
|
@ -1191,130 +940,63 @@ static boolean PIT_CheckThing(mobj_t *thing)
|
|||
if (tmthing->z + tmthing->height < thing->z)
|
||||
return true; // underneath
|
||||
|
||||
if (tmthing->player && tmthing->player->powers[pw_flashing]
|
||||
&& !(thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD))
|
||||
return true;
|
||||
return K_MineExplosionCollide(tmthing, thing);
|
||||
}
|
||||
else if (thing->type == MT_MINEEXPLOSION)
|
||||
{
|
||||
// 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 (tmthing->player && tmthing->player->kartstuff[k_hyudorotimer]) // I thought about doing this for just the objects below but figured it should apply to everything.
|
||||
return true; // no interaction
|
||||
return K_MineExplosionCollide(thing, tmthing);
|
||||
}
|
||||
|
||||
if (thing->type == MT_ORBINAUT_SHIELD || thing->type == MT_JAWZ_SHIELD
|
||||
|| thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD)
|
||||
{
|
||||
if ((thing->target == tmthing) && (thing->threshold > 0))
|
||||
return true;
|
||||
if (tmthing->type == MT_SINK)
|
||||
{
|
||||
// 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 (tmthing->health <= 0 || thing->health <= 0)
|
||||
return true;
|
||||
return K_KitchenSinkCollide(tmthing, thing);
|
||||
}
|
||||
else if (thing->type == MT_SINK)
|
||||
{
|
||||
// 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
|
||||
|
||||
// Player Damage
|
||||
P_DamageMobj(tmthing, thing, thing->target, 1);
|
||||
K_KartBouncing(tmthing, thing, false, false);
|
||||
S_StartSound(tmthing, sfx_s3k7b);
|
||||
return K_KitchenSinkCollide(thing, tmthing);
|
||||
}
|
||||
|
||||
// Other Item Damage
|
||||
if (thing->eflags & MFE_VERTICALFLIP)
|
||||
thing->z -= thing->height;
|
||||
else
|
||||
thing->z += thing->height;
|
||||
if (tmthing->type == MT_FALLINGROCK)
|
||||
{
|
||||
// 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
|
||||
|
||||
S_StartSound(thing, thing->info->deathsound);
|
||||
P_KillMobj(thing, tmthing, tmthing);
|
||||
return K_FallingRockCollide(tmthing, thing);
|
||||
}
|
||||
else if (thing->type == MT_FALLINGROCK)
|
||||
{
|
||||
// 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
|
||||
|
||||
P_SetObjectMomZ(thing, 12*FRACUNIT, false);
|
||||
P_InstaThrust(thing, R_PointToAngle2(tmthing->x, tmthing->y, thing->x, thing->y)+ANGLE_90, 16*FRACUNIT);
|
||||
}
|
||||
else if (thing->type == MT_BANANA_SHIELD || thing->type == MT_BANANA
|
||||
|| thing->type == MT_BALLHOG)
|
||||
{
|
||||
if ((thing->target == tmthing) && (thing->threshold > 0))
|
||||
return true;
|
||||
|
||||
if (tmthing->health <= 0 || thing->health <= 0)
|
||||
return true;
|
||||
|
||||
// Banana snipe!
|
||||
if (thing->type == MT_BANANA && thing->health > 1)
|
||||
S_StartSound(tmthing, sfx_bsnipe);
|
||||
|
||||
// Player Damage
|
||||
K_SpinPlayer(tmthing->player, thing->target, 0, thing, (thing->type == MT_BANANA || thing->type == MT_BANANA_SHIELD));
|
||||
|
||||
// Other Item Damage
|
||||
if (thing->eflags & MFE_VERTICALFLIP)
|
||||
thing->z -= thing->height;
|
||||
else
|
||||
thing->z += thing->height;
|
||||
|
||||
S_StartSound(thing, thing->info->deathsound);
|
||||
P_KillMobj(thing, tmthing, tmthing);
|
||||
|
||||
P_SetObjectMomZ(thing, 12*FRACUNIT, false);
|
||||
P_InstaThrust(thing, R_PointToAngle2(tmthing->x, tmthing->y, thing->x, thing->y)+ANGLE_90, 16*FRACUNIT);
|
||||
}
|
||||
else if (thing->type == MT_SSMINE_SHIELD || thing->type == MT_SSMINE)
|
||||
{
|
||||
if ((thing->target == tmthing) && (thing->threshold > 0))
|
||||
return true;
|
||||
|
||||
if (tmthing->health <= 0 || thing->health <= 0)
|
||||
return true;
|
||||
|
||||
// Bomb punting
|
||||
if ((thing->state >= &states[S_SSMINE1] && thing->state <= &states[S_SSMINE4])
|
||||
|| (thing->state >= &states[S_SSMINE_DEPLOY8] && thing->state <= &states[S_SSMINE_DEPLOY13]))
|
||||
P_KillMobj(thing, tmthing, tmthing);
|
||||
else
|
||||
K_PuntMine(thing, tmthing);
|
||||
}
|
||||
else if (thing->type == MT_MINEEXPLOSION && tmthing->player)
|
||||
{
|
||||
// Player Damage
|
||||
if (thing->state == &states[S_MINEEXPLOSION1])
|
||||
K_ExplodePlayer(tmthing->player, thing->target, thing);
|
||||
else
|
||||
K_SpinPlayer(tmthing->player, thing->target, 0, thing, false);
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (thing->type == MT_SINK)
|
||||
{
|
||||
mobj_t *explosion;
|
||||
|
||||
if ((thing->target == tmthing) && (thing->threshold > 0))
|
||||
return true;
|
||||
|
||||
S_StartSound(NULL, sfx_bsnipe); // let all players hear it.
|
||||
|
||||
HU_SetCEchoFlags(0);
|
||||
HU_SetCEchoDuration(5);
|
||||
HU_DoCEcho(va("%s\\was hit by a kitchen sink.\\\\\\\\", player_names[tmthing->player-players]));
|
||||
I_OutputMsg("%s was hit by a kitchen sink.\n", player_names[tmthing->player-players]);
|
||||
|
||||
explosion = P_SpawnMobj(tmthing->x, tmthing->y, tmthing->z, MT_SPBEXPLOSION);
|
||||
explosion->extravalue1 = 1; // Tell K_ExplodePlayer to use extra knockback
|
||||
if (thing->target && !P_MobjWasRemoved(thing->target))
|
||||
P_SetTarget(&explosion->target, thing->target);
|
||||
|
||||
P_KillMobj(thing, tmthing, tmthing);
|
||||
}
|
||||
|
||||
return true;
|
||||
return K_FallingRockCollide(thing, tmthing);
|
||||
}
|
||||
|
||||
//}
|
||||
|
||||
if ((thing->type == MT_FALLINGROCK && (tmthing->player || tmthing->type == MT_FALLINGROCK))
|
||||
|| (tmthing->type == MT_FALLINGROCK && (thing->player || thing->type == MT_FALLINGROCK)))
|
||||
{
|
||||
// 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
|
||||
K_KartBouncing(thing, tmthing, false, false);
|
||||
}
|
||||
|
||||
if ((thing->type == MT_SPRINGSHELL || thing->type == MT_YELLOWSHELL) && thing->health > 0
|
||||
&& (tmthing->player || (tmthing->flags & MF_PUSHABLE)) && tmthing->health > 0)
|
||||
{
|
||||
|
|
|
|||
474
src/p_mobj.c
474
src/p_mobj.c
|
|
@ -36,6 +36,7 @@
|
|||
#endif
|
||||
|
||||
#include "k_kart.h"
|
||||
#include "k_battle.h"
|
||||
|
||||
// protos.
|
||||
//static CV_PossibleValue_t viewheight_cons_t[] = {{16, "MIN"}, {56, "MAX"}, {0, NULL}};
|
||||
|
|
@ -3614,12 +3615,15 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled
|
|||
dummy.y = thiscam->y;
|
||||
dummy.z = thiscam->z;
|
||||
dummy.height = thiscam->height;
|
||||
if (player->pflags & PF_TIMEOVER)
|
||||
|
||||
if ((player->pflags & PF_TIMEOVER) && G_RaceGametype())
|
||||
player->karthud[khud_timeovercam] = (2*TICRATE)+1;
|
||||
|
||||
if (!resetcalled && !(player->pflags & PF_NOCLIP || leveltime < introtime) && !P_CheckSight(&dummy, player->mo)) // TODO: "P_CheckCameraSight" instead.
|
||||
P_ResetCamera(player, thiscam);
|
||||
else
|
||||
P_SlideCameraMove(thiscam);
|
||||
|
||||
if (resetcalled) // Okay this means the camera is fully reset.
|
||||
return true;
|
||||
}
|
||||
|
|
@ -6268,216 +6272,6 @@ static void P_RemoveOverlay(mobj_t *thing)
|
|||
}
|
||||
}
|
||||
|
||||
// SAL'S KART BATTLE MODE OVERTIME HANDLER
|
||||
#define MAXPLANESPERSECTOR (MAXFFLOORS+1)*2
|
||||
static void P_SpawnOvertimeParticles(fixed_t x, fixed_t y, fixed_t scale, mobjtype_t type, boolean ceiling)
|
||||
{
|
||||
UINT8 i;
|
||||
fixed_t flatz[MAXPLANESPERSECTOR];
|
||||
boolean flip[MAXPLANESPERSECTOR];
|
||||
UINT8 numflats = 0;
|
||||
mobj_t *mo;
|
||||
subsector_t *ss = R_IsPointInSubsector(x, y);
|
||||
sector_t *sec;
|
||||
|
||||
if (!ss)
|
||||
return;
|
||||
sec = ss->sector;
|
||||
|
||||
// convoluted stuff JUST to get all of the planes we need to draw orbs on :V
|
||||
|
||||
for (i = 0; i < MAXPLANESPERSECTOR; i++)
|
||||
flip[i] = false;
|
||||
|
||||
if (sec->floorpic != skyflatnum)
|
||||
{
|
||||
#ifdef ESLOPE
|
||||
flatz[numflats] = (sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : sec->floorheight);
|
||||
#else
|
||||
flatz[numflats] = (sec->floorheight);
|
||||
#endif
|
||||
numflats++;
|
||||
}
|
||||
if (sec->ceilingpic != skyflatnum && ceiling)
|
||||
{
|
||||
#ifdef ESLOPE
|
||||
flatz[numflats] = (sec->c_slope ? P_GetZAt(sec->c_slope, x, y) : sec->ceilingheight) - FixedMul(mobjinfo[type].height, scale);
|
||||
#else
|
||||
flatz[numflats] = (sec->ceilingheight) - FixedMul(mobjinfo[type].height, scale);
|
||||
#endif
|
||||
flip[numflats] = true;
|
||||
numflats++;
|
||||
}
|
||||
|
||||
if (sec->ffloors)
|
||||
{
|
||||
ffloor_t *rover;
|
||||
for (rover = sec->ffloors; rover; rover = rover->next)
|
||||
{
|
||||
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER))
|
||||
continue;
|
||||
if (*rover->toppic != skyflatnum)
|
||||
{
|
||||
#ifdef ESLOPE
|
||||
flatz[numflats] = (*rover->t_slope ? P_GetZAt(*rover->t_slope, x, y) : *rover->topheight);
|
||||
#else
|
||||
flatz[numflats] = (*rover->topheight);
|
||||
#endif
|
||||
numflats++;
|
||||
}
|
||||
if (*rover->bottompic != skyflatnum && ceiling)
|
||||
{
|
||||
#ifdef ESLOPE
|
||||
flatz[numflats] = (*rover->b_slope ? P_GetZAt(*rover->b_slope, x, y) : *rover->bottomheight) - FixedMul(mobjinfo[type].height, scale);
|
||||
#else
|
||||
flatz[numflats] = (*rover->bottomheight) - FixedMul(mobjinfo[type].height, scale);
|
||||
#endif
|
||||
flip[numflats] = true;
|
||||
numflats++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (numflats <= 0) // no flats
|
||||
return;
|
||||
|
||||
for (i = 0; i < numflats; i++)
|
||||
{
|
||||
mo = P_SpawnMobj(x, y, flatz[i], type);
|
||||
|
||||
// Lastly, if this can see the skybox mobj, then... we just wasted our time :V
|
||||
if (skyboxmo[0] && !P_MobjWasRemoved(skyboxmo[0]))
|
||||
{
|
||||
const fixed_t sbz = skyboxmo[0]->z;
|
||||
fixed_t checkz = sec->floorheight;
|
||||
|
||||
while (checkz < sec->ceilingheight)
|
||||
{
|
||||
P_TeleportMove(skyboxmo[0], skyboxmo[0]->x, skyboxmo[0]->y, checkz);
|
||||
if (P_CheckSight(skyboxmo[0], mo))
|
||||
{
|
||||
P_RemoveMobj(mo);
|
||||
break;
|
||||
}
|
||||
else
|
||||
checkz += 32*mapobjectscale;
|
||||
}
|
||||
|
||||
P_TeleportMove(skyboxmo[0], skyboxmo[0]->x, skyboxmo[0]->y, sbz);
|
||||
|
||||
if (P_MobjWasRemoved(mo))
|
||||
continue;
|
||||
}
|
||||
|
||||
P_SetScale(mo, scale);
|
||||
|
||||
if (flip[i])
|
||||
{
|
||||
mo->flags2 |= MF2_OBJECTFLIP;
|
||||
mo->eflags |= MFE_VERTICALFLIP;
|
||||
}
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case MT_OVERTIMEFOG:
|
||||
mo->destscale = 8*mo->scale;
|
||||
mo->momz = P_RandomRange(1,8)*mo->scale;
|
||||
break;
|
||||
case MT_OVERTIMEORB:
|
||||
//mo->destscale = mo->scale/4;
|
||||
mo->frame += ((leveltime/4) % 8);
|
||||
/*if (battleovertime.enabled < 10*TICRATE)
|
||||
mo->flags2 |= MF2_SHADOW;*/
|
||||
mo->angle = R_PointToAngle2(mo->x, mo->y, battleovertime.x, battleovertime.y) + ANGLE_90;
|
||||
mo->z += P_RandomRange(0,48) * mo->scale;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef MAXPLANESPERSECTOR
|
||||
|
||||
void P_RunBattleOvertime(void)
|
||||
{
|
||||
UINT16 i, j;
|
||||
|
||||
if (battleovertime.enabled < 10*TICRATE)
|
||||
{
|
||||
battleovertime.enabled++;
|
||||
if (battleovertime.enabled == TICRATE)
|
||||
S_StartSound(NULL, sfx_bhurry);
|
||||
if (battleovertime.enabled == 10*TICRATE)
|
||||
S_StartSound(NULL, sfx_kc40);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (battleovertime.radius > battleovertime.minradius)
|
||||
battleovertime.radius -= mapobjectscale;
|
||||
else
|
||||
battleovertime.radius = battleovertime.minradius;
|
||||
}
|
||||
|
||||
if (leveltime & 1)
|
||||
{
|
||||
UINT8 transparency = tr_trans50;
|
||||
|
||||
if (!r_splitscreen && players[displayplayers[0]].mo)
|
||||
{
|
||||
INT32 dist = P_AproxDistance(battleovertime.x-players[displayplayers[0]].mo->x, battleovertime.y-players[displayplayers[0]].mo->y);
|
||||
transparency = max(0, NUMTRANSMAPS - ((256 + (dist>>FRACBITS)) / 256));
|
||||
}
|
||||
|
||||
if (transparency < NUMTRANSMAPS)
|
||||
{
|
||||
mobj_t *beam = P_SpawnMobj(battleovertime.x, battleovertime.y, battleovertime.z + (mobjinfo[MT_RANDOMITEM].height/2), MT_OVERTIMEBEAM);
|
||||
P_SetScale(beam, beam->scale*2);
|
||||
if (transparency > 0)
|
||||
beam->frame |= transparency<<FF_TRANSSHIFT;
|
||||
}
|
||||
}
|
||||
|
||||
// 16 orbs at the normal minimum size of 512
|
||||
{
|
||||
const fixed_t pi = (22<<FRACBITS) / 7; // loose approximation, this doesn't need to be incredibly precise
|
||||
fixed_t scale = mapobjectscale + (battleovertime.radius/2048);
|
||||
fixed_t sprwidth = 32*scale;
|
||||
fixed_t circumference = FixedMul(pi, battleovertime.radius<<1);
|
||||
UINT16 orbs = circumference / sprwidth;
|
||||
angle_t angoff = ANGLE_MAX / orbs;
|
||||
|
||||
for (i = 0; i < orbs; i++)
|
||||
{
|
||||
angle_t ang = (i * angoff) + FixedAngle((leveltime/2)<<FRACBITS);
|
||||
fixed_t x = battleovertime.x + P_ReturnThrustX(NULL, ang, battleovertime.radius - FixedMul(mobjinfo[MT_OVERTIMEORB].radius, scale));
|
||||
fixed_t y = battleovertime.y + P_ReturnThrustY(NULL, ang, battleovertime.radius - FixedMul(mobjinfo[MT_OVERTIMEORB].radius, scale));
|
||||
P_SpawnOvertimeParticles(x, y, scale, MT_OVERTIMEORB, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (battleovertime.enabled < 10*TICRATE)
|
||||
return;
|
||||
|
||||
/*if (!S_IdPlaying(sfx_s3kd4s)) // global ambience
|
||||
S_StartSoundAtVolume(NULL, sfx_s3kd4s, min(255, ((4096*mapobjectscale) - battleovertime.radius)>>FRACBITS / 2));*/
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
j = 0;
|
||||
while (j < 32) // max attempts
|
||||
{
|
||||
fixed_t x = battleovertime.x + ((P_RandomRange(-64,64) * 128)<<FRACBITS);
|
||||
fixed_t y = battleovertime.y + ((P_RandomRange(-64,64) * 128)<<FRACBITS);
|
||||
fixed_t closestdist = battleovertime.radius + (8*mobjinfo[MT_OVERTIMEFOG].radius);
|
||||
j++;
|
||||
if (P_AproxDistance(x-battleovertime.x, y-battleovertime.y) < closestdist)
|
||||
continue;
|
||||
P_SpawnOvertimeParticles(x, y, 4*mapobjectscale, MT_OVERTIMEFOG, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void A_BossDeath(mobj_t *mo);
|
||||
// AI for the Koopa boss.
|
||||
static void P_KoopaThinker(mobj_t *koopa)
|
||||
|
|
@ -7124,6 +6918,18 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
P_SetMobjStateNF(smok, smok->info->painstate); // same function, diff sprite
|
||||
}
|
||||
break;
|
||||
case MT_BATTLECAPSULE_PIECE:
|
||||
if (mobj->extravalue2)
|
||||
mobj->frame |= FF_VERTICALFLIP;
|
||||
else
|
||||
mobj->frame &= ~FF_VERTICALFLIP;
|
||||
|
||||
if (mobj->flags2 & MF2_OBJECTFLIP)
|
||||
mobj->eflags |= MFE_VERTICALFLIP;
|
||||
|
||||
if (mobj->tics > 0)
|
||||
mobj->flags2 ^= MF2_DONTDRAW;
|
||||
break;
|
||||
//}
|
||||
case MT_WATERDROP:
|
||||
P_SceneryCheckWater(mobj);
|
||||
|
|
@ -7571,6 +7377,27 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
return;
|
||||
}
|
||||
break;
|
||||
case MT_BATTLECAPSULE:
|
||||
if (!(mobj->fuse & 1))
|
||||
{
|
||||
const SINT8 amt = 96;
|
||||
mobj_t *dust;
|
||||
UINT8 i;
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
fixed_t xoffset = P_RandomRange(-amt, amt) * mobj->scale;
|
||||
fixed_t yoffset = P_RandomRange(-amt, amt) * mobj->scale;
|
||||
fixed_t zoffset = P_RandomRange(-(amt >> 1), (amt >> 1)) * mobj->scale;
|
||||
|
||||
dust = P_SpawnMobj(mobj->x + xoffset, mobj->y + yoffset,
|
||||
mobj->z + (mobj->height >> 1) + zoffset, MT_EXPLODE);
|
||||
}
|
||||
|
||||
if (dust && !P_MobjWasRemoved(dust)) // Only do for 1 explosion
|
||||
S_StartSound(dust, sfx_s3k3d);
|
||||
}
|
||||
break;
|
||||
//}
|
||||
default:
|
||||
break;
|
||||
|
|
@ -9392,6 +9219,229 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
trail->color = mobj->color;
|
||||
}
|
||||
break;
|
||||
case MT_BATTLECAPSULE:
|
||||
{
|
||||
SINT8 realflip = P_MobjFlip(mobj);
|
||||
SINT8 flip = realflip; // Flying capsules needs flipped sprites, but not flipped gravity
|
||||
fixed_t bottom;
|
||||
mobj_t *cur;
|
||||
|
||||
if (mobj->extravalue1)
|
||||
{
|
||||
const INT32 speed = 6*TICRATE; // longer is slower
|
||||
const fixed_t pi = 22*FRACUNIT/7; // Inaccurate, but is close enough for our usage
|
||||
fixed_t sine = FINESINE((((2*pi*speed) * leveltime) >> ANGLETOFINESHIFT) & FINEMASK) * flip;
|
||||
|
||||
// Flying capsules are flipped upside-down, like S3K
|
||||
flip = -flip;
|
||||
|
||||
// ALL CAPSULE MOVEMENT NEEDS TO HAPPEN AFTER THIS & ADD TO MOMENTUM FOR BOBBING TO BE ACCURATE
|
||||
mobj->momz = sine/2;
|
||||
}
|
||||
|
||||
// Moving capsules
|
||||
if (mobj->target && !P_MobjWasRemoved(mobj->target))
|
||||
{
|
||||
fixed_t speed = mobj->movefactor;
|
||||
UINT8 sequence = mobj->lastlook;
|
||||
UINT8 num = mobj->movecount;
|
||||
boolean backandforth = (mobj->flags2 & MF2_AMBUSH);
|
||||
SINT8 direction = mobj->cvmem;
|
||||
mobj_t *next = NULL;
|
||||
thinker_t *th;
|
||||
fixed_t dist, momx, momy, momz;
|
||||
|
||||
dist = P_AproxDistance(mobj->target->x - mobj->x, mobj->target->y - mobj->y);
|
||||
if (mobj->extravalue1)
|
||||
dist = P_AproxDistance(dist, mobj->target->z - mobj->z);
|
||||
if (dist < 1)
|
||||
dist = 1;
|
||||
|
||||
if (speed <= dist)
|
||||
{
|
||||
momx = FixedMul(FixedDiv(mobj->target->x - mobj->x, dist), speed);
|
||||
momy = FixedMul(FixedDiv(mobj->target->y - mobj->y, dist), speed);
|
||||
if (mobj->extravalue1)
|
||||
momz = mobj->momz + FixedMul(FixedDiv(mobj->target->z - mobj->z, dist), speed);
|
||||
|
||||
mobj->momx = momx;
|
||||
mobj->momy = momy;
|
||||
if (mobj->extravalue1)
|
||||
mobj->momz = momz;
|
||||
}
|
||||
else
|
||||
{
|
||||
mobj_t *mo2;
|
||||
|
||||
speed -= dist;
|
||||
|
||||
P_UnsetThingPosition(mobj);
|
||||
mobj->x = mobj->target->x;
|
||||
mobj->y = mobj->target->y;
|
||||
mobj->z = mobj->target->z;
|
||||
P_SetThingPosition(mobj);
|
||||
|
||||
mobj->floorz = mobj->subsector->sector->floorheight;
|
||||
mobj->ceilingz = mobj->subsector->sector->ceilingheight;
|
||||
|
||||
// Onto the next waypoint!
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
|
||||
if (mo2->type != MT_TUBEWAYPOINT)
|
||||
continue;
|
||||
|
||||
if (mo2->threshold == sequence)
|
||||
{
|
||||
if (mo2->health == num + direction)
|
||||
{
|
||||
next = mo2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Are we at the end of the waypoint chain?
|
||||
// If so, search again for the first/previous waypoint (depending on settings)
|
||||
if (next == NULL)
|
||||
{
|
||||
if (backandforth)
|
||||
{
|
||||
mobj->cvmem = -mobj->cvmem;
|
||||
direction = mobj->cvmem;
|
||||
}
|
||||
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
|
||||
if (mo2->type != MT_TUBEWAYPOINT)
|
||||
continue;
|
||||
|
||||
if (mo2->threshold == sequence)
|
||||
{
|
||||
if (backandforth)
|
||||
{
|
||||
if (mo2->health == num + direction)
|
||||
{
|
||||
next = mo2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (direction < 0)
|
||||
{
|
||||
if (next == NULL || mo2->health > next->health)
|
||||
next = mo2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (next == NULL || mo2->health < next->health)
|
||||
next = mo2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (next && !P_MobjWasRemoved(next))
|
||||
{
|
||||
P_SetTarget(&mobj->target, next);
|
||||
mobj->movecount = next->health;
|
||||
|
||||
dist = P_AproxDistance(mobj->target->x - mobj->x, mobj->target->y - mobj->y);
|
||||
if (mobj->extravalue1)
|
||||
dist = P_AproxDistance(dist, mobj->target->z - mobj->z);
|
||||
if (dist < 1)
|
||||
dist = 1;
|
||||
|
||||
momx = FixedMul(FixedDiv(mobj->target->x - mobj->x, dist), speed);
|
||||
momy = FixedMul(FixedDiv(mobj->target->y - mobj->y, dist), speed);
|
||||
if (mobj->extravalue1)
|
||||
momz = mobj->momz + FixedMul(FixedDiv(mobj->target->z - mobj->z, dist), speed);
|
||||
|
||||
mobj->momx = momx;
|
||||
mobj->momy = momy;
|
||||
if (mobj->extravalue1)
|
||||
mobj->momz = momz;
|
||||
}
|
||||
else
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, "Moving capsule could not find next waypoint! (seq: %d)\n", sequence);
|
||||
P_SetTarget(&mobj->target, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (flip == -1)
|
||||
bottom = mobj->z + mobj->height;
|
||||
else
|
||||
bottom = mobj->z;
|
||||
|
||||
cur = mobj->hnext;
|
||||
|
||||
// Move each piece to the proper position
|
||||
while (cur && !P_MobjWasRemoved(cur))
|
||||
{
|
||||
fixed_t newx = mobj->x;
|
||||
fixed_t newy = mobj->y;
|
||||
fixed_t newz = bottom;
|
||||
statenum_t state = (statenum_t)(cur->state-states);
|
||||
|
||||
cur->scale = mobj->scale;
|
||||
cur->destscale = mobj->destscale;
|
||||
cur->scalespeed = mobj->scalespeed;
|
||||
|
||||
cur->extravalue2 = mobj->extravalue1;
|
||||
|
||||
cur->flags2 = (cur->flags2 & ~MF2_OBJECTFLIP)|(mobj->flags2 & MF2_OBJECTFLIP);
|
||||
|
||||
if (state == S_BATTLECAPSULE_TOP)
|
||||
newz += (80 * mobj->scale * flip);
|
||||
else if (state == S_BATTLECAPSULE_BUTTON)
|
||||
newz += (108 * mobj->scale * flip);
|
||||
else if (state == S_BATTLECAPSULE_SUPPORT
|
||||
|| state == S_BATTLECAPSULE_SUPPORTFLY
|
||||
|| state == S_KARMAWHEEL)
|
||||
{
|
||||
fixed_t offx = mobj->radius;
|
||||
fixed_t offy = mobj->radius;
|
||||
|
||||
if (cur->extravalue1 & 1)
|
||||
offx = -offx;
|
||||
|
||||
if (cur->extravalue1 > 1)
|
||||
offy = -offy;
|
||||
|
||||
newx += offx;
|
||||
newy += offy;
|
||||
}
|
||||
else if (state == S_BATTLECAPSULE_SIDE1
|
||||
|| state == S_BATTLECAPSULE_SIDE2)
|
||||
{
|
||||
fixed_t offset = 48 * mobj->scale;
|
||||
angle_t angle = (ANGLE_45 * cur->extravalue1);
|
||||
|
||||
newx += FixedMul(offset, FINECOSINE(angle >> ANGLETOFINESHIFT));
|
||||
newy += FixedMul(offset, FINESINE(angle >> ANGLETOFINESHIFT));
|
||||
newz += (12 * mobj->scale * flip);
|
||||
|
||||
cur->angle = angle + ANGLE_90;
|
||||
}
|
||||
|
||||
P_TeleportMove(cur, newx, newy, newz);
|
||||
|
||||
cur = cur->hnext;
|
||||
}
|
||||
}
|
||||
case MT_RANDOMITEM:
|
||||
if (G_BattleGametype() && mobj->threshold == 70)
|
||||
{
|
||||
|
|
@ -11276,7 +11326,7 @@ void P_SpawnPlayer(INT32 playernum)
|
|||
|| (p->jointime <= 1 && pcount <= 1))
|
||||
{
|
||||
if (leveltime < 1 || (p->jointime <= 1 && pcount <= 1)) // Start of the map?
|
||||
p->kartstuff[k_bumper] = cv_kartbumpers.value; // Reset those bumpers!
|
||||
p->kartstuff[k_bumper] = K_StartingBumperCount(); // Reset those bumpers!
|
||||
|
||||
if (p->kartstuff[k_bumper])
|
||||
{
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#endif
|
||||
|
||||
// SRB2Kart
|
||||
#include "k_battle.h"
|
||||
#include "k_pwrlv.h"
|
||||
|
||||
savedata_t savedata;
|
||||
|
|
@ -3320,6 +3321,8 @@ static void P_NetArchiveMisc(void)
|
|||
|
||||
// SRB2kart
|
||||
WRITEINT32(save_p, numgotboxes);
|
||||
WRITEUINT8(save_p, numtargets);
|
||||
WRITEUINT8(save_p, battlecapsules);
|
||||
|
||||
WRITEUINT8(save_p, gamespeed);
|
||||
WRITEUINT8(save_p, franticitems);
|
||||
|
|
@ -3443,6 +3446,8 @@ static inline boolean P_NetUnArchiveMisc(void)
|
|||
|
||||
// SRB2kart
|
||||
numgotboxes = READINT32(save_p);
|
||||
numtargets = READUINT8(save_p);
|
||||
battlecapsules = (boolean)READUINT8(save_p);
|
||||
|
||||
gamespeed = READUINT8(save_p);
|
||||
franticitems = (boolean)READUINT8(save_p);
|
||||
|
|
|
|||
|
|
@ -84,6 +84,7 @@
|
|||
|
||||
// SRB2Kart
|
||||
#include "k_kart.h"
|
||||
#include "k_battle.h" // K_SpawnBattleCapsules
|
||||
#include "k_pwrlv.h"
|
||||
#include "k_waypoint.h"
|
||||
|
||||
|
|
@ -1026,6 +1027,12 @@ static void P_LoadThings(void)
|
|||
if (mt->type == mobjinfo[MT_RANDOMITEM].doomednum)
|
||||
nummapboxes++;
|
||||
|
||||
if (mt->type == mobjinfo[MT_BATTLECAPSULE].doomednum)
|
||||
{
|
||||
maptargets++;
|
||||
continue; // These should not be spawned *yet*
|
||||
}
|
||||
|
||||
mt->mobj = NULL;
|
||||
P_SpawnMapThing(mt);
|
||||
}
|
||||
|
|
@ -1082,14 +1089,19 @@ static void P_LoadThings(void)
|
|||
for (i = 0; i < nummapthings; i++, mt++)
|
||||
{
|
||||
if (mt->type == 300 || mt->type == 308 || mt->type == 309
|
||||
|| mt->type == 1706 || (mt->type >= 600 && mt->type <= 609)
|
||||
|| mt->type == 1705 || mt->type == 1713 || mt->type == 1800)
|
||||
|| mt->type == 1706 || (mt->type >= 600 && mt->type <= 609)
|
||||
|| mt->type == 1705 || mt->type == 1713 || mt->type == 1800)
|
||||
{
|
||||
sector_t *mtsector = R_PointInSubsector(mt->x << FRACBITS, mt->y << FRACBITS)->sector;
|
||||
|
||||
mt->mobj = NULL;
|
||||
|
||||
// Z for objects Tails 05-26-2002
|
||||
mt->z = (INT16)(R_PointInSubsector(mt->x << FRACBITS, mt->y << FRACBITS)
|
||||
->sector->floorheight>>FRACBITS);
|
||||
// Z for objects
|
||||
mt->z = (INT16)(
|
||||
#ifdef ESLOPE
|
||||
mtsector->f_slope ? P_GetZAt(mtsector->f_slope, mt->x << FRACBITS, mt->y << FRACBITS) :
|
||||
#endif
|
||||
mtsector->floorheight)>>FRACBITS;
|
||||
|
||||
P_SpawnHoopsAndRings (mt);
|
||||
}
|
||||
|
|
@ -2297,15 +2309,13 @@ static void P_LevelInitStuff(void)
|
|||
|
||||
memset(localaiming, 0, sizeof(localaiming));
|
||||
|
||||
// map object scale
|
||||
mapobjectscale = mapheaderinfo[gamemap-1]->mobj_scale;
|
||||
|
||||
// special stage tokens, emeralds, and ring total
|
||||
tokenbits = 0;
|
||||
runemeraldmanager = false;
|
||||
nummaprings = 0;
|
||||
nummapboxes = 0;
|
||||
numgotboxes = 0;
|
||||
nummapboxes = numgotboxes = 0;
|
||||
maptargets = numtargets = 0;
|
||||
battlecapsules = false;
|
||||
|
||||
// emerald hunt
|
||||
hunt1 = hunt2 = hunt3 = NULL;
|
||||
|
|
@ -2634,15 +2644,18 @@ static void P_LoadRecordGhosts(void)
|
|||
}
|
||||
|
||||
// Best Lap ghost
|
||||
if (cv_ghost_bestlap.value)
|
||||
if (modeattacking != ATTACKING_CAPSULES)
|
||||
{
|
||||
for (i = 0; i < numskins; ++i)
|
||||
if (cv_ghost_bestlap.value)
|
||||
{
|
||||
if (cv_ghost_bestlap.value == 1 && players[consoleplayer].skin != i)
|
||||
continue;
|
||||
for (i = 0; i < numskins; ++i)
|
||||
{
|
||||
if (cv_ghost_bestlap.value == 1 && players[consoleplayer].skin != i)
|
||||
continue;
|
||||
|
||||
if (FIL_FileExists(va("%s-%s-lap-best.lmp", gpath, skins[i].name)))
|
||||
G_AddGhost(va("%s-%s-lap-best.lmp", gpath, skins[i].name));
|
||||
if (FIL_FileExists(va("%s-%s-lap-best.lmp", gpath, skins[i].name)))
|
||||
G_AddGhost(va("%s-%s-lap-best.lmp", gpath, skins[i].name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3175,49 +3188,10 @@ boolean P_SetupLevel(boolean skipprecip)
|
|||
}
|
||||
}
|
||||
|
||||
if (modeattacking == ATTACKING_RECORD && !demo.playback)
|
||||
if (modeattacking && !demo.playback)
|
||||
P_LoadRecordGhosts();
|
||||
/*else if (modeattacking == ATTACKING_NIGHTS && !demo.playback)
|
||||
P_LoadNightsGhosts();*/
|
||||
|
||||
if (G_TagGametype())
|
||||
{
|
||||
INT32 realnumplayers = 0;
|
||||
INT32 playersactive[MAXPLAYERS];
|
||||
|
||||
//I just realized how problematic this code can be.
|
||||
//D_NumPlayers() will not always cover the scope of the netgame.
|
||||
//What if one player is node 0 and the other node 31?
|
||||
//The solution? Make a temp array of all players that are currently playing and pick from them.
|
||||
//Future todo? When a player leaves, shift all nodes down so D_NumPlayers() can be used as intended?
|
||||
//Also, you'd never have to loop through all 32 players slots to find anything ever again.
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i] && !players[i].spectator)
|
||||
{
|
||||
playersactive[realnumplayers] = i; //stores the player's node in the array.
|
||||
realnumplayers++;
|
||||
}
|
||||
}
|
||||
|
||||
if (realnumplayers) //this should also fix the dedicated crash bug. You only pick a player if one exists to be picked.
|
||||
{
|
||||
i = P_RandomKey(realnumplayers);
|
||||
players[playersactive[i]].pflags |= PF_TAGIT; //choose our initial tagger before map starts.
|
||||
|
||||
// Taken and modified from G_DoReborn()
|
||||
// Remove the player so he can respawn elsewhere.
|
||||
// first dissasociate the corpse
|
||||
if (players[playersactive[i]].mo)
|
||||
P_RemoveMobj(players[playersactive[i]].mo);
|
||||
|
||||
G_SpawnPlayer(playersactive[i], false); //respawn the lucky player in his dedicated spawn location.
|
||||
}
|
||||
else
|
||||
CONS_Printf(M_GetText("No player currently available to become IT. Awaiting available players.\n"));
|
||||
|
||||
}
|
||||
else if (G_RaceGametype() && server)
|
||||
if (G_RaceGametype() && server)
|
||||
CV_StealthSetValue(&cv_numlaps,
|
||||
((netgame || multiplayer) && cv_basenumlaps.value
|
||||
&& (!(mapheaderinfo[gamemap - 1]->levelflags & LF_SECTIONRACE)
|
||||
|
|
@ -3347,6 +3321,8 @@ boolean P_SetupLevel(boolean skipprecip)
|
|||
if (!(netgame || multiplayer) && !majormods)
|
||||
mapvisited[gamemap-1] |= MV_VISITED;
|
||||
|
||||
G_AddMapToBuffer(gamemap-1);
|
||||
|
||||
levelloading = false;
|
||||
|
||||
P_RunCachedActions();
|
||||
|
|
@ -3384,7 +3360,8 @@ boolean P_SetupLevel(boolean skipprecip)
|
|||
#endif
|
||||
}
|
||||
|
||||
G_AddMapToBuffer(gamemap-1);
|
||||
// NOW you can try to spawn in the Battle capsules, if there's not enough players for a match
|
||||
K_SpawnBattleCapsules();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1983,7 +1983,7 @@ void P_SwitchWeather(UINT8 newWeather)
|
|||
return; // Nothing to do.
|
||||
purge = true;
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
if (precipprops[curWeather].type != MT_NULL)
|
||||
{
|
||||
|
|
@ -2024,7 +2024,7 @@ void P_SwitchWeather(UINT8 newWeather)
|
|||
precipmobj->flags = mobjinfo[swap].flags;
|
||||
|
||||
st = mobjinfo[swap].spawnstate;
|
||||
|
||||
|
||||
if (randomstates > 0)
|
||||
{
|
||||
UINT8 mrand = M_RandomByte();
|
||||
|
|
@ -5699,6 +5699,9 @@ static void P_RunLevelLoadExecutors(void)
|
|||
*/
|
||||
void P_InitSpecials(void)
|
||||
{
|
||||
// Set the map object scale
|
||||
mapobjectscale = mapheaderinfo[gamemap-1]->mobj_scale;
|
||||
|
||||
// Set the default gravity. Custom gravity overrides this setting.
|
||||
gravity = (FRACUNIT*8)/10;
|
||||
|
||||
|
|
|
|||
11
src/p_tick.c
11
src/p_tick.c
|
|
@ -23,6 +23,7 @@
|
|||
#include "lua_script.h"
|
||||
#include "lua_hook.h"
|
||||
#include "k_kart.h"
|
||||
#include "k_battle.h"
|
||||
#include "k_waypoint.h"
|
||||
|
||||
// Object place
|
||||
|
|
@ -636,14 +637,15 @@ void P_Ticker(boolean run)
|
|||
if (run)
|
||||
{
|
||||
P_RunThinkers();
|
||||
if (G_BattleGametype() && battleovertime.enabled)
|
||||
P_RunBattleOvertime();
|
||||
|
||||
// Run any "after all the other thinkers" stuff
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
|
||||
P_PlayerAfterThink(&players[i]);
|
||||
|
||||
if (G_BattleGametype() && battleovertime.enabled)
|
||||
K_RunBattleOvertime();
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
LUAh_ThinkFrame();
|
||||
#endif
|
||||
|
|
@ -793,14 +795,15 @@ void P_PreTicker(INT32 frames)
|
|||
}
|
||||
|
||||
P_RunThinkers();
|
||||
if (G_BattleGametype() && battleovertime.enabled)
|
||||
P_RunBattleOvertime();
|
||||
|
||||
// Run any "after all the other thinkers" stuff
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
|
||||
P_PlayerAfterThink(&players[i]);
|
||||
|
||||
if (G_BattleGametype() && battleovertime.enabled)
|
||||
K_RunBattleOvertime();
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
LUAh_ThinkFrame();
|
||||
#endif
|
||||
|
|
|
|||
11
src/p_user.c
11
src/p_user.c
|
|
@ -1158,10 +1158,10 @@ boolean P_EndingMusic(player_t *player)
|
|||
sprintf(buffer, "k*fail"); // F-Zero death results theme
|
||||
else
|
||||
{
|
||||
if (bestlocalpos == 1)
|
||||
sprintf(buffer, "k*win");
|
||||
else if (K_IsPlayerLosing(bestlocalplayer))
|
||||
if (K_IsPlayerLosing(bestlocalplayer))
|
||||
sprintf(buffer, "k*lose");
|
||||
else if (bestlocalpos == 1)
|
||||
sprintf(buffer, "k*win");
|
||||
else
|
||||
sprintf(buffer, "k*ok");
|
||||
}
|
||||
|
|
@ -6969,9 +6969,10 @@ static void P_DeathThink(player_t *player)
|
|||
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_TIMEOVER)
|
||||
if ((player->pflags & PF_TIMEOVER) && G_RaceGametype())
|
||||
{
|
||||
player->karthud[khud_timeovercam]++;
|
||||
|
||||
if (player->mo)
|
||||
{
|
||||
player->mo->flags |= (MF_NOGRAVITY|MF_NOCLIP);
|
||||
|
|
@ -7186,7 +7187,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
|
|||
|| (leveltime < introtime)); // Kart intro cam
|
||||
#endif
|
||||
|
||||
if (player->pflags & PF_TIMEOVER) // 1 for momentum keep, 2 for turnaround
|
||||
if ((player->pflags & PF_TIMEOVER) && G_RaceGametype()) // 1 for momentum keep, 2 for turnaround
|
||||
timeover = (player->karthud[khud_timeovercam] > 2*TICRATE ? 2 : 1);
|
||||
else
|
||||
timeover = 0;
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@
|
|||
#ifndef __SOUNDS__
|
||||
#define __SOUNDS__
|
||||
|
||||
#include "doomdef.h"
|
||||
|
||||
// Customisable sounds for Skins
|
||||
typedef enum
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1272,7 +1272,7 @@ static void ST_drawNiGHTSHUD(void) // SRB2kart - unused.
|
|||
#endif
|
||||
)
|
||||
{
|
||||
if (modeattacking == ATTACKING_NIGHTS)
|
||||
if (modeattacking == ATTACKING_CAPSULES)
|
||||
{
|
||||
INT32 maretime = max(stplyr->realtime - stplyr->marebegunat, 0);
|
||||
fixed_t cornerx = vid.width, cornery = vid.height-SCZ(20);
|
||||
|
|
|
|||
109
src/y_inter.c
109
src/y_inter.c
|
|
@ -39,6 +39,7 @@
|
|||
#include "m_random.h" // M_RandomKey
|
||||
#include "g_input.h" // PLAYER1INPUTDOWN
|
||||
#include "k_kart.h" // colortranslations
|
||||
#include "k_battle.h"
|
||||
#include "k_pwrlv.h"
|
||||
#include "console.h" // cons_menuhighlight
|
||||
#include "lua_hook.h" // IntermissionThinker hook
|
||||
|
|
@ -168,7 +169,7 @@ static void Y_UnloadVoteData(void);
|
|||
//
|
||||
// SRB2Kart - Y_CalculateMatchData and ancillary functions
|
||||
//
|
||||
static void Y_CompareRace(INT32 i)
|
||||
static void Y_CompareTime(INT32 i)
|
||||
{
|
||||
UINT32 val = ((players[i].pflags & PF_TIMEOVER || players[i].realtime == UINT32_MAX)
|
||||
? (UINT32_MAX-1) : players[i].realtime);
|
||||
|
|
@ -180,7 +181,7 @@ static void Y_CompareRace(INT32 i)
|
|||
data.match.num[data.match.numplayers] = i;
|
||||
}
|
||||
|
||||
static void Y_CompareBattle(INT32 i)
|
||||
static void Y_CompareScore(INT32 i)
|
||||
{
|
||||
UINT32 val = ((players[i].pflags & PF_TIMEOVER)
|
||||
? (UINT32_MAX-1) : players[i].marescore);
|
||||
|
|
@ -440,7 +441,7 @@ void Y_IntermissionDrawer(void)
|
|||
if (data.match.rankingsmode)
|
||||
timeheader = "PWR.LV";
|
||||
else
|
||||
timeheader = (intertype == int_race ? "TIME" : "SCORE");
|
||||
timeheader = ((intertype == int_race || (intertype == int_match && battlecapsules)) ? "TIME" : "SCORE");
|
||||
|
||||
// draw the level name
|
||||
V_DrawCenteredString(-4 + x + BASEVIDWIDTH/2, 12, 0, data.match.levelstring);
|
||||
|
|
@ -559,7 +560,7 @@ void Y_IntermissionDrawer(void)
|
|||
V_DrawRightAlignedThinString(x+152+gutter, y-1, (data.match.numplayers > NUMFORNEWCOLUMN ? V_6WIDTHSPACE : 0), "NO CONTEST.");
|
||||
else
|
||||
{
|
||||
if (intertype == int_race)
|
||||
if (intertype == int_race || (intertype == int_match && battlecapsules))
|
||||
{
|
||||
snprintf(strtime, sizeof strtime, "%i'%02i\"%02i", G_TicsToMinutes(data.match.val[i], true),
|
||||
G_TicsToSeconds(data.match.val[i]), G_TicsToCentiseconds(data.match.val[i]));
|
||||
|
|
@ -745,7 +746,7 @@ void Y_Ticker(void)
|
|||
remove = 10;
|
||||
|
||||
// Remove 10 points at a time
|
||||
data.match.increase[data.match.num[q]] -= remove;
|
||||
data.match.increase[data.match.num[q]] -= remove;
|
||||
|
||||
// Still not zero, no kaching yet
|
||||
if (data.match.increase[data.match.num[q]] != 0)
|
||||
|
|
@ -795,11 +796,26 @@ static void Y_UpdateRecordReplays(void)
|
|||
if (!mainrecords[gamemap-1])
|
||||
G_AllocMainRecordData(gamemap-1);
|
||||
|
||||
if ((mainrecords[gamemap-1]->time == 0) || (players[consoleplayer].realtime < mainrecords[gamemap-1]->time))
|
||||
mainrecords[gamemap-1]->time = players[consoleplayer].realtime;
|
||||
if (players[consoleplayer].pflags & PF_TIMEOVER)
|
||||
{
|
||||
players[consoleplayer].realtime = UINT32_MAX;
|
||||
}
|
||||
|
||||
if ((mainrecords[gamemap-1]->lap == 0) || (bestlap < mainrecords[gamemap-1]->lap))
|
||||
mainrecords[gamemap-1]->lap = bestlap;
|
||||
if (((mainrecords[gamemap-1]->time == 0) || (players[consoleplayer].realtime < mainrecords[gamemap-1]->time))
|
||||
&& (players[consoleplayer].realtime < UINT32_MAX)) // DNF
|
||||
{
|
||||
mainrecords[gamemap-1]->time = players[consoleplayer].realtime;
|
||||
}
|
||||
|
||||
if (modeattacking == ATTACKING_RECORD)
|
||||
{
|
||||
if ((mainrecords[gamemap-1]->lap == 0) || (bestlap < mainrecords[gamemap-1]->lap))
|
||||
mainrecords[gamemap-1]->lap = bestlap;
|
||||
}
|
||||
else
|
||||
{
|
||||
mainrecords[gamemap-1]->lap = 0;
|
||||
}
|
||||
|
||||
// Save demo!
|
||||
bestdemo[255] = '\0';
|
||||
|
|
@ -830,13 +846,16 @@ static void Y_UpdateRecordReplays(void)
|
|||
CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW RECORD TIME!"), M_GetText("Saved replay as"), bestdemo);
|
||||
}
|
||||
|
||||
snprintf(bestdemo, 255, "%s-%s-lap-best.lmp", gpath, cv_chooseskin.string);
|
||||
if (!FIL_FileExists(bestdemo) || G_CmpDemoTime(bestdemo, lastdemo) & (1<<1))
|
||||
{ // Better lap time, save this demo.
|
||||
if (FIL_FileExists(bestdemo))
|
||||
remove(bestdemo);
|
||||
FIL_WriteFile(bestdemo, buf, len);
|
||||
CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW RECORD LAP!"), M_GetText("Saved replay as"), bestdemo);
|
||||
if (modeattacking == ATTACKING_RECORD)
|
||||
{
|
||||
snprintf(bestdemo, 255, "%s-%s-lap-best.lmp", gpath, cv_chooseskin.string);
|
||||
if (!FIL_FileExists(bestdemo) || G_CmpDemoTime(bestdemo, lastdemo) & (1<<1))
|
||||
{ // Better lap time, save this demo.
|
||||
if (FIL_FileExists(bestdemo))
|
||||
remove(bestdemo);
|
||||
FIL_WriteFile(bestdemo, buf, len);
|
||||
CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW RECORD LAP!"), M_GetText("Saved replay as"), bestdemo);
|
||||
}
|
||||
}
|
||||
|
||||
//CONS_Printf("%s '%s'\n", M_GetText("Saved replay as"), lastdemo);
|
||||
|
|
@ -1036,12 +1055,20 @@ void Y_StartIntermission(void)
|
|||
{
|
||||
timer = 0;
|
||||
|
||||
/* // srb2kart: time attack tally is UGLY rn
|
||||
if (modeattacking)
|
||||
intertype = int_timeattack;
|
||||
else
|
||||
*/
|
||||
intertype = int_race;
|
||||
if (!majormods && !multiplayer && !demo.playback) // move this once we have a proper time attack screen
|
||||
{
|
||||
// Update visitation flags
|
||||
mapvisited[gamemap-1] |= MV_BEATEN;
|
||||
if (ALL7EMERALDS(emeralds))
|
||||
mapvisited[gamemap-1] |= MV_ALLEMERALDS;
|
||||
/*if (ultimatemode)
|
||||
mapvisited[gamemap-1] |= MV_ULTIMATE;
|
||||
if (data.coop.gotperfbonus)
|
||||
mapvisited[gamemap-1] |= MV_PERFECT;*/
|
||||
|
||||
if (modeattacking)
|
||||
Y_UpdateRecordReplays();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1056,13 +1083,13 @@ void Y_StartIntermission(void)
|
|||
if (!timer)
|
||||
timer = 1;
|
||||
}
|
||||
|
||||
if (gametype == GT_MATCH)
|
||||
intertype = int_match;
|
||||
else //if (gametype == GT_RACE)
|
||||
intertype = int_race;
|
||||
}
|
||||
|
||||
if (gametype == GT_MATCH)
|
||||
intertype = int_match;
|
||||
else //if (gametype == GT_RACE)
|
||||
intertype = int_race;
|
||||
|
||||
// We couldn't display the intermission even if we wanted to.
|
||||
// But we still need to give the players their score bonuses, dummy.
|
||||
//if (dedicated) return;
|
||||
|
|
@ -1076,30 +1103,24 @@ void Y_StartIntermission(void)
|
|||
case int_match:
|
||||
{
|
||||
// Calculate who won
|
||||
Y_CalculateMatchData(0, Y_CompareBattle);
|
||||
if (battlecapsules)
|
||||
{
|
||||
Y_CalculateMatchData(0, Y_CompareTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
Y_CalculateMatchData(0, Y_CompareScore);
|
||||
}
|
||||
|
||||
if (cv_inttime.value > 0)
|
||||
S_ChangeMusicInternal("racent", true); // loop it
|
||||
|
||||
break;
|
||||
}
|
||||
case int_race: // (time-only race)
|
||||
{
|
||||
if (!majormods && !multiplayer && !demo.playback) // remove this once we have a proper time attack screen
|
||||
{
|
||||
// Update visitation flags
|
||||
mapvisited[gamemap-1] |= MV_BEATEN;
|
||||
if (ALL7EMERALDS(emeralds))
|
||||
mapvisited[gamemap-1] |= MV_ALLEMERALDS;
|
||||
/*if (ultimatemode)
|
||||
mapvisited[gamemap-1] |= MV_ULTIMATE;
|
||||
if (data.coop.gotperfbonus)
|
||||
mapvisited[gamemap-1] |= MV_PERFECT;*/
|
||||
|
||||
if (modeattacking == ATTACKING_RECORD)
|
||||
Y_UpdateRecordReplays();
|
||||
}
|
||||
|
||||
// Calculate who won
|
||||
Y_CalculateMatchData(0, Y_CompareRace);
|
||||
Y_CalculateMatchData(0, Y_CompareTime);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue