mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Boss API + assorted relevant bugfixes, will go over the featureset of this branch with a fine toothed comb when it's time to write the merge request description so this is all you're getting right now
This commit is contained in:
parent
82377fb001
commit
c1f3237157
36 changed files with 1225 additions and 142 deletions
|
|
@ -110,6 +110,7 @@ k_bot.c
|
|||
k_botitem.c
|
||||
k_botsearch.c
|
||||
k_grandprix.c
|
||||
k_boss.c
|
||||
k_hud.c
|
||||
k_terrain.c
|
||||
k_brightmap.c
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@
|
|||
#include "k_pwrlv.h"
|
||||
#include "k_bot.h"
|
||||
#include "k_grandprix.h"
|
||||
#include "k_boss.h"
|
||||
#include "doomstat.h"
|
||||
#include "s_sound.h" // sfx_syfail
|
||||
|
||||
|
|
@ -3757,7 +3758,7 @@ void SV_StartSinglePlayerServer(void)
|
|||
netgame = false;
|
||||
multiplayer = false;
|
||||
|
||||
if (modeattacking == ATTACKING_CAPSULES)
|
||||
if ((modeattacking == ATTACKING_CAPSULES) || (bossinfo.boss == true))
|
||||
{
|
||||
G_SetGametype(GT_BATTLE);
|
||||
}
|
||||
|
|
|
|||
10
src/d_main.c
10
src/d_main.c
|
|
@ -71,6 +71,7 @@
|
|||
|
||||
// SRB2Kart
|
||||
#include "k_grandprix.h"
|
||||
#include "k_boss.h"
|
||||
#include "doomstat.h"
|
||||
|
||||
#ifdef CMAKECONFIG
|
||||
|
|
@ -928,6 +929,13 @@ void D_StartTitle(void)
|
|||
// Reset GP
|
||||
memset(&grandprixinfo, 0, sizeof(struct grandprixinfo));
|
||||
|
||||
// Reset boss info
|
||||
if (bossinfo.enemyname)
|
||||
Z_Free(bossinfo.enemyname);
|
||||
if (bossinfo.subtitle)
|
||||
Z_Free(bossinfo.subtitle);
|
||||
memset(&bossinfo, 0, sizeof(struct bossinfo));
|
||||
|
||||
// empty maptol so mario/etc sounds don't play in sound test when they shouldn't
|
||||
maptol = 0;
|
||||
|
||||
|
|
@ -1105,6 +1113,8 @@ static void IdentifyVersion(void)
|
|||
D_AddFile(startupiwads, va(pandf,srb2waddir,"followers.pk3"));
|
||||
#ifdef USE_PATCH_FILE
|
||||
D_AddFile(startupiwads, va(pandf,srb2waddir,PATCHNAME));
|
||||
// lat` had the right idea
|
||||
D_AddFile(startupiwads, va(pandf,srb2waddir,"bosstest.pk3"));
|
||||
#endif
|
||||
////
|
||||
#undef TEXTURESNAME
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@
|
|||
#include "k_color.h"
|
||||
#include "k_respawn.h"
|
||||
#include "k_grandprix.h"
|
||||
#include "k_boss.h"
|
||||
#include "doomstat.h"
|
||||
#include "deh_tables.h"
|
||||
|
||||
|
|
@ -2376,6 +2377,10 @@ void D_MapChange(INT32 mapnum, INT32 newgametype, boolean pencoremode, boolean r
|
|||
// Too lazy to change the input value for every instance of this function.......
|
||||
pencoremode = grandprixinfo.encore;
|
||||
}
|
||||
else if (bossinfo.boss == true)
|
||||
{
|
||||
pencoremode = bossinfo.encore;
|
||||
}
|
||||
|
||||
if (delay != 2)
|
||||
{
|
||||
|
|
@ -2858,7 +2863,7 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum)
|
|||
else if (gametype != lastgametype)
|
||||
D_GameTypeChanged(lastgametype); // emulate consvar_t behavior for gametype
|
||||
|
||||
if (!(gametyperules & GTR_CIRCUIT))
|
||||
if (!(gametyperules & GTR_CIRCUIT) && !bossinfo.boss)
|
||||
pencoremode = false;
|
||||
|
||||
skipprecutscene = ((flags & (1<<2)) != 0);
|
||||
|
|
@ -4991,9 +4996,9 @@ void Command_Retry_f(void)
|
|||
{
|
||||
CONS_Printf(M_GetText("You must be in a level to use this.\n"));
|
||||
}
|
||||
else if (grandprixinfo.gp == false)
|
||||
else if (grandprixinfo.gp == false && bossinfo.boss == false)
|
||||
{
|
||||
CONS_Printf(M_GetText("This only works in Grand Prix.\n"));
|
||||
CONS_Printf(M_GetText("This only works in Grand Prix or Mission Mode.\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#include "i_sound.h" // musictype_t (for lua)
|
||||
#include "g_state.h" // gamestate_t (for lua)
|
||||
#include "r_data.h" // patchalphastyle_t
|
||||
#include "k_boss.h" // spottype_t (for lua)
|
||||
|
||||
#include "deh_tables.h"
|
||||
|
||||
|
|
@ -5862,6 +5863,8 @@ const char *const MOBJEFLAG_LIST[] = {
|
|||
"APPLYPMOMZ", // Platform movement
|
||||
"TRACERANGLE", // Compute and trigger on mobj angle relative to tracer
|
||||
"JUSTBOUNCEDWALL",
|
||||
"DAMAGEHITLAG",
|
||||
"SLOPELAUNCHED",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
@ -6316,6 +6319,7 @@ struct int_const_s const INT_CONST[] = {
|
|||
{"FRACUNIT",FRACUNIT},
|
||||
{"FU" ,FRACUNIT},
|
||||
{"FRACBITS",FRACBITS},
|
||||
{"M_TAU_FIXED",M_TAU_FIXED},
|
||||
|
||||
// doomdef.h constants
|
||||
{"TICRATE",TICRATE},
|
||||
|
|
@ -6568,7 +6572,7 @@ struct int_const_s const INT_CONST[] = {
|
|||
{"int_none",int_none},
|
||||
{"int_race",int_race},
|
||||
{"int_battle",int_battle},
|
||||
{"int_timeattack",int_timeattack},
|
||||
{"int_battletime", int_battletime},
|
||||
|
||||
// Jingles (jingletype_t)
|
||||
{"JT_NONE",JT_NONE},
|
||||
|
|
@ -6940,6 +6944,11 @@ struct int_const_s const INT_CONST[] = {
|
|||
{"KSPIN_STUNG",KSPIN_STUNG},
|
||||
{"KSPIN_EXPLOSION",KSPIN_EXPLOSION},
|
||||
|
||||
// spottype_t
|
||||
{"SPOT_NONE",SPOT_NONE},
|
||||
{"SPOT_WEAK",SPOT_WEAK},
|
||||
{"SPOT_BUMP",SPOT_BUMP},
|
||||
|
||||
{NULL,0}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -500,11 +500,12 @@ extern INT32 timelimits[NUMGAMETYPES];
|
|||
enum TypeOfLevel
|
||||
{
|
||||
// Gametypes
|
||||
TOL_RACE = 0x0001, ///< Race
|
||||
TOL_BATTLE = 0x0002, ///< Battle
|
||||
TOL_RACE = 0x0001, ///< Race
|
||||
TOL_BATTLE = 0x0002, ///< Battle
|
||||
TOL_BOSS = 0x0004, ///< Boss (variant of battle, but forbidden)
|
||||
|
||||
// Modifiers
|
||||
TOL_TV = 0x0100, ///< Midnight Channel specific: draw TV like overlay on HUD
|
||||
TOL_TV = 0x0100 ///< Midnight Channel specific: draw TV like overlay on HUD
|
||||
};
|
||||
|
||||
#define MAXTOL (1<<31)
|
||||
|
|
|
|||
41
src/g_game.c
41
src/g_game.c
|
|
@ -56,6 +56,7 @@
|
|||
#include "k_color.h"
|
||||
#include "k_respawn.h"
|
||||
#include "k_grandprix.h"
|
||||
#include "k_boss.h"
|
||||
#include "k_bot.h"
|
||||
#include "doomstat.h"
|
||||
|
||||
|
|
@ -2668,7 +2669,7 @@ mapthing_t *G_FindMapStart(INT32 playernum)
|
|||
{
|
||||
// In platform gametypes, spawn in Co-op starts first
|
||||
// Overriden by GTR_BATTLESTARTS.
|
||||
if (gametyperules & GTR_BATTLESTARTS)
|
||||
if (gametyperules & GTR_BATTLESTARTS && bossinfo.boss == false)
|
||||
spawnpoint = G_FindBattleStartOrFallback(playernum);
|
||||
else
|
||||
spawnpoint = G_FindRaceStartOrFallback(playernum);
|
||||
|
|
@ -2775,10 +2776,30 @@ void G_ExitLevel(void)
|
|||
{
|
||||
if (gamestate == GS_LEVEL)
|
||||
{
|
||||
if (grandprixinfo.gp == true && grandprixinfo.wonround != true)
|
||||
UINT8 i;
|
||||
boolean youlost = false;
|
||||
if (bossinfo.boss == true)
|
||||
{
|
||||
UINT8 i;
|
||||
youlost = true;
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i] && !players[i].spectator && !players[i].bot)
|
||||
{
|
||||
if (players[i].bumpers > 0)
|
||||
{
|
||||
youlost = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (grandprixinfo.gp == true)
|
||||
{
|
||||
youlost = (grandprixinfo.wonround != true);
|
||||
}
|
||||
|
||||
if (youlost)
|
||||
{
|
||||
// You didn't win...
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
|
|
@ -3007,6 +3028,7 @@ UINT32 gametypetol[NUMGAMETYPES] =
|
|||
tolinfo_t TYPEOFLEVEL[NUMTOLNAMES] = {
|
||||
{"RACE",TOL_RACE},
|
||||
{"BATTLE",TOL_BATTLE},
|
||||
{"BOSS",TOL_BOSS},
|
||||
{"TV",TOL_TV},
|
||||
{NULL, 0}
|
||||
};
|
||||
|
|
@ -3084,10 +3106,17 @@ boolean G_IsSpecialStage(INT32 mapnum)
|
|||
//
|
||||
boolean G_GametypeUsesLives(void)
|
||||
{
|
||||
if (modeattacking || metalrecording) // NOT in Record Attack
|
||||
return false;
|
||||
|
||||
if (bossinfo.boss == true) // Fighting a boss?
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((grandprixinfo.gp == true) // In Grand Prix
|
||||
&& (gametype == GT_RACE) // NOT in bonus round
|
||||
&& !G_IsSpecialStage(gamemap) // NOT in special stage
|
||||
&& !(modeattacking || metalrecording)) // NOT in Record Attack
|
||||
&& !G_IsSpecialStage(gamemap)) // NOT in special stage
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
@ -3709,7 +3738,7 @@ void G_NextLevel(void)
|
|||
{
|
||||
if (gamestate != GS_VOTING)
|
||||
{
|
||||
if ((cv_advancemap.value == 3) && grandprixinfo.gp == false && !modeattacking && !skipstats && (multiplayer || netgame))
|
||||
if ((cv_advancemap.value == 3) && grandprixinfo.gp == false && bossinfo.boss == false && !modeattacking && !skipstats && (multiplayer || netgame))
|
||||
{
|
||||
UINT8 i;
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
|
|
|
|||
|
|
@ -6784,7 +6784,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
4, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
/// \brief SRB2Kart Battle Mode specific code
|
||||
|
||||
#include "k_battle.h"
|
||||
#include "k_boss.h"
|
||||
#include "k_kart.h"
|
||||
#include "doomtype.h"
|
||||
#include "doomdata.h"
|
||||
|
|
@ -68,6 +69,9 @@ void K_SpawnBattlePoints(player_t *source, player_t *victim, UINT8 amount)
|
|||
pt->color = victim->skincolor;
|
||||
else
|
||||
pt->color = source->skincolor;
|
||||
|
||||
if (encoremode)
|
||||
pt->renderflags ^= RF_HORIZONTALFLIP;
|
||||
}
|
||||
|
||||
void K_CheckBumpers(void)
|
||||
|
|
@ -107,7 +111,19 @@ void K_CheckBumpers(void)
|
|||
winnerscoreadd -= players[i].roundscore;
|
||||
}
|
||||
|
||||
if (numingame <= 1)
|
||||
if (bossinfo.boss)
|
||||
{
|
||||
if (nobumpers)
|
||||
{
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
players[i].pflags |= PF_NOCONTEST;
|
||||
P_DoPlayerExit(&players[i]);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (numingame <= 1)
|
||||
{
|
||||
if (!battlecapsules)
|
||||
{
|
||||
|
|
@ -697,6 +713,9 @@ void K_SpawnBattleCapsules(void)
|
|||
if (battlecapsules)
|
||||
return;
|
||||
|
||||
if (bossinfo.boss)
|
||||
return;
|
||||
|
||||
if (!(gametyperules & GTR_CAPSULES))
|
||||
return;
|
||||
|
||||
|
|
|
|||
188
src/k_boss.c
Normal file
188
src/k_boss.c
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
// SONIC ROBO BLAST 2 KART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2018-2022 by Viv "toaster" Grannell
|
||||
// Copyright (C) 2018-2022 by Kart Krew
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file k_boss.c
|
||||
/// \brief Boss battle game logic
|
||||
|
||||
#include "k_boss.h"
|
||||
#include "doomdef.h"
|
||||
#include "d_player.h"
|
||||
#include "g_game.h"
|
||||
#include "p_local.h"
|
||||
#include "k_kart.h"
|
||||
#include "s_sound.h"
|
||||
#include "st_stuff.h"
|
||||
#include "z_zone.h"
|
||||
|
||||
struct bossinfo bossinfo;
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_BossInfoTicker(void)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
void K_BossInfoTicker(void)
|
||||
{
|
||||
UINT8 i;
|
||||
|
||||
if (bossinfo.boss == false)
|
||||
return;
|
||||
|
||||
// Update healthbar data. (only if the hud is visible)
|
||||
if (leveltime > (TICRATE/2)+3)
|
||||
{
|
||||
// Greater than the actual health?
|
||||
if (bossinfo.visualbar > bossinfo.healthbar)
|
||||
{
|
||||
bossinfo.visualbar--;
|
||||
// If the boss is dying, start shrinking the healthbar.
|
||||
if (bossinfo.visualbar == 0)
|
||||
bossinfo.barlen-= 2;
|
||||
}
|
||||
// Less than the actual health?
|
||||
else if (bossinfo.visualbar < bossinfo.healthbar)
|
||||
bossinfo.visualbar++;
|
||||
// Continue to shrink the healthbar.
|
||||
else if (bossinfo.barlen > 1 && bossinfo.barlen < BOSSHEALTHBARLEN)
|
||||
bossinfo.barlen -= 2;
|
||||
|
||||
// Jitter timer.
|
||||
if (bossinfo.visualbarimpact)
|
||||
bossinfo.visualbarimpact--;
|
||||
}
|
||||
|
||||
if (bossinfo.doweakspotsound != SPOT_NONE)
|
||||
{
|
||||
S_StartSound(NULL, sfx_mbs55); // may change for bump option
|
||||
bossinfo.doweakspotsound = SPOT_NONE;
|
||||
}
|
||||
|
||||
// Update weakspot data.
|
||||
for (i = 0; i < NUMWEAKSPOTS; i++)
|
||||
{
|
||||
// Clean out invalid references.
|
||||
if ((bossinfo.weakspots[i].spot && P_MobjWasRemoved(bossinfo.weakspots[i].spot)))
|
||||
P_SetTarget(&bossinfo.weakspots[i].spot, NULL);
|
||||
|
||||
if (bossinfo.weakspots[i].spot == NULL)
|
||||
continue;
|
||||
|
||||
// Damaged quickly? Make it disappear immediately (making sure to match the flashing).
|
||||
if ((bossinfo.weakspots[i].spot->hitlag > 0) && (bossinfo.weakspots[i].time > TICRATE/2))
|
||||
bossinfo.weakspots[i].time = (TICRATE/2) & ~(bossinfo.weakspots[i].time & 1);
|
||||
|
||||
// Handle counter.
|
||||
if (!bossinfo.weakspots[i].time)
|
||||
continue;
|
||||
bossinfo.weakspots[i].time--;
|
||||
|
||||
// Get rid of concluded spots.
|
||||
if (!bossinfo.weakspots[i].time && !bossinfo.weakspots[i].minimap)
|
||||
P_SetTarget(&bossinfo.weakspots[i].spot, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_InitBossHealthBar(const char *enemyname, const char *subtitle, sfxenum_t titlesound, fixed_t pinchmagnitude, UINT8 divisions)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
|
||||
void K_InitBossHealthBar(const char *enemyname, const char *subtitle, sfxenum_t titlesound, fixed_t pinchmagnitude, UINT8 divisions)
|
||||
{
|
||||
if (enemyname && enemyname[0])
|
||||
{
|
||||
if (bossinfo.enemyname)
|
||||
Z_Free(bossinfo.enemyname);
|
||||
bossinfo.enemyname = Z_StrDup(enemyname);
|
||||
}
|
||||
|
||||
if (subtitle && subtitle[0])
|
||||
{
|
||||
if (bossinfo.subtitle)
|
||||
Z_Free(bossinfo.subtitle);
|
||||
bossinfo.subtitle = Z_StrDup(subtitle);
|
||||
}
|
||||
|
||||
if (titlesound)
|
||||
{
|
||||
bossinfo.titlesound = titlesound;
|
||||
}
|
||||
|
||||
bossinfo.barlen = BOSSHEALTHBARLEN;
|
||||
K_UpdateBossHealthBar(FRACUNIT, 0);
|
||||
|
||||
bossinfo.healthbarpinch = FixedMul(pinchmagnitude, BOSSHEALTHBARLEN*FRACUNIT)>>FRACBITS;
|
||||
|
||||
// we do this here so we can fudge our working a bit
|
||||
if (divisions > 0)
|
||||
{
|
||||
if (divisions > (BOSSHEALTHBARLEN/2)) // megamanification
|
||||
{
|
||||
divisions = (BOSSHEALTHBARLEN/2);
|
||||
}
|
||||
bossinfo.visualdiv = FixedDiv(BOSSHEALTHBARLEN*FRACUNIT, divisions*FRACUNIT);
|
||||
}
|
||||
else
|
||||
{
|
||||
bossinfo.visualdiv = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_UpdateBossHealthBar(fixed_t magnitude, tic_t jitterlen)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
|
||||
void K_UpdateBossHealthBar(fixed_t magnitude, tic_t jitterlen)
|
||||
{
|
||||
if (jitterlen > bossinfo.visualbarimpact)
|
||||
bossinfo.visualbarimpact = jitterlen;
|
||||
bossinfo.healthbar = FixedMul(magnitude, BOSSHEALTHBARLEN);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_DeclareWeakspot(mobj_t *weakspot, spottype_t spottype, boolean minimap)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
void K_DeclareWeakspot(mobj_t *spot, spottype_t spottype, UINT16 color, boolean minimap)
|
||||
{
|
||||
UINT8 i;
|
||||
|
||||
// First check whether the spot is already in the list and simply redeclaring weakness (for example, a vulnerable moment in the pattern).
|
||||
for (i = 0; i < NUMWEAKSPOTS; i++)
|
||||
if (bossinfo.weakspots[i].spot == spot)
|
||||
break;
|
||||
|
||||
// If it's not redeclaring, check for an empty spot.
|
||||
if (i == NUMWEAKSPOTS)
|
||||
{
|
||||
for (i = 0; i < NUMWEAKSPOTS; i++)
|
||||
if (!bossinfo.weakspots[i].spot || P_MobjWasRemoved(bossinfo.weakspots[i].spot))
|
||||
break;
|
||||
}
|
||||
|
||||
// If you've crammed up the list with minimap entries (the only ones that will persist), give up.
|
||||
if (i == NUMWEAKSPOTS)
|
||||
return;
|
||||
|
||||
// OK, now we can slot in the weakspot data...
|
||||
P_SetTarget(&bossinfo.weakspots[i].spot, spot);
|
||||
bossinfo.weakspots[i].type = spottype;
|
||||
bossinfo.weakspots[i].time = WEAKSPOTANIMTIME;
|
||||
bossinfo.weakspots[i].color = color;
|
||||
bossinfo.weakspots[i].minimap = minimap;
|
||||
|
||||
if (spottype && bossinfo.doweakspotsound != SPOT_WEAK)
|
||||
{
|
||||
bossinfo.doweakspotsound = spottype;
|
||||
}
|
||||
}
|
||||
63
src/k_boss.h
Normal file
63
src/k_boss.h
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
// SONIC ROBO BLAST 2 KART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2018-2022 by Viv "toaster" Grannell
|
||||
// Copyright (C) 2018-2022 by Kart Krew
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file k_boss.h
|
||||
/// \brief Boss battle game logic
|
||||
|
||||
#ifndef __K_BOSS__
|
||||
#define __K_BOSS__
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "doomstat.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SPOT_NONE = 0,
|
||||
SPOT_WEAK,
|
||||
SPOT_BUMP,
|
||||
} spottype_t;
|
||||
|
||||
#define NUMWEAKSPOTS 8
|
||||
#define WEAKSPOTANIMTIME (3*TICRATE)
|
||||
|
||||
typedef struct weakspot_t
|
||||
{
|
||||
mobj_t *spot;
|
||||
spottype_t type;
|
||||
tic_t time;
|
||||
UINT16 color;
|
||||
boolean minimap;
|
||||
} weakspot_t;
|
||||
|
||||
#define BOSSHEALTHBARLEN 110
|
||||
|
||||
extern struct bossinfo
|
||||
{
|
||||
boolean boss; ///< If true, then we are fighting a boss
|
||||
UINT8 healthbar; ///< Actual health bar fill amount
|
||||
UINT8 visualbar; ///< Tracks above, but with delay
|
||||
fixed_t visualdiv; ///< How far apart health bar divisions should appear
|
||||
tic_t visualbarimpact; ///< Bar jitter (on damage)
|
||||
UINT8 healthbarpinch; ///< If actual health is lower than this, make it orange
|
||||
UINT8 barlen; ///< The length of the bar (only reduced when a boss is deceased)
|
||||
char *enemyname; ///< The name next to the bar
|
||||
weakspot_t weakspots[NUMWEAKSPOTS]; ///< Array of weak spots (for minimap/object tracking)
|
||||
boolean encore; ///< Copy of encore, just to make sure you can't cheat it with cvars
|
||||
spottype_t doweakspotsound; ///< If nonzero, at least one weakspot was declared this tic
|
||||
tic_t titleshow; ///< Show this many letters on the titlecard
|
||||
sfxenum_t titlesound; ///< Sound to play when title typing
|
||||
char *subtitle; ///< The subtitle under the titlecard
|
||||
} bossinfo;
|
||||
|
||||
void K_BossInfoTicker(void);
|
||||
void K_InitBossHealthBar(const char *enemyname, const char *subtitle, sfxenum_t titlesound, fixed_t pinchmagnitude, UINT8 divisions);
|
||||
void K_UpdateBossHealthBar(fixed_t magnitude, tic_t jitterlen);
|
||||
void K_DeclareWeakspot(mobj_t *spot, spottype_t spottype, UINT16 color, boolean minimap);
|
||||
|
||||
#endif
|
||||
|
|
@ -27,6 +27,7 @@
|
|||
#include "m_random.h"
|
||||
#include "r_things.h" // numskins
|
||||
#include "k_race.h" // finishBeamLine
|
||||
#include "k_boss.h"
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
|
|
@ -166,7 +167,7 @@ void K_UpdateMatchRaceBots(void)
|
|||
}
|
||||
}
|
||||
|
||||
if (difficulty == 0)
|
||||
if (difficulty == 0 || bossinfo.boss == true)
|
||||
{
|
||||
wantedbots = 0;
|
||||
}
|
||||
|
|
@ -260,7 +261,10 @@ void K_UpdateMatchRaceBots(void)
|
|||
--------------------------------------------------*/
|
||||
boolean K_PlayerUsesBotMovement(player_t *player)
|
||||
{
|
||||
if (player->bot || player->exiting || player->quittime)
|
||||
if (player->exiting || player->quittime)
|
||||
return true;
|
||||
|
||||
if (player->bot)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
|
@ -1040,6 +1044,7 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
|
|||
|| player->mo->scale <= 1
|
||||
|| player->playerstate == PST_DEAD
|
||||
|| leveltime <= introtime
|
||||
|| (player->exiting && !(gametyperules & GTR_CIRCUIT))
|
||||
)
|
||||
{
|
||||
// No need to do anything else.
|
||||
|
|
|
|||
|
|
@ -12,6 +12,30 @@
|
|||
#include "doomdef.h" // Sink snipe print
|
||||
#include "g_game.h" // Sink snipe print
|
||||
|
||||
angle_t K_GetCollideAngle(mobj_t *t1, mobj_t *t2)
|
||||
{
|
||||
fixed_t momux, momuy;
|
||||
angle_t test;
|
||||
|
||||
if (!(t1->flags & MF_PAPERCOLLISION))
|
||||
{
|
||||
return R_PointToAngle2(t1->x, t1->y, t2->x, t2->y)+ANGLE_90;
|
||||
}
|
||||
|
||||
test = R_PointToAngle2(0, 0, t2->momx, t2->momy) + ANGLE_90 - t1->angle;
|
||||
if (test > ANGLE_180)
|
||||
test = t1->angle + ANGLE_180;
|
||||
else
|
||||
test = t1->angle;
|
||||
|
||||
// intentional way around - sine...
|
||||
momuy = P_AproxDistance(t2->momx, t2->momy);
|
||||
momux = t2->momx - P_ReturnThrustY(t2, test, 2*momuy);
|
||||
momuy = t2->momy - P_ReturnThrustX(t2, test, 2*momuy);
|
||||
|
||||
return R_PointToAngle2(0, 0, momux, momuy);
|
||||
}
|
||||
|
||||
boolean K_OrbinautJawzCollide(mobj_t *t1, mobj_t *t2)
|
||||
{
|
||||
boolean damageitem = false;
|
||||
|
|
@ -20,7 +44,7 @@ boolean K_OrbinautJawzCollide(mobj_t *t1, mobj_t *t2)
|
|||
if ((t1->threshold > 0 && t2->hitlag > 0) || (t2->threshold > 0 && t1->hitlag > 0))
|
||||
return true;
|
||||
|
||||
if (((t1->target == t2) || (t1->target == t2->target)) && (t1->threshold > 0 || (t2->type != MT_PLAYER && t2->threshold > 0)))
|
||||
if (((t1->target == t2) || (!(t2->flags & (MF_ENEMY|MF_BOSS)) && (t1->target == t2->target))) && (t1->threshold > 0 || (t2->type != MT_PLAYER && t2->threshold > 0)))
|
||||
return true;
|
||||
|
||||
if (t1->health <= 0 || t2->health <= 0)
|
||||
|
|
@ -61,11 +85,13 @@ boolean K_OrbinautJawzCollide(mobj_t *t1, mobj_t *t2)
|
|||
|| t2->type == MT_BALLHOG)
|
||||
{
|
||||
// Other Item Damage
|
||||
angle_t bounceangle = K_GetCollideAngle(t1, t2);
|
||||
|
||||
S_StartSound(t2, t2->info->deathsound);
|
||||
P_KillMobj(t2, t1, t1, DMG_NORMAL);
|
||||
|
||||
P_SetObjectMomZ(t2, 8*FRACUNIT, false);
|
||||
P_InstaThrust(t2, R_PointToAngle2(t1->x, t1->y, t2->x, t2->y)+ANGLE_90, 16*FRACUNIT);
|
||||
P_InstaThrust(t2, bounceangle, 16*FRACUNIT);
|
||||
|
||||
P_SpawnMobj(t2->x/2 + t1->x/2, t2->y/2 + t1->y/2, t2->z/2 + t1->z/2, MT_ITEMCLASH);
|
||||
|
||||
|
|
@ -92,11 +118,12 @@ boolean K_OrbinautJawzCollide(mobj_t *t1, mobj_t *t2)
|
|||
if (damageitem)
|
||||
{
|
||||
// This Item Damage
|
||||
angle_t bounceangle = K_GetCollideAngle(t2, t1);
|
||||
S_StartSound(t1, t1->info->deathsound);
|
||||
P_KillMobj(t1, t2, t2, DMG_NORMAL);
|
||||
|
||||
P_SetObjectMomZ(t1, 8*FRACUNIT, false);
|
||||
P_InstaThrust(t1, R_PointToAngle2(t2->x, t2->y, t1->x, t1->y)+ANGLE_90, 16*FRACUNIT);
|
||||
P_InstaThrust(t1, bounceangle, 16*FRACUNIT);
|
||||
}
|
||||
|
||||
if (sprung)
|
||||
|
|
@ -114,7 +141,7 @@ boolean K_BananaBallhogCollide(mobj_t *t1, mobj_t *t2)
|
|||
if ((t1->threshold > 0 && t2->hitlag > 0) || (t2->threshold > 0 && t1->hitlag > 0))
|
||||
return true;
|
||||
|
||||
if (((t1->target == t2) || (t1->target == t2->target)) && (t1->threshold > 0 || (t2->type != MT_PLAYER && t2->threshold > 0)))
|
||||
if (((t1->target == t2) || (!(t2->flags & (MF_ENEMY|MF_BOSS)) && (t1->target == t2->target))) && (t1->threshold > 0 || (t2->type != MT_PLAYER && t2->threshold > 0)))
|
||||
return true;
|
||||
|
||||
if (t1->health <= 0 || t2->health <= 0)
|
||||
|
|
@ -154,11 +181,13 @@ boolean K_BananaBallhogCollide(mobj_t *t1, mobj_t *t2)
|
|||
|| t2->type == MT_BALLHOG)
|
||||
{
|
||||
// Other Item Damage
|
||||
angle_t bounceangle = K_GetCollideAngle(t1, t2);
|
||||
|
||||
S_StartSound(t2, t2->info->deathsound);
|
||||
P_KillMobj(t2, t1, t1, DMG_NORMAL);
|
||||
|
||||
P_SetObjectMomZ(t2, 8*FRACUNIT, false);
|
||||
P_InstaThrust(t2, R_PointToAngle2(t1->x, t1->y, t2->x, t2->y)+ANGLE_90, 16*FRACUNIT);
|
||||
P_InstaThrust(t2, bounceangle, 16*FRACUNIT);
|
||||
|
||||
P_SpawnMobj(t2->x/2 + t1->x/2, t2->y/2 + t1->y/2, t2->z/2 + t1->z/2, MT_ITEMCLASH);
|
||||
|
||||
|
|
@ -180,11 +209,13 @@ boolean K_BananaBallhogCollide(mobj_t *t1, mobj_t *t2)
|
|||
if (damageitem)
|
||||
{
|
||||
// This Item Damage
|
||||
angle_t bounceangle = K_GetCollideAngle(t2, t1);
|
||||
|
||||
S_StartSound(t1, t1->info->deathsound);
|
||||
P_KillMobj(t1, t2, t2, DMG_NORMAL);
|
||||
|
||||
P_SetObjectMomZ(t1, 8*FRACUNIT, false);
|
||||
P_InstaThrust(t1, R_PointToAngle2(t2->x, t2->y, t1->x, t1->y)+ANGLE_90, 16*FRACUNIT);
|
||||
P_InstaThrust(t1, bounceangle, 16*FRACUNIT);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -270,7 +301,7 @@ boolean K_MineCollide(mobj_t *t1, mobj_t *t2)
|
|||
if ((t1->threshold > 0 && t2->hitlag > 0) || (t2->threshold > 0 && t1->hitlag > 0))
|
||||
return true;
|
||||
|
||||
if (((t1->target == t2) || (t1->target == t2->target)) && (t1->threshold > 0 || (t2->type != MT_PLAYER && t2->threshold > 0)))
|
||||
if (((t1->target == t2) || (!(t2->flags & (MF_ENEMY|MF_BOSS)) && (t1->target == t2->target))) && (t1->threshold > 0 || (t2->type != MT_PLAYER && t2->threshold > 0)))
|
||||
return true;
|
||||
|
||||
if (t1->health <= 0 || t2->health <= 0)
|
||||
|
|
@ -296,6 +327,8 @@ boolean K_MineCollide(mobj_t *t1, mobj_t *t2)
|
|||
|| t2->type == MT_ORBINAUT_SHIELD || t2->type == MT_JAWZ_SHIELD)
|
||||
{
|
||||
// Bomb death
|
||||
angle_t bounceangle = K_GetCollideAngle(t1, t2);
|
||||
|
||||
P_KillMobj(t1, t2, t2, DMG_NORMAL);
|
||||
|
||||
// Other Item Damage
|
||||
|
|
@ -303,7 +336,7 @@ boolean K_MineCollide(mobj_t *t1, mobj_t *t2)
|
|||
P_KillMobj(t2, t1, t1, DMG_NORMAL);
|
||||
|
||||
P_SetObjectMomZ(t2, 8*FRACUNIT, false);
|
||||
P_InstaThrust(t2, R_PointToAngle2(t1->x, t1->y, t2->x, t2->y)+ANGLE_90, 16*FRACUNIT);
|
||||
P_InstaThrust(t2, bounceangle, 16*FRACUNIT);
|
||||
}
|
||||
else if (t2->flags & MF_SHOOTABLE)
|
||||
{
|
||||
|
|
@ -346,7 +379,7 @@ boolean K_LandMineCollide(mobj_t *t1, mobj_t *t2)
|
|||
if ((t1->threshold > 0 && t2->hitlag > 0) || (t2->threshold > 0 && t1->hitlag > 0))
|
||||
return true;
|
||||
|
||||
if (((t1->target == t2) || (t1->target == t2->target)) && (t1->threshold > 0 || (t2->type != MT_PLAYER && t2->threshold > 0)))
|
||||
if (((t1->target == t2) || (!(t2->flags & (MF_ENEMY|MF_BOSS)) && (t1->target == t2->target))) && (t1->threshold > 0 || (t2->type != MT_PLAYER && t2->threshold > 0)))
|
||||
return true;
|
||||
|
||||
if (t1->health <= 0 || t2->health <= 0)
|
||||
|
|
@ -380,6 +413,8 @@ boolean K_LandMineCollide(mobj_t *t1, mobj_t *t2)
|
|||
|| t2->type == MT_BALLHOG)
|
||||
{
|
||||
// Other Item Damage
|
||||
angle_t bounceangle = K_GetCollideAngle(t1, t2);
|
||||
|
||||
if (t2->eflags & MFE_VERTICALFLIP)
|
||||
t2->z -= t2->height;
|
||||
else
|
||||
|
|
@ -389,7 +424,7 @@ boolean K_LandMineCollide(mobj_t *t1, mobj_t *t2)
|
|||
P_KillMobj(t2, t1, t1, DMG_NORMAL);
|
||||
|
||||
P_SetObjectMomZ(t2, 8*FRACUNIT, false);
|
||||
P_InstaThrust(t2, R_PointToAngle2(t1->x, t1->y, t2->x, t2->y)+ANGLE_90, 16*FRACUNIT);
|
||||
P_InstaThrust(t2, bounceangle, 16*FRACUNIT);
|
||||
|
||||
P_SpawnMobj(t2->x/2 + t1->x/2, t2->y/2 + t1->y/2, t2->z/2 + t1->z/2, MT_ITEMCLASH);
|
||||
|
||||
|
|
@ -416,7 +451,7 @@ boolean K_KitchenSinkCollide(mobj_t *t1, mobj_t *t2)
|
|||
if ((t1->threshold > 0 && t2->hitlag > 0) || (t2->threshold > 0 && t1->hitlag > 0))
|
||||
return true;
|
||||
|
||||
if (((t1->target == t2) || (t1->target == t2->target)) && (t1->threshold > 0 || (t2->type != MT_PLAYER && t2->threshold > 0)))
|
||||
if (((t1->target == t2) || (!(t2->flags & (MF_ENEMY|MF_BOSS)) && (t1->target == t2->target))) && (t1->threshold > 0 || (t2->type != MT_PLAYER && t2->threshold > 0)))
|
||||
return true;
|
||||
|
||||
if (t2->player)
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include "doomtype.h"
|
||||
#include "p_mobj.h"
|
||||
|
||||
angle_t K_GetCollideAngle(mobj_t *t1, mobj_t *t2);
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
/// \brief Grand Prix mode game logic & bot behaviors
|
||||
|
||||
#include "k_grandprix.h"
|
||||
#include "k_boss.h"
|
||||
#include "doomdef.h"
|
||||
#include "d_player.h"
|
||||
#include "g_game.h"
|
||||
|
|
@ -595,6 +596,12 @@ boolean K_CanChangeRules(void)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (bossinfo.boss == true)
|
||||
{
|
||||
// Don't cheat the boss!
|
||||
return false;
|
||||
}
|
||||
|
||||
if (modeattacking == true)
|
||||
{
|
||||
// Don't cheat the rules of Time Trials!
|
||||
|
|
|
|||
328
src/k_hud.c
328
src/k_hud.c
|
|
@ -12,6 +12,7 @@
|
|||
#include "k_hud.h"
|
||||
#include "k_kart.h"
|
||||
#include "k_battle.h"
|
||||
#include "k_boss.h"
|
||||
#include "k_color.h"
|
||||
#include "k_director.h"
|
||||
#include "screen.h"
|
||||
|
|
@ -33,6 +34,7 @@
|
|||
#include "s_sound.h"
|
||||
#include "r_things.h"
|
||||
#include "r_fps.h"
|
||||
#include "m_random.h"
|
||||
|
||||
#define NUMPOSNUMS 10
|
||||
#define NUMPOSFRAMES 7 // White, three blues, three reds
|
||||
|
|
@ -164,6 +166,9 @@ static patch_t *kp_cpu;
|
|||
|
||||
static patch_t *kp_nametagstem;
|
||||
|
||||
static patch_t *kp_bossbar[8];
|
||||
static patch_t *kp_bossret[4];
|
||||
|
||||
static patch_t *kp_trickcool[2];
|
||||
|
||||
void K_LoadKartHUDGraphics(void)
|
||||
|
|
@ -606,6 +611,20 @@ void K_LoadKartHUDGraphics(void)
|
|||
|
||||
kp_nametagstem = (patch_t *) W_CachePatchName("K_NAMEST", PU_HUDGFX);
|
||||
|
||||
sprintf(buffer, "K_BOSB0x");
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
buffer[7] = '0'+((i+1)%10);
|
||||
kp_bossbar[i] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX);
|
||||
}
|
||||
|
||||
sprintf(buffer, "K_BOSR0x");
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
buffer[7] = '0'+((i+1)%10);
|
||||
kp_bossret[i] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX);
|
||||
}
|
||||
|
||||
kp_trickcool[0] = W_CachePatchName("K_COOL1", PU_HUDGFX);
|
||||
kp_trickcool[1] = W_CachePatchName("K_COOL2", PU_HUDGFX);
|
||||
}
|
||||
|
|
@ -759,14 +778,22 @@ void K_AdjustXYWithSnap(INT32 *x, INT32 *y, UINT32 options, INT32 dupx, INT32 du
|
|||
|
||||
if (options & V_SLIDEIN)
|
||||
{
|
||||
const tic_t length = TICRATE/2;
|
||||
const tic_t length = TICRATE/4;
|
||||
tic_t timer = lt_exitticker;
|
||||
if (bossinfo.boss == true)
|
||||
{
|
||||
if (leveltime <= 3)
|
||||
timer = 0;
|
||||
else
|
||||
timer = leveltime-3;
|
||||
}
|
||||
|
||||
if (lt_exitticker < length)
|
||||
if (timer < length)
|
||||
{
|
||||
boolean slidefromright = false;
|
||||
|
||||
const INT32 offsetAmount = (screenwidth * FRACUNIT) / length;
|
||||
fixed_t offset = (screenwidth * FRACUNIT) - (lt_exitticker * offsetAmount);
|
||||
const INT32 offsetAmount = (screenwidth * FRACUNIT/2) / length;
|
||||
fixed_t offset = (screenwidth * FRACUNIT/2) - (timer * offsetAmount);
|
||||
|
||||
offset += FixedMul(offsetAmount, renderdeltatics);
|
||||
offset /= FRACUNIT;
|
||||
|
|
@ -1434,7 +1461,7 @@ void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT16 emblemmap, UI
|
|||
if (!mode)
|
||||
{
|
||||
splitflags = V_HUDTRANS|V_SLIDEIN|V_SNAPTOTOP|V_SNAPTORIGHT|V_SPLITSCREEN;
|
||||
if (cv_timelimit.value && timelimitintics > 0)
|
||||
if (cv_timelimit.value && timelimitintics > 0 && !bossinfo.boss) // TODO
|
||||
{
|
||||
if (drawtime >= timelimitintics)
|
||||
drawtime = 0;
|
||||
|
|
@ -1867,6 +1894,115 @@ static boolean K_drawKartPositionFaces(void)
|
|||
return false;
|
||||
}
|
||||
|
||||
static void K_drawBossHealthBar(void)
|
||||
{
|
||||
UINT8 i = 0, barstatus = 1, randlen = 0, darken = 0;
|
||||
const INT32 startx = BASEVIDWIDTH - 23;
|
||||
INT32 starty = BASEVIDHEIGHT - 25;
|
||||
INT32 rolrand = 0;
|
||||
boolean randsign = false;
|
||||
|
||||
if (bossinfo.barlen <= 1)
|
||||
return;
|
||||
|
||||
// Entire bar juddering!
|
||||
if (lt_exitticker < (TICRATE/2))
|
||||
;
|
||||
else if (bossinfo.visualbarimpact)
|
||||
{
|
||||
INT32 mag = min((bossinfo.visualbarimpact/4) + 1, 8);
|
||||
if (bossinfo.visualbarimpact & 1)
|
||||
starty -= mag;
|
||||
else
|
||||
starty += mag;
|
||||
}
|
||||
|
||||
if (bossinfo.enemyname)
|
||||
V_DrawRightAlignedThinString(startx, starty-10, V_HUDTRANS|V_SLIDEIN|V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_6WIDTHSPACE, bossinfo.enemyname);
|
||||
|
||||
// Used for colour and randomisation.
|
||||
if (bossinfo.healthbar <= (bossinfo.visualdiv/FRACUNIT))
|
||||
{
|
||||
barstatus = 3;
|
||||
}
|
||||
else if (bossinfo.healthbar <= bossinfo.healthbarpinch)
|
||||
{
|
||||
barstatus = 2;
|
||||
}
|
||||
|
||||
randlen = M_RandomKey(bossinfo.visualbar-(bossinfo.visualdiv/(2*FRACUNIT)))+1;
|
||||
randsign = M_RandomChance(FRACUNIT/2);
|
||||
|
||||
// Right wing.
|
||||
V_DrawScaledPatch(startx-1, starty, V_HUDTRANS|V_SLIDEIN|V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_FLIP, kp_bossbar[0]);
|
||||
|
||||
// Draw the bar itself...
|
||||
while (i < bossinfo.barlen)
|
||||
{
|
||||
V_DrawScaledPatch(startx-i, starty, V_HUDTRANS|V_SLIDEIN|V_SNAPTOBOTTOM|V_SNAPTORIGHT, kp_bossbar[1]);
|
||||
if (i < bossinfo.visualbar)
|
||||
{
|
||||
randlen--;
|
||||
if (!randlen)
|
||||
{
|
||||
randlen = M_RandomKey(bossinfo.visualbar-(bossinfo.visualdiv/(2*FRACUNIT)))+1;
|
||||
if (barstatus > 1)
|
||||
{
|
||||
rolrand = M_RandomKey(barstatus)+1;
|
||||
}
|
||||
else
|
||||
{
|
||||
rolrand = 1;
|
||||
}
|
||||
if (randsign)
|
||||
{
|
||||
rolrand = -rolrand;
|
||||
}
|
||||
randsign = !randsign;
|
||||
}
|
||||
else
|
||||
{
|
||||
rolrand = 0;
|
||||
}
|
||||
if (lt_exitticker < (TICRATE/2))
|
||||
;
|
||||
else if ((bossinfo.visualbar - i) < (INT32)(bossinfo.visualbarimpact/8))
|
||||
{
|
||||
if (bossinfo.visualbarimpact & 1)
|
||||
rolrand += (bossinfo.visualbar - i);
|
||||
else
|
||||
rolrand -= (bossinfo.visualbar - i);
|
||||
}
|
||||
if (bossinfo.visualdiv)
|
||||
{
|
||||
fixed_t work = 0;
|
||||
if ((i+1) == bossinfo.visualbar)
|
||||
darken = 1;
|
||||
else
|
||||
{
|
||||
darken = 0;
|
||||
// a hybrid fixed-int modulo...
|
||||
while ((work/FRACUNIT) < bossinfo.visualbar)
|
||||
{
|
||||
if (work/FRACUNIT != i)
|
||||
{
|
||||
work += bossinfo.visualdiv;
|
||||
continue;
|
||||
}
|
||||
darken = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
V_DrawScaledPatch(startx-i, starty+rolrand, V_HUDTRANS|V_SLIDEIN|V_SNAPTOBOTTOM|V_SNAPTORIGHT, kp_bossbar[(2*barstatus)+darken]);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
// Left wing.
|
||||
V_DrawScaledPatch(startx-i, starty, V_HUDTRANS|V_SLIDEIN|V_SNAPTOBOTTOM|V_SNAPTORIGHT, kp_bossbar[0]);
|
||||
}
|
||||
|
||||
static void K_drawKartEmeralds(void)
|
||||
{
|
||||
static const INT32 emeraldOffsets[7][2] = {
|
||||
|
|
@ -2233,7 +2369,9 @@ static void K_drawKartAccessibilityIcons(INT32 fx)
|
|||
|
||||
if (r_splitscreen < 2) // adjust to speedometer height
|
||||
{
|
||||
if (gametype == GT_BATTLE)
|
||||
if (bossinfo.boss)
|
||||
fy += 8;
|
||||
else if (gametype == GT_BATTLE)
|
||||
fy -= 4;
|
||||
}
|
||||
else
|
||||
|
|
@ -2247,7 +2385,7 @@ static void K_drawKartAccessibilityIcons(INT32 fx)
|
|||
}
|
||||
}
|
||||
|
||||
if (stplyr->pflags & PF_KICKSTARTACCEL) // just KICKSTARTACCEL right now, maybe more later
|
||||
if ((stplyr->pflags & PF_KICKSTARTACCEL) && gametype != GT_BATTLE) // just KICKSTARTACCEL right now, maybe more later
|
||||
{
|
||||
fil = 7-(stplyr->kickstartaccel*7)/ACCEL_KICKSTART;
|
||||
i = 7;
|
||||
|
|
@ -2320,7 +2458,9 @@ static void K_drawKartSpeedometer(void)
|
|||
numbers[1] = ((convSpeed / 10) % 10);
|
||||
numbers[2] = (convSpeed % 10);
|
||||
|
||||
if (gametype == GT_BATTLE)
|
||||
if (bossinfo.boss)
|
||||
battleoffset = 8;
|
||||
else if (gametype == GT_BATTLE)
|
||||
battleoffset = -4;
|
||||
|
||||
V_DrawScaledPatch(LAPS_X, LAPS_Y-25 + battleoffset, V_HUDTRANS|V_SLIDEIN|splitflags, kp_speedometersticker);
|
||||
|
|
@ -2470,7 +2610,10 @@ static void K_drawKartBumpersOrKarma(void)
|
|||
V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|V_SLIDEIN|splitflags, kp_bumpersticker, colormap);
|
||||
|
||||
// TODO BETTER HUD
|
||||
V_DrawKartString(LAPS_X+47, LAPS_Y+3, V_HUDTRANS|V_SLIDEIN|splitflags, va("%d/%d %d", stplyr->bumpers, maxbumper, stplyr->overtimekarma / TICRATE));
|
||||
if (bossinfo.boss)
|
||||
V_DrawKartString(LAPS_X+47, LAPS_Y+3, V_HUDTRANS|V_SLIDEIN|splitflags, va("%d/%d", stplyr->bumpers, maxbumper));
|
||||
else
|
||||
V_DrawKartString(LAPS_X+47, LAPS_Y+3, V_HUDTRANS|V_SLIDEIN|splitflags, va("%d/%d %d", stplyr->bumpers, maxbumper, stplyr->overtimekarma / TICRATE));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2770,6 +2913,43 @@ static void K_DrawNameTagForPlayer(fixed_t x, fixed_t y, player_t *p, UINT8 cnum
|
|||
V_DrawThinStringAtFixed(x + (5*FRACUNIT), y - (26*FRACUNIT), V_6WIDTHSPACE|V_ALLOWLOWERCASE|clr, player_names[p - players]);
|
||||
}
|
||||
|
||||
typedef struct weakspotdraw_t
|
||||
{
|
||||
UINT8 i;
|
||||
INT32 x;
|
||||
INT32 y;
|
||||
boolean candrawtag;
|
||||
} weakspotdraw_t;
|
||||
|
||||
static void K_DrawWeakSpot(weakspotdraw_t *ws)
|
||||
{
|
||||
UINT8 *colormap;
|
||||
UINT8 j = (bossinfo.weakspots[ws->i].type == SPOT_BUMP) ? 1 : 0;
|
||||
tic_t flashtime = ~1; // arbitrary high even number
|
||||
|
||||
if (bossinfo.weakspots[ws->i].time < TICRATE)
|
||||
{
|
||||
if (bossinfo.weakspots[ws->i].time & 1)
|
||||
return;
|
||||
|
||||
flashtime = bossinfo.weakspots[ws->i].time;
|
||||
}
|
||||
else if (bossinfo.weakspots[ws->i].time > (WEAKSPOTANIMTIME - TICRATE))
|
||||
flashtime = WEAKSPOTANIMTIME - bossinfo.weakspots[ws->i].time;
|
||||
|
||||
if (flashtime & 1)
|
||||
colormap = R_GetTranslationColormap(TC_ALLWHITE, 0, GTC_CACHE);
|
||||
else
|
||||
colormap = R_GetTranslationColormap(TC_RAINBOW, bossinfo.weakspots[ws->i].color, GTC_CACHE);
|
||||
|
||||
V_DrawFixedPatch(ws->x, ws->y, FRACUNIT, 0, kp_bossret[j], colormap);
|
||||
|
||||
if (!ws->candrawtag || flashtime & 1 || flashtime < TICRATE/2)
|
||||
return;
|
||||
|
||||
V_DrawFixedPatch(ws->x, ws->y, FRACUNIT, 0, kp_bossret[j+1], colormap);
|
||||
}
|
||||
|
||||
static void K_drawKartNameTags(void)
|
||||
{
|
||||
const fixed_t maxdistance = 8192*mapobjectscale;
|
||||
|
|
@ -2818,6 +2998,81 @@ static void K_drawKartNameTags(void)
|
|||
c.z = R_InterpolateFixed(stplyr->mo->old_z, stplyr->mo->z);
|
||||
}
|
||||
|
||||
// Maybe shouldn't be handling this here... but the camera info is too good.
|
||||
if (bossinfo.boss)
|
||||
{
|
||||
weakspotdraw_t weakspotdraw[NUMWEAKSPOTS];
|
||||
UINT8 numdraw = 0;
|
||||
boolean onleft = false;
|
||||
|
||||
for (i = 0; i < NUMWEAKSPOTS; i++)
|
||||
{
|
||||
trackingResult_t result;
|
||||
vector3_t v;
|
||||
|
||||
if (bossinfo.weakspots[i].spot == NULL || P_MobjWasRemoved(bossinfo.weakspots[i].spot))
|
||||
{
|
||||
// No object
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bossinfo.weakspots[i].time == 0 || bossinfo.weakspots[i].type == SPOT_NONE)
|
||||
{
|
||||
// not visible
|
||||
continue;
|
||||
}
|
||||
|
||||
v.x = R_InterpolateFixed(bossinfo.weakspots[i].spot->old_x, bossinfo.weakspots[i].spot->x);
|
||||
v.y = R_InterpolateFixed(bossinfo.weakspots[i].spot->old_y, bossinfo.weakspots[i].spot->y);
|
||||
v.z = R_InterpolateFixed(bossinfo.weakspots[i].spot->old_z, bossinfo.weakspots[i].spot->z);
|
||||
|
||||
v.z += (bossinfo.weakspots[i].spot->height / 2);
|
||||
|
||||
K_ObjectTracking(&result, &v, cnum, 0);
|
||||
if (result.onScreen == false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
weakspotdraw[numdraw].i = i;
|
||||
weakspotdraw[numdraw].x = result.x;
|
||||
weakspotdraw[numdraw].y = result.y;
|
||||
weakspotdraw[numdraw].candrawtag = true;
|
||||
|
||||
for (j = 0; j < numdraw; j++)
|
||||
{
|
||||
if (abs(weakspotdraw[j].x - weakspotdraw[numdraw].x) > 50*FRACUNIT)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
onleft = (weakspotdraw[j].x < weakspotdraw[numdraw].x);
|
||||
|
||||
if (abs((onleft ? -5 : 5)
|
||||
+ weakspotdraw[j].y - weakspotdraw[numdraw].y) > 18*FRACUNIT)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (weakspotdraw[j].x < weakspotdraw[numdraw].x)
|
||||
{
|
||||
weakspotdraw[j].candrawtag = false;
|
||||
break;
|
||||
}
|
||||
|
||||
weakspotdraw[numdraw].candrawtag = false;
|
||||
break;
|
||||
}
|
||||
|
||||
numdraw++;
|
||||
}
|
||||
|
||||
for (i = 0; i < numdraw; i++)
|
||||
{
|
||||
K_DrawWeakSpot(&weakspotdraw[i]);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
player_t *ntplayer = &players[i];
|
||||
|
|
@ -3252,6 +3507,34 @@ static void K_drawKartMinimap(void)
|
|||
splitflags &= ~V_HUDTRANSHALF;
|
||||
splitflags |= V_HUDTRANS;
|
||||
|
||||
// ...but first, any boss targets.
|
||||
if (bossinfo.boss)
|
||||
{
|
||||
for (i = 0; i < NUMWEAKSPOTS; i++)
|
||||
{
|
||||
// exists at all?
|
||||
if (bossinfo.weakspots[i].spot == NULL || P_MobjWasRemoved(bossinfo.weakspots[i].spot))
|
||||
continue;
|
||||
// shows on the minimap?
|
||||
if (bossinfo.weakspots[i].minimap == false)
|
||||
continue;
|
||||
// in the flashing period?
|
||||
if ((bossinfo.weakspots[i].time > (WEAKSPOTANIMTIME-(TICRATE/2))) && (bossinfo.weakspots[i].time & 1))
|
||||
continue;
|
||||
|
||||
colormap = NULL;
|
||||
|
||||
if (bossinfo.weakspots[i].color)
|
||||
colormap = R_GetTranslationColormap(TC_RAINBOW, bossinfo.weakspots[i].color, GTC_CACHE);
|
||||
|
||||
interpx = R_InterpolateFixed(bossinfo.weakspots[i].spot->old_x, bossinfo.weakspots[i].spot->x);
|
||||
interpy = R_InterpolateFixed(bossinfo.weakspots[i].spot->old_y, bossinfo.weakspots[i].spot->y);
|
||||
|
||||
// temporary graphic?
|
||||
K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, kp_wantedreticle, colormap, AutomapPic);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < numlocalplayers; i++)
|
||||
{
|
||||
if (i == -1)
|
||||
|
|
@ -3482,7 +3765,8 @@ static void K_drawKartStartCountdown(void)
|
|||
}
|
||||
else if (leveltime >= introtime && leveltime < starttime-(3*TICRATE))
|
||||
{
|
||||
K_drawKartStartBulbs();
|
||||
if (bossinfo.boss == false)
|
||||
K_drawKartStartBulbs();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -4412,14 +4696,15 @@ void K_drawKartHUD(void)
|
|||
K_drawKartAccessibilityIcons((r_splitscreen > 1) ? 0 : 8);
|
||||
}
|
||||
|
||||
if (gametyperules & GTR_SPHERES)
|
||||
if (!bossinfo.boss && gametyperules & GTR_SPHERES)
|
||||
{
|
||||
K_drawBlueSphereMeter();
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the countdowns after everything else.
|
||||
if (leveltime >= introtime
|
||||
if (starttime != introtime
|
||||
&& leveltime >= introtime
|
||||
&& leveltime < starttime+TICRATE)
|
||||
{
|
||||
K_drawKartStartCountdown();
|
||||
|
|
@ -4450,6 +4735,18 @@ void K_drawKartHUD(void)
|
|||
if (stplyr->karthud[khud_trickcool])
|
||||
K_drawTrickCool();
|
||||
|
||||
if (gametype == GT_BATTLE)
|
||||
{
|
||||
if (bossinfo.boss)
|
||||
{
|
||||
K_drawBossHealthBar();
|
||||
}
|
||||
else if (!freecam)
|
||||
{
|
||||
K_drawKartEmeralds();
|
||||
}
|
||||
}
|
||||
|
||||
if (modeattacking || freecam) // everything after here is MP and debug only
|
||||
return;
|
||||
|
||||
|
|
@ -4457,7 +4754,7 @@ void K_drawKartHUD(void)
|
|||
V_DrawScaledPatch(BASEVIDWIDTH/2 - (SHORT(kp_yougotem->width)/2), 32, V_HUDTRANS, kp_yougotem);
|
||||
|
||||
// Draw FREE PLAY.
|
||||
if (isfreeplay && !stplyr->spectator)
|
||||
if (isfreeplay && !bossinfo.boss && !stplyr->spectator)
|
||||
{
|
||||
if (LUA_HudEnabled(hud_freeplay))
|
||||
K_drawKartFreePlay();
|
||||
|
|
@ -4510,9 +4807,4 @@ void K_drawKartHUD(void)
|
|||
|
||||
K_DrawWaypointDebugger();
|
||||
K_DrawDirectorDebugger();
|
||||
|
||||
if (gametype == GT_BATTLE)
|
||||
{
|
||||
K_drawKartEmeralds();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
25
src/k_kart.c
25
src/k_kart.c
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "k_kart.h"
|
||||
#include "k_battle.h"
|
||||
#include "k_boss.h"
|
||||
#include "k_pwrlv.h"
|
||||
#include "k_color.h"
|
||||
#include "k_respawn.h"
|
||||
|
|
@ -56,6 +57,10 @@ void K_TimerInit(void)
|
|||
UINT8 i;
|
||||
UINT8 numPlayers = 0;//, numspec = 0;
|
||||
|
||||
// Bosses handle it elsewhere!
|
||||
if (bossinfo.boss == true)
|
||||
return;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
|
|
@ -271,6 +276,9 @@ boolean K_IsPlayerLosing(player_t *player)
|
|||
if (battlecapsules && player->bumpers <= 0)
|
||||
return true; // DNF in break the capsules
|
||||
|
||||
if (bossinfo.boss)
|
||||
return (player->bumpers <= 0); // anything short of DNF is COOL
|
||||
|
||||
if (player->position == 1)
|
||||
return false;
|
||||
|
||||
|
|
@ -1043,13 +1051,20 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd)
|
|||
}
|
||||
else if (gametype == GT_BATTLE)
|
||||
{
|
||||
if (mashed && (modeattacking || cv_banana.value)) // ANY mashed value? You get a banana.
|
||||
if (mashed && (modeattacking || bossinfo.boss || cv_banana.value)) // ANY mashed value? You get a banana.
|
||||
{
|
||||
K_KartGetItemResult(player, KITEM_BANANA);
|
||||
player->karthud[khud_itemblinkmode] = 1;
|
||||
if (P_IsDisplayPlayer(player))
|
||||
S_StartSound(NULL, sfx_itrolm);
|
||||
}
|
||||
else if (bossinfo.boss)
|
||||
{
|
||||
K_KartGetItemResult(player, KITEM_ORBINAUT);
|
||||
player->karthud[khud_itemblinkmode] = 0;
|
||||
if (P_IsDisplayPlayer(player))
|
||||
S_StartSound(NULL, sfx_itrolf);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (modeattacking || cv_tripleorbinaut.value) // Waited patiently? You get Orbinaut x3!
|
||||
|
|
@ -3545,7 +3560,11 @@ void K_HandleBumperChanges(player_t *player, UINT8 prevBumpers)
|
|||
|
||||
player->karmadelay = comebacktime;
|
||||
|
||||
if (netgame)
|
||||
if (bossinfo.boss)
|
||||
{
|
||||
P_DoTimeOver(player);
|
||||
}
|
||||
else if (netgame)
|
||||
{
|
||||
CONS_Printf(M_GetText("%s lost all of their bumpers!\n"), player_names[player-players]);
|
||||
}
|
||||
|
|
@ -5578,7 +5597,7 @@ void K_DropHnextList(player_t *player, boolean keepshields)
|
|||
dropwork->angle = work->angle;
|
||||
|
||||
P_SetScale(dropwork, work->scale);
|
||||
dropwork->destscale = work->destscale;
|
||||
dropwork->destscale = K_ItemScaleForPlayer(player); //work->destscale;
|
||||
dropwork->scalespeed = work->scalespeed;
|
||||
|
||||
dropwork->flags |= MF_NOCLIPTHING;
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include "m_cond.h" // M_UpdateUnlockablesAndExtraEmblems
|
||||
#include "p_tick.h" // leveltime
|
||||
#include "k_grandprix.h"
|
||||
#include "k_boss.h"
|
||||
|
||||
// Online rankings for the main gametypes.
|
||||
// This array is saved to the gamedata.
|
||||
|
|
@ -30,7 +31,7 @@ SINT8 K_UsingPowerLevels(void)
|
|||
{
|
||||
SINT8 pt = PWRLV_DISABLED;
|
||||
|
||||
if (!cv_kartusepwrlv.value || !(netgame || (demo.playback && demo.netgame)) || grandprixinfo.gp == true)
|
||||
if (!cv_kartusepwrlv.value || !(netgame || (demo.playback && demo.netgame)) || grandprixinfo.gp == true || bossinfo.boss == true)
|
||||
{
|
||||
return PWRLV_DISABLED;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@
|
|||
#include "console.h"
|
||||
#include "k_kart.h" // SRB2Kart
|
||||
#include "k_battle.h"
|
||||
#include "k_boss.h"
|
||||
#include "k_collide.h"
|
||||
#include "k_color.h"
|
||||
#include "k_hud.h"
|
||||
#include "d_netcmd.h" // IsPlayerAdmin
|
||||
|
|
@ -2921,8 +2923,9 @@ static int lib_sSoundPlaying(lua_State *L)
|
|||
INLEVEL
|
||||
if (id >= NUMSFX)
|
||||
return luaL_error(L, "sfx %d out of range (0 - %d)", id, NUMSFX-1);
|
||||
if (!GetValidSoundOrigin(L, &origin))
|
||||
return LUA_ErrInvalid(L, "mobj_t/sector_t");
|
||||
if (!lua_isnil(L, 1))
|
||||
if (!GetValidSoundOrigin(L, &origin))
|
||||
return LUA_ErrInvalid(L, "mobj_t/sector_t");
|
||||
lua_pushboolean(L, S_SoundPlaying(origin, id));
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -3807,6 +3810,66 @@ static int lib_kGetItemPatch(lua_State *L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int lib_kGetCollideAngle(lua_State *L)
|
||||
{
|
||||
mobj_t *t1 = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
|
||||
mobj_t *t2 = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
|
||||
//HUDSAFE
|
||||
if (!t1)
|
||||
return LUA_ErrInvalid(L, "mobj_t");
|
||||
if (!t2)
|
||||
return LUA_ErrInvalid(L, "mobj_t");
|
||||
lua_pushinteger(L, K_GetCollideAngle(t1, t2));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_kAddHitLag(lua_State *L)
|
||||
{
|
||||
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
|
||||
tic_t tics = (tic_t)luaL_checkinteger(L, 2);
|
||||
boolean fromdamage = lua_opttrueboolean(L, 3);
|
||||
NOHUD
|
||||
if (!mo)
|
||||
return LUA_ErrInvalid(L, "mobj_t");
|
||||
K_AddHitLag(mo, tics, fromdamage);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int lib_kInitBossHealthBar(lua_State *L)
|
||||
{
|
||||
const char *enemyname = luaL_checkstring(L, 1);
|
||||
const char *subtitle = luaL_checkstring(L, 2);
|
||||
sfxenum_t titlesound = luaL_checkinteger(L, 3);
|
||||
fixed_t pinchmagnitude = luaL_checkfixed(L, 4);
|
||||
UINT8 divisions = (UINT8)luaL_checkinteger(L, 5);
|
||||
NOHUD
|
||||
K_InitBossHealthBar(enemyname, subtitle, titlesound, pinchmagnitude, divisions);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_kUpdateBossHealthBar(lua_State *L)
|
||||
{
|
||||
fixed_t magnitude = luaL_checkfixed(L, 1);
|
||||
tic_t jitterlen = (tic_t)luaL_checkinteger(L, 2);
|
||||
NOHUD
|
||||
K_UpdateBossHealthBar(magnitude, jitterlen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_kDeclareWeakspot(lua_State *L)
|
||||
{
|
||||
mobj_t *spot = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
|
||||
spottype_t spottype = luaL_checkinteger(L, 2);
|
||||
UINT16 color = luaL_checkinteger(L, 3);
|
||||
boolean minimap = lua_optboolean(L, 4);
|
||||
NOHUD
|
||||
if (!spot)
|
||||
return LUA_ErrInvalid(L, "mobj_t");
|
||||
K_DeclareWeakspot(spot, spottype, color, minimap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static luaL_Reg lib[] = {
|
||||
{"print", lib_print},
|
||||
{"chatprint", lib_chatprint},
|
||||
|
|
@ -4077,6 +4140,14 @@ static luaL_Reg lib[] = {
|
|||
{"K_GetKartFlashing",lib_kGetKartFlashing},
|
||||
{"K_GetItemPatch",lib_kGetItemPatch},
|
||||
|
||||
{"K_GetCollideAngle",lib_kGetCollideAngle},
|
||||
{"K_AddHitLag",lib_kAddHitLag},
|
||||
|
||||
// k_boss
|
||||
{"K_InitBossHealthBar", lib_kInitBossHealthBar},
|
||||
{"K_UpdateBossHealthBar", lib_kUpdateBossHealthBar},
|
||||
{"K_DeclareWeakspot", lib_kDeclareWeakspot},
|
||||
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -300,6 +300,12 @@ int LUA_PushGlobals(lua_State *L, const char *word)
|
|||
} else if (fastcmp(word,"leveltime")) {
|
||||
lua_pushinteger(L, leveltime);
|
||||
return 1;
|
||||
} else if (fastcmp(word,"introtime")) {
|
||||
lua_pushinteger(L, introtime);
|
||||
return 1;
|
||||
} else if (fastcmp(word,"starttime")) {
|
||||
lua_pushinteger(L, starttime);
|
||||
return 1;
|
||||
} else if (fastcmp(word,"defrosting")) {
|
||||
lua_pushinteger(L, hook_defrosting);
|
||||
return 1;
|
||||
|
|
|
|||
|
|
@ -33,6 +33,10 @@
|
|||
unit used as fixed_t
|
||||
*/
|
||||
|
||||
#if (FRACBITS == 16)
|
||||
#define M_TAU_FIXED 411769
|
||||
#endif
|
||||
|
||||
typedef INT32 fixed_t;
|
||||
|
||||
/*!
|
||||
|
|
|
|||
94
src/m_menu.c
94
src/m_menu.c
|
|
@ -63,6 +63,7 @@
|
|||
#include "d_player.h" // KITEM_ constants
|
||||
#include "k_color.h"
|
||||
#include "k_grandprix.h"
|
||||
#include "k_boss.h"
|
||||
|
||||
#include "i_joy.h" // for joystick menu controls
|
||||
|
||||
|
|
@ -154,7 +155,8 @@ typedef enum
|
|||
LLM_CREATESERVER,
|
||||
LLM_LEVELSELECT,
|
||||
LLM_TIMEATTACK,
|
||||
LLM_BREAKTHECAPSULES
|
||||
LLM_BREAKTHECAPSULES,
|
||||
LLM_BOSS
|
||||
} levellist_mode_t;
|
||||
|
||||
levellist_mode_t levellistmode = LLM_CREATESERVER;
|
||||
|
|
@ -253,6 +255,8 @@ menu_t MISC_ScrambleTeamDef, MISC_ChangeTeamDef, MISC_ChangeSpectateDef;
|
|||
// Single Player
|
||||
static void M_GrandPrixTemp(INT32 choice);
|
||||
static void M_StartGrandPrix(INT32 choice);
|
||||
static void M_BossTemp(INT32 choice);
|
||||
static void M_StartBoss(INT32 choice);
|
||||
static void M_TimeAttack(INT32 choice);
|
||||
static boolean M_QuitTimeAttackMenu(void);
|
||||
static void M_BreakTheCapsules(INT32 choice);
|
||||
|
|
@ -849,13 +853,15 @@ static menuitem_t SP_MainMenu[] =
|
|||
{IT_STRING|IT_CALL, NULL, "Grand Prix", M_GrandPrixTemp, 92},
|
||||
{IT_SECRET, NULL, "Time Attack", M_TimeAttack, 100},
|
||||
{IT_SECRET, NULL, "Break the Capsules", M_BreakTheCapsules, 108},
|
||||
{IT_STRING|IT_CALL, NULL, "Boss Missions", M_BossTemp, 116},
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
spgrandprix,
|
||||
sptimeattack,
|
||||
spbreakthecapsules
|
||||
spbreakthecapsules,
|
||||
spboss
|
||||
};
|
||||
|
||||
// Single Player Load Game
|
||||
|
|
@ -871,6 +877,17 @@ static menuitem_t SP_GrandPrixPlaceholderMenu[] =
|
|||
{IT_STRING|IT_CALL, NULL, "Start", M_StartGrandPrix, 80},
|
||||
};
|
||||
|
||||
static menuitem_t SP_BossPlaceholderMenu[] =
|
||||
{
|
||||
{IT_STRING|IT_CVAR, NULL, "Character", &cv_chooseskin, 50},
|
||||
{IT_STRING|IT_CVAR, NULL, "Color", &cv_playercolor[0], 58},
|
||||
|
||||
{IT_STRING|IT_CVAR, NULL, "Encore Rematch", &cv_dummygpencore, 68},
|
||||
|
||||
{IT_STRING|IT_CVAR, NULL, "Boss", &cv_nextmap, 78},
|
||||
{IT_STRING|IT_CALL, NULL, "Start", M_StartBoss, 130},
|
||||
};
|
||||
|
||||
// Single Player Time Attack
|
||||
static menuitem_t SP_TimeAttackMenu[] =
|
||||
{
|
||||
|
|
@ -1747,7 +1764,7 @@ inline static void M_GetGametypeColor(void)
|
|||
else
|
||||
gt = gametype;
|
||||
|
||||
if (gt == GT_BATTLE)
|
||||
if (gt == GT_BATTLE || levellistmode == LLM_BOSS)
|
||||
{
|
||||
highlightflags = V_REDMAP;
|
||||
warningflags = V_ORANGEMAP;
|
||||
|
|
@ -1842,6 +1859,8 @@ menu_t SP_LevelStatsDef =
|
|||
|
||||
static menu_t SP_GrandPrixTempDef = DEFAULTMENUSTYLE(MN_NONE, NULL, SP_GrandPrixPlaceholderMenu, &MainDef, 60, 30);
|
||||
|
||||
static menu_t SP_BossTempDef = MAPICONMENUSTYLE(NULL, SP_BossPlaceholderMenu, &MainDef);
|
||||
|
||||
static menu_t SP_TimeAttackDef =
|
||||
{
|
||||
MN_NONE,
|
||||
|
|
@ -4404,7 +4423,7 @@ boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt)
|
|||
{
|
||||
// Random map!
|
||||
if (mapnum == -1)
|
||||
return (gamestate != GS_TIMEATTACK && !modeattacking);
|
||||
return (levellistmode == LLM_CREATESERVER);
|
||||
|
||||
// Does the map exist?
|
||||
if (!mapheaderinfo[mapnum])
|
||||
|
|
@ -4459,6 +4478,13 @@ boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt)
|
|||
return false;
|
||||
|
||||
return true;
|
||||
|
||||
case LLM_BOSS:
|
||||
if (!(mapheaderinfo[mapnum]->typeoflevel & TOL_BOSS))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
|
@ -4935,8 +4961,12 @@ static boolean M_AddonsRefresh(void)
|
|||
return true;
|
||||
}
|
||||
|
||||
#ifdef DEVELOP
|
||||
prevmajormods = majormods;
|
||||
#else
|
||||
if (!majormods && prevmajormods)
|
||||
prevmajormods = false;
|
||||
#endif
|
||||
|
||||
if ((refreshdirmenu & REFRESHDIR_ADDFILE) || (majormods && !prevmajormods))
|
||||
{
|
||||
|
|
@ -6339,7 +6369,7 @@ static void M_RetryResponse(INT32 ch)
|
|||
static void M_Retry(INT32 choice)
|
||||
{
|
||||
(void)choice;
|
||||
M_StartMessage(M_GetText("Start this race over?\n\n(Press 'Y' to confirm)\n"),M_RetryResponse,MM_YESNO);
|
||||
M_StartMessage(va("Start this %s over?\n\n(Press 'Y' to confirm)\n", (bossinfo.boss == true) ? "boss" : "race"),M_RetryResponse,MM_YESNO);
|
||||
}
|
||||
|
||||
static void M_SelectableClearMenus(INT32 choice)
|
||||
|
|
@ -6826,6 +6856,7 @@ static void M_SinglePlayerMenu(INT32 choice)
|
|||
(M_SecretUnlocked(SECRET_TIMEATTACK)) ? IT_CALL|IT_STRING : IT_SECRET;
|
||||
SP_MainMenu[spbreakthecapsules].status =
|
||||
(M_SecretUnlocked(SECRET_BREAKTHECAPSULES)) ? IT_CALL|IT_STRING : IT_SECRET;
|
||||
SP_MainMenu[spboss].status = IT_CALL|IT_STRING;
|
||||
|
||||
M_SetupNextMenu(&SP_MainDef);
|
||||
}
|
||||
|
|
@ -7714,6 +7745,29 @@ static void M_GrandPrixTemp(INT32 choice)
|
|||
M_SetupNextMenu(&SP_GrandPrixTempDef);
|
||||
}
|
||||
|
||||
static void M_BossTemp(INT32 choice)
|
||||
{
|
||||
(void)choice;
|
||||
|
||||
levellistmode = LLM_BOSS; // Don't be dependent on cv_newgametype
|
||||
|
||||
if (M_CountLevelsToShowInList() == 0)
|
||||
{
|
||||
M_StartMessage(M_GetText("No bosses found.\n"),NULL,MM_NOTHING);
|
||||
return;
|
||||
}
|
||||
|
||||
M_PatchSkinNameTable();
|
||||
|
||||
M_PrepareLevelSelect();
|
||||
|
||||
if (cv_nextmap.value)
|
||||
Nextmap_OnChange();
|
||||
else
|
||||
CV_AddValue(&cv_nextmap, 1);
|
||||
M_SetupNextMenu(&SP_BossTempDef);
|
||||
}
|
||||
|
||||
// Start Grand Prix!
|
||||
static void M_StartGrandPrix(INT32 choice)
|
||||
{
|
||||
|
|
@ -7778,6 +7832,32 @@ static void M_StartGrandPrix(INT32 choice)
|
|||
);
|
||||
}
|
||||
|
||||
// Start Boss!
|
||||
static void M_StartBoss(INT32 choice)
|
||||
{
|
||||
(void)choice;
|
||||
|
||||
M_ClearMenus(true);
|
||||
|
||||
// Reset boss info
|
||||
if (bossinfo.enemyname)
|
||||
Z_Free(bossinfo.enemyname);
|
||||
if (bossinfo.subtitle)
|
||||
Z_Free(bossinfo.subtitle);
|
||||
memset(&bossinfo, 0, sizeof(struct bossinfo));
|
||||
|
||||
bossinfo.boss = true;
|
||||
bossinfo.encore = (boolean)(cv_dummygpencore.value);
|
||||
|
||||
G_DeferedInitNew(
|
||||
false,
|
||||
G_BuildMapName(cv_nextmap.value),
|
||||
(UINT8)(cv_chooseskin.value - 1),
|
||||
(UINT8)(cv_splitplayers.value - 1),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
// ===========
|
||||
// MODE ATTACK
|
||||
// ===========
|
||||
|
|
@ -8807,14 +8887,14 @@ static INT32 M_FindFirstMap(INT32 gtype)
|
|||
{
|
||||
INT32 i;
|
||||
|
||||
if (mapheaderinfo[gamemap] && (mapheaderinfo[gamemap]->typeoflevel & gtype))
|
||||
if (mapheaderinfo[gamemap] && (mapheaderinfo[gamemap]->typeoflevel & gametypetol[gtype]))
|
||||
return gamemap;
|
||||
|
||||
for (i = 0; i < NUMMAPS; i++)
|
||||
{
|
||||
if (!mapheaderinfo[i])
|
||||
continue;
|
||||
if (!(mapheaderinfo[i]->typeoflevel & gtype))
|
||||
if (!(mapheaderinfo[i]->typeoflevel & gametypetol[gtype]))
|
||||
continue;
|
||||
return i + 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9432,7 +9432,7 @@ void A_ForceWin(mobj_t *actor)
|
|||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i] && ((players[i].mo && players[i].mo->health)
|
||||
|| ((netgame || multiplayer) && players[i].lives)))
|
||||
&& !(players[i].pflags & PF_NOCONTEST)))
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -11089,14 +11089,10 @@ void A_Boss5Jump(mobj_t *actor)
|
|||
if (!actor->tracer)
|
||||
return; // Don't even bother if we've got nothing to aim at.
|
||||
|
||||
// Look up actor's current gravity situation
|
||||
if (actor->subsector->sector->gravity)
|
||||
g = FixedMul(gravity,(FixedDiv(*actor->subsector->sector->gravity>>FRACBITS, 1000)));
|
||||
else
|
||||
g = gravity;
|
||||
g = FixedMul(gravity, mapobjectscale);
|
||||
|
||||
// Look up distance between actor and its tracer
|
||||
x = P_AproxDistance(actor->tracer->x - actor->x, actor->tracer->y - actor->y);
|
||||
x = FixedHypot(actor->tracer->x - actor->x, actor->tracer->y - actor->y);
|
||||
// Look up height difference between actor and its tracer
|
||||
y = actor->tracer->z - actor->z;
|
||||
|
||||
|
|
@ -13302,6 +13298,7 @@ void A_ItemPop(mobj_t *actor)
|
|||
remains->flags = actor->flags; // Transfer flags
|
||||
remains->flags2 = actor->flags2; // Transfer flags2
|
||||
remains->fuse = actor->fuse; // Transfer respawn timer
|
||||
remains->cvmem = leveltime;
|
||||
remains->threshold = (actor->threshold == 70 ? 70 : (actor->threshold == 69 ? 69 : 68));
|
||||
remains->skin = NULL;
|
||||
remains->spawnpoint = actor->spawnpoint;
|
||||
|
|
|
|||
39
src/p_mobj.c
39
src/p_mobj.c
|
|
@ -37,6 +37,7 @@
|
|||
// SRB2kart
|
||||
#include "k_kart.h"
|
||||
#include "k_battle.h"
|
||||
#include "k_boss.h"
|
||||
#include "k_color.h"
|
||||
#include "k_respawn.h"
|
||||
#include "k_bot.h"
|
||||
|
|
@ -4250,6 +4251,9 @@ boolean P_SupermanLook4Players(mobj_t *actor)
|
|||
if (players[c].mo->health <= 0)
|
||||
continue; // dead
|
||||
|
||||
if ((gametyperules & GTR_BUMPERS) && players[c].bumpers <= 0)
|
||||
continue; // other dead
|
||||
|
||||
playersinthegame[stop] = &players[c];
|
||||
stop++;
|
||||
}
|
||||
|
|
@ -4970,6 +4974,9 @@ void P_RunOverlays(void)
|
|||
mo->eflags = (mo->eflags & ~MFE_VERTICALFLIP) | (mo->target->eflags & MFE_VERTICALFLIP);
|
||||
mo->scale = mo->destscale = mo->target->scale;
|
||||
mo->angle = mo->target->angle + mo->movedir;
|
||||
mo->rollangle = mo->target->rollangle;
|
||||
mo->pitch = mo->target->pitch;
|
||||
mo->roll = mo->target->roll;
|
||||
|
||||
if ((mo->flags & MF_DONTENCOREMAP) != (mo->target->flags & MF_DONTENCOREMAP))
|
||||
mo->flags ^= MF_DONTENCOREMAP;
|
||||
|
|
@ -5360,6 +5367,8 @@ static void P_MobjSceneryThink(mobj_t *mobj)
|
|||
}
|
||||
else
|
||||
P_AddOverlay(mobj);
|
||||
if (mobj->target->hitlag) // move to the correct position, update to the correct properties, but DON'T STATE-ANIMATE
|
||||
return;
|
||||
break;
|
||||
case MT_WATERDROP:
|
||||
P_SceneryCheckWater(mobj);
|
||||
|
|
@ -7850,7 +7859,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
|||
mobj->extravalue1 = 1;
|
||||
}
|
||||
|
||||
if (!S_SoundPlaying(mobj, mobj->info->attacksound))
|
||||
if (mobj->extravalue1 != 2 && !S_SoundPlaying(mobj, mobj->info->attacksound))
|
||||
S_StartSound(mobj, mobj->info->attacksound);
|
||||
|
||||
if (mobj->extravalue2 <= 8) // Short delay
|
||||
|
|
@ -8917,6 +8926,8 @@ static boolean P_FuseThink(mobj_t *mobj)
|
|||
{
|
||||
P_SpawnMapThing(mobj->spawnpoint);
|
||||
newmobj = mobj->spawnpoint->mobj; // this is set to the new mobj in P_SpawnMapThing
|
||||
if (nummapboxes > 0)
|
||||
nummapboxes--; // just to avoid doubling up
|
||||
}
|
||||
else
|
||||
newmobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobj->type);
|
||||
|
|
@ -10633,12 +10644,17 @@ void P_RespawnBattleBoxes(void)
|
|||
if (box->type != MT_RANDOMITEM || box->threshold != 68 || box->fuse) // only popped items
|
||||
continue;
|
||||
|
||||
if ((tic_t)box->cvmem+1 >= leveltime) // This one was just popped, don't respawn!
|
||||
continue;
|
||||
|
||||
// Respawn from mapthing if you have one!
|
||||
if (box->spawnpoint)
|
||||
{
|
||||
P_SpawnMapThing(box->spawnpoint);
|
||||
newmobj = box->spawnpoint->mobj; // this is set to the new mobj in P_SpawnMapThing
|
||||
P_SpawnMobj(box->spawnpoint->mobj->x, box->spawnpoint->mobj->y, box->spawnpoint->mobj->z, MT_EXPLODE); // poof into existance
|
||||
if (nummapboxes > 0)
|
||||
nummapboxes--; // just to avoid doubling up
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -10650,9 +10666,8 @@ void P_RespawnBattleBoxes(void)
|
|||
newmobj->flags2 = box->flags2;
|
||||
P_RemoveMobj(box); // make sure they disappear
|
||||
|
||||
numgotboxes--; // you've restored a box, remove it from the count
|
||||
if (numgotboxes < 0)
|
||||
numgotboxes = 0;
|
||||
if (numgotboxes > 0)
|
||||
numgotboxes--; // you've restored a box, remove it from the count
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -10678,8 +10693,8 @@ void P_RespawnSpecials(void)
|
|||
INT32 time = 30*TICRATE; // Respawn things in empty dedicated servers
|
||||
mapthing_t *mthing = NULL;
|
||||
|
||||
//if (!(gametyperules & GTR_CIRCUIT) && numgotboxes >= (4*nummapboxes/5)) // Battle Mode respawns all boxes in a different way
|
||||
//P_RespawnBattleBoxes();
|
||||
if (!(gametyperules & GTR_CIRCUIT) && numgotboxes >= (4*nummapboxes/5)) // Battle Mode respawns all boxes in a different way
|
||||
P_RespawnBattleBoxes();
|
||||
|
||||
// wait time depends on player count
|
||||
for (p = 0; p < MAXPLAYERS; p++)
|
||||
|
|
@ -11271,6 +11286,11 @@ static boolean P_AllowMobjSpawn(mapthing_t* mthing, mobjtype_t i)
|
|||
break;
|
||||
}
|
||||
|
||||
// No bosses outside of a combat situation.
|
||||
// (just in case we want boss arenas to do double duty as battle maps)
|
||||
if (!bossinfo.boss && (mobjinfo[i].flags & MF_BOSS))
|
||||
return false;
|
||||
|
||||
if (metalrecording) // Metal Sonic can't use these things.
|
||||
{
|
||||
if (mobjinfo[i].flags & (MF_ENEMY|MF_BOSS))
|
||||
|
|
@ -11287,7 +11307,7 @@ static mobjtype_t P_GetMobjtypeSubstitute(mapthing_t *mthing, mobjtype_t i)
|
|||
if ((gametyperules & GTR_SPHERES) && (i == MT_RING))
|
||||
return MT_BLUESPHERE;
|
||||
|
||||
if ((gametyperules & GTR_PAPERITEMS) && (i == MT_RANDOMITEM))
|
||||
if ((gametyperules & GTR_PAPERITEMS) && !bossinfo.boss && (i == MT_RANDOMITEM))
|
||||
return MT_PAPERITEMSPOT;
|
||||
|
||||
return i;
|
||||
|
|
@ -12215,6 +12235,11 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean
|
|||
}
|
||||
break;
|
||||
}
|
||||
case MT_RANDOMITEM:
|
||||
{
|
||||
nummapboxes++;
|
||||
break;
|
||||
}
|
||||
case MT_ITEMCAPSULE:
|
||||
{
|
||||
// we have to adjust for reverse gravity early so that the below grounded checks work
|
||||
|
|
|
|||
|
|
@ -91,6 +91,7 @@
|
|||
#include "k_waypoint.h"
|
||||
#include "k_bot.h"
|
||||
#include "k_grandprix.h"
|
||||
#include "k_boss.h"
|
||||
#include "k_terrain.h" // TRF_TRIPWIRE
|
||||
#include "k_brightmap.h"
|
||||
#include "k_director.h" // K_InitDirector
|
||||
|
|
@ -3524,7 +3525,7 @@ static void P_InitLevelSettings(void)
|
|||
if (playeringame[i] && !players[i].spectator)
|
||||
p++;
|
||||
|
||||
if (grandprixinfo.gp == false)
|
||||
if (grandprixinfo.gp == false && bossinfo.boss == false)
|
||||
players[i].lives = 3;
|
||||
|
||||
G_PlayerReborn(i, true);
|
||||
|
|
@ -3549,6 +3550,12 @@ static void P_InitLevelSettings(void)
|
|||
franticitems = false;
|
||||
comeback = true;
|
||||
}
|
||||
else if (bossinfo.boss)
|
||||
{
|
||||
gamespeed = KARTSPEED_EASY;
|
||||
franticitems = false;
|
||||
comeback = true;
|
||||
}
|
||||
else if (modeattacking)
|
||||
{
|
||||
// Just play it safe and set everything
|
||||
|
|
@ -4073,6 +4080,15 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
|
|||
}
|
||||
|
||||
F_RunWipe(wipedefs[wipe_level_toblack], false, ((levelfadecol == 0) ? "FADEMAP1" : "FADEMAP0"), false, false);
|
||||
|
||||
{
|
||||
sfxenum_t kstart = sfx_kstart;
|
||||
if (bossinfo.boss)
|
||||
kstart = sfx_ssa021;
|
||||
else if (encoremode)
|
||||
kstart = sfx_ruby2;
|
||||
S_StartSound(NULL, kstart);
|
||||
}
|
||||
}
|
||||
/*if (!titlemapinaction)
|
||||
wipegamestate = GS_LEVEL;*/
|
||||
|
|
@ -4279,6 +4295,20 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
|
|||
K_UpdateMatchRaceBots();
|
||||
}
|
||||
|
||||
if (bossinfo.boss)
|
||||
{
|
||||
// Reset some pesky boss state that can't be handled elsewhere.
|
||||
bossinfo.barlen = BOSSHEALTHBARLEN;
|
||||
if (bossinfo.enemyname)
|
||||
Z_Free(bossinfo.enemyname);
|
||||
if (bossinfo.subtitle)
|
||||
Z_Free(bossinfo.subtitle);
|
||||
bossinfo.enemyname = bossinfo.subtitle = NULL;
|
||||
bossinfo.titleshow = 0;
|
||||
bossinfo.titlesound = sfx_typri1;
|
||||
memset(&(bossinfo.weakspots), 0, sizeof(weakspot_t)*NUMWEAKSPOTS);
|
||||
}
|
||||
|
||||
if (!fromnetsave) // uglier hack
|
||||
{ // to make a newly loaded level start on the second frame.
|
||||
INT32 buf = gametic % TICQUEUE;
|
||||
|
|
|
|||
42
src/p_tick.c
42
src/p_tick.c
|
|
@ -33,6 +33,7 @@
|
|||
#include "k_kart.h"
|
||||
#include "k_race.h"
|
||||
#include "k_battle.h"
|
||||
#include "k_boss.h"
|
||||
#include "k_waypoint.h"
|
||||
#include "k_director.h"
|
||||
|
||||
|
|
@ -327,6 +328,7 @@ if ((*mop = targ) != NULL) // Set new target and if non-NULL, increase its count
|
|||
static inline void P_RunThinkers(void)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < NUM_THINKERLISTS; i++)
|
||||
{
|
||||
ps_thlist_times[i] = I_GetPreciseTime();
|
||||
|
|
@ -610,24 +612,36 @@ void P_Ticker(boolean run)
|
|||
if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
|
||||
P_PlayerAfterThink(&players[i]);
|
||||
|
||||
// Plays the music after the starting countdown.
|
||||
if (leveltime == (starttime + (TICRATE/2)))
|
||||
// Bosses have a punchy start, so no position.
|
||||
if (bossinfo.boss == true)
|
||||
{
|
||||
S_ChangeMusic(mapmusname, mapmusflags, true);
|
||||
S_ShowMusicCredit();
|
||||
}
|
||||
|
||||
if (encoremode)
|
||||
{
|
||||
// Encore humming starts immediately.
|
||||
if (leveltime == 3)
|
||||
S_ChangeMusicInternal("encore", true);
|
||||
{
|
||||
S_ChangeMusic(mapmusname, mapmusflags, true);
|
||||
S_ShowMusicCredit();
|
||||
}
|
||||
}
|
||||
// Plays the music after the starting countdown.
|
||||
else
|
||||
{
|
||||
// Plays the POSITION music after the camera spin
|
||||
if (leveltime == introtime)
|
||||
S_ChangeMusicInternal("postn", true);
|
||||
if (leveltime == (starttime + (TICRATE/2)))
|
||||
{
|
||||
S_ChangeMusic(mapmusname, mapmusflags, true);
|
||||
S_ShowMusicCredit();
|
||||
}
|
||||
|
||||
if (encoremode)
|
||||
{
|
||||
// Encore humming starts immediately.
|
||||
if (leveltime == 3)
|
||||
S_ChangeMusicInternal("encore", true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Plays the POSITION music after the camera spin
|
||||
if (leveltime == introtime)
|
||||
S_ChangeMusicInternal("postn", true);
|
||||
}
|
||||
}
|
||||
|
||||
ps_lua_thinkframe_time = I_GetPreciseTime();
|
||||
|
|
@ -665,6 +679,8 @@ void P_Ticker(boolean run)
|
|||
if (hyubgone > 0)
|
||||
hyubgone--;
|
||||
|
||||
K_BossInfoTicker();
|
||||
|
||||
if ((gametyperules & GTR_BUMPERS))
|
||||
{
|
||||
if (wantedcalcdelay && --wantedcalcdelay <= 0)
|
||||
|
|
|
|||
11
src/p_user.c
11
src/p_user.c
|
|
@ -52,6 +52,7 @@
|
|||
#include "k_respawn.h"
|
||||
#include "k_bot.h"
|
||||
#include "k_grandprix.h"
|
||||
#include "k_boss.h"
|
||||
#include "k_terrain.h" // K_SpawnSplashForMobj
|
||||
#include "k_color.h"
|
||||
|
||||
|
|
@ -805,7 +806,9 @@ void P_RestoreMusic(player_t *player)
|
|||
return;
|
||||
|
||||
// Event - Level Start
|
||||
if (leveltime >= (starttime + (TICRATE/2))) // see also where time overs are handled - search for "lives = 2" in this file
|
||||
if (bossinfo.boss == false && (leveltime < (starttime + (TICRATE/2)))) // see also where time overs are handled
|
||||
return;
|
||||
|
||||
{
|
||||
INT32 wantedmus = 0; // 0 is level music, 1 is invincibility, 2 is grow
|
||||
|
||||
|
|
@ -3002,7 +3005,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
|
|||
else
|
||||
timeover = 0;
|
||||
|
||||
if (!(player->playerstate == PST_DEAD || player->exiting))
|
||||
if (!(player->playerstate == PST_DEAD || player->exiting || leveltime < introtime))
|
||||
{
|
||||
if (player->spectator) // force cam off for spectators
|
||||
return true;
|
||||
|
|
@ -3757,7 +3760,7 @@ void P_DoTimeOver(player_t *player)
|
|||
legitimateexit = true; // SRB2kart: losing a race is still seeing it through to the end :p
|
||||
}
|
||||
|
||||
if (netgame && !player->bot)
|
||||
if (netgame && !player->bot && !bossinfo.boss)
|
||||
{
|
||||
CON_LogMessage(va(M_GetText("%s ran out of time.\n"), player_names[player-players]));
|
||||
}
|
||||
|
|
@ -4322,7 +4325,7 @@ void P_PlayerThink(player_t *player)
|
|||
}
|
||||
|
||||
// Accessibility - kickstart your acceleration
|
||||
if (!(player->pflags & PF_KICKSTARTACCEL))
|
||||
if (gametype == GT_BATTLE || !(player->pflags & PF_KICKSTARTACCEL))
|
||||
player->kickstartaccel = 0;
|
||||
else if (cmd->buttons & BT_ACCELERATE)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -762,16 +762,16 @@ boolean R_SpriteIsFlashing(vissprite_t *vis)
|
|||
return (!(vis->cut & SC_PRECIP)
|
||||
&& (vis->mobj->flags & (MF_ENEMY|MF_BOSS))
|
||||
&& (vis->mobj->flags2 & MF2_FRET)
|
||||
&& !(vis->mobj->flags & MF_GRENADEBOUNCE)
|
||||
&& (leveltime & 1));
|
||||
&& !(vis->mobj->flags & MF_GRENADEBOUNCE));
|
||||
}
|
||||
|
||||
UINT8 *R_GetSpriteTranslation(vissprite_t *vis)
|
||||
{
|
||||
if (vis->mobj->hitlag > 0 && (vis->mobj->eflags & MFE_DAMAGEHITLAG))
|
||||
if ((vis->mobj->hitlag > 0 && (vis->mobj->eflags & MFE_DAMAGEHITLAG)) || R_SpriteIsFlashing(vis))
|
||||
{
|
||||
return R_GetTranslationColormap(TC_HITLAG, 0, GTC_CACHE);
|
||||
}
|
||||
/*
|
||||
else if (R_SpriteIsFlashing(vis)) // Bosses "flash"
|
||||
{
|
||||
if (vis->mobj->type == MT_CYBRAKDEMON || vis->mobj->colorized)
|
||||
|
|
@ -781,6 +781,7 @@ UINT8 *R_GetSpriteTranslation(vissprite_t *vis)
|
|||
else
|
||||
return R_GetTranslationColormap(TC_BOSS, 0, GTC_CACHE);
|
||||
}
|
||||
*/
|
||||
else if (vis->mobj->color)
|
||||
{
|
||||
// New colormap stuff for skins Tails 06-07-2002
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "m_misc.h" // for tunes command
|
||||
#include "m_cond.h" // for conditionsets
|
||||
#include "lua_hook.h" // MusicChange hook
|
||||
#include "k_boss.h" // bossinfo
|
||||
|
||||
#ifdef HW3SOUND
|
||||
// 3D Sound Interface
|
||||
|
|
@ -2351,7 +2352,9 @@ void S_StartEx(boolean reset)
|
|||
S_StopMusic(); // Starting ambience should always be restarted, if playing.
|
||||
|
||||
if (leveltime < (starttime + (TICRATE/2))) // SRB2Kart
|
||||
S_StartSound(NULL, encoremode ? sfx_ruby2 : sfx_kstart);
|
||||
{
|
||||
;
|
||||
}
|
||||
else
|
||||
S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0);
|
||||
|
||||
|
|
|
|||
|
|
@ -1100,6 +1100,8 @@ sfxinfo_t S_sfx[NUMSFX] =
|
|||
{"cock", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Hammer cocks, bang bang
|
||||
{"itcaps", false, 64, 16, -1, NULL, 0, -1, -1, LUMPERROR, "Item capsule"},
|
||||
{"kstart", false, 64, 16, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Sonic Adventure shwing!
|
||||
{"typri1", false, 64, 16, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // SA2 boss typewriting 1
|
||||
{"typri2", false, 64, 16, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // SA2 final boss-type typewriting
|
||||
|
||||
// SRB2Kart - Engine sounds
|
||||
// Engine class A
|
||||
|
|
|
|||
|
|
@ -1164,6 +1164,8 @@ typedef enum
|
|||
sfx_cock,
|
||||
sfx_itcaps,
|
||||
sfx_kstart,
|
||||
sfx_typri1,
|
||||
sfx_typri2,
|
||||
|
||||
// Next up: UNIQUE ENGINE SOUNDS! Hoooooo boy...
|
||||
// Engine class A - Low Speed, Low Weight
|
||||
|
|
|
|||
138
src/st_stuff.c
138
src/st_stuff.c
|
|
@ -32,6 +32,7 @@
|
|||
#include "m_anigif.h" // cv_gif_downscale
|
||||
#include "p_setup.h" // NiGHTS grading
|
||||
#include "k_grandprix.h" // we need to know grandprix status for titlecards
|
||||
#include "k_boss.h"
|
||||
|
||||
//random index
|
||||
#include "m_random.h"
|
||||
|
|
@ -647,6 +648,9 @@ static patch_t *tcroundnum[10];
|
|||
static patch_t *tcactnum[10];
|
||||
static patch_t *tcact;
|
||||
|
||||
static patch_t *twarn;
|
||||
static patch_t *twarn2;
|
||||
|
||||
// some coordinates define to make my life easier....
|
||||
#define FINAL_ROUNDX (24)
|
||||
#define FINAL_EGGY (160)
|
||||
|
|
@ -700,6 +704,9 @@ static void ST_cacheLevelTitle(void)
|
|||
|
||||
tcact = (patch_t *)W_CachePatchName("TT_ACT", PU_HUDGFX);
|
||||
|
||||
twarn = (patch_t *)W_CachePatchName("K_BOSW01", PU_HUDGFX);
|
||||
twarn2 = (patch_t *)W_CachePatchName("K_BOSW02", PU_HUDGFX);
|
||||
|
||||
// Cache round #
|
||||
for (i=1; i < 11; i++)
|
||||
{
|
||||
|
|
@ -786,7 +793,36 @@ void ST_runTitleCard(void)
|
|||
|
||||
// SRB2KART
|
||||
// side Zig-Zag positions...
|
||||
|
||||
if (bossinfo.boss == true)
|
||||
{
|
||||
// Handle name info...
|
||||
if (bossinfo.enemyname)
|
||||
{
|
||||
UINT32 len = strlen(bossinfo.enemyname)+1;
|
||||
if (len > 1 && bossinfo.titleshow < len)
|
||||
{
|
||||
len = (lt_endtime-(TICRATE/2))/len;
|
||||
if (lt_ticker % len == 0)
|
||||
{
|
||||
char c = toupper(bossinfo.enemyname[bossinfo.titleshow]);
|
||||
bossinfo.titleshow++;
|
||||
c -= LT_FONTSTART;
|
||||
if (c < 0 || c >= LT_FONTSIZE || !tc_font[1][(INT32)c] || !bossinfo.titlesound)
|
||||
{
|
||||
;
|
||||
}
|
||||
else
|
||||
{
|
||||
S_StartSound(NULL, bossinfo.titlesound);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// No matter the circumstances, scroll the WARN...
|
||||
bannerx = -(lt_ticker%((encoremode ? twarn2 : twarn)->width));
|
||||
}
|
||||
else
|
||||
{
|
||||
// TITLECARD START
|
||||
if (lt_ticker < TTANIMSTART)
|
||||
{
|
||||
|
|
@ -909,6 +945,7 @@ void ST_runTitleCard(void)
|
|||
|
||||
// No matter the circumstances, scroll the banner...
|
||||
bannerx = -(lt_ticker%(tcbanner->width));
|
||||
}
|
||||
|
||||
|
||||
// used for hud slidein
|
||||
|
|
@ -952,6 +989,101 @@ void ST_drawTitleCard(void)
|
|||
if (lt_ticker < TTANIMSTART)
|
||||
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, levelfadecol);
|
||||
|
||||
if (bossinfo.boss == true)
|
||||
{
|
||||
// WARNING!
|
||||
// https://twitter.com/matthewseiji/status/1485003284196716544
|
||||
// the above tweet is directly responsible for the existence of bosses in this game at all
|
||||
{
|
||||
#define LOTIME 5
|
||||
#define HITIME 15
|
||||
patch_t *localwarn = (encoremode ? twarn2 : twarn);
|
||||
INT32 transp = (lt_ticker+HITIME) % (LOTIME+HITIME);
|
||||
boolean encorehack = (encoremode && lt_ticker <= PRELEVELTIME+4);
|
||||
|
||||
if (lt_ticker + (HITIME-transp) <= lt_endtime)
|
||||
{
|
||||
if (transp > HITIME-1)
|
||||
{
|
||||
transp = HITIME-1;
|
||||
}
|
||||
|
||||
transp = (((10*transp)/HITIME)<<V_ALPHASHIFT) | (encorehack ? V_SUBTRACT : V_ADD);
|
||||
|
||||
for (i=0; i < 3; i++)
|
||||
{
|
||||
V_DrawFixedPatch((bannerx + bx)*FRACUNIT, 55*FRACUNIT, FRACUNIT, V_SNAPTOLEFT|transp, localwarn, NULL);
|
||||
bx += localwarn->width;
|
||||
}
|
||||
}
|
||||
#undef LOTIME
|
||||
#undef HITIME
|
||||
}
|
||||
|
||||
// Everything else...
|
||||
if (bossinfo.enemyname)
|
||||
{
|
||||
bx = V_TitleCardStringWidth(bossinfo.enemyname);
|
||||
|
||||
// Name.
|
||||
V_DrawTitleCardString((BASEVIDWIDTH - bx)/2, 75, bossinfo.enemyname, 0, true, bossinfo.titleshow, lt_exitticker);
|
||||
|
||||
// Under-bar.
|
||||
{
|
||||
angle_t fakeang = 0;
|
||||
fixed_t scalex = FRACUNIT;
|
||||
|
||||
// Handle scaling.
|
||||
if (lt_ticker <= 3)
|
||||
{
|
||||
fakeang = (lt_ticker*ANGLE_45)/2;
|
||||
scalex = FINESINE(fakeang>>ANGLETOFINESHIFT);
|
||||
}
|
||||
else if (lt_exitticker > 1)
|
||||
{
|
||||
if (lt_exitticker <= 4)
|
||||
{
|
||||
fakeang = ((lt_exitticker-1)*ANGLE_45)/2;
|
||||
scalex = FINECOSINE(fakeang>>ANGLETOFINESHIFT);
|
||||
}
|
||||
else
|
||||
{
|
||||
scalex = 0;
|
||||
}
|
||||
}
|
||||
// Handle subtitle.
|
||||
else if (bossinfo.subtitle && lt_ticker >= TICRATE/2)
|
||||
{
|
||||
INT32 by = 75+32;
|
||||
if (lt_ticker == TICRATE/2 || lt_exitticker == 1)
|
||||
{
|
||||
;
|
||||
}
|
||||
else if (lt_ticker == (TICRATE/2)+1 || lt_ticker == lt_endtime)
|
||||
{
|
||||
by += 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
by += 5;
|
||||
}
|
||||
|
||||
V_DrawRightAlignedThinString((BASEVIDWIDTH+bx)/2, by, V_6WIDTHSPACE, bossinfo.subtitle);
|
||||
}
|
||||
|
||||
// Now draw the under-bar itself.
|
||||
if (scalex > 0)
|
||||
{
|
||||
bx = FixedMul(bx, scalex);
|
||||
V_DrawFill((BASEVIDWIDTH-(bx+2))/2, 75+32, bx+2, 3, 31);
|
||||
V_DrawFill((BASEVIDWIDTH-(bx))/2, 75+32+1, bx, 1, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
lt_lasttic = lt_ticker;
|
||||
goto luahook;
|
||||
}
|
||||
|
||||
// Background zig-zags
|
||||
V_DrawFixedPatch((chev1x)*FRACUNIT, (chev1y)*FRACUNIT, FRACUNIT, chevtflag, tcchev1, NULL);
|
||||
V_DrawFixedPatch((chev2x)*FRACUNIT, (chev2y)*FRACUNIT, FRACUNIT, chevtflag, tcchev2, NULL);
|
||||
|
|
@ -982,10 +1114,10 @@ void ST_drawTitleCard(void)
|
|||
V_DrawFixedPatch(eggx2*FRACUNIT, eggy2*FRACUNIT, FRACUNIT, V_SNAPTOBOTTOM|V_SNAPTOLEFT, tccirclebottom, NULL);
|
||||
|
||||
// Now the level name.
|
||||
V_DrawTitleCardString((actnum) ? 265 : 280, 60, lvlttl, V_SNAPTORIGHT, true, lt_ticker, TTANIMENDTHRESHOLD);
|
||||
V_DrawTitleCardString((actnum) ? 265 : 280, 60, lvlttl, V_SNAPTORIGHT, false, lt_ticker, TTANIMENDTHRESHOLD);
|
||||
|
||||
if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE))
|
||||
V_DrawTitleCardString((actnum) ? 265 : 280, 60+32, strlen(zonttl) ? zonttl : "ZONE", V_SNAPTORIGHT, true, lt_ticker - strlen(lvlttl), TTANIMENDTHRESHOLD);
|
||||
V_DrawTitleCardString((actnum) ? 265 : 280, 60+32, strlen(zonttl) ? zonttl : "ZONE", false, false, lt_ticker - strlen(lvlttl), TTANIMENDTHRESHOLD);
|
||||
|
||||
// the act has a similar graphic animation, but we'll handle it here since it's only like 2 graphics lmfao.
|
||||
if (actnum && actnum < 10)
|
||||
|
|
|
|||
|
|
@ -1719,7 +1719,7 @@ INT32 V_TitleCardStringWidth(const char *str)
|
|||
// V_DrawTitleCardScreen.
|
||||
// see v_video.h's prototype for more information.
|
||||
//
|
||||
void V_DrawTitleCardString(INT32 x, INT32 y, const char *str, INT32 flags, boolean alignright, INT32 timer, INT32 threshold)
|
||||
void V_DrawTitleCardString(INT32 x, INT32 y, const char *str, INT32 flags, boolean bossmode, INT32 timer, INT32 threshold)
|
||||
{
|
||||
|
||||
INT32 xoffs = 0;
|
||||
|
|
@ -1740,7 +1740,7 @@ void V_DrawTitleCardString(INT32 x, INT32 y, const char *str, INT32 flags, boole
|
|||
|
||||
x -= 2; // Account for patch width...
|
||||
|
||||
if (alignright)
|
||||
if (flags & V_SNAPTORIGHT)
|
||||
x -= V_TitleCardStringWidth(str);
|
||||
|
||||
|
||||
|
|
@ -1778,11 +1778,25 @@ void V_DrawTitleCardString(INT32 x, INT32 y, const char *str, INT32 flags, boole
|
|||
ol = tc_font[0][(INT32)c];
|
||||
pp = tc_font[1][(INT32)c];
|
||||
|
||||
if (timer)
|
||||
if (bossmode)
|
||||
{
|
||||
if (let_time <= 0)
|
||||
return;
|
||||
if (threshold > 0)
|
||||
{
|
||||
if (threshold > 3)
|
||||
return;
|
||||
fakeang = (threshold*ANGLE_45)/2;
|
||||
scalex = FINECOSINE(fakeang>>ANGLETOFINESHIFT);
|
||||
}
|
||||
offs = ((FRACUNIT-scalex)*pp->width)/2;
|
||||
}
|
||||
else if (timer)
|
||||
{
|
||||
|
||||
// make letters appear
|
||||
if (!threshold || let_time < threshold)
|
||||
if (!threshold)
|
||||
;
|
||||
else if (let_time < threshold)
|
||||
{
|
||||
if (let_time <= 0)
|
||||
return; // No reason to continue drawing, none of the next letters will be drawn either.
|
||||
|
|
@ -1792,7 +1806,7 @@ void V_DrawTitleCardString(INT32 x, INT32 y, const char *str, INT32 flags, boole
|
|||
fakeang = min(360 + 90, let_time*41) * ANG1;
|
||||
scalex = FINESINE(fakeang>>ANGLETOFINESHIFT);
|
||||
}
|
||||
else if (let_time > threshold)
|
||||
else if (!bossmode && let_time > threshold)
|
||||
{
|
||||
// Make letters disappear...
|
||||
let_time -= threshold;
|
||||
|
|
|
|||
|
|
@ -269,7 +269,7 @@ void V_DrawRightAlignedThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, con
|
|||
// threshold: when the letters start disappearing (leave to 0 to disable) (both are INT32 in case you supply negative values...)
|
||||
// NOTE: This function ignores most conventional string flags (V_RETURN8, V_ALLOWLOWERCASE ...)
|
||||
// NOTE: This font only works with uppercase letters.
|
||||
void V_DrawTitleCardString(INT32 x, INT32 y, const char *str, INT32 flags, boolean alignright, INT32 timer, INT32 threshold);
|
||||
void V_DrawTitleCardString(INT32 x, INT32 y, const char *str, INT32 flags, boolean bossmode, INT32 timer, INT32 threshold);
|
||||
|
||||
// returns thr width of a string drawn using the above function.
|
||||
INT32 V_TitleCardStringWidth(const char *str);
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@
|
|||
#include "m_random.h" // M_RandomKey
|
||||
#include "g_input.h" // PlayerInputDown
|
||||
#include "k_battle.h"
|
||||
#include "k_boss.h"
|
||||
#include "k_pwrlv.h"
|
||||
#include "console.h" // cons_menuhighlight
|
||||
#include "k_grandprix.h"
|
||||
|
|
@ -222,7 +223,14 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32))
|
|||
else
|
||||
{
|
||||
// set up the levelstring
|
||||
if (mapheaderinfo[prevmap]->levelflags & LF_NOZONE)
|
||||
if (bossinfo.boss == true && bossinfo.enemyname)
|
||||
{
|
||||
snprintf(data.levelstring,
|
||||
sizeof data.levelstring,
|
||||
"* %s *",
|
||||
bossinfo.enemyname);
|
||||
}
|
||||
else if (mapheaderinfo[prevmap]->levelflags & LF_NOZONE)
|
||||
{
|
||||
if (mapheaderinfo[prevmap]->actnum > 0)
|
||||
snprintf(data.levelstring,
|
||||
|
|
@ -493,7 +501,7 @@ void Y_IntermissionDrawer(void)
|
|||
x += (((16 - count) * vid.width) / (8 * vid.dupx));
|
||||
}
|
||||
|
||||
if (intertype == int_race || intertype == int_battle)
|
||||
if (intertype == int_race || intertype == int_battle || intertype == int_battletime)
|
||||
{
|
||||
#define NUMFORNEWCOLUMN 8
|
||||
INT32 y = 41, gutter = ((data.numplayers > NUMFORNEWCOLUMN) ? 0 : (BASEVIDWIDTH/2));
|
||||
|
|
@ -516,19 +524,11 @@ void Y_IntermissionDrawer(void)
|
|||
{
|
||||
switch (intertype)
|
||||
{
|
||||
default:
|
||||
case int_race:
|
||||
timeheader = "TIME";
|
||||
break;
|
||||
case int_battle:
|
||||
if (battlecapsules)
|
||||
{
|
||||
timeheader = "TIME";
|
||||
}
|
||||
else
|
||||
{
|
||||
timeheader = "SCORE";
|
||||
}
|
||||
timeheader = "SCORE";
|
||||
break;
|
||||
default:
|
||||
timeheader = "TIME";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -653,7 +653,7 @@ void Y_IntermissionDrawer(void)
|
|||
V_DrawRightAlignedThinString(x+152+gutter, y-1, (data.numplayers > NUMFORNEWCOLUMN ? V_6WIDTHSPACE : 0), "NO CONTEST.");
|
||||
else
|
||||
{
|
||||
if (intertype == int_race || (intertype == int_battle && battlecapsules))
|
||||
if (intertype == int_race || intertype == int_battletime)
|
||||
{
|
||||
snprintf(strtime, sizeof strtime, "%i'%02i\"%02i", G_TicsToMinutes(data.val[i], true),
|
||||
G_TicsToSeconds(data.val[i]), G_TicsToCentiseconds(data.val[i]));
|
||||
|
|
@ -695,7 +695,7 @@ skiptallydrawer:
|
|||
if (!LUA_HudEnabled(hud_intermissionmessages))
|
||||
return;
|
||||
|
||||
if (timer && grandprixinfo.gp == false)
|
||||
if (timer && grandprixinfo.gp == false && bossinfo.boss == false)
|
||||
{
|
||||
char *string;
|
||||
INT32 tickdown = (timer+1)/TICRATE;
|
||||
|
|
@ -797,11 +797,11 @@ void Y_Ticker(void)
|
|||
if (intertic < TICRATE || intertic & 1 || endtic != -1)
|
||||
return;
|
||||
|
||||
if (intertype == int_race || intertype == int_battle)
|
||||
if (intertype == int_race || intertype == int_battle || intertype == int_battletime)
|
||||
{
|
||||
//if (!(multiplayer && demo.playback)) // Don't advance to rankings in replays
|
||||
{
|
||||
if (!data.rankingsmode && (intertic >= sorttic + 8))
|
||||
if (!data.rankingsmode && sorttic != -1 && (intertic >= sorttic + 8))
|
||||
{
|
||||
Y_CalculateMatchData(1, Y_CompareRank);
|
||||
}
|
||||
|
|
@ -1034,12 +1034,19 @@ void Y_DetermineIntermissionType(void)
|
|||
|
||||
if (intermissiontypes[gametype] != int_none)
|
||||
intertype = intermissiontypes[gametype];
|
||||
else if (modeattacking)
|
||||
intertype = int_timeattack;
|
||||
else if (gametype == GT_RACE)
|
||||
intertype = int_race;
|
||||
else if (gametype == GT_BATTLE)
|
||||
intertype = int_battle;
|
||||
{
|
||||
UINT8 i = 0, nump = 0;
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i] || players[i].spectator)
|
||||
continue;
|
||||
nump++;
|
||||
}
|
||||
intertype = (nump < 2 ? int_battletime : int_battle);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -1081,7 +1088,14 @@ void Y_StartIntermission(void)
|
|||
if (intermissiontypes[gametype] != int_none)
|
||||
intertype = intermissiontypes[gametype];
|
||||
|
||||
sorttic = max((timer/2) - 2*TICRATE, 2*TICRATE); // 8 second pause after match results
|
||||
if (multiplayer)
|
||||
{
|
||||
sorttic = max((timer/2) - 2*TICRATE, 2*TICRATE); // 8 second pause after match results
|
||||
}
|
||||
else
|
||||
{
|
||||
sorttic = -1;
|
||||
}
|
||||
|
||||
// We couldn't display the intermission even if we wanted to.
|
||||
// But we still need to give the players their score bonuses, dummy.
|
||||
|
|
@ -1094,23 +1108,20 @@ void Y_StartIntermission(void)
|
|||
switch (intertype)
|
||||
{
|
||||
case int_battle:
|
||||
case int_battletime:
|
||||
{
|
||||
// Calculate who won
|
||||
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;
|
||||
// Calculate who won
|
||||
if (intertype == int_battle)
|
||||
{
|
||||
Y_CalculateMatchData(0, Y_CompareScore);
|
||||
break;
|
||||
}
|
||||
}
|
||||
case int_race: // (time-only race)
|
||||
// FALLTHRU
|
||||
case int_race:
|
||||
{
|
||||
// Calculate who won
|
||||
Y_CalculateMatchData(0, Y_CompareTime);
|
||||
|
|
|
|||
|
|
@ -32,8 +32,8 @@ typedef enum
|
|||
{
|
||||
int_none,
|
||||
int_race, // Race
|
||||
int_battle, // Battle
|
||||
int_timeattack, // Time Attack
|
||||
int_battle, // Battle (score-based)
|
||||
int_battletime, // Battle (time-based)
|
||||
} intertype_t;
|
||||
|
||||
extern intertype_t intertype;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue