Merge branch 'master' into reloadmap-fix

This commit is contained in:
SteelT 2024-03-06 16:03:11 -05:00
commit e97de3d6f3
64 changed files with 762 additions and 335 deletions

View file

@ -579,7 +579,7 @@ target_compile_definitions(SRB2SDL2 PRIVATE -DCMAKECONFIG)
# Misc. build options from Makefiles
if(SRB2_CONFIG_DEBUGMODE)
target_compile_definitions(SRB2SDL2 PRIVATE -DZDEBUG -DPARANOIA -DRANGECHECK -DPACKETDROP)
target_compile_definitions(SRB2SDL2 PRIVATE -DZDEBUG -DPARANOIA -DPACKETDROP)
endif()
if(SRB2_CONFIG_TESTERS)
target_compile_definitions(SRB2SDL2 PRIVATE -DTESTERS)

View file

@ -356,7 +356,7 @@ consvar_t cv_drawdist_precip = Player("drawdist_precip", "1024").values({
{0, "None"},
});
consvar_t cv_drawinput = Player("drawinput", "No").yes_no();
consvar_t cv_drawinput = Player("drawinput", "Off").on_off();
consvar_t cv_ffloorclip = Player("ffloorclip", "On").on_off();
consvar_t cv_fpscap = Player("fpscap", "Match refresh rate").values({
@ -873,6 +873,10 @@ consvar_t cv_1pswap = PlayerCheat("1pswap", "1").min_max(1, MAXSPLITSCREENPLAYER
consvar_t cv_debugfinishline = PlayerCheat("debugfinishline", "Off").on_off().description("Highlight finish lines, respawn lines, death pits and instakill planes with high contrast colors");
consvar_t cv_debughudtracker = PlayerCheat("debughudtracker", "Off").on_off().description("Highlight overlapping HUD tracker blocks");
#ifdef DEVELOP
consvar_t cv_debugprisoncd = PlayerCheat("debugprisoncd", "Off").on_off().description("Always drop a CD from breaking Prisons");
#endif
consvar_t cv_debugrank = PlayerCheat("debugrank", "Off").description("Show GP rank state on the HUD; optionally force a rank grade").values({
{0, "Off"},
{1, "On"},
@ -890,6 +894,7 @@ consvar_t cv_debugrender_freezebsp = PlayerCheat("debugrender_freezebsp", "Off")
consvar_t cv_debugrender_portal = PlayerCheat("debugrender_portal", "Off").on_off().description("Highlight visual portals in red");
consvar_t cv_debugrender_spriteclip = PlayerCheat("debugrender_spriteclip", "Off").on_off().description("Let sprites draw through walls");
consvar_t cv_debugrender_visplanes = PlayerCheat("debugrender_visplanes", "Off").on_off().description("Highlight the number of visplanes");
consvar_t cv_debugvirtualkeyboard = PlayerCheat("debugvirtualkeyboard", "Off").on_off().description("Always show virtual keyboard instead of using real keyboard input.");
consvar_t cv_devmode_screen = PlayerCheat("devmode_screen", "1").min_max(1, 4).description("Choose which splitscreen player devmode applies to");
consvar_t cv_drawpickups = PlayerCheat("drawpickups", "Yes").yes_no().description("Hide rings, spheres, item capsules, prison capsules (visual only)");
@ -926,6 +931,7 @@ consvar_t cv_dummygpdifficulty = MenuDummy("dummygpdifficulty", "Normal").values
consvar_t cv_dummygpencore = MenuDummy("dummygpencore", "Off").on_off();
consvar_t cv_dummyip = MenuDummy("dummyip", "");
consvar_t cv_dummyipselect = MenuDummy("dummyipselect", "0").min_max(0, 2);
extern CV_PossibleValue_t dummykartspeed_cons_t[];
consvar_t cv_dummykartspeed = MenuDummy("dummykartspeed", "Gear 2").values(dummykartspeed_cons_t);
@ -951,6 +957,7 @@ void Dummymenuplayer_OnChange(void);
consvar_t cv_dummymenuplayer = MenuDummy("dummymenuplayer", "P1").onchange(Dummymenuplayer_OnChange).values({{0, "NOPE"}, {1, "P1"}, {2, "P2"}, {3, "P3"}, {4, "P4"}});
consvar_t cv_dummyprofileautoroulette = MenuDummy("dummyprofileautoroulette", "Off").on_off();
consvar_t cv_dummyprofilefov = MenuDummy("dummyprofilefov", "90").min_max(70, 110);
consvar_t cv_dummyprofilelitesteer = MenuDummy("dummyprofilelitesteer", "On").on_off();
consvar_t cv_dummyprofilekickstart = MenuDummy("dummyprofilekickstart", "Off").on_off();
consvar_t cv_dummyprofilename = MenuDummy("dummyprofilename", "");

View file

@ -1947,7 +1947,7 @@ void D_SRB2Main(void)
profile_t *pr = PR_GetProfile(cv_ttlprofilen.value);
if (pr != NULL)
{
INT32 importskin = R_SkinAvailable(pr->skinname);
INT32 importskin = R_SkinAvailableEx(pr->skinname, false);
if (importskin != -1)
{
skins[importskin].records.wins = pr->wins;

View file

@ -960,7 +960,7 @@ static void SendNameAndColor(const UINT8 n)
// check if player has the skin loaded (cv_skin may have
// the name of a skin that was available in the previous game)
cv_skin[n].value = R_SkinAvailable(cv_skin[n].string);
cv_skin[n].value = R_SkinAvailableEx(cv_skin[n].string, false);
if ((cv_skin[n].value < 0) || !R_SkinUsable(playernum, cv_skin[n].value, false))
{
CV_StealthSet(&cv_skin[n], DEFAULTSKIN);

View file

@ -987,11 +987,13 @@ struct player_t
INT16 incontrol; // -1 to -175 when spinning out or tumbling, 1 to 175 when not. Use to check for combo hits or emergency inputs.
UINT16 progressivethrust; // When getting beat up in GTR_BUMPERS, speed up the longer you've been out of control.
UINT8 ringvisualwarning; // Check with > 1, not >= 1! Set when put in debt, counts down and holds at 1 when still in debt.
boolean analoginput; // Has an input been recorded that requires analog usage? For input display.
boolean markedfordeath;
boolean dotrickfx;
boolean stingfx;
UINT8 bumperinflate;
UINT8 ringboxdelay; // Delay until Ring Box auto-activates

View file

@ -506,6 +506,10 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi
// Prison Egg Drops
"S_PRISONEGGDROP_CD",
"S_PRISONEGGDROP_FLAREA1",
"S_PRISONEGGDROP_FLAREA2",
"S_PRISONEGGDROP_FLAREB1",
"S_PRISONEGGDROP_FLAREB2",
// Bubble Source
"S_BUBBLES1",

View file

@ -67,12 +67,10 @@ extern "C" {
#if !defined (NDEBUG)
#define PACKETDROP
#define PARANOIA
//#define RANGECHECK
#define ZDEBUG
#endif
// Uncheck this to compile debugging code
#define RANGECHECK
//#ifndef PARANOIA
//#define PARANOIA // do some tests that never fail but maybe
// turn this on by make etc.. DEBUGMODE = 1 or use the Debug profile in the VC++ projects

View file

@ -1345,12 +1345,12 @@ void F_TitleScreenDrawer(void)
if (cache_gametrulystarted == true)
{
const char *eggName = "eggman";
INT32 eggSkin = R_SkinAvailable(eggName);
INT32 eggSkin = R_SkinAvailableEx(eggName, false);
skincolornum_t eggColor = SKINCOLOR_RED;
UINT8 *eggColormap = NULL;
const char *tailsName = "tails";
INT32 tailsSkin = R_SkinAvailable(tailsName);
INT32 tailsSkin = R_SkinAvailableEx(tailsName, false);
skincolornum_t tailsColor = SKINCOLOR_ORANGE;
UINT8 *tailsColormap = NULL;

View file

@ -317,8 +317,8 @@ void G_ReadDemoExtraData(void)
skinid = READUINT8(demobuf.p);
if (skinid >= demo.numskins)
skinid = 0;
SetPlayerSkinByNum(p, demo.skinlist[skinid].mapping);
demo.currentskinid[p] = skinid;
ghostext[p].skinid = demo.currentskinid[p] = skinid;
SetPlayerSkinByNum(p, skinid);
players[p].kartspeed = ghostext[p].kartspeed = demo.skinlist[skinid].kartspeed;
players[p].kartweight = ghostext[p].kartweight = demo.skinlist[skinid].kartweight;
@ -424,7 +424,7 @@ void G_WriteDemoExtraData(void)
{
for (j = 0; j < MAXAVAILABILITY; j++)
{
WRITEUINT8(demobuf.p, players[i].availabilities[i]);
WRITEUINT8(demobuf.p, players[i].availabilities[j]);
}
WRITEUINT8(demobuf.p, (UINT8)players[i].bot);
@ -2033,7 +2033,6 @@ static void G_SaveDemoSkins(UINT8 **pp)
static democharlist_t *G_LoadDemoSkins(savebuffer_t *info, UINT8 *worknumskins, boolean getclosest)
{
char skin[17];
UINT8 i, byte, shif;
democharlist_t *skinlist = NULL;
@ -2052,8 +2051,6 @@ static democharlist_t *G_LoadDemoSkins(savebuffer_t *info, UINT8 *worknumskins,
I_Error("G_LoadDemoSkins: Insufficient memory to allocate list");
}
skin[16] = '\0';
for (i = 0; i < (*worknumskins); i++)
{
INT32 result = -1;
@ -2064,12 +2061,14 @@ static democharlist_t *G_LoadDemoSkins(savebuffer_t *info, UINT8 *worknumskins,
return NULL;
}
READMEM(info->p, skin, 16);
READMEM(info->p, skinlist[i].name, 16);
skinlist[i].name[16] = '\0';
skinlist[i].namehash = quickncasehash(skinlist[i].name, SKINNAMESIZE);
skinlist[i].kartspeed = READUINT8(info->p);
skinlist[i].kartweight = READUINT8(info->p);
skinlist[i].flags = READUINT32(info->p);
result = R_SkinAvailable(skin);
result = R_SkinAvailableEx(skinlist[i].name, false);
if (result == -1)
{
if (!getclosest)
@ -3354,12 +3353,9 @@ void G_DoPlayDemo(const char *defdemoname)
// Skin
i = READUINT8(demobuf.p);
if (i >= demo.numskins)
i = 0;
SetPlayerSkinByNum(p, demo.skinlist[i].mapping);
demo.currentskinid[p] = ghostext[p].skinid = i;
demo.currentskinid[p] = READUINT8(demobuf.p);
if (demo.currentskinid[p] >= demo.numskins)
demo.currentskinid[p] = 0;
lastfakeskin[p] = READUINT8(demobuf.p);
// Color
@ -3442,6 +3438,15 @@ void G_DoPlayDemo(const char *defdemoname)
UINT8 j;
p = slots[i];
for (j = 0; j < MAXAVAILABILITY; j++)
{
players[p].availabilities[j] = availabilities[p][j];
}
ghostext[p].skinid = demo.currentskinid[p];
SetPlayerSkinByNum(p, demo.currentskinid[p]);
if (players[p].mo)
{
players[p].mo->color = players[p].skincolor;
@ -3457,11 +3462,6 @@ void G_DoPlayDemo(const char *defdemoname)
players[p].kartweight = ghostext[p].kartweight = demo.skinlist[demo.currentskinid[p]].kartweight;
players[p].charflags = ghostext[p].charflags = demo.skinlist[demo.currentskinid[p]].flags;
players[p].lastfakeskin = lastfakeskin[p];
for (j = 0; j < MAXAVAILABILITY; j++)
{
players[p].availabilities[j] = availabilities[p][j];
}
}
demo.deferstart = true;
@ -3591,7 +3591,7 @@ void G_AddGhost(savebuffer_t *buffer, const char *defdemoname)
// Skip unlockables
{
UINT32 unlockables = READUINT32(p);
p += std::min<UINT32>(unlockables, MAXUNLOCKABLES);
p += unlockables;
}
p++; // mapmusrng
@ -3814,7 +3814,7 @@ staffbrief_t *G_GetStaffGhostBrief(UINT8 *buffer)
// Skip unlockables
{
UINT32 unlockables = READUINT32(p);
p += std::min<UINT32>(unlockables, MAXUNLOCKABLES);
p += unlockables;
}
p++; // mapmusrng
@ -4131,7 +4131,6 @@ boolean G_CheckDemoTitleEntry(void)
demo.willsave = true;
M_OpenVirtualKeyboard(
false,
sizeof demo.titlename,
[](const char* replace) -> const char*
{

View file

@ -69,6 +69,8 @@ extern consvar_t cv_recordmultiplayerdemos, cv_netdemosyncquality;
extern tic_t demostarttime;
struct democharlist_t {
char name[17];
UINT32 namehash;
UINT8 mapping; // No, this isn't about levels. It maps to loaded character ID.
UINT8 kartspeed;
UINT8 kartweight;

View file

@ -508,7 +508,7 @@ void srb2::load_ng_gamedata()
for (auto& skinpair : js.skins)
{
INT32 skin = R_SkinAvailable(skinpair.first.c_str());
INT32 skin = R_SkinAvailableEx(skinpair.first.c_str(), false);
skinrecord_t dummyrecord {};
dummyrecord.wins = skinpair.second.records.wins;
@ -683,7 +683,7 @@ void srb2::load_ng_gamedata()
dummywindata[j].best_skin.id = MAXSKINS;
dummywindata[j].best_skin.unloaded = nullptr;
int skinloaded = R_SkinAvailable(cuppair.second.records[j].bestskin.c_str());
int skinloaded = R_SkinAvailableEx(cuppair.second.records[j].bestskin.c_str(), false);
if (skinloaded >= 0)
{
dummywindata[j].best_skin.id = skinloaded;

View file

@ -418,6 +418,12 @@ static INT32 AssignDeviceToFirstUnassignedPlayer(INT32 device)
return -1;
}
static void update_vkb_axis(INT32 axis)
{
if (axis > JOYAXISRANGE/2)
M_SwitchVirtualKeyboard(true);
}
//
// Remaps the inputs to game controls.
//
@ -460,6 +466,8 @@ void G_MapEventsToControls(event_t *ev)
case ev_keydown:
if (ev->data1 < NUMINPUTS)
{
M_MenuTypingInput(ev->data1);
if (ev->data2) // OS repeat? We handle that ourselves
{
break;
@ -556,11 +564,13 @@ void G_MapEventsToControls(event_t *ev)
if (ev->data2 != INT32_MAX)
{
DeviceGameKeyDownArray[KEY_AXIS1 + (JOYANALOGS * 4) + (i * 2)] = max(0, ev->data2);
update_vkb_axis(max(0, ev->data2));
}
if (ev->data3 != INT32_MAX)
{
DeviceGameKeyDownArray[KEY_AXIS1 + (JOYANALOGS * 4) + (i * 2) + 1] = max(0, ev->data3);
update_vkb_axis(max(0, ev->data3));
}
}
else
@ -592,6 +602,7 @@ void G_MapEventsToControls(event_t *ev)
DeviceGameKeyDownArray[KEY_AXIS1 + (i * 4)] = 0;
DeviceGameKeyDownArray[KEY_AXIS1 + (i * 4) + 1] = abs(ev->data2);
}
update_vkb_axis(abs(ev->data2));
}
if (ev->data3 != INT32_MAX)
@ -608,6 +619,7 @@ void G_MapEventsToControls(event_t *ev)
DeviceGameKeyDownArray[KEY_AXIS1 + (i * 4) + 2] = 0;
DeviceGameKeyDownArray[KEY_AXIS1 + (i * 4) + 3] = abs(ev->data3);
}
update_vkb_axis(abs(ev->data3));
}
}
break;

View file

@ -4740,10 +4740,11 @@ static void HWR_ProjectSprite(mobj_t *thing)
tr_y = FIXED_TO_FLOAT(interp.y);
// decide which patch to use for sprite relative to player
#ifdef RANGECHECK
if ((unsigned)thing->sprite >= numsprites)
I_Error("HWR_ProjectSprite: invalid sprite number %i ", thing->sprite);
#endif
{
CONS_Debug(DBG_RENDER, "HWR_ProjectSprite: invalid sprite number %i\n", thing->sprite);
return;
}
rot = thing->frame&FF_FRAMEMASK;
@ -5184,22 +5185,20 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing)
// decide which patch to use for sprite relative to player
if ((unsigned)thing->sprite >= numsprites)
#ifdef RANGECHECK
I_Error("HWR_ProjectPrecipitationSprite: invalid sprite number %i ",
{
CONS_Debug(DBG_RENDER, "HWR_ProjectPrecipitationSprite: invalid sprite number %i\n",
thing->sprite);
#else
return;
#endif
}
sprdef = &sprites[thing->sprite];
if ((size_t)(thing->frame&FF_FRAMEMASK) >= sprdef->numframes)
#ifdef RANGECHECK
I_Error("HWR_ProjectPrecipitationSprite: invalid sprite frame %i : %i for %s",
{
CONS_Debug(DBG_RENDER, "HWR_ProjectPrecipitationSprite: invalid sprite frame %i : %i for %s\n",
thing->sprite, thing->frame, sprnames[thing->sprite]);
#else
return;
#endif
}
sprframe = &sprdef->spriteframes[ thing->frame & FF_FRAMEMASK];

View file

@ -570,7 +570,7 @@ void HWR_InitModels(void)
addskinmodel:
// add player model
s = R_SkinAvailable(skinname);
s = R_SkinAvailableEx(skinname, false);
if (s != -1)
{
md2_playermodels[s].skin = s;

View file

@ -1013,6 +1013,10 @@ state_t states[NUMSTATES] =
// Prison Egg Drops
{SPR_ALTM, 0|FF_PAPERSPRITE|FF_SEMIBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_PRISONEGGDROP_CD
{SPR_LENS, 14|FF_FULLBRIGHT|FF_ADD|FF_TRANS10, 1, {NULL}, 0, 0, S_PRISONEGGDROP_FLAREA2}, // S_PRISONEGGDROP_FLAREA1
{SPR_NULL, 0, 1, {NULL}, 0, 0, S_PRISONEGGDROP_FLAREA1}, // S_PRISONEGGDROP_FLAREA2
{SPR_LENS, 11|FF_FULLBRIGHT|FF_ADD|FF_TRANS10|FF_ANIMATE, 16, {NULL}, 7, 2, S_PRISONEGGDROP_FLAREB2}, // S_PRISONEGGDROP_FLAREB1
{SPR_LENS, 19|FF_FULLBRIGHT|FF_ADD|FF_TRANS10|FF_ANIMATE, 6, {NULL}, 1, 2, S_NULL}, // S_PRISONEGGDROP_FLAREB2
// Bubble Source
{SPR_BBLS, 0, 8, {A_BubbleSpawn}, 2048, 0, S_BUBBLES2}, // S_BUBBLES1

View file

@ -1499,6 +1499,10 @@ typedef enum state
// Prison Egg Drops
S_PRISONEGGDROP_CD,
S_PRISONEGGDROP_FLAREA1,
S_PRISONEGGDROP_FLAREA2,
S_PRISONEGGDROP_FLAREB1,
S_PRISONEGGDROP_FLAREB2,
// Bubble Source
S_BUBBLES1,

View file

@ -177,12 +177,12 @@ void K_UpdateMatchRaceBots(void)
UINT8 numbots = 0;
UINT8 numwaiting = 0;
SINT8 wantedbots = 0;
UINT8 usableskins = 0;
UINT8 usableskins = 0, skincount = (demo.playback ? demo.numskins : numskins);;
UINT8 grabskins[MAXSKINS+1];
UINT8 i;
// Init usable bot skins list
for (i = 0; i < numskins; i++)
for (i = 0; i < skincount; i++)
{
grabskins[usableskins++] = i;
}

View file

@ -133,7 +133,7 @@ void K_InitGrandPrixBots(void)
UINT8 numplayers = 0;
UINT8 competitors[MAXSPLITSCREENPLAYERS];
UINT8 usableskins;
UINT8 usableskins, skincount = (demo.playback ? demo.numskins : numskins);;
UINT8 grabskins[MAXSKINS+1];
UINT8 botskinlist[MAXPLAYERS];
@ -146,7 +146,7 @@ void K_InitGrandPrixBots(void)
memset(botskinlist, defaultbotskin, sizeof (botskinlist));
// Init usable bot skins list
for (usableskins = 0; usableskins < numskins; usableskins++)
for (usableskins = 0; usableskins < skincount; usableskins++)
{
grabskins[usableskins] = usableskins;
}
@ -671,7 +671,7 @@ void K_RetireBots(void)
const UINT8 defaultbotskin = R_BotDefaultSkin();
SINT8 newDifficulty;
UINT8 usableskins;
UINT8 usableskins, skincount = (demo.playback ? demo.numskins : numskins);
UINT8 grabskins[MAXSKINS+1];
UINT8 i;
@ -687,7 +687,7 @@ void K_RetireBots(void)
}
// Init usable bot skins list
for (usableskins = 0; usableskins < numskins; usableskins++)
for (usableskins = 0; usableskins < skincount; usableskins++)
{
grabskins[usableskins] = usableskins;
}

View file

@ -88,6 +88,7 @@ patch_t *kp_facenum[MAXPLAYERS+1];
static patch_t *kp_facehighlight[8];
static patch_t *kp_nocontestminimap;
static patch_t *kp_unknownminimap;
static patch_t *kp_spbminimap;
static patch_t *kp_wouldyoustillcatchmeifiwereaworm;
static patch_t *kp_catcherminimap;
@ -386,7 +387,7 @@ void K_LoadKartHUDGraphics(void)
// Special minimap icons
HU_UpdatePatch(&kp_nocontestminimap, "MINIDEAD");
HU_UpdatePatch(&kp_unknownminimap, "HUHMAP");
HU_UpdatePatch(&kp_spbminimap, "SPBMMAP");
HU_UpdatePatch(&kp_wouldyoustillcatchmeifiwereaworm, "MINIPROG");
@ -2957,7 +2958,19 @@ static void K_drawRingCounter(boolean gametypeinfoshown)
rn[0] = ((abs(stplyr->hudrings) / 10) % 10);
rn[1] = (abs(stplyr->hudrings) % 10);
if (stplyr->hudrings <= 0 && (leveltime/5 & 1)) // In debt
if (stplyr->hudrings <= 0 && stplyr->ringvisualwarning > 1)
{
colorring = true;
if ((leveltime/2 & 1))
{
ringmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_CRIMSON, GTC_CACHE);
}
else
{
ringmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_WHITE, GTC_CACHE);
}
}
else if (stplyr->hudrings <= 0 && (leveltime/5 & 1)) // In debt
{
ringmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_CRIMSON, GTC_CACHE);
colorring = true;
@ -3068,16 +3081,24 @@ static void K_drawRingCounter(boolean gametypeinfoshown)
V_DrawMappedPatch(LAPS_X+ringx+7, fy-5, V_HUDTRANS|V_SLIDEIN|splitflags|ringflip, kp_ring[ringanim_realframe], (colorring ? ringmap : NULL));
// "Why fy-4? Why LAPS_X+29+1?"
// "use magic numbers" - jartha 2024-03-05
if (stplyr->hudrings < 0) // Draw the minus for ring debt
{
V_DrawMappedPatch(LAPS_X+23, fy, V_HUDTRANS|V_SLIDEIN|splitflags, kp_ringdebtminus, ringmap);
V_DrawMappedPatch(LAPS_X+29, fy, V_HUDTRANS|V_SLIDEIN|splitflags, kp_facenum[rn[0]], ringmap);
V_DrawMappedPatch(LAPS_X+35, fy, V_HUDTRANS|V_SLIDEIN|splitflags, kp_facenum[rn[1]], ringmap);
V_DrawMappedPatch(LAPS_X+23-1, fy, V_HUDTRANS|V_SLIDEIN|splitflags, kp_ringdebtminus, ringmap);
using srb2::Draw;
Draw row = Draw(LAPS_X+29+0, fy-4).flags(V_HUDTRANS|V_SLIDEIN|splitflags).font(Draw::Font::kThinTimer).colormap(ringmap);
row.text("{:02}", abs(stplyr->hudrings));
// V_DrawMappedPatch(LAPS_X+29, fy, V_HUDTRANS|V_SLIDEIN|splitflags, fontv[TALLNUM_FONT].font[rn[0]], ringmap);
// V_DrawMappedPatch(LAPS_X+35, fy, V_HUDTRANS|V_SLIDEIN|splitflags, fontv[TALLNUM_FONT].font[rn[1]], ringmap);
}
else
{
V_DrawMappedPatch(LAPS_X+23, fy, V_HUDTRANS|V_SLIDEIN|splitflags, kp_facenum[rn[0]], ringmap);
V_DrawMappedPatch(LAPS_X+29, fy, V_HUDTRANS|V_SLIDEIN|splitflags, kp_facenum[rn[1]], ringmap);
using srb2::Draw;
Draw row = Draw(LAPS_X+23+3, fy-4).flags(V_HUDTRANS|V_SLIDEIN|splitflags).font(Draw::Font::kThinTimer).colormap(ringmap);
row.text("{:02}", abs(stplyr->hudrings));
// V_DrawMappedPatch(LAPS_X+23, fy, V_HUDTRANS|V_SLIDEIN|splitflags, fontv[TALLNUM_FONT].font[rn[0]], ringmap);
// V_DrawMappedPatch(LAPS_X+29, fy, V_HUDTRANS|V_SLIDEIN|splitflags, fontv[TALLNUM_FONT].font[rn[1]], ringmap);
}
// SPB ring lock
@ -4401,6 +4422,9 @@ static void K_drawKartMinimap(void)
skin = ((skin_t*)g->mo->skin)-skins;
else
skin = 0;
workingPic = R_CanShowSkinInDemo(skin) ? faceprefix[skin][FACE_MINIMAP] : kp_unknownminimap;
if (g->mo->color)
{
if (g->mo->colorized)
@ -4414,7 +4438,7 @@ static void K_drawKartMinimap(void)
interpx = R_InterpolateFixed(g->mo->old_x, g->mo->x);
interpy = R_InterpolateFixed(g->mo->old_y, g->mo->y);
K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, faceprefix[skin][FACE_MINIMAP], colormap);
K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, workingPic, colormap);
g = g->next;
}
}
@ -4470,7 +4494,7 @@ static void K_drawKartMinimap(void)
{
skin = ((skin_t*)mobj->skin)-skins;
workingPic = faceprefix[skin][FACE_MINIMAP];
workingPic = R_CanShowSkinInDemo(skin) ? faceprefix[skin][FACE_MINIMAP] : kp_unknownminimap;
if (mobj->color)
{
@ -4666,7 +4690,7 @@ static void K_drawKartMinimap(void)
{
skin = ((skin_t*)mobj->skin)-skins;
workingPic = faceprefix[skin][FACE_MINIMAP];
workingPic = R_CanShowSkinInDemo(skin) ? faceprefix[skin][FACE_MINIMAP] : kp_unknownminimap;
if (mobj->color)
{

View file

@ -4819,6 +4819,12 @@ void K_DebtStingPlayer(player_t *player, mobj_t *source)
player->spinouttimer = length;
player->wipeoutslow = min(length-1, wipeoutslowtime+1);
player->ringvisualwarning = TICRATE*2;
player->stingfx = true;
if (P_IsDisplayPlayer(player))
S_StartSoundAtVolume(NULL, sfx_sting0, 200);
P_SetPlayerMobjState(player->mo, S_KART_SPINOUT);
}
@ -8095,7 +8101,7 @@ void K_KartPlayerHUDUpdate(player_t *player)
else
player->karthud[khud_finish] = 0;
if (demo.playback == false && P_IsLocalPlayer(player) == true)
if (demo.playback == false && P_IsMachineLocalPlayer(player) == true)
{
if (player->tumbleBounces != 0 && gamedata->totaltumbletime != UINT32_MAX)
{
@ -8423,20 +8429,38 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
// Battle: spawn zero-bumpers indicator
if ((gametyperules & GTR_SPHERES) ? player->mo->health <= 1 : player->rings <= 0)
{
mobj_t *debtflag = P_SpawnMobj(player->mo->x + player->mo->momx, player->mo->y + player->mo->momy,
player->mo->z + P_GetMobjZMovement(player->mo) + player->mo->height + (24*player->mo->scale), MT_THOK);
UINT8 doubler;
P_SetMobjState(debtflag, S_RINGDEBT);
P_SetScale(debtflag, (debtflag->destscale = player->mo->scale));
// GROSS. In order to have a transparent version of this for a splitscreen local player, we actually need to spawn two!
for (doubler = 0; doubler < 2; doubler++)
{
mobj_t *debtflag = P_SpawnMobj(player->mo->x + player->mo->momx, player->mo->y + player->mo->momy,
player->mo->z + P_GetMobjZMovement(player->mo) + player->mo->height + (24*player->mo->scale), MT_THOK);
K_MatchGenericExtraFlags(debtflag, player->mo);
debtflag->frame += (leveltime % 4);
P_SetMobjState(debtflag, S_RINGDEBT);
P_SetScale(debtflag, (debtflag->destscale = player->mo->scale));
if ((leveltime/12) & 1)
debtflag->frame += 4;
K_MatchGenericExtraFlags(debtflag, player->mo);
debtflag->frame += (leveltime % 4);
debtflag->color = player->skincolor;
debtflag->fuse = 2;
if ((leveltime/12) & 1)
debtflag->frame += 4;
debtflag->color = player->skincolor;
debtflag->fuse = 2;
if (doubler == 0) // Real copy. Draw for everyone but us.
{
debtflag->renderflags |= K_GetPlayerDontDrawFlag(player);
}
else if (doubler == 1) // Fake copy. Draw for only us, and go transparent after a bit.
{
debtflag->renderflags |= (RF_DONTDRAW & ~K_GetPlayerDontDrawFlag(player));
if (player->ringvisualwarning <= 1 || gametyperules & GTR_SPHERES)
debtflag->renderflags |= RF_TRANS50;
}
}
}
if (player->springstars && (leveltime & 1))
@ -8960,6 +8984,12 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
player->dotrickfx = false;
}
if (player->stingfx && !player->mo->hitlag)
{
S_StartSound(player->mo, sfx_s226l);
player->stingfx = false;
}
// Don't screw up chain ring pickup/usage with instawhip charge.
// If the button stays held, delay charge a bit.
if (player->instaWhipChargeLockout)
@ -9024,6 +9054,21 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
player->incontrol++;
}
if (player->rings <= 0)
{
if (player->ringvisualwarning > 1)
player->ringvisualwarning--;
}
else
{
player->ringvisualwarning = 0;
}
if (player->ringvisualwarning == 0 && player->rings <= 0)
{
player->ringvisualwarning = 6*TICRATE/2;
}
player->incontrol = min(player->incontrol, 5*TICRATE);
player->incontrol = max(player->incontrol, -5*TICRATE);

View file

@ -295,10 +295,26 @@ extern menu_t PLAY_MP_OptSelectDef;
typedef enum
{
mp_host = 0,
mp_browse,
mp_directjoin,
mp_back,
} mp_e;
typedef enum
{
mhost_gametype = 0,
mhost_gameplay_options,
mhost_server_options,
mhost_boxend,
mhost_mapselect = mhost_boxend,
mhost_back,
// TODO, remove these (old code)
mhost_sname = 0,
mhost_public,
mhost_maxp,
mhost_gametype,
//mhost_gametype,
mhost_go,
} mhost_e;
@ -686,9 +702,10 @@ void M_PlayMenuJam(void);
boolean M_ConsiderSealedSwapAlert(void);
void M_OpenVirtualKeyboard(boolean gamepad, size_t cachelen, vkb_query_fn_t queryfn, menu_t *dummymenu);
void M_OpenVirtualKeyboard(size_t cachelen, vkb_query_fn_t queryfn, menu_t *dummymenu);
void M_AbortVirtualKeyboard(void);
void M_MenuTypingInput(INT32 key);
void M_SwitchVirtualKeyboard(boolean gamepad);
void M_QuitResponse(INT32 ch);
void M_QuitSRB2(INT32 choice);
@ -1047,6 +1064,7 @@ extern consvar_t cv_dummyprofilekickstart;
extern consvar_t cv_dummyprofileautoroulette;
extern consvar_t cv_dummyprofilelitesteer;
extern consvar_t cv_dummyprofilerumble;
extern consvar_t cv_dummyprofilefov;
void M_ResetOptions(void);
void M_InitOptions(INT32 choice); // necessary for multiplayer since there's some options we won't want to access
@ -1057,6 +1075,8 @@ void M_OptionsChangeBGColour(INT16 newcolour); // changes the background colour
void M_VideoOptions(INT32 choice);
void M_SoundOptions(INT32 choice);
void M_GameplayOptions(INT32 choice);
void M_ServerOptions(INT32 choice);
void M_HandleItemToggles(INT32 choice); // For item toggling
void M_EraseData(INT32 choice); // For data erasing
@ -1090,6 +1110,9 @@ void M_HandleVideoModes(INT32 ch);
// data stuff
void M_HandleProfileErase(INT32 choice);
// Draws "List via" at the bottom of the screen.
void M_DrawMasterServerReminder(void);
// Draws the EGGA CHANNEL background.
void M_DrawEggaChannel(void);

View file

@ -345,7 +345,7 @@ UINT16 M_GetCvPlayerColor(UINT8 pnum)
if (color != SKINCOLOR_NONE)
return color;
INT32 skin = R_SkinAvailable(cv_skin[pnum].string);
INT32 skin = R_SkinAvailableEx(cv_skin[pnum].string, false);
if (skin == -1)
return SKINCOLOR_NONE;
@ -377,7 +377,7 @@ static void M_DrawMenuParty(void)
// Despite the work put into it, can't use M_GetCvPlayerColor directly - we need to reference skin always.
#define grab_skin_and_colormap(pnum) \
{ \
skin = R_SkinAvailable(cv_skin[pnum].string); \
skin = R_SkinAvailableEx(cv_skin[pnum].string, false); \
color = cv_playercolor[pnum].value; \
if (skin == -1) \
skin = 0; \
@ -999,12 +999,12 @@ void M_Drawer(void)
F_VersionDrawer();
}
// Draw message overlay when needed
M_DrawMenuMessage();
// Draw typing overlay when needed, above all other menu elements.
if (menutyping.active)
M_DrawMenuTyping();
// Draw message overlay when needed
M_DrawMenuMessage();
}
if (menuwipe)
@ -1222,6 +1222,38 @@ void M_DrawGenericMenu(void)
static tic_t gm_flipStart;
static INT32 M_DrawRejoinIP(INT32 x, INT32 y, INT32 tx)
{
extern consvar_t cv_dummyipselect;
char (*ip)[MAX_LOGIP] = joinedIPlist[cv_dummyipselect.value];
if (!*ip[0])
return 0;
INT16 shift = 20;
x -= shift;
INT16 j = 0;
for (j=0; j <= (GM_YOFFSET + 10) / 2; j++)
{
// Draw rectangles that look like the current selected item starting from the top of the actual selection graphic and going up to where it's supposed to go.
// With colour 169 (that's the index of the shade of black the plague colourization gives us. ...No I don't like using a magic number either.
V_DrawFill((x-1) + j, y + (2*j), 226, 2, 169);
}
x += GM_XOFFSET + 14;
y += GM_YOFFSET;
const char *text = ip[0];
INT32 w = V_ThinStringWidth(text, 0);
INT32 f = highlightflags;
V_DrawMenuString(x - 10 - (skullAnimCounter/5), y, f, "\x1C"); // left arrow
V_DrawMenuString(x + w + 2+ (skullAnimCounter/5), y, f, "\x1D"); // right arrow
V_DrawThinString(x, y, f, text);
V_DrawRightAlignedThinString(BASEVIDWIDTH + 4 + tx, y, V_ORANGEMAP, "\xAC Rejoin");
return shift;
}
//
// M_DrawKartGamemodeMenu
//
@ -1266,10 +1298,19 @@ void M_DrawKartGamemodeMenu(void)
}
INT32 cx = x;
boolean selected = (i == itemOn && menutransition.tics == menutransition.dest);
if (i == itemOn && menutransition.tics == menutransition.dest)
if (selected)
{
cx -= Easing_OutSine(M_DueFrac(gm_flipStart, GM_FLIPTIME), 0, GM_XOFFSET / 2);
fixed_t f = M_DueFrac(gm_flipStart, GM_FLIPTIME);
cx -= Easing_OutSine(f, 0, (GM_XOFFSET / 2));
// Direct Join
if (currentMenu == &PLAY_MP_OptSelectDef && i == mp_directjoin)
{
INT32 shift = M_DrawRejoinIP(cx, y, cx - x);
cx -= Easing_OutSine(f, 0, shift);
}
}
type = (currentMenu->menuitems[i].status & IT_DISPLAY);
@ -1281,7 +1322,7 @@ void M_DrawKartGamemodeMenu(void)
{
UINT8 *colormap = NULL;
if (i == itemOn && menutransition.tics == menutransition.dest)
if (selected)
{
colormap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_PLAGUE, GTC_CACHE);
}
@ -2277,7 +2318,7 @@ void M_DrawProfileCard(INT32 x, INT32 y, boolean greyedout, profile_t *p)
if (p != NULL && p->version)
{
truecol = p->color;
skinnum = R_SkinAvailable(p->skinname);
skinnum = R_SkinAvailableEx(p->skinname, false);
strcpy(pname, p->profilename);
}
@ -2550,7 +2591,7 @@ void M_DrawRaceDifficulty(void)
for (i = 0; i < currentMenu->numitems; i++)
{
if (i >= drace_boxend)
if (i >= currentMenu->extra1)
{
x = GM_STARTX + (GM_XOFFSET * 5 / 2);
y = GM_STARTY + (GM_YOFFSET * 5 / 2);
@ -2615,7 +2656,7 @@ void M_DrawRaceDifficulty(void)
{
colormap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_PLAGUE, GTC_CACHE);
if (i >= drace_boxend)
if (i >= currentMenu->extra1)
{
cx -= Easing_OutSine(M_DueFrac(gm_flipStart, GM_FLIPTIME), 0, GM_XOFFSET / 2);
}
@ -2626,17 +2667,21 @@ void M_DrawRaceDifficulty(void)
}
if (currentMenu->menuitems[i].status & IT_CVAR)
if (currentMenu->menuitems[i].status & (IT_CVAR | IT_ARROWS))
{
INT32 fx = (cx - tx);
INT32 centx = fx + (320-fx)/2 + (tx); // undo the menutransition movement to redo it here otherwise the text won't move at the same speed lole.
// implicitely we'll only take care of normal consvars
consvar_t *cv = currentMenu->menuitems[i].itemaction.cvar;
const char *val = currentMenu->menuitems[i].text;
if (currentMenu->menuitems[i].status & IT_CVAR)
{
consvar_t *cv = currentMenu->menuitems[i].itemaction.cvar;
val = cv->string;
}
V_DrawFixedPatch(cx*FRACUNIT, y*FRACUNIT, FRACUNIT, 0, W_CachePatchName("MENUSHRT", PU_CACHE), colormap);
V_DrawCenteredGamemodeString(centx, y - 3, 0, colormap, cv->string);
V_DrawCenteredGamemodeString(centx, y - 3, 0, colormap, val);
if (i == itemOn)
{
@ -2656,7 +2701,7 @@ void M_DrawRaceDifficulty(void)
x += GM_XOFFSET;
y += GM_YOFFSET;
if (i < drace_boxend)
if (i < currentMenu->extra1)
{
y += 2; // extra spacing for Match Race options
}
@ -3715,7 +3760,7 @@ void M_DrawTimeAttack(void)
// NOTE: This is pretty rigid and only intended for use with the multiplayer options menu which has *3* choices.
static void M_DrawMasterServerReminder(void)
void M_DrawMasterServerReminder(void)
{
// Did you change the Server Browser address? Have a little reminder.
@ -3725,7 +3770,7 @@ static void M_DrawMasterServerReminder(void)
else
mservflags = warningflags;
INT32 y = BASEVIDHEIGHT - 24;
INT32 y = BASEVIDHEIGHT - 10;
V_DrawFadeFill(0, y-1, BASEVIDWIDTH, 10+1, 0, 31, 5);
V_DrawCenteredThinString(BASEVIDWIDTH/2, y,
@ -3785,7 +3830,7 @@ void M_DrawEggaChannel(void)
patch_t *background = W_CachePatchName("M_EGGACH", PU_CACHE);
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 25);
V_DrawFixedPatch(160<<FRACBITS, 104<<FRACBITS, FRACUNIT, 0, background, NULL);
V_DrawFixedPatch((menuactive ? 75 : 160)<<FRACBITS, 104<<FRACBITS, FRACUNIT, 0, background, NULL);
V_DrawVhsEffect(false); // VHS the background! (...sorry OGL my love)
}
@ -4119,6 +4164,13 @@ static void M_DrawServerCountAndHorizontalBar(void)
void M_DrawMPServerBrowser(void)
{
const char *header[3][2] = {
{"Server Browser", "BG_MPS1"},
{"Core Servers", "BG_MPS1"},
{"Modded Servers", "BG_MPS2"},
};
int mode = M_SecretUnlocked(SECRET_ADDONS, true) ? (mpmenu.room ? 2 : 1) : 0;
patch_t *text1 = W_CachePatchName("MENUBGT1", PU_CACHE);
patch_t *text2 = W_CachePatchName("MENUBGT2", PU_CACHE);
@ -4138,7 +4190,7 @@ void M_DrawMPServerBrowser(void)
UINT8 i;
// background stuff
V_DrawFixedPatch(0, 0, FRACUNIT, 0, W_CachePatchName("BG_MPS3", PU_CACHE), NULL);
V_DrawFixedPatch(0, 0, FRACUNIT, 0, W_CachePatchName(header[mode][1], PU_CACHE), NULL);
V_DrawFixedPatch(0, (BASEVIDHEIGHT + 16) * FRACUNIT, FRACUNIT, V_TRANSLUCENT, W_CachePatchName("MENUBG2", PU_CACHE), NULL);
@ -4212,12 +4264,7 @@ void M_DrawMPServerBrowser(void)
V_DrawFill(0, 53, 320, 1, 31);
V_DrawFill(0, 55, 320, 1, 31);
const char *headertext;
if (M_SecretUnlocked(SECRET_ADDONS, true))
headertext = va("%s Servers", mpmenu.room ? "Modded" : "Core");
else
headertext = "Server Browser";
V_DrawCenteredGamemodeString(160, 2, 0, 0, headertext);
V_DrawCenteredGamemodeString(160, 2, 0, 0, header[mode][0]);
// normal menu options
M_DrawGenericMenu();
@ -6516,7 +6563,7 @@ static void M_DrawChallengeTile(INT16 i, INT16 j, INT32 x, INT32 y, boolean hili
INT32 skin = M_UnlockableFollowerNum(ref);
if (skin != -1)
{
INT32 psk = R_SkinAvailable(cv_skin[0].string);
INT32 psk = R_SkinAvailableEx(cv_skin[0].string, false);
UINT16 col = K_GetEffectiveFollowerColor(followers[skin].defaultcolor, &followers[skin], cv_playercolor[0].value, (psk != -1) ? &skins[psk] : &skins[0]);
colormap = R_GetTranslationColormap(TC_DEFAULT, col, GTC_MENUCACHE);
pat = W_CachePatchName(followers[skin].icon, PU_CACHE);
@ -6775,7 +6822,7 @@ static void M_DrawChallengePreview(INT32 x, INT32 y)
}
case SECRET_FOLLOWER:
{
INT32 skin = R_SkinAvailable(cv_skin[0].string);
INT32 skin = R_SkinAvailableEx(cv_skin[0].string, false);
INT32 fskin = M_UnlockableFollowerNum(ref);
// Draw proximity reference for character
@ -6806,7 +6853,7 @@ static void M_DrawChallengePreview(INT32 x, INT32 y)
INT32 colorid = M_UnlockableColorNum(ref);
if (colorid == SKINCOLOR_NONE)
break;
INT32 skin = R_SkinAvailable(cv_skin[0].string);
INT32 skin = R_SkinAvailableEx(cv_skin[0].string, false);
if (skin == -1)
skin = 0;
colormap = R_GetTranslationColormap(skin, colorid, GTC_MENUCACHE);

View file

@ -275,8 +275,6 @@ static boolean M_GamestateCanOpenMenu(void)
//
boolean M_Responder(event_t *ev)
{
boolean menuKeyJustChanged = false;
if (dedicated
|| (demo.playback && demo.attract)
|| M_GamestateCanOpenMenu() == false)
@ -311,7 +309,6 @@ boolean M_Responder(event_t *ev)
{
// Record keyboard presses
menuKey = ev->data1;
menuKeyJustChanged = true;
}
// Profiles: Control mapping.
@ -457,12 +454,6 @@ boolean M_Responder(event_t *ev)
return false;
}
// Typing for CV_IT_STRING
if (menuKeyJustChanged && menutyping.active && !menutyping.menutypingclose && menutyping.keyboardtyping)
{
M_ChangeStringCvar(menuKey);
}
// We're in the menu itself now.
// M_Ticker will take care of the rest.
return true;
@ -1097,7 +1088,7 @@ static void M_HandleMenuInput(void)
// Typing for CV_IT_STRING
if (menutyping.active)
{
M_MenuTypingInput(thisMenuKey);
M_MenuTypingInput(-1);
return;
}
@ -1136,7 +1127,7 @@ static void M_HandleMenuInput(void)
if (M_MenuConfirmPressed(pid))
{
// If we entered this menu by pressing a menu Key, default to keyboard typing, otherwise use controller.
M_OpenVirtualKeyboard(thisMenuKey == -1, MAXSTRINGLENGTH, M_QueryCvarAction, NULL);
M_OpenVirtualKeyboard(MAXSTRINGLENGTH, M_QueryCvarAction, NULL);
return;
}
else if (M_MenuExtraPressed(pid))

View file

@ -28,6 +28,8 @@
#include "k_color.h"
#include "command.h"
extern "C" consvar_t cv_dummyprofilefov, cv_fov[MAXSPLITSCREENPLAYERS];
CV_PossibleValue_t lastprofile_cons_t[] = {{-1, "MIN"}, {MAXPROFILES, "MAX"}, {0, NULL}};
// List of all the profiles.
@ -79,6 +81,7 @@ profile_t* PR_MakeProfile(
newprofile->autoroulette = false;
newprofile->litesteer = true;
newprofile->rumble = true;
newprofile->fov = atoi(cv_dummyprofilefov.defaultvalue);
// Copy from gamecontrol directly as we'll be setting controls up directly in the profile.
memcpy(newprofile->controls, controlarray, sizeof(newprofile->controls));
@ -98,6 +101,7 @@ profile_t* PR_MakeProfileFromPlayer(const char *prname, const char *pname, const
newprofile->autoroulette = cv_autoroulette[pnum].value;
newprofile->litesteer = cv_litesteer[pnum].value;
newprofile->rumble = cv_rumble[pnum].value;
newprofile->fov = cv_fov[pnum].value / FRACUNIT;
return newprofile;
}
@ -292,6 +296,7 @@ void PR_SaveProfiles(void)
jsonprof.preferences.autoroulette = cprof->autoroulette;
jsonprof.preferences.litesteer = cprof->litesteer;
jsonprof.preferences.rumble = cprof->rumble;
jsonprof.preferences.fov = cprof->fov;
for (size_t j = 0; j < num_gamecontrols; j++)
{
@ -456,6 +461,7 @@ void PR_LoadProfiles(void)
newprof->autoroulette = jsprof.preferences.autoroulette;
newprof->litesteer = jsprof.preferences.litesteer;
newprof->rumble = jsprof.preferences.rumble;
newprof->fov = jsprof.preferences.fov;
try
{
@ -495,6 +501,7 @@ static void PR_ApplyProfile_Settings(profile_t *p, UINT8 playernum)
CV_StealthSetValue(&cv_autoroulette[playernum], p->autoroulette);
CV_StealthSetValue(&cv_litesteer[playernum], p->litesteer);
CV_StealthSetValue(&cv_rumble[playernum], p->rumble);
CV_StealthSetValue(&cv_fov[playernum], p->fov);
// set controls...
G_ApplyControlScheme(playernum, p->controls);

View file

@ -47,6 +47,7 @@ struct ProfilePreferencesJson
bool autoroulette;
bool litesteer;
bool rumble;
uint8_t fov;
tm test;
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(
@ -54,7 +55,8 @@ struct ProfilePreferencesJson
kickstartaccel,
autoroulette,
litesteer,
rumble
rumble,
fov
)
};
@ -153,6 +155,7 @@ struct profile_t
boolean autoroulette; // cv_autoroulette
boolean litesteer; // cv_litesteer
boolean rumble; // cv_rumble
UINT8 fov; // cv_fov
// Finally, control data itself
INT32 controls[num_gamecontrols][MAXINPUTMAPPING]; // Lists of all the controls, defined the same way as default inputs in g_input.c

View file

@ -2266,9 +2266,10 @@ static int lib_rSetPlayerSkin(lua_State *L)
return luaL_error(L, "argument #2 not given (expected number or string)");
else if (lua_type(L, 2) == LUA_TNUMBER) // skin number
{
INT32 skincount = (demo.playback ? demo.numskins : numskins);
i = luaL_checkinteger(L, 2);
if (i < 0 || i >= numskins)
return luaL_error(L, "skin %d (argument #2) out of range (0 - %d)", i, numskins-1);
if (i < 0 || i >= skincount)
return luaL_error(L, "skin %d (argument #2) out of range (0 - %d)", i, skincount-1);
}
else // skin name
{

View file

@ -378,7 +378,7 @@ static int libd_getSprite2Patch(lua_State *L)
i = lua_tonumber(L, 1);
if (i < 0 || i >= MAXSKINS)
return luaL_error(L, "skin number %d out of range (0 - %d)", i, MAXSKINS-1);
if (i >= numskins)
if (i >= (demo.playback ? demo.numskins : numskins))
return 0;
}
else // find skin by name
@ -389,6 +389,9 @@ static int libd_getSprite2Patch(lua_State *L)
return 0;
}
if (demo.playback)
i = demo.skinlist[i].mapping;
lua_remove(L, 1); // remove skin now
if (lua_isnumber(L, 1)) // sprite number given, e.g. SPR2_STIL
@ -1041,6 +1044,9 @@ static int libd_getColormap(lua_State *L)
skinnum = i;
}
if (demo.playback)
skinnum = demo.skinlist[skinnum].mapping;
// all was successful above, now we generate the colormap at last!
colormap = R_GetTranslationColormap(skinnum, color, GTC_CACHE);

View file

@ -721,7 +721,11 @@ static int mobj_set(lua_State *L)
if (skin != -1)
{
if (!mo->player || R_SkinUsable(mo->player-players, skin, false))
{
if (demo.playback)
skin = demo.skinlist[skin].mapping;
mo->skin = &skins[skin];
}
return 0;
}

View file

@ -263,8 +263,12 @@ static int player_get(lua_State *L)
lua_pushboolean(L, plr->incontrol);
else if (fastcmp(field,"progressivethrust"))
lua_pushboolean(L, plr->progressivethrust);
else if (fastcmp(field,"ringvisualwarning"))
lua_pushboolean(L, plr->ringvisualwarning);
else if (fastcmp(field,"dotrickfx"))
lua_pushboolean(L, plr->dotrickfx);
else if (fastcmp(field,"stingfx"))
lua_pushboolean(L, plr->stingfx);
else if (fastcmp(field,"bumperinflate"))
lua_pushboolean(L, plr->bumperinflate);
else if (fastcmp(field,"ringboxdelay"))
@ -801,12 +805,16 @@ static int player_set(lua_State *L)
plr->incontrol = luaL_checkinteger(L, 3);
else if (fastcmp(field,"progressivethrust"))
plr->progressivethrust = luaL_checkboolean(L, 3);
else if (fastcmp(field,"ringvisualwarning"))
plr->ringvisualwarning = luaL_checkboolean(L, 3);
else if (fastcmp(field,"analoginput"))
plr->markedfordeath = luaL_checkboolean(L, 3);
else if (fastcmp(field,"markedfordeath"))
plr->markedfordeath = luaL_checkboolean(L, 3);
else if (fastcmp(field,"dotrickfx"))
plr->dotrickfx = luaL_checkboolean(L, 3);
else if (fastcmp(field,"stingfx"))
plr->stingfx = luaL_checkboolean(L, 3);
else if (fastcmp(field,"bumperinflate"))
plr->bumperinflate = luaL_checkboolean(L, 3);
else if (fastcmp(field,"ringboxdelay"))

View file

@ -16,6 +16,7 @@
#include "deh_lua.h"
#include "z_zone.h"
#include "w_wad.h"
#include "r_things.h" // numskins
#include "p_setup.h"
#include "r_state.h"
#include "r_sky.h"
@ -371,6 +372,9 @@ int LUA_PushGlobals(lua_State *L, const char *word)
} else if (fastcmp(word,"replayplayback")) {
lua_pushboolean(L, demo.playback);
return 1;
} else if (fastcmp(word,"replaynumskins")) {
lua_pushinteger(L, (demo.playback ? demo.numskins : numskins));
return 1;
} else if (fastcmp(word, "gamestate")) {
lua_pushinteger(L, gamestate);
return 1;

View file

@ -196,7 +196,7 @@ static int lib_getSkin(lua_State *L)
}
// find skin by name
i = R_SkinAvailable(field);
i = R_SkinAvailableEx(field, false);
if (i != -1)
{
LUA_PushUserdata(L, &skins[i], META_SKIN);

View file

@ -1019,6 +1019,32 @@ cacheprisoneggpickup:
}
//CONS_Printf("thisprisoneggpickup = %u (MAXCONDITIONSETS is %u)\n", gamedata->thisprisoneggpickup, MAXCONDITIONSETS);
#ifdef DEVELOP
extern consvar_t cv_debugprisoncd;
// If all drops are collected, just force the first valid one.
if (cv_debugprisoncd.value && gamedata->thisprisoneggpickup_cached == NULL)
{
for (i = 0; gamedata->thisprisoneggpickup_cached == NULL &&
i < gamedata->numprisoneggpickups; i++)
{
c = &conditionSets[gamedata->prisoneggpickups[i]];
if (c->numconditions)
{
for (j = 0; j < c->numconditions; ++j)
{
cn = &c->condition[j];
if (cn->type != UC_PRISONEGGCD)
continue;
gamedata->thisprisoneggpickup = gamedata->prisoneggpickups[i];
gamedata->thisprisoneggpickup_cached = cn;
break;
}
}
}
}
#endif
}
static void M_PrecacheLevelLocks(void)
@ -1206,7 +1232,7 @@ void M_UpdateConditionSetsPending(void)
case UCRP_ISCHARACTER:
case UCRP_MAKERETIRE:
{
cn->requirement = R_SkinAvailable(cn->stringvar);
cn->requirement = R_SkinAvailableEx(cn->stringvar, false);
if (cn->requirement < 0)
{
@ -2021,7 +2047,7 @@ static const char *M_GetConditionCharacter(INT32 skin, boolean directlyrequires)
for (j = 0; j < SKINRIVALS; j++)
{
const char *rivalname = skins[i].rivals[j];
INT32 rivalnum = R_SkinAvailable(rivalname);
INT32 rivalnum = R_SkinAvailableEx(rivalname, false);
if (rivalnum != skin)
continue;
@ -3504,7 +3530,7 @@ INT32 M_UnlockableSkinNum(unlockable_t *unlock)
}
// Get the skin from the string.
skinnum = R_SkinAvailable(unlock->stringVar);
skinnum = R_SkinAvailableEx(unlock->stringVar, false);
if (skinnum != -1)
{
unlock->stringVarCache = skinnum;

View file

@ -714,7 +714,7 @@ void M_ChallengesTick(void)
INT32 fskin = M_UnlockableFollowerNum(ref);
if (fskin != -1)
{
INT32 psk = R_SkinAvailable(cv_skin[0].string);
INT32 psk = R_SkinAvailableEx(cv_skin[0].string, false);
if (psk == -1)
psk = 0;
bombcolor = K_GetEffectiveFollowerColor(followers[fskin].defaultcolor, &followers[fskin], cv_playercolor[0].value, &skins[psk]);

View file

@ -84,7 +84,7 @@ public:
{
if (!skinName.empty())
{
this->skinID = R_SkinAvailable(skinName.c_str());
this->skinID = R_SkinAvailableEx(skinName.c_str(), false);
}
this->offset = offset;

View file

@ -23,11 +23,11 @@ menuitem_t OPTIONS_Main[] =
{IT_STRING | IT_SUBMENU, "HUD Options", "Options related to the Heads-Up Display.",
NULL, {.submenu = &OPTIONS_HUDDef}, 0, 0},
{IT_STRING | IT_SUBMENU, "Gameplay Options", "Change various game related options",
NULL, {.submenu = &OPTIONS_GameplayDef}, 0, 0},
{IT_STRING | IT_CALL, "Gameplay Options", "Change various game related options",
NULL, {.routine = M_GameplayOptions}, 0, 0},
{IT_STRING | IT_SUBMENU, "Server Options", "Change various specific options for your game server.",
NULL, {.submenu = &OPTIONS_ServerDef}, 0, 0},
{IT_STRING | IT_CALL, "Server Options", "Change various specific options for your game server.",
NULL, {.routine = M_ServerOptions}, 0, 0},
{IT_STRING | IT_SUBMENU, "Data Options", "Miscellaneous data options such as the screenshot format.",
NULL, {.submenu = &OPTIONS_DataDef}, 0, 0},
@ -90,8 +90,8 @@ void M_InitOptions(INT32 choice)
if (gamestate == GS_MENU
|| ((server || IsPlayerAdmin(consoleplayer)) && K_CanChangeRules(false)))
{
OPTIONS_MainDef.menuitems[mopt_gameplay].status = IT_STRING | IT_SUBMENU;
OPTIONS_MainDef.menuitems[mopt_server].status = IT_STRING | IT_SUBMENU;
OPTIONS_MainDef.menuitems[mopt_gameplay].status = IT_STRING | IT_CALL;
OPTIONS_MainDef.menuitems[mopt_server].status = IT_STRING | IT_CALL;
OPTIONS_GameplayDef.menuitems[gopt_encore].status =
(M_SecretUnlocked(SECRET_ENCORE, false) ? (IT_STRING | IT_CVAR) : IT_DISABLED);
}
@ -228,6 +228,18 @@ void M_SoundOptions(INT32 choice)
M_GonerResetLooking(GDGONER_SOUND);
}
void M_GameplayOptions(INT32 choice)
{
(void)choice;
M_OptionsMenuGoto(&OPTIONS_GameplayDef);
}
void M_ServerOptions(INT32 choice)
{
(void)choice;
M_OptionsMenuGoto(&OPTIONS_ServerDef);
}
boolean M_OptionsInputs(INT32 ch)
{

View file

@ -93,6 +93,7 @@ void M_StartEditProfile(INT32 c)
CV_StealthSetValue(&cv_dummyprofileautoroulette, optionsmenu.profile->autoroulette);
CV_StealthSetValue(&cv_dummyprofilelitesteer, optionsmenu.profile->litesteer);
CV_StealthSetValue(&cv_dummyprofilerumble, optionsmenu.profile->rumble);
CV_StealthSetValue(&cv_dummyprofilefov, optionsmenu.profile->fov);
}
else
{
@ -102,6 +103,7 @@ void M_StartEditProfile(INT32 c)
CV_StealthSetValue(&cv_dummyprofileautoroulette, 0); // off
CV_StealthSetValue(&cv_dummyprofilelitesteer, 1); // on
CV_StealthSetValue(&cv_dummyprofilerumble, 1); // on
CV_StealthSetValue(&cv_dummyprofilefov, 90);
}
// Setup greyout and stuff.

View file

@ -90,15 +90,18 @@ static void M_ProfileEditApply(void)
optionsmenu.profile->autoroulette = cv_dummyprofileautoroulette.value;
optionsmenu.profile->litesteer = cv_dummyprofilelitesteer.value;
optionsmenu.profile->rumble = cv_dummyprofilerumble.value;
optionsmenu.profile->fov = cv_dummyprofilefov.value;
// If this profile is in-use by anyone, apply the changes immediately upon exiting.
// Don't apply the profile itself as that would lead to issues mid-game.
if (belongsto > -1 && belongsto < MAXSPLITSCREENPLAYERS)
{
extern consvar_t cv_fov[MAXSPLITSCREENPLAYERS];
CV_SetValue(&cv_kickstartaccel[belongsto], cv_dummyprofilekickstart.value);
CV_SetValue(&cv_autoroulette[belongsto], cv_dummyprofileautoroulette.value);
CV_SetValue(&cv_litesteer[belongsto], cv_dummyprofilelitesteer.value);
CV_SetValue(&cv_rumble[belongsto], cv_dummyprofilerumble.value);
CV_SetValue(&cv_fov[belongsto], cv_dummyprofilefov.value);
}
// Reapply player 1's real profile.

View file

@ -102,6 +102,9 @@ menuitem_t OPTIONS_ProfileAccessibility[] = {
{IT_STRING | IT_CVAR, "Lite Steer", "Hold DOWN on d-pad/keyboard for shallow turns.",
NULL, {.cvar = &cv_dummyprofilelitesteer}, 0, 0},
{IT_STRING | IT_CVAR, "Field of View", "Higher FOV lets you see more.",
NULL, {.cvar = &cv_dummyprofilefov}, 0, 0},
{IT_SPACE | IT_NOTHING, NULL, NULL,
NULL, {NULL}, 0, 0},
@ -129,7 +132,7 @@ menu_t OPTIONS_ProfileAccessibilityDef = {
&OPTIONS_EditProfileDef,
0,
OPTIONS_ProfileAccessibility,
145, 52,
145, 41,
SKINCOLOR_ULTRAMARINE, 0,
MBF_DRAWBGWHILEPLAYING,
"FILE",

View file

@ -203,7 +203,7 @@ static INT16 M_GetMenuCategoryFromFollower(setup_player_t *p)
static void M_SetupProfileGridPos(setup_player_t *p)
{
profile_t *pr = PR_GetProfile(p->profilen);
INT32 i = R_SkinAvailable(pr->skinname);
INT32 i = R_SkinAvailableEx(pr->skinname, false);
INT32 alt = 0; // Hey it's my character's name!
if (i == -1)
@ -247,7 +247,7 @@ static void M_SetupProfileGridPos(setup_player_t *p)
static void M_SetupMidGameGridPos(setup_player_t *p, UINT8 num)
{
INT32 i = R_SkinAvailable(cv_skin[num].zstring);
INT32 i = R_SkinAvailableEx(cv_skin[num].zstring, false);
INT32 alt = 0; // Hey it's my character's name!
if (i == -1)

View file

@ -94,7 +94,7 @@ menu_t PLAY_RaceDifficultyDef = {
0,
PLAY_RaceDifficulty,
0, 0,
0, 0,
drace_boxend, 0,
0,
NULL,
1, 5,

View file

@ -5,6 +5,7 @@
#include "../m_cond.h"
#include "../s_sound.h"
#include "../mserv.h" // cv_masterserver
#include "../m_misc.h"
#if defined (TESTERS)
#define IT_STRING_CALL_NOTESTERS IT_DISABLED
@ -73,20 +74,117 @@ static void M_PreMPRoomSelectInit(INT32 choice)
M_MPRoomSelectInit(0);
}
static const char *query_ip(const char *replace)
{
if (replace)
M_JoinIP(replace);
return "";
}
static boolean uses_gamepad;
static void ip_entry(void)
{
M_OpenVirtualKeyboard(MAXSTRINGLENGTH, query_ip, NULL);
}
static consvar_t *ip_cvar(void)
{
extern consvar_t cv_dummyipselect;
return &cv_dummyipselect;
}
static void confirm_ip_select(INT32 choice)
{
if (choice == MA_YES)
{
consvar_t *cv = ip_cvar();
M_JoinIP(joinedIPlist[cv->value][0]);
}
}
static void find_ip(INT32 add)
{
consvar_t *cv = ip_cvar();
for (int i = 0; i < NUMLOGIP; ++i)
{
CV_AddValue(cv, add);
if (*joinedIPlist[cv->value][0])
break;
}
}
static void direct_join_routine(INT32 choice)
{
consvar_t *cv = ip_cvar();
INT32 index = cv->value;
if (choice == 2)
ip_entry();
else if (choice == -1)
{
const char *ip = joinedIPlist[index][0];
if (*ip)
{
M_StartMessage("Direct Join", va("Connect to %s?", joinedIPlist[index][0]),
&confirm_ip_select, MM_YESNO, "Connect", "Back");
}
}
else
find_ip(choice ? 1 : -1);
}
// mp_e
menuitem_t PLAY_MP_OptSelect[] =
{
{IT_STRING_CALL_NOTESTERS, "Host Game", "Start your own online game!",
NULL, {.routine = M_PreMPHostInit}, 0, 0},
{IT_STRING | IT_CALL, "Server Browser", "Search for game servers to play in.",
{IT_STRING | IT_CALL, "Browse", "Search for game servers to play in.",
NULL, {.routine = M_PreMPRoomSelectInit}, 0, 0},
{IT_STRING | IT_CALL, "Join by IP", "Join an online game by its IP address.",
NULL, {.routine = M_MPJoinIPInit}, 0, 0},
{IT_STRING | IT_ARROWS, "Direct Join", "Join an online game by its IP address.",
NULL, {.routine = direct_join_routine}, 0, 0},
{IT_STRING | IT_CALL, "Back", NULL, NULL, {.routine = M_GoBack}, 0, 0},
};
#undef IT_STRING_CALL_NOTESTERS
static void draw_routine(void)
{
M_DrawKartGamemodeMenu();
M_DrawMasterServerReminder();
}
static boolean any_stored_ips(void)
{
for (int i = 0; i < NUMLOGIP; ++i)
{
if (*joinedIPlist[i][0])
return true;
}
return false;
}
static void init_routine(void)
{
menuitem_t *it = &PLAY_MP_OptSelect[mp_directjoin];
CV_SetValue(ip_cvar(), 0);
if (any_stored_ips())
{
it->status = IT_STRING | IT_ARROWS;
find_ip(1);
}
else
it->status = IT_STRING | IT_CALL;
}
static boolean input_routine(INT32 key)
{
uses_gamepad = (key == -1);
return false;
}
menu_t PLAY_MP_OptSelectDef = {
sizeof (PLAY_MP_OptSelect) / sizeof (menuitem_t),
@ -101,13 +199,13 @@ menu_t PLAY_MP_OptSelectDef = {
0, 0,
0,
"NETMD2",
-1, 1,
M_DrawMPOptSelect,
4, 5,
draw_routine,
M_DrawEggaChannel,
M_MPOptSelectTick,
NULL,
init_routine,
NULL,
NULL
input_routine
};
struct mpmenu_s mpmenu;

View file

@ -6,9 +6,21 @@
#include "../z_zone.h"
#include "../mserv.h"
static void draw_routine(void)
{
M_DrawRaceDifficulty();
M_DrawMasterServerReminder();
}
static void tick_routine(void)
{
PLAY_MP_Host[mhost_gametype].text = gametypes[menugametype]->name;
}
// MULTIPLAYER HOST SCREEN -- see mhost_e
menuitem_t PLAY_MP_Host[] =
{
#if 0
//{IT_NOTHING | IT_KEYHANDLER, NULL, NULL, NULL, M_MPOptSelect, 0, 0},
{IT_STRING | IT_CVAR | IT_CV_STRING, "Server Name", "Display name for your game online. Other players will see this.",
@ -25,7 +37,21 @@ menuitem_t PLAY_MP_Host[] =
{IT_STRING | IT_CALL, "GO", "Select a map with the currently selected gamemode",
NULL, {.routine = M_MPSetupNetgameMapSelect}, 0, 0},
#endif
{IT_STRING | IT_ARROWS, "Gametype", "Choose the type of play on your serer.",
NULL, {.routine = M_HandleHostMenuGametype}, 0, 0},
{IT_STRING2 | IT_CALL, "Gameplay Options...", "Adjust settings pertaining to gameplay.",
NULL, {.routine = M_GameplayOptions}, 0, 0},
{IT_STRING2 | IT_CALL, "Server Options...", "Adjust settings pertaining to online play.",
NULL, {.routine = M_ServerOptions}, 0, 0},
{IT_STRING | IT_CALL, "Map Select", "Go on and select a level!",
NULL, {.routine = M_MPSetupNetgameMapSelect}, 0, 0},
{IT_STRING | IT_CALL, "Back", NULL,
NULL, {.routine = M_GoBack}, 0, 0},
};
menu_t PLAY_MP_HostDef = {
@ -34,13 +60,13 @@ menu_t PLAY_MP_HostDef = {
0,
PLAY_MP_Host,
0, 0,
0, 0,
mhost_boxend, 0,
0,
"NETMD2",
-1, 1, // 1 frame transition.... This is really just because I don't want the black fade when we press esc, hehe
M_DrawMPHost,
4, 5,
draw_routine,
M_DrawEggaChannel,
M_MPOptSelectTick, // This handles the unfolding options
tick_routine,
NULL,
M_MPResetOpts,
NULL
@ -66,8 +92,8 @@ void M_MPHostInit(INT32 choice)
{
(void)choice;
mpmenu.modewinextend[0][0] = 1;
M_SetupNextMenu(&PLAY_MP_HostDef, true);
itemOn = mhost_go;
PLAY_MP_HostDef.lastOn = mhost_mapselect;
M_SetupNextMenu(&PLAY_MP_HostDef, false);
Get_rules();
// There's one downside to doing it this way:

View file

@ -77,7 +77,6 @@ void M_JoinIP(const char *ipa)
{
if (*(ipa) == '\0') // Jack shit
{
M_StartMessage("Online Play", "Please specify an address.\n", NULL, MM_NOTHING, NULL, NULL);
return;
}

View file

@ -54,15 +54,22 @@ menu_t PAUSE_PlaybackMenuDef = {
void M_EndModeAttackRun(void)
{
G_CheckDemoStatus(); // Cancel recording
if (demo.playback)
{
G_CheckDemoStatus(); // Cancel recording
return;
}
Command_ExitGame_f(); // Clear a bunch of state
if (!modeattacking)
return;
modeattacking = ATTACKING_NONE; // Kept until now because of Command_ExitGame_f
if (demo.attract == DEMO_ATTRACT_TITLE)
{
D_StartTitle();
D_SetDeferredStartTitle(true);
}
else if (demo.attract == DEMO_ATTRACT_CREDITS)
{

View file

@ -190,24 +190,29 @@ void M_AbortVirtualKeyboard(void)
return;
menutyping.active = false;
menutyping.menutypingfade = 0;
Z_Free(menutyping.cache);
if (currentMenu == menutyping.dummymenu)
M_GoBack(0);
}
static boolean M_IsTypingKey(INT32 key)
{
return key == KEY_BACKSPACE || key == KEY_ENTER
|| key == KEY_ESCAPE || key == KEY_DEL
|| key == KEY_LCTRL || key == KEY_RCTRL
|| isprint(key);
}
void M_MenuTypingInput(INT32 key)
{
const UINT8 pid = 0;
// Determine when to check for keyboard inputs or controller inputs using menuKey, which is the key passed here as argument.
if (key > 0)
{
boolean gamepad = (key >= NUMKEYS);
M_SwitchVirtualKeyboard(gamepad);
if (gamepad)
return;
}
if (!menutyping.active)
return;
// Fade-in
if (menutyping.menutypingclose)
@ -233,6 +238,25 @@ void M_MenuTypingInput(INT32 key)
menutyping.menutypingfade++;
}
if (menutyping.menutypingfade >= 9) // either is visible
{
if (key == KEY_ENTER || key == KEY_ESCAPE)
{
M_CloseVirtualKeyboard();
M_SetMenuDelay(pid);
S_StartSound(NULL, sfx_s3k5b);
return;
}
if (menutyping.keyboardtyping)
{
M_ChangeStringCvar(key);
return;
}
}
if (menutyping.menutypingfade != destination)
{
// Don't allow typing until it's fully opened.
@ -240,68 +264,6 @@ void M_MenuTypingInput(INT32 key)
}
}
// Determine when to check for keyboard inputs or controller inputs using menuKey, which is the key passed here as argument.
if (!menutyping.keyboardtyping) // controller inputs
{
// we pressed a keyboard input that's not any of our buttons
if (key >= 0 && M_IsTypingKey(key) && menucmd[pid].dpad_lr == 0 && menucmd[pid].dpad_ud == 0
&& !(menucmd[pid].buttons & MBT_A)
&& !(menucmd[pid].buttons & MBT_B)
&& !(menucmd[pid].buttons & MBT_C)
&& !(menucmd[pid].buttons & MBT_X)
&& !(menucmd[pid].buttons & MBT_Y)
&& !(menucmd[pid].buttons & MBT_Z)
&& !(menucmd[pid].buttons & MBT_START))
{
menutyping.keyboardtyping = true;
}
}
else // Keyboard inputs.
{
// On the flipside, if we're pressing any keyboard input, switch to controller inputs.
if (key >= 0 && !M_IsTypingKey(key) && (
M_MenuButtonPressed(pid, MBT_A)
|| M_MenuButtonPressed(pid, MBT_B)
|| M_MenuButtonPressed(pid, MBT_C)
|| M_MenuButtonPressed(pid, MBT_X)
|| M_MenuButtonPressed(pid, MBT_Y)
|| M_MenuButtonPressed(pid, MBT_Z)
|| M_MenuButtonPressed(pid, MBT_START)
|| (menucmd[pid].dpad_lr != 0 && menucmd[pid].prev_dpad_lr == 0)
|| (menucmd[pid].dpad_ud != 0 && menucmd[pid].prev_dpad_ud != 0)
))
{
/*CONS_Printf("key is %d, \
%c%c%c-%c%c%c-%c-%c%c%c%c\n",
key,
M_MenuButtonPressed(pid, MBT_A) ? 'A' : ' ',
M_MenuButtonPressed(pid, MBT_B) ? 'B' : ' ',
M_MenuButtonPressed(pid, MBT_C) ? 'C' : ' ',
M_MenuButtonPressed(pid, MBT_X) ? 'X' : ' ',
M_MenuButtonPressed(pid, MBT_Y) ? 'Y' : ' ',
M_MenuButtonPressed(pid, MBT_Z) ? 'Z' : ' ',
M_MenuButtonPressed(pid, MBT_START) ? '+' : ' ',
menucmd[pid].dpad_lr < 0 ? '<' : ' ',
menucmd[pid].dpad_ud > 0 ? '^' : ' ',
menucmd[pid].dpad_ud < 0 ? 'v' : ' ',
menucmd[pid].dpad_lr > 0 ? '>' : ' '
);*/
menutyping.keyboardtyping = false;
return;
}
// OTHERWISE, process keyboard inputs for typing!
if (key == KEY_ENTER || key == KEY_ESCAPE)
{
M_CloseVirtualKeyboard();
M_SetMenuDelay(pid);
S_StartSound(NULL, sfx_s3k5b);
return;
}
}
if (menucmd[pid].delay == 0 && !menutyping.keyboardtyping) // We must check for this here because we bypass the normal delay check to allow for normal keyboard inputs
{
if (menucmd[pid].dpad_ud > 0) // down
@ -418,9 +380,8 @@ void M_MenuTypingInput(INT32 key)
}
}
void M_OpenVirtualKeyboard(boolean gamepad, size_t cachelen, vkb_query_fn_t queryfn, menu_t *dummymenu)
void M_OpenVirtualKeyboard(size_t cachelen, vkb_query_fn_t queryfn, menu_t *dummymenu)
{
menutyping.keyboardtyping = !gamepad;
menutyping.active = true;
menutyping.menutypingclose = false;
@ -443,3 +404,9 @@ void M_OpenVirtualKeyboard(boolean gamepad, size_t cachelen, vkb_query_fn_t quer
M_SetupNextMenu(dummymenu, true);
}
}
void M_SwitchVirtualKeyboard(boolean gamepad)
{
extern consvar_t cv_debugvirtualkeyboard;
menutyping.keyboardtyping = cv_debugvirtualkeyboard.value ? false : !gamepad;
}

View file

@ -3522,6 +3522,16 @@ void A_AttractChase(mobj_t *actor)
S_ReducedVFXSoundAtVolume(actor->target, sfx_s1b5, actor->target->player->ringvolume, NULL);
if (actor->target->player->rings <= 10 && P_IsDisplayPlayer(actor->target->player))
{
S_ReducedVFXSoundAtVolume(actor->target, sfx_gshab,
210 - 10*actor->target->player->rings
, NULL);
if (actor->target->player->rings == 0)
S_ReducedVFXSoundAtVolume(actor->target, sfx_gshad, 127, NULL);
}
actor->target->player->ringvolume -= RINGVOLUMEUSEPENALTY;
sparkle = P_SpawnMobj(actor->target->x, actor->target->y, actor->target->z, MT_RINGSPARKS);

View file

@ -1198,13 +1198,21 @@ static void P_AddBrokenPrison(mobj_t *target, mobj_t *inflictor, mobj_t *source)
secretextratime = TICRATE/2;
}
if (
#ifdef DEVELOP
extern consvar_t cv_debugprisoncd;
#endif
if ((
grandprixinfo.gp == true // Bonus Round
&& demo.playback == false // Not playback
&& netgame == false // game design + makes it easier to implement
&& gamedata->thisprisoneggpickup_cached != NULL
&& gamedata->prisoneggstothispickup == 0
&& gamedata->thisprisoneggpickupgrabbed == false
)
#ifdef DEVELOP
|| (cv_debugprisoncd.value && gamedata->thisprisoneggpickup_cached != NULL)
#endif
)
{
// Will be 0 for the next level
@ -1218,6 +1226,10 @@ static void P_AddBrokenPrison(mobj_t *target, mobj_t *inflictor, mobj_t *source)
if (secretpickup)
{
// Grab attention with a long sound effect.
target->hitlag += 56;
S_StartSound(target, sfx_s3k85);
secretpickup->hitlag = target->hitlag;
secretpickup->z -= secretpickup->height/2;
@ -1244,6 +1256,26 @@ static void P_AddBrokenPrison(mobj_t *target, mobj_t *inflictor, mobj_t *source)
secretpickup, secretpickup->angle,
P_ReturnThrustX(secretpickup, launchangle, launchmomentum)
);
mobj_t *flare = P_SpawnMobj(
target->x, target->y,
target->z + target->height/2,
MT_SPARK
);
if (flare)
{
// Will flicker in place until secretpickup exits hitlag.
flare->colorized = true;
flare->renderflags |= RF_ALWAYSONTOP;
P_InstaScale(flare, 4 * flare->scale);
P_SetTarget(&secretpickup->target, flare);
P_SetMobjStateNF(flare, S_PRISONEGGDROP_FLAREA1);
}
// Darken the level for roughly how long it takes until the last sound effect stops playing.
g_darkness.start = leveltime;
g_darkness.end = leveltime + target->hitlag + TICRATE + DARKNESS_FADE_TIME;
}
}
}

View file

@ -7499,6 +7499,10 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
mobj->z += P_MobjFlip(mobj);
mobj->flags2 |= MF2_AMBUSH;
// Finish flare animation.
if (mobj->target && !P_MobjWasRemoved(mobj->target))
P_SetMobjStateNF(mobj->target, S_PRISONEGGDROP_FLAREB1);
}
if (teststate == S_PRISONEGGDROP_CD)
@ -7538,6 +7542,12 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
sparkle->color = M_RandomChance(FRACUNIT/2) ? SKINCOLOR_ULTRAMARINE : SKINCOLOR_MAGENTA;
sparkle->momz += 8 * mobj->scale * P_MobjFlip(mobj);
sparkle->scale = 3 * sparkle->scale;
sparkle->scalespeed = abs(sparkle->scale - sparkle->destscale) / 16;
// Colorize flare.
if (mobj->target && !P_MobjWasRemoved(mobj->target))
mobj->target->color = sparkle->color;
}
}
}

View file

@ -1427,15 +1427,11 @@ void T_PolyObjRotate(polyrotate_t *th)
polyobj_t *po = Polyobj_GetForNum(th->polyObjNum);
if (!po)
#ifdef RANGECHECK
I_Error("T_PolyObjRotate: thinker has invalid id %d\n", th->polyObjNum);
#else
{
CONS_Debug(DBG_POLYOBJ, "T_PolyObjRotate: thinker with invalid id %d removed.\n", th->polyObjNum);
P_RemoveThinker(&th->thinker);
return;
}
#endif
// check for displacement due to override and reattach when possible
if (po->thinker == NULL)
@ -1508,15 +1504,11 @@ void T_PolyObjMove(polymove_t *th)
polyobj_t *po = Polyobj_GetForNum(th->polyObjNum);
if (!po)
#ifdef RANGECHECK
I_Error("T_PolyObjMove: thinker has invalid id %d\n", th->polyObjNum);
#else
{
CONS_Debug(DBG_POLYOBJ, "T_PolyObjMove: thinker with invalid id %d removed.\n", th->polyObjNum);
P_RemoveThinker(&th->thinker);
return;
}
#endif
// check for displacement due to override and reattach when possible
if (po->thinker == NULL)
@ -1598,15 +1590,11 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
fixed_t speed = th->speed;
if (!po)
#ifdef RANGECHECK
I_Error("T_PolyObjWaypoint: thinker has invalid id %d\n", th->polyObjNum);
#else
{
CONS_Debug(DBG_POLYOBJ, "T_PolyObjWaypoint: thinker with invalid id %d removed.", th->polyObjNum);
P_RemoveThinker(&th->thinker);
return;
}
#endif
// check for displacement due to override and reattach when possible
if (!po->thinker)
@ -1714,15 +1702,11 @@ void T_PolyDoorSlide(polyslidedoor_t *th)
polyobj_t *po = Polyobj_GetForNum(th->polyObjNum);
if (!po)
#ifdef RANGECHECK
I_Error("T_PolyDoorSlide: thinker has invalid id %d\n", th->polyObjNum);
#else
{
CONS_Debug(DBG_POLYOBJ, "T_PolyDoorSlide: thinker with invalid id %d removed.\n", th->polyObjNum);
P_RemoveThinker(&th->thinker);
return;
}
#endif
// check for displacement due to override and reattach when possible
if (po->thinker == NULL)
@ -1819,15 +1803,11 @@ void T_PolyDoorSwing(polyswingdoor_t *th)
polyobj_t *po = Polyobj_GetForNum(th->polyObjNum);
if (!po)
#ifdef RANGECHECK
I_Error("T_PolyDoorSwing: thinker has invalid id %d\n", th->polyObjNum);
#else
{
CONS_Debug(DBG_POLYOBJ, "T_PolyDoorSwing: thinker with invalid id %d removed.\n", th->polyObjNum);
P_RemoveThinker(&th->thinker);
return;
}
#endif
// check for displacement due to override and reattach when possible
if (po->thinker == NULL)
@ -1918,15 +1898,11 @@ void T_PolyObjDisplace(polydisplace_t *th)
fixed_t dx, dy;
if (!po)
#ifdef RANGECHECK
I_Error("T_PolyObjDisplace: thinker has invalid id %d\n", th->polyObjNum);
#else
{
CONS_Debug(DBG_POLYOBJ, "T_PolyObjDisplace: thinker with invalid id %d removed.\n", th->polyObjNum);
P_RemoveThinker(&th->thinker);
return;
}
#endif
// check for displacement due to override and reattach when possible
if (po->thinker == NULL)
@ -1958,15 +1934,11 @@ void T_PolyObjRotDisplace(polyrotdisplace_t *th)
fixed_t rotangle;
if (!po)
#ifdef RANGECHECK
I_Error("T_PolyObjRotDisplace: thinker has invalid id %d\n", th->polyObjNum);
#else
{
CONS_Debug(DBG_POLYOBJ, "T_PolyObjRotDisplace: thinker with invalid id %d removed.\n", th->polyObjNum);
P_RemoveThinker(&th->thinker);
return;
}
#endif
// check for displacement due to override and reattach when possible
if (po->thinker == NULL)
@ -2442,15 +2414,11 @@ void T_PolyObjFlag(polymove_t *th)
size_t i;
if (!po)
#ifdef RANGECHECK
I_Error("T_PolyObjFlag: thinker has invalid id %d\n", th->polyObjNum);
#else
{
CONS_Debug(DBG_POLYOBJ, "T_PolyObjFlag: thinker with invalid id %d removed.\n", th->polyObjNum);
P_RemoveThinker(&th->thinker);
return;
}
#endif
// check for displacement due to override and reattach when possible
if (po->thinker == NULL)
@ -2549,15 +2517,11 @@ void T_PolyObjFade(polyfade_t *th)
polyobj_t *po = Polyobj_GetForNum(th->polyObjNum);
if (!po)
#ifdef RANGECHECK
I_Error("T_PolyObjFade: thinker has invalid id %d\n", th->polyObjNum);
#else
{
CONS_Debug(DBG_POLYOBJ, "T_PolyObjFade: thinker with invalid id %d removed.\n", th->polyObjNum);
P_RemoveThinker(&th->thinker);
return;
}
#endif
// check for displacement due to override and reattach when possible
if (po->thinker == NULL)

View file

@ -150,7 +150,7 @@ static boolean P_UnArchivePlayer(savebuffer_t *save)
INT32 skin;
READSTRINGN(save->p, skinname, SKINNAMESIZE);
skin = R_SkinAvailable(skinname);
skin = R_SkinAvailableEx(skinname, false);
if (skin == -1)
{
@ -176,7 +176,7 @@ static boolean P_UnArchivePlayer(savebuffer_t *save)
savedata.bots[pid].valid = true;
READSTRINGN(save->p, skinname, SKINNAMESIZE);
skin = R_SkinAvailable(skinname);
skin = R_SkinAvailableEx(skinname, false);
if (skin == -1)
{
@ -598,11 +598,13 @@ static void P_NetArchivePlayers(savebuffer_t *save)
WRITEINT16(save->p, players[i].incontrol);
WRITEUINT16(save->p, players[i].progressivethrust);
WRITEUINT8(save->p, players[i].ringvisualwarning);
WRITEUINT8(save->p, players[i].analoginput);
WRITEUINT8(save->p, players[i].markedfordeath);
WRITEUINT8(save->p, players[i].dotrickfx);
WRITEUINT8(save->p, players[i].stingfx);
WRITEUINT8(save->p, players[i].bumperinflate);
WRITEUINT8(save->p, players[i].ringboxdelay);
@ -1184,11 +1186,13 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
players[i].incontrol = READINT16(save->p);
players[i].progressivethrust = READUINT16(save->p);
players[i].ringvisualwarning = READUINT8(save->p);
players[i].analoginput = READUINT8(save->p);
players[i].markedfordeath = READUINT8(save->p);
players[i].dotrickfx = READUINT8(save->p);
players[i].stingfx = READUINT8(save->p);
players[i].bumperinflate = READUINT8(save->p);
players[i].ringboxdelay = READUINT8(save->p);

View file

@ -7850,8 +7850,8 @@ static void P_LoadRecordGhosts(void)
if (sameGhosts)
{
INT32 skin = R_SkinAvailable(cv_skin[0].string);
if (skin < 0 || !R_SkinUsable(consoleplayer, skin, false))
INT32 skin = R_SkinAvailableEx(cv_skin[0].string, false);
if (skin < 0 || !R_SkinUsable(-1, skin, false))
skin = 0; // use default skin
add_ghosts(fmt::format("{}-{}{}", gpath, skins[skin].name, modeprefix), sameGhosts);
}

View file

@ -469,10 +469,11 @@ static boolean P_CrossSubsector(size_t num, register los_t *los, register los_fu
seg_t *seg;
INT32 count;
#ifdef RANGECHECK
if (num >= numsubsectors)
I_Error("P_CrossSubsector: ss %s with numss = %s\n", sizeu1(num), sizeu2(numsubsectors));
#endif
{
CONS_Debug(DBG_RENDER, "P_CrossSubsector: ss %s with numss = %s\n", sizeu1(num), sizeu2(numsubsectors));
return true;
}
// haleyjd 02/23/06: this assignment should be after the above check
seg = segs + subsectors[num].firstline;

View file

@ -1906,12 +1906,31 @@ void P_SwitchWeather(preciptype_t newWeather)
P_SpawnPrecipitation();
}
static boolean K_IgnoreFinishLine(player_t *player)
{
// Lightsnake travels to the first waypoint in a straight
// line (init).
// This has the potential to inadvertently cross a finish
// line and remove a lap (happened on Hardhat Havoc).
// After the first waypoint, lightsnake follows the
// waypoints in order so it's not an issue there.
if (player->respawn.state == RESPAWNST_MOVE && player->respawn.init == true)
return true;
// If potential lap cheating has been detected, do not
// interact with the finish line at all.
if (player->bigwaypointgap)
return true;
return false;
}
// Passed over the finish line forwards
static void K_HandleLapIncrement(player_t *player)
{
if (player)
{
if (player->respawn.state == RESPAWNST_MOVE || player->bigwaypointgap)
if (K_IgnoreFinishLine(player))
return;
if (!G_TimeAttackStart() && leveltime < starttime && !(gametyperules & GTR_ROLLINGSTART))
{
@ -2184,7 +2203,7 @@ static void K_HandleLapDecrement(player_t *player)
{
if (player)
{
if (player->respawn.state == RESPAWNST_MOVE || player->bigwaypointgap)
if (K_IgnoreFinishLine(player))
return;
if ((player->cheatchecknum == 0) && (player->laps > 0))
{

View file

@ -1314,13 +1314,13 @@ void P_DoPlayerExit(player_t *player, pflags_t flags)
PR_SaveProfiles();
}
if (P_IsLocalPlayer(player) && player->skin < numskins)
if (P_IsMachineLocalPlayer(player) && player->skin < numskins)
{
skins[player->skin].records.wins++;
}
}
if (!demo.savebutton && P_IsLocalPlayer(player))
if (!demo.savebutton && P_IsMachineLocalPlayer(player))
demo.savebutton = leveltime;
}
}

View file

@ -909,14 +909,12 @@ static void R_Subsector(size_t num)
ZoneScoped;
#ifdef RANGECHECK
if (num >= numsubsectors)
I_Error("R_Subsector: ss %s with numss = %s\n", sizeu1(num), sizeu2(numsubsectors));
#endif
// subsectors added at run-time
if (num >= numsubsectors)
{
CONS_Debug(DBG_RENDER, "R_Subsector: ss %s with numss = %s\n", sizeu1(num), sizeu2(numsubsectors));
return;
}
sub = &subsectors[num];
frontsector = sub->sector;

View file

@ -105,12 +105,10 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc)
return;
}
#ifdef RANGECHECK
if ((unsigned)dc->x >= (unsigned)vid.width || dc->yl < 0 || dc->yh >= vid.height)
{
return;
}
#endif
if constexpr (Type & DrawColumnType::DC_LIGHTLIST)
{
@ -341,10 +339,8 @@ void R_DrawFogColumn(drawcolumndata_t *dc)
if (count < 0)
return;
#ifdef RANGECHECK
if ((unsigned)dc->x >= (unsigned)vid.width || dc->yl < 0 || dc->yh >= vid.height)
return;
#endif
// Framebuffer destination address.
// Use ylookup LUT to avoid multiply with ScreenWidth.
@ -408,10 +404,8 @@ void R_DrawColumn_Flat(drawcolumndata_t *dc)
if (count < 0) // Zero length, column does not exceed a pixel.
return;
#ifdef RANGECHECK
if ((unsigned)dc->x >= (unsigned)vid.width || dc->yl < 0 || dc->yh >= vid.height)
return;
#endif
// Framebuffer destination address.
// Use ylookup LUT to avoid multiply with ScreenWidth.

View file

@ -1435,7 +1435,7 @@ static void R_ParseSpriteInfoSkin(struct ParseSpriteInfoState *parser)
skinName[sprinfoTokenLength] = '\0';
strlwr(skinName);
skinnum = R_SkinAvailable(skinName);
skinnum = R_SkinAvailableEx(skinName, false);
if (skinnum == -1)
I_Error("Error parsing SPRTINFO lump: Unknown skin \"%s\"", skinName);

View file

@ -136,15 +136,17 @@ static void Sk_SetDefaultValue(skin_t *skin)
}
// Grab the default skin
#define DEFAULTBOTSKINNAME "eggrobo"
UINT8 R_BotDefaultSkin(void)
{
static INT32 defaultbotskin = -1;
if (demo.playback)
return R_SkinAvailableEx(DEFAULTBOTSKINNAME, true);
if (defaultbotskin == -1)
{
const char *defaultbotskinname = "eggrobo";
defaultbotskin = R_SkinAvailable(defaultbotskinname);
defaultbotskin = R_SkinAvailableEx(DEFAULTBOTSKINNAME, false);
if (defaultbotskin == -1)
{
@ -155,6 +157,7 @@ UINT8 R_BotDefaultSkin(void)
return (UINT8)defaultbotskin;
}
#undef DEFAULTBOTSKINNAME
//
// Initialize the basic skins
@ -226,7 +229,7 @@ UINT8 *R_GetSkinAvailabilities(boolean demolock, INT32 botforcecharacter)
boolean R_SkinUsable(INT32 playernum, INT32 skinnum, boolean demoskins)
{
boolean needsunlocked = false;
boolean useplayerstruct = (Playing() && playernum != -1);
boolean useplayerstruct = ((Playing() || demo.playback) && playernum >= 0);
UINT16 i;
INT32 skinid;
@ -296,6 +299,13 @@ boolean R_SkinUsable(INT32 playernum, INT32 skinnum, boolean demoskins)
return (boolean)(gamedata->unlocked[i]);
}
boolean R_CanShowSkinInDemo(INT32 skinnum)
{
if (modeattacking == ATTACKING_NONE && !(demo.playback && demo.attract))
return true;
return R_SkinUsable(-2, skinnum, false);
}
// Returns a random unlocked skin ID.
UINT32 R_GetLocalRandomSkin(void)
{
@ -304,7 +314,7 @@ UINT32 R_GetLocalRandomSkin(void)
for (i = 0; i < numskins; i++)
{
if (!R_SkinUsable(-1, i, false))
if (!R_SkinUsable(-2, i, false))
continue;
grabskins[usableskins++] = i;
}
@ -318,10 +328,29 @@ UINT32 R_GetLocalRandomSkin(void)
// returns true if the skin name is found (loaded from pwad)
// warning return -1 if not found
INT32 R_SkinAvailable(const char *name)
{
return R_SkinAvailableEx(name, true);
}
INT32 R_SkinAvailableEx(const char *name, boolean demoskins)
{
INT32 i;
UINT32 hash = quickncasehash(name, SKINNAMESIZE);
if (demo.playback && demoskins)
{
for (i = 0; i < demo.numskins; i++)
{
if (demo.skinlist[i].namehash != hash)
continue;
if (stricmp(demo.skinlist[i].name,name)!=0)
continue;
return i;
}
}
for (i = 0; i < numskins; i++)
{
if (skins[i].namehash != hash)
@ -357,6 +386,9 @@ engineclass_t R_GetEngineClass(SINT8 speed, SINT8 weight, skinflags_t flags)
// Auxillary function that actually sets the skin
static void SetSkin(player_t *player, INT32 skinnum)
{
if (demo.playback)
skinnum = demo.skinlist[skinnum].mapping;
skin_t *skin = &skins[skinnum];
player->skin = skinnum;
@ -404,9 +436,9 @@ static void SetSkin(player_t *player, INT32 skinnum)
// (If your mod locked them all, then you kinda stupid)
static INT32 GetPlayerDefaultSkin(INT32 playernum)
{
INT32 i;
INT32 i, skincount = (demo.playback ? demo.numskins : numskins);
for (i = 0; i < numskins; i++)
for (i = 0; i < skincount; i++)
{
if (R_SkinUsable(playernum, i, false))
{
@ -943,7 +975,7 @@ void R_AddSkins(UINT16 wadnum, boolean mainfile)
// Others can't go in there because we don't want them to be patchable.
if (!stricmp(stoken, "name"))
{
INT32 skinnum = R_SkinAvailable(value);
INT32 skinnum = R_SkinAvailableEx(value, false);
strlwr(value);
if (skinnum == -1)
STRBUFCPY(skin->name, value);
@ -958,7 +990,7 @@ void R_AddSkins(UINT16 wadnum, boolean mainfile)
snprintf(value2, stringspace,
"%s%d", value, numskins);
value2[stringspace - 1] = '\0';
if (R_SkinAvailable(value2) == -1)
if (R_SkinAvailableEx(value2, false) == -1)
// I'm lazy so if NEW name is already used I leave the 'skin x'
// default skin name set in Sk_SetDefaultValue
STRBUFCPY(skin->name, value2);
@ -1138,7 +1170,7 @@ void R_PatchSkins(UINT16 wadnum, boolean mainfile)
if (!stricmp(stoken, "name"))
{
strlwr(value);
skinnum = R_SkinAvailable(value);
skinnum = R_SkinAvailableEx(value, false);
if (skinnum != -1)
skin = &skins[skinnum];
else

View file

@ -112,8 +112,10 @@ void R_PatchSkins(UINT16 wadnum, boolean mainfile);
// Access
INT32 R_SkinAvailable(const char *name);
INT32 R_SkinAvailableEx(const char *name, boolean demoskins);
boolean R_SkinUsable(INT32 playernum, INT32 skinnum, boolean demoskins);
UINT8 *R_GetSkinAvailabilities(boolean demolock, INT32 botforcecharacter);
boolean R_CanShowSkinInDemo(INT32 skinnum);
// Setting
void SetPlayerSkin(INT32 playernum,const char *skinname);

View file

@ -44,6 +44,13 @@ INT32 R_ThingLightLevel(mobj_t* thing)
{
lightlevel -= 255;
}
if (!R_CanShowSkinInDemo((skin_t*)thing->skin-skins)
&& !thing->colorized
&& !thing->hitlag)
{
lightlevel -= 128;
}
}
return lightlevel;

View file

@ -835,37 +835,42 @@ boolean R_ThingIsFlashing(mobj_t *thing)
UINT8 *R_GetSpriteTranslation(vissprite_t *vis)
{
if (!(vis->cut & SC_PRECIP) &&
R_ThingIsFlashing(vis->mobj))
if (vis->cut & SC_PRECIP)
{
return R_GetTranslationColormap(TC_HITLAG, static_cast<skincolornum_t>(0), GTC_CACHE);
// Simplified func, less safe properties to check
if (vis->mobj->color)
R_GetTranslationColormap(TC_DEFAULT, static_cast<skincolornum_t>(vis->mobj->color), GTC_CACHE);
return NULL;
}
/*
else if (R_SpriteIsFlashing(vis)) // Bosses "flash"
size_t skinnum = TC_DEFAULT;
if (vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // This thing is a player!
{
if (vis->mobj->type == MT_CYBRAKDEMON || vis->mobj->colorized)
return R_GetTranslationColormap(TC_ALLWHITE, 0, GTC_CACHE);
else if (vis->mobj->type == MT_METALSONIC_BATTLE)
return R_GetTranslationColormap(TC_METALSONIC, 0, GTC_CACHE);
else
return R_GetTranslationColormap(TC_BOSS, 0, GTC_CACHE);
}
*/
else if (vis->mobj->color)
{
// New colormap stuff for skins Tails 06-07-2002
if (!(vis->cut & SC_PRECIP) && vis->mobj->colorized)
return R_GetTranslationColormap(TC_RAINBOW, static_cast<skincolornum_t>(vis->mobj->color), GTC_CACHE);
else if (!(vis->cut & SC_PRECIP) && vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // This thing is a player!
skinnum = (skin_t*)vis->mobj->skin-skins;
// Hide not-yet-unlocked characters in replays from other people
if (!R_CanShowSkinInDemo(skinnum))
{
size_t skinnum = (skin_t*)vis->mobj->skin-skins;
return R_GetTranslationColormap((INT32)skinnum, static_cast<skincolornum_t>(vis->mobj->color), GTC_CACHE);
skinnum = TC_BLINK;
}
else // Use the defaults
return R_GetTranslationColormap(TC_DEFAULT, static_cast<skincolornum_t>(vis->mobj->color), GTC_CACHE);
}
else if (vis->mobj->sprite == SPR_PLAY) // Looks like a player, but doesn't have a color? Get rid of green sonic syndrome.
return R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_BLUE, GTC_CACHE);
if (R_ThingIsFlashing(vis->mobj))
{
if (skinnum != (size_t)TC_BLINK)
skinnum = TC_HITLAG;
return R_GetTranslationColormap(skinnum, static_cast<skincolornum_t>(0), GTC_CACHE);
}
if (vis->mobj->color)
{
if (skinnum != (size_t)TC_BLINK && vis->mobj->colorized)
skinnum = TC_RAINBOW;
return R_GetTranslationColormap(skinnum, static_cast<skincolornum_t>(vis->mobj->color), GTC_CACHE);
}
return NULL;
}
@ -1073,9 +1078,7 @@ static void R_DrawVisSprite(vissprite_t *vis)
}
else if (vis->cut & SC_SHEAR)
{
#ifdef RANGECHECK
pwidth = patch->width;
#endif
// Vertically sheared sprite
for (dc.x = vis->x1; dc.x <= vis->x2; dc.x++, frac += vis->xiscale, dc.texturemid -= vis->shear.tan)
@ -1093,7 +1096,7 @@ static void R_DrawVisSprite(vissprite_t *vis)
else
{
#ifdef RANGECHECK
#if 0
if (vis->x1test && vis->x2test)
{
INT32 x1test = vis->x1test;
@ -1112,7 +1115,7 @@ static void R_DrawVisSprite(vissprite_t *vis)
CONS_Printf("THE GAME WOULD HAVE CRASHED, %d (old) vs %d (new)\n", (x2test - x1test), (vis->x2 - vis->x1));
}
}
#endif // RANGECHECK
#endif
// Non-paper drawing loop
for (dc.x = vis->x1; dc.x <= vis->x2; dc.x++, frac += vis->xiscale, sprtopscreen += vis->shear.tan)
@ -1191,10 +1194,11 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis)
{
texturecolumn = frac>>FRACBITS;
#ifdef RANGECHECK
if (texturecolumn < 0 || texturecolumn >= patch->width)
I_Error("R_DrawPrecipitationSpriteRange: bad texturecolumn");
#endif
{
CONS_Debug(DBG_RENDER, "R_DrawPrecipitationSpriteRange: bad texturecolumn\n");
break;
}
column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[texturecolumn]));
@ -1832,10 +1836,11 @@ static void R_ProjectSprite(mobj_t *thing)
sortscale = FixedDiv(projectiony[viewssnum], tz);
// decide which patch to use for sprite relative to player
#ifdef RANGECHECK
if ((size_t)(thing->sprite) >= numsprites)
I_Error("R_ProjectSprite: invalid sprite number %d ", thing->sprite);
#endif
{
CONS_Debug(DBG_RENDER, "R_ProjectSprite: invalid sprite number %d\n", thing->sprite);
return;
}
frame = thing->frame&FF_FRAMEMASK;
@ -2634,19 +2639,21 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
yscale = FixedDiv(projectiony[viewssnum], tz);
// decide which patch to use for sprite relative to player
#ifdef RANGECHECK
if ((unsigned)thing->sprite >= numsprites)
I_Error("R_ProjectPrecipitationSprite: invalid sprite number %d ",
{
CONS_Debug(DBG_RENDER, "R_ProjectPrecipitationSprite: invalid sprite number %d\n",
thing->sprite);
#endif
return;
}
sprdef = &sprites[thing->sprite];
#ifdef RANGECHECK
if ((UINT8)(thing->frame&FF_FRAMEMASK) >= sprdef->numframes)
I_Error("R_ProjectPrecipitationSprite: invalid sprite frame %d : %d for %s",
{
CONS_Debug(DBG_RENDER, "R_ProjectPrecipitationSprite: invalid sprite frame %d : %d for %s\n",
thing->sprite, thing->frame, sprnames[thing->sprite]);
#endif
return;
}
sprframe = &sprdef->spriteframes[thing->frame & FF_FRAMEMASK];

View file

@ -534,7 +534,7 @@ sfxinfo_t S_sfx[NUMSFX] =
{"s3k82", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Burst"},
{"s3k83", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Collapsing"},
{"s3k84", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Powering up"},
{"s3k85", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Powering down"},
{"s3k85", false, 64, 24, -1, NULL, 0, -1, -1, LUMPERROR, "Powering down"},
{"s3k86", false, 128, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Alarm"},
{"s3k87", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bounce"},
{"s3k88", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Metallic squeak"},
@ -1520,6 +1520,12 @@ sfxinfo_t S_sfx[NUMSFX] =
{"tmxbdn", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Button down
{"tmxbup", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Button up
// SMS
{"sting0", false, 64, 2, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Ring loss
// Patching up base sounds
{"s226l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // s2 spikes LOUD
// SRB2kart - Skin sounds
{"kwin", false, 64, 96, -1, NULL, 0, SKSKWIN, -1, LUMPERROR, ""},
{"klose", false, 64, 96, -1, NULL, 0, SKSKLOSE, -1, LUMPERROR, ""},

View file

@ -1596,6 +1596,12 @@ typedef enum
sfx_tmxbdn,
sfx_tmxbup,
// SMS
sfx_sting0,
// Patch-up
sfx_s226l,
// And LASTLY, Kart's skin sounds.
sfx_kwin,
sfx_klose,

View file

@ -987,10 +987,8 @@ void V_DrawBlock(INT32 x, INT32 y, INT32 scrn, INT32 width, INT32 height, const
UINT8 *dest;
const UINT8 *deststop;
#ifdef RANGECHECK
if (x < 0 || x + width > vid.width || y < 0 || y + height > vid.height || (unsigned)scrn > 4)
I_Error("Bad V_DrawBlock");
#endif
dest = screens[scrn] + y*vid.width + x;
deststop = screens[scrn] + vid.rowbytes * vid.height;