From c92926bfb6e080e39e658086fbc6f44b605348d3 Mon Sep 17 00:00:00 2001 From: Matthew Marsalko Date: Sun, 24 Dec 2017 23:09:06 -0800 Subject: [PATCH 001/146] Add support for overriding the ESC key --- src/g_input.c | 1 + src/g_input.h | 1 + src/m_menu.c | 5 +++++ 3 files changed, 7 insertions(+) diff --git a/src/g_input.c b/src/g_input.c index b004384c0..4f87332c2 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -990,6 +990,7 @@ static const char *gamecontrolname[num_gamecontrols] = "jump", "console", "pause", + "systemmenu", "custom1", "custom2", "custom3", diff --git a/src/g_input.h b/src/g_input.h index d65339321..633504826 100644 --- a/src/g_input.h +++ b/src/g_input.h @@ -118,6 +118,7 @@ typedef enum gc_jump, gc_console, gc_pause, + gc_systemmenu, gc_custom1, // Lua scriptable gc_custom2, // Lua scriptable gc_custom3, // Lua scriptable diff --git a/src/m_menu.c b/src/m_menu.c index ea93d1e2d..f438508a9 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1077,6 +1077,8 @@ static menuitem_t OP_MiscControlsMenu[] = {IT_CALL | IT_STRING2, NULL, "Custom Action 2", M_ChangeControl, gc_custom2 }, {IT_CALL | IT_STRING2, NULL, "Custom Action 3", M_ChangeControl, gc_custom3 }, + {IT_CALL | IT_STRING2, NULL, "System Menu (ESC)",M_ChangeControl, gc_systemmenu }, + {IT_CALL | IT_STRING2, NULL, "Pause", M_ChangeControl, gc_pause }, {IT_CALL | IT_STRING2, NULL, "Console", M_ChangeControl, gc_console }, }; @@ -2176,11 +2178,14 @@ boolean M_Responder(event_t *ev) if (ch == -1) return false; + else if (ch == gamecontrol[gc_systemmenu][0]) // allow remappable ESC key + ch = KEY_ESCAPE; // F-Keys if (!menuactive) { noFurtherInput = true; + switch (ch) { case KEY_F1: // Help key From d582a9dd97998593e42af37e98e5f0a6ced41abd Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 23 Jul 2018 23:50:41 +0100 Subject: [PATCH 002/146] Encore mode - a fresh take on mirror mode! * Palette remaps. * Branding. TODO: * Doesn't work in GL. (Mostly.) I have SOME ideas on how to tackle this, but... * Transmaps are broken in Encore for some reason. * I tried to make in-level colormaps shimmy over, but it didn't quite work, so I commented it out and only semi-fixed it. --- src/d_netcmd.c | 14 ++--- src/d_netcmd.h | 2 +- src/doomstat.h | 2 +- src/g_game.c | 8 +-- src/hardware/hw_defs.h | 2 +- src/hardware/hw_main.c | 8 ++- src/info.c | 4 +- src/k_kart.c | 18 +++--- src/m_menu.c | 4 +- src/p_mobj.c | 2 +- src/p_saveg.c | 4 +- src/p_setup.c | 57 +++++++++--------- src/p_user.c | 2 +- src/r_bsp.c | 22 +++++-- src/r_data.c | 130 ++++++++++++++++++++++++++++++++++------- src/r_data.h | 2 +- src/r_draw8.c | 4 ++ src/r_plane.c | 10 +++- src/r_plane.h | 4 +- src/r_segs.c | 20 +++++++ src/r_state.h | 1 + src/r_things.c | 7 +++ src/s_sound.c | 4 +- src/st_stuff.c | 15 ++++- src/y_inter.c | 6 ++ 25 files changed, 256 insertions(+), 96 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index a83f23b21..bb9a9f761 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -112,7 +112,7 @@ static void SoundTest_OnChange(void); static void BaseNumLaps_OnChange(void); static void KartFrantic_OnChange(void); static void KartSpeed_OnChange(void); -static void KartMirror_OnChange(void); +static void KartEncore_OnChange(void); static void KartComeback_OnChange(void); #ifdef NETGAME_DEVMODE @@ -362,7 +362,7 @@ static CV_PossibleValue_t kartbumpers_cons_t[] = {{1, "MIN"}, {12, "MAX"}, {0, N consvar_t cv_kartbumpers = {"kartbumpers", "3", CV_NETVAR|CV_CHEAT, kartbumpers_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_kartfrantic = {"kartfrantic", "Off", CV_NETVAR|CV_CHEAT|CV_CALL|CV_NOINIT, CV_OnOff, KartFrantic_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_kartcomeback = {"kartcomeback", "On", CV_NETVAR|CV_CHEAT|CV_CALL|CV_NOINIT, CV_OnOff, KartComeback_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_kartmirror = {"kartmirror", "Off", CV_NETVAR|CV_CHEAT|CV_CALL|CV_NOINIT, CV_OnOff, KartMirror_OnChange, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_kartencore = {"kartencore", "Off", CV_NETVAR|CV_CHEAT|CV_CALL|CV_NOINIT, CV_OnOff, KartEncore_OnChange, 0, NULL, NULL, 0, 0, NULL}; static CV_PossibleValue_t kartspeedometer_cons_t[] = {{0, "Off"}, {1, "Kilometers"}, {2, "Miles"}, {3, "Fracunits"}, {0, NULL}}; consvar_t cv_kartspeedometer = {"kartdisplayspeed", "Off", CV_SAVE, kartspeedometer_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; // use tics in display @@ -5231,16 +5231,16 @@ static void KartSpeed_OnChange(void) } } -static void KartMirror_OnChange(void) +static void KartEncore_OnChange(void) { if (G_RaceGametype()) { - if ((boolean)cv_kartmirror.value != mirrormode && gamestate == GS_LEVEL /*&& leveltime > starttime*/) - CONS_Printf(M_GetText("Mirrored tracks will be turned %s next round.\n"), cv_kartmirror.value ? M_GetText("on") : M_GetText("off")); + if ((boolean)cv_kartencore.value != encoremode && gamestate == GS_LEVEL /*&& leveltime > starttime*/) + CONS_Printf(M_GetText("Encore tracks will be turned %s next round.\n"), cv_kartencore.value ? M_GetText("on") : M_GetText("off")); else { - CONS_Printf(M_GetText("Mirrored tracks has been turned %s.\n"), cv_kartmirror.value ? M_GetText("on") : M_GetText("off")); - mirrormode = (boolean)cv_kartmirror.value; + CONS_Printf(M_GetText("Encore tracks has been turned %s.\n"), cv_kartencore.value ? M_GetText("on") : M_GetText("off")); + encoremode = (boolean)cv_kartencore.value; } } } diff --git a/src/d_netcmd.h b/src/d_netcmd.h index 0805a41f8..960390ef3 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -124,7 +124,7 @@ extern consvar_t cv_kartspeed; extern consvar_t cv_kartbumpers; extern consvar_t cv_kartfrantic; extern consvar_t cv_kartcomeback; -extern consvar_t cv_kartmirror; +extern consvar_t cv_kartencore; extern consvar_t cv_kartspeedometer; extern consvar_t cv_votetime; diff --git a/src/doomstat.h b/src/doomstat.h index 8f1469a3a..0f2657b02 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -446,7 +446,7 @@ extern INT32 cheats; // SRB2kart extern UINT8 gamespeed; extern boolean franticitems; -extern boolean mirrormode; +extern boolean encoremode; extern boolean comeback; extern SINT8 battlewanted[4]; diff --git a/src/g_game.c b/src/g_game.c index a652e83f4..59042ff20 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -248,7 +248,7 @@ INT32 cheats; //for multiplayer cheat commands // SRB2Kart // Cvars that we don't want changed mid-game UINT8 gamespeed; // Game's current speed (or difficulty, or cc, or etc); 0 for easy, 1 for normal, 2 for hard -boolean mirrormode; // Mirror Mode currently enabled? +boolean encoremode; // Encore Mode currently enabled? boolean franticitems; // Frantic items currently enabled? boolean comeback; // Battle Mode's karma comeback is on/off @@ -1267,7 +1267,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) axis = JoyAxis(AXISTURN, ssplayer); - if (mirrormode) + if (encoremode) { turnright ^= turnleft; // swap these using three XORs turnleft ^= turnright; @@ -1318,8 +1318,8 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) // Specator mouse turning if (player->spectator) { - cmd->angleturn = (INT16)(cmd->angleturn - (mousex*(mirrormode ? -1 : 1)*8)); - cmd->driftturn = (INT16)(cmd->driftturn - (mousex*(mirrormode ? -1 : 1)*8)); + cmd->angleturn = (INT16)(cmd->angleturn - (mousex*(encoremode ? -1 : 1)*8)); + cmd->driftturn = (INT16)(cmd->driftturn - (mousex*(encoremode ? -1 : 1)*8)); } // Speed bump strafing diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index 9a490a964..2d3468781 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -109,7 +109,7 @@ typedef struct FLOAT fovxangle, fovyangle; UINT8 splitscreen; boolean flip; // screenflip - boolean mirror; // SRB2Kart: Mirror Mode + boolean mirror; // SRB2Kart: Encore Mode } FTransform; // Transformed vector, as passed to HWR API diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 4b088dfd3..be176f7dd 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -3147,7 +3147,6 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, v3d->z = FIXED_TO_FLOAT(polysector->vertices[i]->y); } - if (planecolormap) Surf.FlatColor.rgba = HWR_Lighting(lightlevel, planecolormap->rgba, planecolormap->fadergba, false, true); else @@ -5441,7 +5440,11 @@ static void HWR_ProjectSprite(mobj_t *thing) vis->colormap = R_GetTranslationColormap(TC_DEFAULT, thing->color, GTC_CACHE); } else + { vis->colormap = colormaps; + if (encoremap && (thing->flags & (MF_SCENERY|MF_NOTHINK))) + vis->colormap += (256*32); + } // set top/bottom coords vis->ty = gzt; @@ -5545,6 +5548,8 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) vis->mobj = (mobj_t *)thing; vis->colormap = colormaps; + if (encoremap) + vis->colormap += (256*32); // set top/bottom coords vis->ty = FIXED_TO_FLOAT(thing->z + spritecachedinfo[lumpoff].topoffset); @@ -6537,6 +6542,7 @@ static void HWR_RenderWall(wallVert3D *wallVerts, FSurfaceInfo *pSurf, FBITFIE alpha = pSurf->FlatColor.s.alpha; // retain the alpha // Lighting is done here instead so that fog isn't drawn incorrectly on transparent walls after sorting + if (wallcolormap) { if (fogwall) diff --git a/src/info.c b/src/info.c index 939efd44e..8565702c8 100644 --- a/src/info.c +++ b/src/info.c @@ -13240,7 +13240,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY|MF_SCENERY, // flags + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY|MF_SCENERY|MF_SLIDEME, // flags S_NULL // raisestate }, @@ -14349,7 +14349,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY|MF_SLIDEME, // flags S_NULL // raisestate }, diff --git a/src/k_kart.c b/src/k_kart.c index 8d64af575..e65942a3f 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -24,7 +24,7 @@ // SOME IMPORTANT VARIABLES DEFINED IN DOOMDEF.H: // gamespeed is cc (0 for easy, 1 for normal, 2 for hard) // franticitems is Frantic Mode items, bool -// mirrormode is Mirror Mode (duh), bool +// encoremode is Encore Mode (duh), bool // comeback is Battle Mode's karma comeback, also bool // battlewanted is an array of the WANTED player nums, -1 for no player in that slot // indirectitemcooldown is timer before anyone's allowed another Shrink/SPB @@ -401,7 +401,7 @@ void K_RegisterKartStuff(void) CV_RegisterVar(&cv_kartbumpers); CV_RegisterVar(&cv_kartfrantic); CV_RegisterVar(&cv_kartcomeback); - CV_RegisterVar(&cv_kartmirror); + CV_RegisterVar(&cv_kartencore); CV_RegisterVar(&cv_kartspeedometer); CV_RegisterVar(&cv_votetime); @@ -5174,7 +5174,7 @@ fixed_t K_FindCheckX(fixed_t px, fixed_t py, angle_t ang, fixed_t mx, fixed_t my else x = (FixedMul(FINETANGENT(((diff+ANGLE_90)>>ANGLETOFINESHIFT) & 4095), 160<>FRACBITS; - if (mirrormode) + if (encoremode) x = 320-x; if (splitscreen > 1) @@ -5383,14 +5383,14 @@ static void K_drawKartMinimapHead(mobj_t *mo, INT32 x, INT32 y, INT32 flags, pat amnumxpos = (FixedMul(mo->x, zoom) - FixedMul(xoffset, zoom)); amnumypos = -(FixedMul(mo->y, zoom) - FixedMul(yoffset, zoom)); - if (mirrormode) + if (encoremode) amnumxpos = -amnumxpos; amxpos = amnumxpos + ((x + AutomapPic->width/2 - (iconprefix[skin]->width/2))<height/2 - (iconprefix[skin]->height/2))<width/2 + (iconprefix[skin]->width/2))<width), y, splitflags|V_FLIP, AutomapPic); else V_DrawScaledPatch(x, y, splitflags, AutomapPic); @@ -5462,7 +5462,7 @@ static void K_drawKartMinimap(void) } // let offsets transfer to the heads, too! - if (mirrormode) + if (encoremode) x += SHORT(AutomapPic->leftoffset); else x -= SHORT(AutomapPic->leftoffset); @@ -5730,7 +5730,7 @@ static void K_drawKartFirstPerson(void) else // forward target = 0; - if (mirrormode) + if (encoremode) target = -target; if (pn < target) @@ -5797,7 +5797,7 @@ static void K_drawKartFirstPerson(void) if (stplyr->mo->momz > 0) // TO-DO: Draw more of the kart so we can remove this if! yoffs += stplyr->mo->momz/3; - if (mirrormode) + if (encoremode) x -= xoffs; else x += xoffs; diff --git a/src/m_menu.c b/src/m_menu.c index 48857e20b..9cc87453f 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1413,7 +1413,7 @@ static menuitem_t OP_GameOptionsMenu[] = {IT_STRING | IT_CVAR, NULL, "Game Speed", &cv_kartspeed, 30}, {IT_STRING | IT_CVAR, NULL, "Frantic Items", &cv_kartfrantic, 40}, - {IT_STRING | IT_CVAR, NULL, "Mirror Mode", &cv_kartmirror, 50}, + {IT_STRING | IT_CVAR, NULL, "Encore Mode", &cv_kartencore, 50}, {IT_STRING | IT_CVAR, NULL, "Number of Laps", &cv_basenumlaps, 70}, {IT_STRING | IT_CVAR, NULL, "Exit Countdown Timer", &cv_countdowntime, 80}, @@ -1470,7 +1470,7 @@ static menuitem_t OP_ServerOptionsMenu[] = { {IT_HEADER, NULL, "RACE", NULL, 2}, {IT_STRING | IT_CVAR, NULL, "Game Speed", &cv_kartspeed, 10}, - {IT_STRING | IT_CVAR, NULL, "Mirror Mode", &cv_kartmirror, 18}, + {IT_STRING | IT_CVAR, NULL, "Encore Mode", &cv_kartencore, 18}, {IT_STRING | IT_CVAR, NULL, "Number of Laps", &cv_numlaps, 26}, {IT_STRING | IT_CVAR, NULL, "Use Map Lap Counts", &cv_usemapnumlaps, 34}, diff --git a/src/p_mobj.c b/src/p_mobj.c index 9e13db6d9..74b9e54c2 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -3643,7 +3643,7 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled || (thiscam == &camera4 && players[fourthdisplayplayer].mo && (players[fourthdisplayplayer].mo->flags2 & MF2_TWOD))) itsatwodlevel = true; - if (mirrormode) + if (encoremode) postimg = postimg_mirror; else if (player->pflags & PF_FLIPCAM && !(player->pflags & PF_NIGHTSMODE) && player->mo->eflags & MFE_VERTICALFLIP) postimg = postimg_flip; diff --git a/src/p_saveg.c b/src/p_saveg.c index fdbe4033c..8f4e12d42 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -3256,7 +3256,7 @@ static void P_NetArchiveMisc(void) WRITEINT32(save_p, numgotboxes); WRITEUINT8(save_p, gamespeed); - WRITEUINT8(save_p, mirrormode); + WRITEUINT8(save_p, encoremode); WRITEUINT8(save_p, franticitems); WRITEUINT8(save_p, comeback); @@ -3361,7 +3361,7 @@ static inline boolean P_NetUnArchiveMisc(void) numgotboxes = READINT32(save_p); gamespeed = READUINT8(save_p); - mirrormode = (boolean)READUINT8(save_p); + encoremode = (boolean)READUINT8(save_p); franticitems = (boolean)READUINT8(save_p); comeback = (boolean)READUINT8(save_p); diff --git a/src/p_setup.c b/src/p_setup.c index f4c28663c..30e882d5a 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2726,7 +2726,35 @@ boolean P_SetupLevel(boolean skipprecip) // internal game map lastloadedmaplumpnum = W_GetNumForName(maplumpname = G_BuildMapName(gamemap)); - R_ReInitColormaps(mapheaderinfo[gamemap-1]->palette); + // SRB2Kart: map load variables + if (modeattacking) // Just play it safe and set everything + { + gamespeed = 2; + encoremode = false; + franticitems = false; + comeback = true; + } + else + { + if (G_BattleGametype()) + { + gamespeed = 0; + encoremode = false; + } + else + { + gamespeed = (UINT8)cv_kartspeed.value; + encoremode = (boolean)cv_kartencore.value; + } + franticitems = (boolean)cv_kartfrantic.value; + comeback = (boolean)cv_kartcomeback.value; + } + + for (i = 0; i < 4; i++) + battlewanted[i] = -1; + + R_ReInitColormaps(mapheaderinfo[gamemap-1]->palette, + (encoremode ? W_CheckNumForName(va("%sE", maplumpname)) : LUMPERROR)); CON_SetupBackColormap(); // SRB2 determines the sky texture to be used depending on the map header. @@ -2986,33 +3014,6 @@ boolean P_SetupLevel(boolean skipprecip) CV_SetValue(&cv_analog, false); }*/ - // SRB2Kart: map load variables - if (modeattacking) // Just play it safe and set everything - { - gamespeed = 2; - mirrormode = false; - franticitems = false; - comeback = true; - } - else - { - if (G_BattleGametype()) - { - gamespeed = 0; - mirrormode = false; - } - else - { - gamespeed = (UINT8)cv_kartspeed.value; - mirrormode = (boolean)cv_kartmirror.value; - } - franticitems = (boolean)cv_kartfrantic.value; - comeback = (boolean)cv_kartcomeback.value; - } - - for (i = 0; i < 4; i++) - battlewanted[i] = -1; - wantedcalcdelay = wantedfrequency*2; indirectitemcooldown = 0; spbincoming = 0; diff --git a/src/p_user.c b/src/p_user.c index f612e81d9..0a54696ea 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -9015,7 +9015,7 @@ static void P_CalcPostImg(player_t *player) } #endif - if (mirrormode) // srb2kart + if (encoremode) // srb2kart *type = postimg_mirror; } diff --git a/src/r_bsp.c b/src/r_bsp.c index 56f159c28..48f2f1793 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -37,6 +37,16 @@ drawseg_t *ds_p = NULL; // indicates doors closed wrt automap bugfix: INT32 doorclosed; +static boolean R_NoEncore(sector_t *sector) +{ + INT32 val = GETSECSPECIAL(sector->special, 3); + if (val == 1 || val == 3) + return true; + if (GETSECSPECIAL(sector->special, 4) == 6) + return true; + return false; +} + // // R_ClearDrawSegs // @@ -935,7 +945,7 @@ static void R_Subsector(size_t num, UINT8 viewnumber) #ifdef ESLOPE , frontsector->f_slope #endif - ); + , R_NoEncore(frontsector)); } else floorplane = NULL; @@ -957,7 +967,7 @@ static void R_Subsector(size_t num, UINT8 viewnumber) #ifdef ESLOPE , frontsector->c_slope #endif - ); + , R_NoEncore(frontsector)); } else ceilingplane = NULL; @@ -1018,7 +1028,7 @@ static void R_Subsector(size_t num, UINT8 viewnumber) #ifdef ESLOPE , *rover->b_slope #endif - ); + , R_NoEncore(rover->master->frontsector)); #ifdef ESLOPE ffloor[numffloors].slope = *rover->b_slope; @@ -1064,7 +1074,7 @@ static void R_Subsector(size_t num, UINT8 viewnumber) #ifdef ESLOPE , *rover->t_slope #endif - ); + , R_NoEncore(rover->master->frontsector)); #ifdef ESLOPE ffloor[numffloors].slope = *rover->t_slope; @@ -1133,7 +1143,7 @@ static void R_Subsector(size_t num, UINT8 viewnumber) #ifdef ESLOPE , NULL // will ffloors be slopable eventually? #endif - ); + , R_NoEncore(polysec)); ffloor[numffloors].height = polysec->floorheight; ffloor[numffloors].polyobj = po; @@ -1179,7 +1189,7 @@ static void R_Subsector(size_t num, UINT8 viewnumber) #ifdef ESLOPE , NULL // will ffloors be slopable eventually? #endif - ); + , R_NoEncore(polysec)); ffloor[numffloors].polyobj = po; ffloor[numffloors].height = polysec->ceilingheight; diff --git a/src/r_data.c b/src/r_data.c index d19882dd3..4719b908f 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -112,6 +112,7 @@ INT32 *texturetranslation; sprcache_t *spritecachedinfo; lighttable_t *colormaps; +lighttable_t *encoremap; // for debugging/info purposes static size_t flatmemory, spritememory, texturememory; @@ -932,7 +933,7 @@ static inline lumpnum_t R_CheckNumForNameList(const char *name, lumplist_t *list return LUMPERROR; } -static lumplist_t *colormaplumps = NULL; ///\todo free leak +/*static lumplist_t *colormaplumps = NULL; ///\todo free leak static size_t numcolormaplumps = 0; static void R_InitExtraColormaps(void) @@ -966,7 +967,7 @@ static void R_InitExtraColormaps(void) numcolormaplumps++; } CONS_Printf(M_GetText("Number of Extra Colormaps: %s\n"), sizeu1(numcolormaplumps)); -} +}*/ // 12/14/14 -- only take flats in F_START/F_END lumpnum_t R_GetFlatNumForName(const char *name) @@ -1010,15 +1011,17 @@ static void R_InitColormaps(void) // Load in the light tables lump = W_GetNumForName("COLORMAP"); - colormaps = Z_MallocAlign(W_LumpLength (lump), PU_STATIC, NULL, 8); + //Z_MallocAlign(W_LumpLength (lump), PU_STATIC, NULL, 8); + colormaps = Z_MallocAlign((256 * 64), PU_STATIC, NULL, 8); W_ReadLump(lump, colormaps); + // no need to init encoremap at this stage // Init Boom colormaps. R_ClearColormaps(); - R_InitExtraColormaps(); + //R_InitExtraColormaps(); } -void R_ReInitColormaps(UINT16 num) +void R_ReInitColormaps(UINT16 num, lumpnum_t newencoremap) { char colormap[9] = "COLORMAP"; lumpnum_t lump; @@ -1032,6 +1035,30 @@ void R_ReInitColormaps(UINT16 num) lump = W_GetNumForName("COLORMAP"); W_ReadLump(lump, colormaps); + // Encore mode. + if (newencoremap != LUMPERROR) + { + lighttable_t *colormap_p, *colormap_p2; + size_t p, i; + + encoremap = Z_MallocAlign(256 + 10, PU_LEVEL, NULL, 8); + W_ReadLump(newencoremap, encoremap); + colormap_p = colormap_p2 = colormaps; + colormap_p += (256 * 32); + + for (p = 0; p < 32; p++) + { + for (i = 0; i < 256; i++) + { + *colormap_p = colormap_p2[encoremap[i]]; + colormap_p++; + } + colormap_p2 += 256; + } + } + else + encoremap = NULL; + // Init Boom colormaps. R_ClearColormaps(); } @@ -1060,7 +1087,7 @@ void R_ClearColormaps(void) memset(extra_colormaps, 0, sizeof (extra_colormaps)); } -INT32 R_ColormapNumForName(char *name) +/*INT32 R_ColormapNumForName(char *name) { lumpnum_t lump, i; @@ -1092,7 +1119,7 @@ INT32 R_ColormapNumForName(char *name) num_extra_colormaps++; return (INT32)num_extra_colormaps - 1; -} +}*/ // // R_CreateColormap @@ -1121,10 +1148,20 @@ INT32 R_CreateColormap(char *p1, char *p2, char *p3) if (p1[0] == '#') { cr = ((HEX2INT(p1[1]) * 16) + HEX2INT(p1[2])); - cmaskr = cr; cg = ((HEX2INT(p1[3]) * 16) + HEX2INT(p1[4])); - cmaskg = cg; cb = ((HEX2INT(p1[5]) * 16) + HEX2INT(p1[6])); + + // i don't know why this doesn't work... + /*if (encoremap) + { + i = NearestColor(cr, cg, cb); + cr = pLocalPalette[encoremap[i]].s.red; + cg = pLocalPalette[encoremap[i]].s.green; + cb = pLocalPalette[encoremap[i]].s.blue; + }*/ + + cmaskr = cr; + cmaskg = cg; cmaskb = cb; // Create a rough approximation of the color (a 16 bit color) maskcolor = ((cb) >> 3) + (((cg) >> 2) << 5) + (((cr) >> 3) << 11); @@ -1167,9 +1204,22 @@ INT32 R_CreateColormap(char *p1, char *p2, char *p3) if (p3[0] == '#') { - cdestr = cr = ((HEX2INT(p3[1]) * 16) + HEX2INT(p3[2])); - cdestg = cg = ((HEX2INT(p3[3]) * 16) + HEX2INT(p3[4])); - cdestb = cb = ((HEX2INT(p3[5]) * 16) + HEX2INT(p3[6])); + cr = ((HEX2INT(p3[1]) * 16) + HEX2INT(p3[2])); + cg = ((HEX2INT(p3[3]) * 16) + HEX2INT(p3[4])); + cb = ((HEX2INT(p3[5]) * 16) + HEX2INT(p3[6])); + + // i don't know why this doesn't work... + /*if (encoremap) + { + i = NearestColor(cr, cg, cb); + cr = pLocalPalette[encoremap[i]].s.red; + cg = pLocalPalette[encoremap[i]].s.green; + cb = pLocalPalette[encoremap[i]].s.blue; + }*/ + + cdestr = cr; + cdestg = cg; + cdestb = cb; fadecolor = (((cb) >> 3) + (((cg) >> 2) << 5) + (((cr) >> 3) << 11)); } else @@ -1257,10 +1307,10 @@ void R_CreateColormap2(char *p1, char *p2, char *p3) double cmaskr, cmaskg, cmaskb, cdestr, cdestg, cdestb; double r, g, b, cbrightness; double maskamt = 0, othermask = 0; - int mask, p, fog = 0; + INT32 mask, p, fog = 0; size_t mapnum = num_extra_colormaps; size_t i; - char *colormap_p; + lighttable_t *colormap_p, *colormap_p2; UINT32 cr, cg, cb, maskcolor, fadecolor; UINT32 fadestart = 0, fadeend = 33, fadedist = 33; @@ -1268,10 +1318,20 @@ void R_CreateColormap2(char *p1, char *p2, char *p3) if (p1[0] == '#') { cr = ((HEX2INT(p1[1]) * 16) + HEX2INT(p1[2])); - cmaskr = cr; cg = ((HEX2INT(p1[3]) * 16) + HEX2INT(p1[4])); - cmaskg = cg; cb = ((HEX2INT(p1[5]) * 16) + HEX2INT(p1[6])); + + // i don't know why this doesn't work... + /*if (encoremap) + { + i = NearestColor(cr, cg, cb); + cr = pLocalPalette[encoremap[i]].s.red; + cg = pLocalPalette[encoremap[i]].s.green; + cb = pLocalPalette[encoremap[i]].s.blue; + }*/ + + cmaskr = cr; + cmaskg = cg; cmaskb = cb; // Create a rough approximation of the color (a 16 bit color) maskcolor = ((cb) >> 3) + (((cg) >> 2) << 5) + (((cr) >> 3) << 11); @@ -1314,9 +1374,22 @@ void R_CreateColormap2(char *p1, char *p2, char *p3) if (p3[0] == '#') { - cdestr = cr = ((HEX2INT(p3[1]) * 16) + HEX2INT(p3[2])); - cdestg = cg = ((HEX2INT(p3[3]) * 16) + HEX2INT(p3[4])); - cdestb = cb = ((HEX2INT(p3[5]) * 16) + HEX2INT(p3[6])); + cr = ((HEX2INT(p3[1]) * 16) + HEX2INT(p3[2])); + cg = ((HEX2INT(p3[3]) * 16) + HEX2INT(p3[4])); + cb = ((HEX2INT(p3[5]) * 16) + HEX2INT(p3[6])); + + // i don't know why this doesn't work... + /*if (encoremap) + { + i = NearestColor(cr, cg, cb); + cr = pLocalPalette[encoremap[i]].s.red; + cg = pLocalPalette[encoremap[i]].s.green; + cb = pLocalPalette[encoremap[i]].s.blue; + }*/ + + cdestr = cr; + cdestg = cg; + cdestb = cb; fadecolor = (((cb) >> 3) + (((cg) >> 2) << 5) + (((cr) >> 3) << 11)); } else @@ -1383,10 +1456,10 @@ void R_CreateColormap2(char *p1, char *p2, char *p3) #define ABS2(x) ((x) < 0 ? -(x) : (x)) if (rendermode == render_soft) { - colormap_p = Z_MallocAlign((256 * 34) + 10, PU_LEVEL, NULL, 8); + colormap_p = Z_MallocAlign((256 * (encoremap ? 64 : 32)) + 10, PU_LEVEL, NULL, 8); extra_colormaps[mapnum].colormap = (UINT8 *)colormap_p; - for (p = 0; p < 34; p++) + for (p = 0; p < 32; p++) { for (i = 0; i < 256; i++) { @@ -1414,6 +1487,21 @@ void R_CreateColormap2(char *p1, char *p2, char *p3) map[i][2] = cdestb; } } + + if (!encoremap) + return; + + colormap_p2 = extra_colormaps[mapnum].colormap; + + for (p = 0; p < 32; p++) + { + for (i = 0; i < 256; i++) + { + *colormap_p = colormap_p2[encoremap[i]]; + colormap_p++; + } + colormap_p2 += 256; + } } #undef ABS2 diff --git a/src/r_data.h b/src/r_data.h index 1e9e0eb5e..fb8756dfc 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -89,7 +89,7 @@ void R_ClearTextureNumCache(boolean btell); INT32 R_TextureNumForName(const char *name); INT32 R_CheckTextureNumForName(const char *name); -void R_ReInitColormaps(UINT16 num); +void R_ReInitColormaps(UINT16 num, lumpnum_t newencoremap); void R_ClearColormaps(void); INT32 R_ColormapNumForName(char *name); INT32 R_CreateColormap(char *p1, char *p2, char *p3); diff --git a/src/r_draw8.c b/src/r_draw8.c index 39585f587..b6efd6cfe 100644 --- a/src/r_draw8.c +++ b/src/r_draw8.c @@ -1379,6 +1379,8 @@ void R_DrawColumnShadowed_8(void) if (height <= dc_yl) { dc_colormap = dc_lightlist[i].rcolormap; + if (encoremap) + dc_colormap += (256*32); if (solid && dc_yl < bheight) dc_yl = bheight; continue; @@ -1395,6 +1397,8 @@ void R_DrawColumnShadowed_8(void) dc_yl = dc_yh + 1; dc_colormap = dc_lightlist[i].rcolormap; + if (encoremap) + dc_colormap += (256*32); } dc_yh = realyh; if (dc_yl <= realyh) diff --git a/src/r_plane.c b/src/r_plane.c index 92e0cacb9..225156393 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -335,6 +335,8 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2) else #endif ds_colormap = planezlight[pindex]; + if (encoremap && !currentplane->noencore) + ds_colormap += (256*32); if (currentplane->extra_colormap) ds_colormap = currentplane->extra_colormap->colormap + (ds_colormap - colormaps); @@ -437,7 +439,7 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, #ifdef ESLOPE , pslope_t *slope #endif - ) + , boolean noencore) { visplane_t *check; unsigned hash; @@ -486,7 +488,7 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, #ifdef ESLOPE && check->slope == slope #endif - ) + && check->noencore == noencore) { return check; } @@ -514,6 +516,7 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, #ifdef ESLOPE check->slope = slope; #endif + check->noencore = noencore; memset(check->top, 0xff, sizeof (check->top)); memset(check->bottom, 0x00, sizeof (check->bottom)); @@ -586,6 +589,7 @@ visplane_t *R_CheckPlane(visplane_t *pl, INT32 start, INT32 stop) #ifdef ESLOPE new_pl->slope = pl->slope; #endif + new_pl->noencore = pl->noencore; pl = new_pl; pl->minx = start; pl->maxx = stop; @@ -703,6 +707,8 @@ void R_DrawPlanes(void) // Because of this hack, sky is not affected // by INVUL inverse mapping. dc_colormap = colormaps; + if (encoremap) + dc_colormap += (256*32); dc_texturemid = skytexturemid; dc_texheight = textureheight[skytexture] >>FRACBITS; diff --git a/src/r_plane.h b/src/r_plane.h index dff58669a..9b25c65e9 100644 --- a/src/r_plane.h +++ b/src/r_plane.h @@ -65,6 +65,8 @@ typedef struct visplane_s #ifdef ESLOPE pslope_t *slope; #endif + + boolean noencore; } visplane_t; extern visplane_t *floorplane; @@ -103,7 +105,7 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, fixed_t #ifdef ESLOPE , pslope_t *slope #endif - ); + , boolean noencore); visplane_t *R_CheckPlane(visplane_t *pl, INT32 start, INT32 stop); void R_ExpandPlane(visplane_t *pl, INT32 start, INT32 stop); void R_PlaneBounds(visplane_t *plane); diff --git a/src/r_segs.c b/src/r_segs.c index 025c920cc..5c09d34e8 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -202,6 +202,8 @@ static void R_DrawWallSplats(void) if (pindex >= MAXLIGHTSCALE) pindex = MAXLIGHTSCALE - 1; dc_colormap = walllights[pindex]; + if (encoremap) + dc_colormap += (256*32); if (frontsector->extra_colormap) dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps); @@ -596,6 +598,8 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) if (height <= windowtop) { dc_colormap = rlight->rcolormap; + if (encoremap) + dc_colormap += (256*32); continue; } @@ -615,6 +619,8 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) colfunc_2s(col); windowtop = windowbottom + 1; dc_colormap = rlight->rcolormap; + if (encoremap) + dc_colormap += (256*32); } windowbottom = realbot; if (windowtop < windowbottom) @@ -631,6 +637,8 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) pindex = MAXLIGHTSCALE - 1; dc_colormap = walllights[pindex]; + if (encoremap) + dc_colormap += (256*32); if (frontsector->extra_colormap) dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps); @@ -1210,7 +1218,11 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) if (height <= windowtop) { if (lighteffect) + { dc_colormap = rlight->rcolormap; + if (encoremap) + dc_colormap += (256*32); + } if (solid && windowtop < bheight) windowtop = bheight; continue; @@ -1236,7 +1248,11 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) else windowtop = windowbottom + 1; if (lighteffect) + { dc_colormap = rlight->rcolormap; + if (encoremap) + dc_colormap += (256*32); + } } windowbottom = sprbotscreen; if (windowtop < windowbottom) @@ -1253,6 +1269,8 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) pindex = MAXLIGHTSCALE - 1; dc_colormap = walllights[pindex]; + if (encoremap) + dc_colormap += (256*32); if (frontsector->extra_colormap) dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps); if (pfloor->flags & FF_FOG && pfloor->master->frontsector->extra_colormap) @@ -1483,6 +1501,8 @@ static void R_RenderSegLoop (void) pindex = MAXLIGHTSCALE-1; dc_colormap = walllights[pindex]; + if (encoremap) + dc_colormap += (256*32); dc_x = rw_x; dc_iscale = 0xffffffffu / (unsigned)rw_scale; diff --git a/src/r_state.h b/src/r_state.h index 8436413bb..a651bda71 100644 --- a/src/r_state.h +++ b/src/r_state.h @@ -38,6 +38,7 @@ typedef struct extern sprcache_t *spritecachedinfo; extern lighttable_t *colormaps; +extern lighttable_t *encoremap; // Boom colormaps. // Had to put a limit on colormaps :( diff --git a/src/r_things.c b/src/r_things.c index ae9358976..d65969136 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -873,6 +873,11 @@ static void R_DrawVisSprite(vissprite_t *vis) if (!dc_colormap) dc_colormap = colormaps; + if (encoremap && !vis->mobj->color + && (vis->mobj->flags & (MF_SCENERY|MF_NOTHINK)) + && !(vis->mobj->flags & ~(MF_SCENERY|MF_NOTHINK|MF_NOCLIP|MF_NOBLOCKMAP|MF_NOGRAVITY))) + dc_colormap += (256*32); + dc_texturemid = vis->texturemid; dc_texheight = 0; @@ -973,6 +978,8 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis) } dc_colormap = colormaps; + if (encoremap) + dc_colormap += (256*32); dc_iscale = FixedDiv(FRACUNIT, vis->scale); dc_texturemid = vis->texturemid; diff --git a/src/s_sound.c b/src/s_sound.c index 44e7e7aea..3c7715d09 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -391,7 +391,7 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume) { INT32 sep, pitch, priority, cnum; sfxinfo_t *sfx; - const boolean reverse = (stereoreverse.value ^ mirrormode); + const boolean reverse = (stereoreverse.value ^ encoremode); const mobj_t *origin = (const mobj_t *)origin_p; listener_t listener = {0,0,0,0}; @@ -1198,7 +1198,7 @@ INT32 S_AdjustSoundParams(const mobj_t *listener, const mobj_t *source, INT32 *v listener_t listensource; - const boolean reverse = (stereoreverse.value ^ mirrormode); + const boolean reverse = (stereoreverse.value ^ encoremode); (void)pitch; if (!listener) diff --git a/src/st_stuff.c b/src/st_stuff.c index 7efbe6d22..5c2c1c030 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -797,15 +797,24 @@ static void ST_drawLevelTitle(void) } { + const char *subttlstr; + dupcalc = (dupcalc - BASEVIDWIDTH)>>1; V_DrawFill(sub - dupcalc, bary+9, ttlnumxpos+dupcalc + 1, 2, 31); V_DrawDiag(sub + ttlnumxpos + 1, bary, 11, 31); V_DrawFill(sub - dupcalc, bary, ttlnumxpos+dupcalc, 10, gtc); V_DrawDiag(sub + ttlnumxpos, bary, 10, gtc); - if (subttl[0]) - V_DrawRightAlignedString(sub + zonexpos - 8, bary+1, V_ALLOWLOWERCASE, subttl); + + if (encoremode) + subttlstr = "Encore Mode"; + else if (subttl[0]) + subttlstr = subttl; + else if (mapheaderinfo[gamemap-1]->menuflags & LF2_HIDEINMENU) + subttlstr = "MAP HELL"; else - V_DrawRightAlignedString(sub + zonexpos - 8, bary+1, V_ALLOWLOWERCASE, va("%s Mode", gametype_cons_t[gametype].strvalue)); + subttlstr = va("%s Mode", gametype_cons_t[gametype].strvalue); + + V_DrawRightAlignedString(sub + zonexpos - 8, bary+1, V_ALLOWLOWERCASE, subttlstr); } ttlnumxpos += sub; diff --git a/src/y_inter.c b/src/y_inter.c index 4c5d9e267..18495bf97 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -93,6 +93,7 @@ typedef union UINT32 val[MAXPLAYERS]; //Gametype-specific value UINT8 pos[MAXPLAYERS]; // player positions. used for ties boolean rankingsmode; // rankings mode + boolean encore; // encore mode } match; } y_data; @@ -204,6 +205,8 @@ static void Y_CalculateMatchData(boolean rankingsmode, void (*comparison)(INT32) if ((data.match.rankingsmode = rankingsmode)) sprintf(data.match.levelstring, "* Total Rankings *"); + data.match.encore = (!rankingsmode && encoremode); + for (i = 0; i < MAXPLAYERS; i++) { data.match.val[i] = UINT32_MAX; @@ -379,6 +382,9 @@ void Y_IntermissionDrawer(void) V_DrawCenteredString(-4 + x + BASEVIDWIDTH/2, 20, 0, data.match.levelstring); V_DrawFill(x, 42, 312, 1, 0); + if (data.match.encore) + V_DrawCenteredString(-4 + x + BASEVIDWIDTH/2, 20-8, hilicol, "ENCORE MODE"); + if (data.match.numplayers > 8) { V_DrawFill(160, 32, 1, 152, 0); From 829674aa6d40edbccf44886e70bf7cffee93b195 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 8 Aug 2018 15:03:02 +0100 Subject: [PATCH 003/146] Encore mode is shippable, if still a tad incomplete! * Turns out the Linedef Type 606 support WAS working and I just had a bad MAP01E lump. * Ruby fade and ambience start track. * Fix bad phrasing. --- src/d_netcmd.c | 2 +- src/p_setup.c | 87 +++++++++++++++++++++++++++----------------------- src/p_user.c | 2 +- src/r_data.c | 53 +++++++++++++++--------------- src/sounds.c | 2 ++ src/sounds.h | 2 ++ 6 files changed, 78 insertions(+), 70 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index e6ff6a423..e1e0a6353 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -5252,7 +5252,7 @@ static void KartEncore_OnChange(void) CONS_Printf(M_GetText("Encore tracks will be turned %s next round.\n"), cv_kartencore.value ? M_GetText("on") : M_GetText("off")); else { - CONS_Printf(M_GetText("Encore tracks has been turned %s.\n"), cv_kartencore.value ? M_GetText("on") : M_GetText("off")); + CONS_Printf(M_GetText("Encore tracks have been turned %s.\n"), cv_kartencore.value ? M_GetText("on") : M_GetText("off")); encoremode = (boolean)cv_kartencore.value; } } diff --git a/src/p_setup.c b/src/p_setup.c index 30e882d5a..196eb5c72 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2244,6 +2244,33 @@ static void P_LevelInitStuff(void) // and this stupid flag as a result players[i].pflags &= ~PF_TRANSFERTOCLOSEST; } + + // SRB2Kart: map load variables + if (modeattacking) // Just play it safe and set everything + { + gamespeed = 2; + encoremode = false; + franticitems = false; + comeback = true; + } + else + { + if (G_BattleGametype()) + { + gamespeed = 0; + encoremode = false; + } + else + { + gamespeed = (UINT8)cv_kartspeed.value; + encoremode = (boolean)cv_kartencore.value; + } + franticitems = (boolean)cv_kartfrantic.value; + comeback = (boolean)cv_kartcomeback.value; + } + + for (i = 0; i < 4; i++) + battlewanted[i] = -1; } // @@ -2618,23 +2645,31 @@ boolean P_SetupLevel(boolean skipprecip) // will be set by player think. players[consoleplayer].viewz = 1; - // Special stage fade to white + // Encore mode fade to pink to white // This is handled BEFORE sounds are stopped. - /*if (rendermode != render_none && G_IsSpecialStage(gamemap)) + if (rendermode != render_none && encoremode) { - tic_t starttime = I_GetTime(); - tic_t endtime = starttime + (3*TICRATE)/2; - tic_t nowtime; + tic_t starttime, endtime, nowtime; - S_StartSound(NULL, sfx_s3kaf); + S_StopMusic(); // er, about that... + + S_StartSound(NULL, sfx_ruby1); F_WipeStartScreen(); - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 0); + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 122); F_WipeEndScreen(); F_RunWipe(wipedefs[wipe_speclevel_towhite], false); - nowtime = lastwipetic; + F_WipeStartScreen(); + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 120); + + F_WipeEndScreen(); + F_RunWipe(wipedefs[wipe_level_final], false); + + starttime = nowtime = lastwipetic; + endtime = starttime + (3*TICRATE)/2; + // Hold on white for extra effect. while (nowtime < endtime) { @@ -2647,23 +2682,22 @@ boolean P_SetupLevel(boolean skipprecip) } ranspecialwipe = 1; - }*/ + } // Make sure all sounds are stopped before Z_FreeTags. S_StopSounds(); S_ClearSfx(); - // As oddly named as this is, this handles music only. // We should be fine starting it here. S_Start(); // SRB2 Kart - Yes this is weird, but we don't want the music to start until after the countdown is finished // but we do still need the mapmusname to be changed if (leveltime < (starttime + (TICRATE/2))) - S_ChangeMusicInternal("kstart", false); //S_StopMusic(); + S_ChangeMusicInternal((encoremode ? "estart" : "kstart"), false); //S_StopMusic(); - // Let's fade to black here - // But only if we didn't do the special stage wipe + // Let's fade to white here + // But only if we didn't do the encore wipe if (rendermode != render_none && !ranspecialwipe) { F_WipeStartScreen(); @@ -2726,33 +2760,6 @@ boolean P_SetupLevel(boolean skipprecip) // internal game map lastloadedmaplumpnum = W_GetNumForName(maplumpname = G_BuildMapName(gamemap)); - // SRB2Kart: map load variables - if (modeattacking) // Just play it safe and set everything - { - gamespeed = 2; - encoremode = false; - franticitems = false; - comeback = true; - } - else - { - if (G_BattleGametype()) - { - gamespeed = 0; - encoremode = false; - } - else - { - gamespeed = (UINT8)cv_kartspeed.value; - encoremode = (boolean)cv_kartencore.value; - } - franticitems = (boolean)cv_kartfrantic.value; - comeback = (boolean)cv_kartcomeback.value; - } - - for (i = 0; i < 4; i++) - battlewanted[i] = -1; - R_ReInitColormaps(mapheaderinfo[gamemap-1]->palette, (encoremode ? W_CheckNumForName(va("%sE", maplumpname)) : LUMPERROR)); CON_SetupBackColormap(); diff --git a/src/p_user.c b/src/p_user.c index 8f0f3dec8..771161b30 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1221,7 +1221,7 @@ void P_RestoreMusic(player_t *player) // Event - Level Start if (leveltime < (starttime + (TICRATE/2))) - S_ChangeMusicInternal("kstart", false); //S_StopMusic(); + S_ChangeMusicInternal((encoremode ? "estart" : "kstart"), false); //S_StopMusic(); else // see also where time overs are handled - search for "lives = 2" in this file { // Item - Grow diff --git a/src/r_data.c b/src/r_data.c index 4719b908f..1e2bc628b 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1151,14 +1151,14 @@ INT32 R_CreateColormap(char *p1, char *p2, char *p3) cg = ((HEX2INT(p1[3]) * 16) + HEX2INT(p1[4])); cb = ((HEX2INT(p1[5]) * 16) + HEX2INT(p1[6])); - // i don't know why this doesn't work... - /*if (encoremap) + if (encoremap) { - i = NearestColor(cr, cg, cb); - cr = pLocalPalette[encoremap[i]].s.red; - cg = pLocalPalette[encoremap[i]].s.green; - cb = pLocalPalette[encoremap[i]].s.blue; - }*/ + i = encoremap[NearestColor((UINT8)cr, (UINT8)cg, (UINT8)cb)]; + //CONS_Printf("R_CreateColormap: encoremap[%d] = %d\n", i, encoremap[i]); -- moved encoremap upwards for optimisation + cr = pLocalPalette[i].s.red; + cg = pLocalPalette[i].s.green; + cb = pLocalPalette[i].s.blue; + } cmaskr = cr; cmaskg = cg; @@ -1208,14 +1208,13 @@ INT32 R_CreateColormap(char *p1, char *p2, char *p3) cg = ((HEX2INT(p3[3]) * 16) + HEX2INT(p3[4])); cb = ((HEX2INT(p3[5]) * 16) + HEX2INT(p3[6])); - // i don't know why this doesn't work... - /*if (encoremap) + if (encoremap) { - i = NearestColor(cr, cg, cb); - cr = pLocalPalette[encoremap[i]].s.red; - cg = pLocalPalette[encoremap[i]].s.green; - cb = pLocalPalette[encoremap[i]].s.blue; - }*/ + i = encoremap[NearestColor((UINT8)cr, (UINT8)cg, (UINT8)cb)]; + cr = pLocalPalette[i].s.red; + cg = pLocalPalette[i].s.green; + cb = pLocalPalette[i].s.blue; + } cdestr = cr; cdestg = cg; @@ -1321,14 +1320,13 @@ void R_CreateColormap2(char *p1, char *p2, char *p3) cg = ((HEX2INT(p1[3]) * 16) + HEX2INT(p1[4])); cb = ((HEX2INT(p1[5]) * 16) + HEX2INT(p1[6])); - // i don't know why this doesn't work... - /*if (encoremap) + if (encoremap) { - i = NearestColor(cr, cg, cb); - cr = pLocalPalette[encoremap[i]].s.red; - cg = pLocalPalette[encoremap[i]].s.green; - cb = pLocalPalette[encoremap[i]].s.blue; - }*/ + i = encoremap[NearestColor((UINT8)cr, (UINT8)cg, (UINT8)cb)]; + cr = pLocalPalette[i].s.red; + cg = pLocalPalette[i].s.green; + cb = pLocalPalette[i].s.blue; + } cmaskr = cr; cmaskg = cg; @@ -1378,14 +1376,13 @@ void R_CreateColormap2(char *p1, char *p2, char *p3) cg = ((HEX2INT(p3[3]) * 16) + HEX2INT(p3[4])); cb = ((HEX2INT(p3[5]) * 16) + HEX2INT(p3[6])); - // i don't know why this doesn't work... - /*if (encoremap) + if (encoremap) { - i = NearestColor(cr, cg, cb); - cr = pLocalPalette[encoremap[i]].s.red; - cg = pLocalPalette[encoremap[i]].s.green; - cb = pLocalPalette[encoremap[i]].s.blue; - }*/ + i = encoremap[NearestColor((UINT8)cr, (UINT8)cg, (UINT8)cb)]; + cr = pLocalPalette[i].s.red; + cg = pLocalPalette[i].s.green; + cb = pLocalPalette[i].s.blue; + } cdestr = cr; cdestg = cg; diff --git a/src/sounds.c b/src/sounds.c index 3b41dfa10..984f5a57d 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -809,6 +809,8 @@ sfxinfo_t S_sfx[NUMSFX] = {"yeeeah", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"noooo1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"noooo2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"ruby1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"ruby2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"hogbom", false, 110, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // SRB2kart - Skin sounds diff --git a/src/sounds.h b/src/sounds.h index 0f8d5a3b7..210feba7d 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -881,6 +881,8 @@ typedef enum sfx_yeeeah, sfx_noooo1, sfx_noooo2, + sfx_ruby1, + sfx_ruby2, sfx_hogbom, sfx_kwin, From 36ec90ed21d1cbd75ca0baaf24112883332a703d Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 8 Aug 2018 20:48:29 +0100 Subject: [PATCH 004/146] * Make Encore Mode an unlockable, rather than freely available. * Make unlockables have a "showing" conditionset, for when you're able to see them on the Extras screen. * A shorter Encore ruby-pulse fade, for when encore mode is already active! --- src/command.c | 7 +++++++ src/d_netcmd.c | 8 ++++---- src/dehacked.c | 6 ++++-- src/m_cond.c | 16 +++++++++++----- src/m_cond.h | 4 +++- src/m_menu.c | 8 ++++++-- src/p_setup.c | 14 +++++++++----- 7 files changed, 44 insertions(+), 19 deletions(-) diff --git a/src/command.c b/src/command.c index 305a5eeeb..54406adeb 100644 --- a/src/command.c +++ b/src/command.c @@ -28,6 +28,7 @@ #include "byteptr.h" #include "p_saveg.h" #include "g_game.h" // for player_names +#include "m_cond.h" // for encore mode #include "d_netcmd.h" #include "hu_stuff.h" #include "p_setup.h" @@ -1373,6 +1374,12 @@ static void CV_SetCVar(consvar_t *var, const char *value, boolean stealth) return; } + if (var == &cv_kartencore && !M_SecretUnlocked(SECRET_ENCORE)) + { + CONS_Printf(M_GetText("You haven't unlocked Encore Mode yet!\n")); + return; + } + // Only add to netcmd buffer if in a netgame, otherwise, just change it. if (netgame || multiplayer) { diff --git a/src/d_netcmd.c b/src/d_netcmd.c index e1e0a6353..a504453e5 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -352,7 +352,7 @@ static CV_PossibleValue_t kartbumpers_cons_t[] = {{1, "MIN"}, {12, "MAX"}, {0, N consvar_t cv_kartbumpers = {"kartbumpers", "3", CV_NETVAR|CV_CHEAT, kartbumpers_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_kartfrantic = {"kartfrantic", "Off", CV_NETVAR|CV_CHEAT|CV_CALL|CV_NOINIT, CV_OnOff, KartFrantic_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_kartcomeback = {"kartcomeback", "On", CV_NETVAR|CV_CHEAT|CV_CALL|CV_NOINIT, CV_OnOff, KartComeback_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_kartencore = {"kartencore", "Off", CV_NETVAR|CV_CHEAT|CV_CALL|CV_NOINIT, CV_OnOff, KartEncore_OnChange, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_kartencore = {"kartencore", "Off", CV_NETVAR|CV_CALL|CV_NOINIT, CV_OnOff, KartEncore_OnChange, 0, NULL, NULL, 0, 0, NULL}; static CV_PossibleValue_t kartspeedometer_cons_t[] = {{0, "Off"}, {1, "Kilometers"}, {2, "Miles"}, {3, "Fracunits"}, {0, NULL}}; consvar_t cv_kartspeedometer = {"kartdisplayspeed", "Off", CV_SAVE, kartspeedometer_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; // use tics in display static CV_PossibleValue_t kartvoices_cons_t[] = {{0, "Never"}, {1, "Tasteful"}, {2, "Meme"}, {0, NULL}}; @@ -5249,11 +5249,11 @@ static void KartEncore_OnChange(void) if (G_RaceGametype()) { if ((boolean)cv_kartencore.value != encoremode && gamestate == GS_LEVEL /*&& leveltime > starttime*/) - CONS_Printf(M_GetText("Encore tracks will be turned %s next round.\n"), cv_kartencore.value ? M_GetText("on") : M_GetText("off")); + CONS_Printf(M_GetText("Encore Mode will be turned %s next round.\n"), cv_kartencore.value ? M_GetText("on") : M_GetText("off")); else { - CONS_Printf(M_GetText("Encore tracks have been turned %s.\n"), cv_kartencore.value ? M_GetText("on") : M_GetText("off")); - encoremode = (boolean)cv_kartencore.value; + CONS_Printf(M_GetText("Encore Mode has been turned %s.\n"), cv_kartencore.value ? M_GetText("on") : M_GetText("off")); + //encoremode = (boolean)cv_kartencore.value; } } } diff --git a/src/dehacked.c b/src/dehacked.c index 8fcf597df..15586934d 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -2384,8 +2384,8 @@ static void readunlockable(MYFILE *f, INT32 num) else if (fastcmp(word, "OBJECTIVE")) deh_strlcpy(unlockables[num].objective, word2, sizeof (unlockables[num].objective), va("Unlockable %d: objective", num)); - else if (fastcmp(word, "HEIGHT")) - unlockables[num].height = (UINT16)i; + else if (fastcmp(word, "SHOWCONDITIONSET")) + unlockables[num].showconditionset = (UINT8)i; else if (fastcmp(word, "CONDITIONSET")) unlockables[num].conditionset = (UINT8)i; else if (fastcmp(word, "NOCECHO")) @@ -2416,6 +2416,8 @@ static void readunlockable(MYFILE *f, INT32 num) unlockables[num].type = SECRET_WARP; else if (fastcmp(word2, "SOUNDTEST")) unlockables[num].type = SECRET_SOUNDTEST; + else if (fastcmp(word2, "ENCORE")) + unlockables[num].type = SECRET_ENCORE; else unlockables[num].type = (INT16)i; } diff --git a/src/m_cond.c b/src/m_cond.c index 7d07d00ad..63f88cb61 100644 --- a/src/m_cond.c +++ b/src/m_cond.c @@ -96,12 +96,14 @@ extraemblem_t extraemblems[MAXEXTRAEMBLEMS] = // Default Unlockables unlockable_t unlockables[MAXUNLOCKABLES] = { - // Name, Objective, Menu Height, ConditionSet, Unlock Type, Variable, NoCecho, NoChecklist - /* 01 */ {"Egg Cup", "", 0, 1, SECRET_NONE, 0, false, false, 0}, - /* 02 */ {"SMK Cup", "", 0, 2, SECRET_NONE, 0, false, false, 0}, - /* 03 */ {"Chao Cup", "", 0, 3, SECRET_NONE, 0, false, false, 0}, + // Name, Objective, Showing Conditionset, ConditionSet, Unlock Type, Variable, NoCecho, NoChecklist + /* 01 */ {"Egg Cup", "", -1, 1, SECRET_NONE, 0, false, false, 0}, + /* 02 */ {"SMK Cup", "", -1, 2, SECRET_NONE, 0, false, false, 0}, + /* 03 */ {"Chao Cup", "", -1, 3, SECRET_NONE, 0, false, false, 0}, - /* 04 */ {"Record Attack", "", 0, -1, SECRET_RECORDATTACK, 0, true, true, 0}, + /* 04 */ {"Encore Mode", "", 3, 4, SECRET_ENCORE, 0, false, false, 0}, + + /* 05 */ {"Record Attack", "", -1, -1, SECRET_RECORDATTACK, 0, true, true, 0}, }; // Default number of emblems and extra emblems @@ -125,6 +127,10 @@ void M_SetupDefaultConditionSets(void) M_AddRawCondition(3, 1, UC_TOTALEMBLEMS, 30, 0, 0); M_AddRawCondition(3, 2, UC_MATCHESPLAYED, 50, 0, 0); + // -- 4: Collect 50 emblems OR play 150 matches + M_AddRawCondition(4, 1, UC_TOTALEMBLEMS, 50, 0, 0); + M_AddRawCondition(4, 2, UC_MATCHESPLAYED, 150, 0, 0); + // -- 10: Play 100 matches M_AddRawCondition(10, 1, UC_MATCHESPLAYED, 100, 0, 0); } diff --git a/src/m_cond.h b/src/m_cond.h index 052c31f2f..5c8762ad8 100644 --- a/src/m_cond.h +++ b/src/m_cond.h @@ -103,7 +103,7 @@ typedef struct { char name[64]; char objective[64]; - UINT16 height; // menu height + UINT8 showconditionset; UINT8 conditionset; INT16 type; INT16 variable; @@ -112,6 +112,7 @@ typedef struct UINT8 unlocked; } unlockable_t; +// I have NO idea why these are going negative, but whatever. #define SECRET_NONE -6 // Does nil. Use with levels locked by UnlockRequired #define SECRET_ITEMFINDER -5 // Enables Item Finder/Emblem Radar #define SECRET_EMBLEMHINTS -4 // Enables Emblem Hints @@ -123,6 +124,7 @@ typedef struct #define SECRET_WARP 2 // Selectable warp #define SECRET_SOUNDTEST 3 // Sound Test #define SECRET_CREDITS 4 // Enables Credits +#define SECRET_ENCORE 5 // Enables Encore mode cvar // If you have more secrets than these variables allow in your game, // you seriously need to get a life. diff --git a/src/m_menu.c b/src/m_menu.c index 3e12c65d7..07a2a9c3c 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1444,7 +1444,7 @@ static menuitem_t OP_GameOptionsMenu[] = {IT_STRING | IT_CVAR, NULL, "Game Speed", &cv_kartspeed, 30}, {IT_STRING | IT_CVAR, NULL, "Frantic Items", &cv_kartfrantic, 40}, - {IT_STRING | IT_CVAR, NULL, "Encore Mode", &cv_kartencore, 50}, + {IT_SECRET, NULL, "Encore Mode", &cv_kartencore, 50}, {IT_STRING | IT_CVAR, NULL, "Number of Laps", &cv_basenumlaps, 70}, {IT_STRING | IT_CVAR, NULL, "Exit Countdown Timer", &cv_countdowntime, 80}, @@ -4311,6 +4311,9 @@ static void M_Options(INT32 choice) OP_MainMenu[7].status = (Playing()) ? (IT_GRAYEDOUT) : (IT_STRING|IT_CALL); OP_MainMenu[8].status = (Playing()) ? (IT_GRAYEDOUT) : (IT_STRING|IT_SUBMENU); + OP_GameOptionsMenu[3].status = + (M_SecretUnlocked(SECRET_ENCORE)) ? (IT_CVAR|IT_STRING) : IT_SECRET; // cv_kartencore + OP_MainDef.prevMenu = currentMenu; M_SetupNextMenu(&OP_MainDef); } @@ -4463,7 +4466,8 @@ static void M_DrawChecklist(void) for (i = 0; i < MAXUNLOCKABLES; i++) { if (unlockables[i].name[0] == 0 || unlockables[i].nochecklist - || !unlockables[i].conditionset || unlockables[i].conditionset > MAXCONDITIONSETS) + || !unlockables[i].conditionset || unlockables[i].conditionset > MAXCONDITIONSETS + || !M_Achieved(unlockables[i].showconditionset - 1)) continue; ++line; diff --git a/src/p_setup.c b/src/p_setup.c index 196eb5c72..39a26260c 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -136,6 +136,8 @@ mapthing_t *playerstarts[MAXPLAYERS]; mapthing_t *bluectfstarts[MAXPLAYERS]; mapthing_t *redctfstarts[MAXPLAYERS]; +boolean prevencoremode = false; + /** Logs an error about a map being corrupt, then terminate. * This allows reporting highly technical errors for usefulness, without * confusing a novice map designer who simply needs to run ZenNode. @@ -2245,6 +2247,8 @@ static void P_LevelInitStuff(void) players[i].pflags &= ~PF_TRANSFERTOCLOSEST; } + prevencoremode = ((wipegamestate == GS_TITLESCREEN) ? false : encoremode); + // SRB2Kart: map load variables if (modeattacking) // Just play it safe and set everything { @@ -2647,7 +2651,7 @@ boolean P_SetupLevel(boolean skipprecip) // Encore mode fade to pink to white // This is handled BEFORE sounds are stopped. - if (rendermode != render_none && encoremode) + if (rendermode != render_none && encoremode && !prevencoremode) { tic_t starttime, endtime, nowtime; @@ -2697,14 +2701,14 @@ boolean P_SetupLevel(boolean skipprecip) S_ChangeMusicInternal((encoremode ? "estart" : "kstart"), false); //S_StopMusic(); // Let's fade to white here - // But only if we didn't do the encore wipe + // But only if we didn't do the encore startup wipe if (rendermode != render_none && !ranspecialwipe) { F_WipeStartScreen(); - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 120); + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (encoremode ? 122 : 120)); F_WipeEndScreen(); - F_RunWipe(wipedefs[wipe_level_toblack], false); + F_RunWipe(wipedefs[(encoremode ? wipe_level_final : wipe_level_toblack)], false); } // Reset the palette now all fades have been done @@ -3045,7 +3049,7 @@ boolean P_SetupLevel(boolean skipprecip) // Remove the loading shit from the screen if (rendermode != render_none) - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 120); + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (encoremode && !ranspecialwipe ? 122 : 120)); if (precache || dedicated) R_PrecacheLevel(); From eac0af999d16bd2ee844ae37bfdc845d63b9d7c4 Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 10 Aug 2018 19:31:30 +0100 Subject: [PATCH 005/146] More control over what stuff get Encore mapping applied to it, with sensible defaults so you don't have to do much to your map to get it to be supported! * Objects! * Gone is the arcane, difficult-to-remember list of random flags. Say hello to MF_DONTENCOREMAP! * Alternatively, if the object has a skincolour applied to it, it isn't encoremapped either. (Useful for ghosts, for example.) * Sectors! * The autodetecting of sneaker and spring panels is now much more intelligent, and only avoids remapping the plane(s) the effect is availible upon. * Sector special group 2 no. 15 is now "Invert Encore Remap". It inverts the above detection. * Linedefs! * The "Transfer Line" linedef flag can now also be used to deny Encore remappings on linedef textures. * Right now it applies to every pixel drawn specifically belonging to that linedef, but if people decide it needs changing, we CAN make it apply to midtextures only (like linedef types 900-910). --- src/dehacked.c | 1 + src/info.c | 180 ++++++++++++++++++++++++------------------------- src/p_mobj.h | 4 +- src/p_spec.c | 2 + src/r_bsp.c | 31 +++++---- src/r_segs.c | 16 ++--- src/r_things.c | 4 +- 7 files changed, 124 insertions(+), 114 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 5ef770d3e..af72719bd 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -7367,6 +7367,7 @@ static const char *const MOBJFLAG_LIST[] = { "NOCLIPTHING", "GRENADEBOUNCE", "RUNSPAWNFUNC", + "DONTENCOREMAP", NULL }; diff --git a/src/info.c b/src/info.c index b8fc81825..5c3de1238 100644 --- a/src/info.c +++ b/src/info.c @@ -3028,7 +3028,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // mass 0, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags + MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -3055,7 +3055,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // mass 0, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -3082,7 +3082,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 16, // mass 0, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -3109,7 +3109,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 1000, // mass MT_THOK, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE, // flags + MF_SOLID|MF_SHOOTABLE|MF_DONTENCOREMAP, // flags (statenum_t)MT_THOK // raisestate }, @@ -5135,7 +5135,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_SLIDEME|MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags + MF_SLIDEME|MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -5162,7 +5162,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_SLIDEME|MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags + MF_SLIDEME|MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -5189,7 +5189,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_None, // activesound - MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags + MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -5216,7 +5216,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_NOGRAVITY|MF_NOBLOCKMAP|MF_NOCLIP, // flags + MF_NOGRAVITY|MF_NOBLOCKMAP|MF_NOCLIP|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -5243,7 +5243,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 16, // mass 0, // damage sfx_None, // activesound - MF_SPECIAL, // flags + MF_SPECIAL|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -5270,7 +5270,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 16, // mass 0, // damage sfx_None, // activesound - MF_SPECIAL, // flags + MF_SPECIAL|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -5297,7 +5297,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 4, // mass 0, // damage sfx_None, // activesound - MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags + MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -5324,7 +5324,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 16, // mass 0, // damage sfx_None, // activesound - MF_NOGRAVITY|MF_SPECIAL, // flags + MF_NOGRAVITY|MF_SPECIAL|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, { // MT_EMERALD2 @@ -5350,7 +5350,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 16, // mass 0, // damage sfx_None, // activesound - MF_NOGRAVITY|MF_SPECIAL, // flags + MF_NOGRAVITY|MF_SPECIAL|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, { // MT_EMERALD3 @@ -5376,7 +5376,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 16, // mass 0, // damage sfx_None, // activesound - MF_NOGRAVITY|MF_SPECIAL, // flags + MF_NOGRAVITY|MF_SPECIAL|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, { // MT_EMERALD4 @@ -5402,7 +5402,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 16, // mass 0, // damage sfx_None, // activesound - MF_NOGRAVITY|MF_SPECIAL, // flags + MF_NOGRAVITY|MF_SPECIAL|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, { // MT_EMERALD5 @@ -5428,7 +5428,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 16, // mass 0, // damage sfx_None, // activesound - MF_NOGRAVITY|MF_SPECIAL, // flags + MF_NOGRAVITY|MF_SPECIAL|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, { // MT_EMERALD6 @@ -5454,7 +5454,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 16, // mass 0, // damage sfx_None, // activesound - MF_NOGRAVITY|MF_SPECIAL, // flags + MF_NOGRAVITY|MF_SPECIAL|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, { // MT_EMERALD7 @@ -5480,7 +5480,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 16, // mass 0, // damage sfx_None, // activesound - MF_NOGRAVITY|MF_SPECIAL, // flags + MF_NOGRAVITY|MF_SPECIAL|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -5507,7 +5507,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 4, // mass 0, // damage sfx_None, // activesound - MF_SPECIAL|MF_NOGRAVITY, // flags + MF_SPECIAL|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -5561,7 +5561,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_SLIDEME|MF_SPECIAL, // flags + MF_SLIDEME|MF_SPECIAL|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -5615,7 +5615,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 20*FRACUNIT, // mass 0, // damage sfx_None, // activesound - MF_SOLID, // flags + MF_SOLID|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -5642,7 +5642,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 14*FRACUNIT, // mass 0, // damage sfx_None, // activesound - MF_SOLID|MF_SPRING, // flags + MF_SOLID|MF_SPRING|MF_DONTENCOREMAP, // flags S_BLUESPRING2 // raisestate }, @@ -5669,7 +5669,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 26*FRACUNIT, // mass 0, // damage sfx_None, // activesound - MF_SOLID|MF_SPRING, // flags + MF_SOLID|MF_SPRING|MF_DONTENCOREMAP, // flags S_YELLOWSPRING2 // raisestate }, @@ -5696,7 +5696,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 40*FRACUNIT, // mass 0, // damage sfx_None, // activesound - MF_SOLID|MF_SPRING, // flags + MF_SOLID|MF_SPRING|MF_DONTENCOREMAP, // flags S_REDSPRING2 // raisestate }, @@ -5723,7 +5723,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 26*FRACUNIT, // mass 26*FRACUNIT, // damage sfx_None, // activesound - MF_SOLID|MF_SPRING, // flags + MF_SOLID|MF_SPRING|MF_DONTENCOREMAP, // flags S_YDIAG2 // raisestate }, @@ -5750,7 +5750,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 40*FRACUNIT, // mass 40*FRACUNIT, // damage sfx_None, // activesound - MF_SOLID|MF_SPRING, // flags + MF_SOLID|MF_SPRING|MF_DONTENCOREMAP, // flags S_RDIAG2 // raisestate }, @@ -5804,7 +5804,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 16, // mass 0, // damage sfx_None, // activesound - MF_NOCLIP|MF_SCENERY, // flags + MF_NOCLIP|MF_SCENERY|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -5912,7 +5912,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 4, // mass 0, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOGRAVITY|MF_SCENERY|MF_NOCLIPHEIGHT, // flags + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_SCENERY|MF_NOCLIPHEIGHT, // flags S_NULL // raisestate }, @@ -8022,7 +8022,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_None, // activesound - MF_NOGRAVITY|MF_SPECIAL|MF_NOCLIPHEIGHT, // flags + MF_NOGRAVITY|MF_SPECIAL|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -8049,7 +8049,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_None, // activesound - MF_NOGRAVITY|MF_SPECIAL|MF_NOCLIPHEIGHT, // flags + MF_NOGRAVITY|MF_SPECIAL|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -8076,7 +8076,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_mswing, // activesound - MF_PAIN|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags + MF_PAIN|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -8103,7 +8103,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_mswing, // activesound - MF_PAIN|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags + MF_PAIN|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -10482,7 +10482,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 16, // mass 0, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY, // flags + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -10509,7 +10509,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -10753,7 +10753,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY|MF_SCENERY, // flags + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -10942,7 +10942,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 4, // mass 0, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_NOCLIP, // flags + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_NOCLIP|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -14277,7 +14277,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 6*FRACUNIT, // mass 0, // damage sfx_None, // activesound - MF_SOLID|MF_SPRING, // flags + MF_SOLID|MF_SPRING|MF_DONTENCOREMAP, // flags S_GRAYSPRING2 // raisestate }, @@ -14331,7 +14331,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 14*FRACUNIT, // mass 14*FRACUNIT, // damage sfx_None, // activesound - MF_SOLID|MF_SPRING, // flags + MF_SOLID|MF_SPRING|MF_DONTENCOREMAP, // flags S_BDIAG2 // raisestate }, @@ -14358,7 +14358,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_RANDOMITEMPOP, // damage sfx_None, // activesound - MF_SLIDEME|MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags + MF_SLIDEME|MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -14385,7 +14385,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = MT_EXPLODE, // mass 0, // damage sfx_None, // activesound - MF_NOCLIP, // flags + MF_NOCLIP|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -14412,7 +14412,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY|MF_SLIDEME, // flags + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY|MF_SLIDEME|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -14439,7 +14439,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -14466,7 +14466,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY, // flags + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -14493,7 +14493,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -14520,7 +14520,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 16, // mass 0, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -14547,7 +14547,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_FLOAT|MF_SCENERY, // flags + MF_NOBLOCKMAP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_FLOAT|MF_SCENERY|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -14574,7 +14574,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_None, // activesound - MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY, // flags + MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -14601,7 +14601,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_fake, // activesound - MF_BOUNCE|MF_SHOOTABLE, // flags + MF_BOUNCE|MF_SHOOTABLE|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -14628,7 +14628,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_peel, // activesound - MF_BOUNCE|MF_SHOOTABLE, // flags + MF_BOUNCE|MF_SHOOTABLE|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -14655,7 +14655,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_None, // activesound - MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY, // flags + MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -14682,7 +14682,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_s3k96, // activesound - MF_SHOOTABLE|MF_BOUNCE, // flags + MF_SHOOTABLE|MF_BOUNCE|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -14709,7 +14709,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_None, // activesound - MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY, // flags + MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -14736,7 +14736,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_s3kc0s, // activesound - MF_SHOOTABLE, // flags + MF_SHOOTABLE|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -14763,7 +14763,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_s3kc0s, // activesound - MF_SHOOTABLE, // flags + MF_SHOOTABLE|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -14790,7 +14790,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_None, // activesound - MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY, // flags + MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -14817,7 +14817,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_s3k5c, // activesound - MF_BOUNCE|MF_SHOOTABLE, // flags + MF_BOUNCE|MF_SHOOTABLE|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -14844,7 +14844,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_None, // activesound - MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY, // flags + MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -14871,7 +14871,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_SOLID|MF_NOGRAVITY, // flags + MF_SOLID|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -14925,7 +14925,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // mass 0, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_SCENERY, // flags + MF_NOBLOCKMAP|MF_SCENERY|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -14952,7 +14952,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // mass 0, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOGRAVITY|MF_BOUNCE|MF_SCENERY, // flags + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_BOUNCE|MF_SCENERY|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -14979,7 +14979,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // mass 0, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_BOUNCE|MF_SCENERY, // flags + MF_NOBLOCKMAP|MF_BOUNCE|MF_SCENERY|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -15006,7 +15006,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_None, // activesound - MF_SHOOTABLE|MF_BOUNCE, // flags + MF_SHOOTABLE|MF_BOUNCE|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -15033,7 +15033,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_None, // activesound - MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING, // flags + MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -15060,7 +15060,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 16, // mass 0, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY|MF_SCENERY, // flags + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -15087,7 +15087,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_None, // activesound - MF_BOUNCE|MF_FLOAT|MF_NOCLIPTHING|MF_MISSILE|MF_SHOOTABLE, // flags + MF_BOUNCE|MF_FLOAT|MF_NOCLIPTHING|MF_MISSILE|MF_SHOOTABLE|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -15114,7 +15114,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 16, // mass 0, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY|MF_SCENERY, // flags + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -15141,7 +15141,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 16, // mass 0, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY, // flags + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -15168,7 +15168,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_bomb, // activesound - MF_BOUNCE|MF_SHOOTABLE, // flags + MF_BOUNCE|MF_SHOOTABLE|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -15195,7 +15195,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_SCENERY, // flags + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_SCENERY|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -15222,7 +15222,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_NOGRAVITY|MF_SCENERY, // flags + MF_NOBLOCKMAP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -15249,7 +15249,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 16, // mass 0, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_NOGRAVITY|MF_SCENERY, // flags + MF_NOBLOCKMAP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -15357,7 +15357,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags + MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -15384,7 +15384,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 1000, // mass 0, // damage sfx_None, // activesound - 2, // flags + MF_NOTHINK|MF_NOBLOCKMAP|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -15411,7 +15411,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 1000, // mass 0, // damage sfx_None, // activesound - 2, // flags + MF_NOTHINK|MF_NOBLOCKMAP|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -15438,7 +15438,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 1000, // mass 0, // damage sfx_None, // activesound - 2, // flags + MF_NOTHINK|MF_NOBLOCKMAP|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -15465,7 +15465,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 1000, // mass 0, // damage sfx_None, // activesound - 2, // flags + MF_NOTHINK|MF_NOBLOCKMAP|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -15492,7 +15492,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 1000, // mass 0, // damage sfx_None, // activesound - 2, // flags + MF_NOTHINK|MF_NOBLOCKMAP|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -15519,7 +15519,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 1000, // mass 0, // damage sfx_None, // activesound - 2, // flags + MF_NOTHINK|MF_NOBLOCKMAP|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -15546,7 +15546,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 1000, // mass 0, // damage sfx_None, // activesound - 2, // flags + MF_NOTHINK|MF_NOBLOCKMAP|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -15573,7 +15573,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 1000, // mass 0, // damage sfx_None, // activesound - 2, // flags + MF_NOTHINK|MF_NOBLOCKMAP|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -16626,7 +16626,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_NOGRAVITY|MF_SCENERY|MF_NOCLIP|MF_NOCLIPHEIGHT, // flags + MF_NOGRAVITY|MF_SCENERY|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -16653,7 +16653,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT, // flags + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -16680,7 +16680,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_clash, // activesound - MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_SCENERY|MF_RUNSPAWNFUNC, // flags + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_SCENERY|MF_RUNSPAWNFUNC|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -16707,7 +16707,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_SCENERY, // flags + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_SCENERY|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -16734,7 +16734,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT, // flags + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -16761,7 +16761,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT, // flags + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -16788,7 +16788,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 16, // mass 0, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -16815,7 +16815,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 16, // mass 0, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -16842,7 +16842,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // mass 0, // damage sfx_None, // activesound - MF_SPECIAL|MF_NOCLIPHEIGHT|MF_NOGRAVITY, // flags + MF_SPECIAL|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -16869,7 +16869,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // mass 0, // damage sfx_None, // activesound - MF_NOTHINK|MF_NOCLIP|MF_NOCLIPHEIGHT, // flags + MF_NOTHINK|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, diff --git a/src/p_mobj.h b/src/p_mobj.h index 50645e4be..34d1f644e 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -160,7 +160,9 @@ typedef enum MF_GRENADEBOUNCE = 1<<28, // Run the action thinker on spawn. MF_RUNSPAWNFUNC = 1<<29, - // free: 1<<30 and 1<<31 + // Don't remap in Encore mode. + MF_DONTENCOREMAP = 1<<30, + // free: 1<<31 } mobjflag_t; typedef enum diff --git a/src/p_spec.c b/src/p_spec.c index 02d94d90f..ccb895f13 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3745,6 +3745,8 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers break; case 12: // Lua sector special break; + case 15: // Invert Encore Remap + break; } DoneSection2: diff --git a/src/r_bsp.c b/src/r_bsp.c index 48f2f1793..981d0b56e 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -37,14 +37,21 @@ drawseg_t *ds_p = NULL; // indicates doors closed wrt automap bugfix: INT32 doorclosed; -static boolean R_NoEncore(sector_t *sector) +static boolean R_NoEncore(sector_t *sector, boolean ceiling) { + boolean invertencore = (GETSECSPECIAL(sector->special, 2) != 15); +#if 0 // perfect implementation INT32 val = GETSECSPECIAL(sector->special, 3); - if (val == 1 || val == 3) - return true; - if (GETSECSPECIAL(sector->special, 4) == 6) - return true; - return false; + if (val != 1 && val != 3 // spring panel +#else // optimised, see #define GETSECSPECIAL(i,j) ((i >> ((j-1)*4))&15) + if ((!(sector->special & (1<<8)) || (sector->special & ((4|8)<<8))) // spring panel +#endif + && GETSECSPECIAL(sector->special, 4) != 6) // sneaker panel + return !invertencore; + + if (ceiling) + return ((boolean)(sector->flags & SF_FLIPSPECIAL_CEILING) == invertencore); + return ((boolean)(sector->flags & SF_FLIPSPECIAL_FLOOR) == invertencore); } // @@ -945,7 +952,7 @@ static void R_Subsector(size_t num, UINT8 viewnumber) #ifdef ESLOPE , frontsector->f_slope #endif - , R_NoEncore(frontsector)); + , R_NoEncore(frontsector, false)); } else floorplane = NULL; @@ -967,7 +974,7 @@ static void R_Subsector(size_t num, UINT8 viewnumber) #ifdef ESLOPE , frontsector->c_slope #endif - , R_NoEncore(frontsector)); + , R_NoEncore(frontsector, true)); } else ceilingplane = NULL; @@ -1028,7 +1035,7 @@ static void R_Subsector(size_t num, UINT8 viewnumber) #ifdef ESLOPE , *rover->b_slope #endif - , R_NoEncore(rover->master->frontsector)); + , R_NoEncore(rover->master->frontsector, true)); #ifdef ESLOPE ffloor[numffloors].slope = *rover->b_slope; @@ -1074,7 +1081,7 @@ static void R_Subsector(size_t num, UINT8 viewnumber) #ifdef ESLOPE , *rover->t_slope #endif - , R_NoEncore(rover->master->frontsector)); + , R_NoEncore(rover->master->frontsector, false)); #ifdef ESLOPE ffloor[numffloors].slope = *rover->t_slope; @@ -1143,7 +1150,7 @@ static void R_Subsector(size_t num, UINT8 viewnumber) #ifdef ESLOPE , NULL // will ffloors be slopable eventually? #endif - , R_NoEncore(polysec)); + , R_NoEncore(polysec, false)); ffloor[numffloors].height = polysec->floorheight; ffloor[numffloors].polyobj = po; @@ -1189,7 +1196,7 @@ static void R_Subsector(size_t num, UINT8 viewnumber) #ifdef ESLOPE , NULL // will ffloors be slopable eventually? #endif - , R_NoEncore(polysec)); + , R_NoEncore(polysec, true)); ffloor[numffloors].polyobj = po; ffloor[numffloors].height = polysec->ceilingheight; diff --git a/src/r_segs.c b/src/r_segs.c index 5c09d34e8..11287f16d 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -202,7 +202,7 @@ static void R_DrawWallSplats(void) if (pindex >= MAXLIGHTSCALE) pindex = MAXLIGHTSCALE - 1; dc_colormap = walllights[pindex]; - if (encoremap) + if (encoremap && !(seg->linedef->flags & ML_TFERLINE)) dc_colormap += (256*32); if (frontsector->extra_colormap) @@ -598,7 +598,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) if (height <= windowtop) { dc_colormap = rlight->rcolormap; - if (encoremap) + if (encoremap && !(ldef->flags & ML_TFERLINE)) dc_colormap += (256*32); continue; } @@ -619,7 +619,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) colfunc_2s(col); windowtop = windowbottom + 1; dc_colormap = rlight->rcolormap; - if (encoremap) + if (encoremap && !(ldef->flags & ML_TFERLINE)) dc_colormap += (256*32); } windowbottom = realbot; @@ -637,7 +637,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) pindex = MAXLIGHTSCALE - 1; dc_colormap = walllights[pindex]; - if (encoremap) + if (encoremap && !(ldef->flags & ML_TFERLINE)) dc_colormap += (256*32); if (frontsector->extra_colormap) @@ -1220,7 +1220,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) if (lighteffect) { dc_colormap = rlight->rcolormap; - if (encoremap) + if (encoremap && !(curline->linedef->flags & ML_TFERLINE)) dc_colormap += (256*32); } if (solid && windowtop < bheight) @@ -1250,7 +1250,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) if (lighteffect) { dc_colormap = rlight->rcolormap; - if (encoremap) + if (encoremap && !(curline->linedef->flags & ML_TFERLINE)) dc_colormap += (256*32); } } @@ -1269,7 +1269,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) pindex = MAXLIGHTSCALE - 1; dc_colormap = walllights[pindex]; - if (encoremap) + if (encoremap && !(curline->linedef->flags & ML_TFERLINE)) dc_colormap += (256*32); if (frontsector->extra_colormap) dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps); @@ -1501,7 +1501,7 @@ static void R_RenderSegLoop (void) pindex = MAXLIGHTSCALE-1; dc_colormap = walllights[pindex]; - if (encoremap) + if (encoremap && !(curline->linedef->flags & ML_TFERLINE)) dc_colormap += (256*32); dc_x = rw_x; dc_iscale = 0xffffffffu / (unsigned)rw_scale; diff --git a/src/r_things.c b/src/r_things.c index d65969136..67b1a5c7f 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -873,9 +873,7 @@ static void R_DrawVisSprite(vissprite_t *vis) if (!dc_colormap) dc_colormap = colormaps; - if (encoremap && !vis->mobj->color - && (vis->mobj->flags & (MF_SCENERY|MF_NOTHINK)) - && !(vis->mobj->flags & ~(MF_SCENERY|MF_NOTHINK|MF_NOCLIP|MF_NOBLOCKMAP|MF_NOGRAVITY))) + if (encoremap && !vis->mobj->color && !(vis->mobj->flags & MF_DONTENCOREMAP)) dc_colormap += (256*32); dc_texturemid = vis->texturemid; From 132dd5828a31c48e2b58f12a7841500ec6aa6287 Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 10 Aug 2018 21:11:45 +0100 Subject: [PATCH 006/146] * For testing purposes, show Encoremaps on the level select icons. * HOWEVER, we should seriously address this again later, because the antialiasing DOES result in some unfortunate bullshit... * Encoremap maces per Oni's request and Sal's suggestion --- src/info.c | 8 ++++---- src/m_menu.c | 53 ++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 49 insertions(+), 12 deletions(-) diff --git a/src/info.c b/src/info.c index 5c3de1238..2109f74bd 100644 --- a/src/info.c +++ b/src/info.c @@ -8022,7 +8022,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_None, // activesound - MF_NOGRAVITY|MF_SPECIAL|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags + MF_NOGRAVITY|MF_SPECIAL|MF_NOCLIPHEIGHT, // flags S_NULL // raisestate }, @@ -8049,7 +8049,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_None, // activesound - MF_NOGRAVITY|MF_SPECIAL|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags + MF_NOGRAVITY|MF_SPECIAL|MF_NOCLIPHEIGHT, // flags S_NULL // raisestate }, @@ -8076,7 +8076,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_mswing, // activesound - MF_PAIN|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags + MF_PAIN|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags S_NULL // raisestate }, @@ -8103,7 +8103,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_mswing, // activesound - MF_PAIN|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags + MF_PAIN|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags S_NULL // raisestate }, diff --git a/src/m_menu.c b/src/m_menu.c index b23f28a57..18bdf09ee 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6749,9 +6749,11 @@ static void M_DrawLevelSelectOnly(boolean leftfade, boolean rightfade) lumpnum_t lumpnum; patch_t *PictureOfLevel; INT32 x, y, w, i, oldval, trans, dupadjust = ((vid.width/vid.dupx) - BASEVIDWIDTH)>>1; + const char *mapname = G_BuildMapName(cv_nextmap.value); + boolean doencore = (cv_kartencore.value && cv_newgametype.value == GT_RACE); // A 160x100 image of the level as entry MAPxxP - lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(cv_nextmap.value))); + lumpnum = W_CheckNumForName(va("%sP", mapname)); if (lumpnum != LUMPERROR) PictureOfLevel = W_CachePatchNum(lumpnum, PU_CACHE); @@ -6770,13 +6772,24 @@ static void M_DrawLevelSelectOnly(boolean leftfade, boolean rightfade) V_DrawFill(x-1, y-1, w+2, i+2, trans); // variable reuse... - V_DrawSmallScaledPatch(x, y, 0, PictureOfLevel); + if (!doencore) + V_DrawSmallScaledPatch(x, y, 0, PictureOfLevel); + else + { + UINT8 *mappingforencore = NULL; + if ((lumpnum = W_CheckNumForName(va("%sE", mapname))) != LUMPERROR) + mappingforencore = W_CachePatchNum(lumpnum, PU_CACHE); + + V_DrawFixedPatch((x+w)<width)/4; - V_DrawTinyScaledPatch(x, y, trans, PictureOfLevel); + x -= horizspac + w/2; + + if (!doencore) + V_DrawTinyScaledPatch(x, y, trans, PictureOfLevel); + else + { + UINT8 *mappingforencore = NULL; + if ((lumpnum = W_CheckNumForName(va("%sE", mapname))) != LUMPERROR) + mappingforencore = W_CachePatchNum(lumpnum, PU_CACHE); + + V_DrawFixedPatch((x+(w/2))< horizspac-dupadjust); x = (BASEVIDWIDTH + w)/2 + horizspac; i = cv_nextmap.value - 1; trans = (rightfade ? V_TRANSLUCENT : 0); + if (doencore) + trans |= V_FLIP; while (x < BASEVIDWIDTH+dupadjust-horizspac) { @@ -6830,15 +6856,26 @@ static void M_DrawLevelSelectOnly(boolean leftfade, boolean rightfade) } while (!M_CanShowLevelInList(i, cv_newgametype.value)); // A 160x100 image of the level as entry MAPxxP - lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(i+1))); + mapname = G_BuildMapName(i+1); + lumpnum = W_CheckNumForName(va("%sP", mapname)); if (lumpnum != LUMPERROR) PictureOfLevel = W_CachePatchNum(lumpnum, PU_CACHE); else PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); - V_DrawTinyScaledPatch(x, y, trans, PictureOfLevel); - x += horizspac + SHORT(PictureOfLevel->width)/4; + if (!doencore) + V_DrawTinyScaledPatch(x, y, trans, PictureOfLevel); + else + { + UINT8 *mappingforencore = NULL; + if ((lumpnum = W_CheckNumForName(va("%sE", mapname))) != LUMPERROR) + mappingforencore = W_CachePatchNum(lumpnum, PU_CACHE); + + V_DrawFixedPatch((x+(w/2))< Date: Sat, 11 Aug 2018 22:23:40 +0100 Subject: [PATCH 007/146] * Encore on the voting screen! Appears randomly once unlocked in the same slot as that which sometimes represents a gametype change (odds inflated for testing purposes). * A better representation of an Encore level, now with inverted graphics (a special remapping we can now use elsewhere whenever if we want!) and a floating Ruby! * Decouple encore's setting from cv_kartencore on mapload. Instead, bake it into D_MapChange and related, which will only some of the time be fed by cv_kartencore's value. * Encore mode now has a special mapheader palette setting, "encorepal", rather than using the same one as non-encore. --- src/d_clisrv.c | 2 +- src/d_main.c | 2 +- src/d_netcmd.c | 40 ++++++++++++------------ src/d_netcmd.h | 2 +- src/dehacked.c | 2 ++ src/doomstat.h | 5 +-- src/f_finale.c | 2 +- src/g_game.c | 26 ++++++++------- src/g_game.h | 4 +-- src/m_menu.c | 51 +++++++++++------------------- src/p_setup.c | 13 ++------ src/p_tick.c | 2 +- src/r_data.c | 12 ++++++- src/r_data.h | 1 + src/r_state.h | 3 +- src/v_video.c | 3 +- src/y_inter.c | 85 ++++++++++++++++++++++++++++++++++++-------------- 17 files changed, 144 insertions(+), 111 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 13650c59d..63393690a 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -4758,7 +4758,7 @@ void TryRunTics(tic_t realtics) { COM_BufExecute(); if (mapchangepending) - D_MapChange(-1, 0, ultimatemode, false, 2, false, fromlevelselect); // finish the map change + D_MapChange(-1, 0, encoremode, false, 2, false, fromlevelselect); // finish the map change } NetUpdate(); diff --git a/src/d_main.c b/src/d_main.c index 0100db38b..bf6af7ea6 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1489,7 +1489,7 @@ void D_SRB2Main(void) else if (!dedicated && M_MapLocked(pstartmap)) I_Error("You need to unlock this level before you can warp to it!\n"); else - D_MapChange(pstartmap, gametype, ultimatemode, true, 0, false, false); + D_MapChange(pstartmap, gametype, (boolean)cv_kartencore.value, true, 0, false, false); } } else if (M_CheckParm("-skipintro")) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index c157f21ce..28d33be97 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -446,6 +446,7 @@ consvar_t cv_sleep = {"cpusleep", "-1", CV_SAVE, sleeping_cons_t, NULL, -1, NULL INT16 gametype = GT_RACE; // SRB2kart boolean forceresetplayers = false; +boolean deferencoremode = false; UINT8 splitscreen = 0; boolean circuitmap = true; // SRB2kart INT32 adminplayers[MAXPLAYERS]; @@ -1872,7 +1873,7 @@ INT32 mapchangepending = 0; * * \param mapnum Map number to change to. * \param gametype Gametype to switch to. - * \param pultmode Is this 'Ultimate Mode'? + * \param pencoremode Is this 'Encore Mode'? * \param resetplayers 1 to reset player scores and lives and such, 0 not to. * \param delay Determines how the function will be executed: 0 to do * it all right now (must not be done from a menu), 1 to @@ -1881,18 +1882,16 @@ INT32 mapchangepending = 0; * \sa D_GameTypeChanged, Command_Map_f * \author Graue */ -void D_MapChange(INT32 mapnum, INT32 newgametype, boolean pultmode, boolean resetplayers, INT32 delay, boolean skipprecutscene, boolean FLS) +void D_MapChange(INT32 mapnum, INT32 newgametype, boolean pencoremode, boolean resetplayers, INT32 delay, boolean skipprecutscene, boolean FLS) { static char buf[2+MAX_WADPATH+1+4]; static char *buf_p = buf; - forceresetplayers = false; - // The supplied data are assumed to be good. I_Assert(delay >= 0 && delay <= 2); - CONS_Debug(DBG_GAMELOGIC, "Map change: mapnum=%d gametype=%d ultmode=%d resetplayers=%d delay=%d skipprecutscene=%d\n", - mapnum, newgametype, pultmode, resetplayers, delay, skipprecutscene); + CONS_Debug(DBG_GAMELOGIC, "Map change: mapnum=%d gametype=%d encoremode=%d resetplayers=%d delay=%d skipprecutscene=%d\n", + mapnum, newgametype, pencoremode, resetplayers, delay, skipprecutscene); if (netgame || multiplayer) FLS = false; @@ -1905,7 +1904,7 @@ void D_MapChange(INT32 mapnum, INT32 newgametype, boolean pultmode, boolean rese I_Assert(W_CheckNumForName(mapname) != LUMPERROR); buf_p = buf; - if (pultmode) + if (pencoremode) flags |= 1; if (!resetplayers) flags |= 1<<1; @@ -1973,8 +1972,12 @@ void D_SetupVote(void) INT32 i; UINT8 secondgt = G_SometimesGetDifferentGametype(); - WRITEUINT8(p, gametype); + if (cv_kartencore.value && G_RaceGametype()) + WRITEUINT8(p, (gametype|0x80)); + else + WRITEUINT8(p, gametype); WRITEUINT8(p, secondgt); + secondgt &= ~0x80; for (i = 0; i < 5; i++) { @@ -2109,10 +2112,6 @@ static void Command_Map_f(void) return; } - // Ultimate Mode only in SP via menu - if (netgame || multiplayer) - ultimatemode = false; - // new gametype value // use current one by default i = COM_CheckParm("-gametype"); @@ -2177,7 +2176,7 @@ static void Command_Map_f(void) } fromlevelselect = false; - D_MapChange(newmapnum, newgametype, false, newresetplayers, 0, false, false); + D_MapChange(newmapnum, newgametype, (boolean)cv_kartencore.value, newresetplayers, 0, false, false); } /** Receives a map command and changes the map. @@ -2193,6 +2192,9 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum) UINT8 flags; INT32 resetplayer = 1, lastgametype; UINT8 skipprecutscene, FLS; + boolean pencoremode; + + forceresetplayers = deferencoremode = false; if (playernum != serverplayer && !IsPlayerAdmin(playernum)) { @@ -2213,9 +2215,7 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum) flags = READUINT8(*cp); - ultimatemode = ((flags & 1) != 0); - if (netgame || multiplayer) - ultimatemode = false; + pencoremode = ((flags & 1) != 0); resetplayer = ((flags & (1<<1)) == 0); @@ -2225,6 +2225,9 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum) if (gametype != lastgametype) D_GameTypeChanged(lastgametype); // emulate consvar_t behavior for gametype + if (!G_RaceGametype()) + pencoremode = false; + skipprecutscene = ((flags & (1<<2)) != 0); FLS = ((flags & (1<<3)) != 0); @@ -2256,7 +2259,7 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum) LUAh_MapChange(); #endif - G_InitNew(ultimatemode, mapname, resetplayer, skipprecutscene); + G_InitNew(pencoremode, mapname, resetplayer, skipprecutscene); if (demoplayback && !timingdemo) precache = true; CON_ToggleOff(); @@ -5250,10 +5253,7 @@ static void KartEncore_OnChange(void) if ((boolean)cv_kartencore.value != encoremode && gamestate == GS_LEVEL /*&& leveltime > starttime*/) CONS_Printf(M_GetText("Encore Mode will be turned %s next round.\n"), cv_kartencore.value ? M_GetText("on") : M_GetText("off")); else - { CONS_Printf(M_GetText("Encore Mode has been turned %s.\n"), cv_kartencore.value ? M_GetText("on") : M_GetText("off")); - //encoremode = (boolean)cv_kartencore.value; - } } } diff --git a/src/d_netcmd.h b/src/d_netcmd.h index b7721b796..5238c44e1 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -251,7 +251,7 @@ void D_SendPlayerConfig(void); void Command_ExitGame_f(void); void Command_Retry_f(void); void D_GameTypeChanged(INT32 lastgametype); // not a real _OnChange function anymore -void D_MapChange(INT32 pmapnum, INT32 pgametype, boolean pultmode, boolean presetplayers, INT32 pdelay, boolean pskipprecutscene, boolean pfromlevelselect); +void D_MapChange(INT32 pmapnum, INT32 pgametype, boolean pencoremode, boolean presetplayers, INT32 pdelay, boolean pskipprecutscene, boolean pfromlevelselect); void D_SetupVote(void); void D_ModifyClientVote(SINT8 voted, UINT8 splitplayer); void D_PickVote(void); diff --git a/src/dehacked.c b/src/dehacked.c index af72719bd..cd013148a 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1221,6 +1221,8 @@ static void readlevelheader(MYFILE *f, INT32 num) mapheaderinfo[num-1]->countdown = (INT16)i; else if (fastcmp(word, "PALETTE")) mapheaderinfo[num-1]->palette = (UINT16)i; + else if (fastcmp(word, "ENCOREPAL")) + mapheaderinfo[num-1]->encorepal = (UINT16)i; else if (fastcmp(word, "NUMLAPS")) mapheaderinfo[num-1]->numlaps = (UINT8)i; else if (fastcmp(word, "UNLOCKABLE")) diff --git a/src/doomstat.h b/src/doomstat.h index dbe9fa34c..f54abebcb 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -80,7 +80,7 @@ extern INT16 gametype; extern UINT8 splitscreen; extern boolean circuitmap; // Does this level have 'circuit mode'? extern boolean fromlevelselect; -extern boolean forceresetplayers; +extern boolean forceresetplayers, deferencoremode; // ======================================== // Internal parameters for sound rendering. @@ -243,6 +243,7 @@ typedef struct UINT8 cutscenenum; ///< Cutscene number to use, 0 for none. INT16 countdown; ///< Countdown until level end? UINT16 palette; ///< PAL lump to use on this map + UINT16 encorepal; ///< PAL for encore mode UINT8 numlaps; ///< Number of laps in circuit mode, unless overridden. SINT8 unlockrequired; ///< Is an unlockable required to play this level? -1 if no. UINT8 levelselect; ///< Is this map available in the level select? If so, which map list is it available in? @@ -448,7 +449,7 @@ extern INT32 cheats; // SRB2kart extern UINT8 gamespeed; extern boolean franticitems; -extern boolean encoremode; +extern boolean encoremode, prevencoremode; extern boolean comeback; extern SINT8 battlewanted[4]; diff --git a/src/f_finale.c b/src/f_finale.c index ab79fa782..e5d342ad1 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1252,7 +1252,7 @@ void F_EndCutScene(void) if (runningprecutscene) { if (server) - D_MapChange(gamemap, gametype, ultimatemode, precutresetplayer, 0, true, false); + D_MapChange(gamemap, gametype, false, precutresetplayer, 0, true, false); } else { diff --git a/src/g_game.c b/src/g_game.c index 48ba8724b..cb7f276cf 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -248,7 +248,8 @@ INT32 cheats; //for multiplayer cheat commands // SRB2Kart // Cvars that we don't want changed mid-game UINT8 gamespeed; // Game's current speed (or difficulty, or cc, or etc); 0 for easy, 1 for normal, 2 for hard -boolean encoremode; // Encore Mode currently enabled? +boolean encoremode = false; // Encore Mode currently enabled? +boolean prevencoremode; boolean franticitems; // Frantic items currently enabled? boolean comeback; // Battle Mode's karma comeback is on/off @@ -3097,13 +3098,16 @@ boolean G_BattleGametype(void) // // G_SometimesGetDifferentGametype // -// I pity the fool who adds more gametypes later, because it'll require some element of randomisation which needs to be synched... -// Although given this only gets called for the host, you could probably get away with M_Random. +// Oh, yeah, and we sometimes flip encore mode on here too. // INT16 G_SometimesGetDifferentGametype(void) { if (randmapbuffer[NUMMAPS] != -1) + { + if (M_SecretUnlocked(SECRET_ENCORE) && (M_RandomChance(FRACUNIT/2/*56*/) != cv_kartencore.value) && G_RaceGametype()) + return (gametype|0x80); return gametype; + } randmapbuffer[NUMMAPS] = gametype; @@ -3477,6 +3481,7 @@ void G_NextLevel(void) } forceresetplayers = false; + deferencoremode = (boolean)cv_kartencore.value; } gameaction = ga_worlddone; @@ -3489,7 +3494,7 @@ static void G_DoWorldDone(void) // SRB2Kart D_MapChange(nextmap+1, gametype, - ultimatemode, + deferencoremode, forceresetplayers, 0, false, @@ -3561,7 +3566,7 @@ static void G_DoContinued(void) // Reset # of lives pl->lives = (ultimatemode) ? 1 : 3; - D_MapChange(gamemap, gametype, ultimatemode, false, 0, false, false); + D_MapChange(gamemap, gametype, false, false, 0, false, false); gameaction = ga_nothing; } @@ -4075,7 +4080,7 @@ void G_SaveGame(UINT32 savegameslot) // Can be called by the startup code or the menu task, // consoleplayer, displayplayer, playeringame[] should be set. // -void G_DeferedInitNew(boolean pultmode, const char *mapname, INT32 pickedchar, UINT8 ssplayers, boolean FLS) +void G_DeferedInitNew(boolean pencoremode, const char *mapname, INT32 pickedchar, UINT8 ssplayers, boolean FLS) { INT32 i; UINT8 color = 0; @@ -4120,14 +4125,14 @@ void G_DeferedInitNew(boolean pultmode, const char *mapname, INT32 pickedchar, U CV_StealthSetValue(&cv_playercolor, color); if (mapname) - D_MapChange(M_MapNumber(mapname[3], mapname[4]), gametype, pultmode, true, 1, false, FLS); + D_MapChange(M_MapNumber(mapname[3], mapname[4]), gametype, pencoremode, true, 1, false, FLS); } // // This is the map command interpretation something like Command_Map_f // // called at: map cmd execution, doloadgame, doplaydemo -void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean skipprecutscene) +void G_InitNew(UINT8 pencoremode, const char *mapname, boolean resetplayer, boolean skipprecutscene) { INT32 i; @@ -4137,8 +4142,8 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean S_ResumeAudio(); } - if (netgame || multiplayer) // Nice try, haxor. - ultimatemode = false; + prevencoremode = ((gamestate == GS_TITLESCREEN) ? false : encoremode); + encoremode = pencoremode; legitimateexit = false; // SRB2Kart comebackshowninfo = false; @@ -4227,7 +4232,6 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean // Don't carry over custom music change to another map. mapmusflags |= MUSIC_RELOADRESET; - ultimatemode = pultmode; playerdeadview = false; automapactive = false; imcontinuing = false; diff --git a/src/g_game.h b/src/g_game.h index ad099bf24..10eb4c681 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -107,7 +107,7 @@ extern boolean camspin, camspin2, camspin3, camspin4; // SRB2Kart void G_ChangePlayerReferences(mobj_t *oldmo, mobj_t *newmo); void G_DoReborn(INT32 playernum); void G_PlayerReborn(INT32 player); -void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, +void G_InitNew(UINT8 pencoremode, const char *mapname, boolean resetplayer, boolean skipprecutscene); char *G_BuildMapTitle(INT32 mapnum); @@ -119,7 +119,7 @@ void G_SpawnPlayer(INT32 playernum, boolean starpost); // Can be called by the startup code or M_Responder. // A normal game starts at map 1, but a warp test can start elsewhere -void G_DeferedInitNew(boolean pultmode, const char *mapname, INT32 pickedchar, +void G_DeferedInitNew(boolean pencoremode, const char *mapname, INT32 pickedchar, UINT8 ssplayers, boolean FLS); void G_DoLoadLevel(boolean resetplayer); diff --git a/src/m_menu.c b/src/m_menu.c index 18bdf09ee..5d557f89c 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5420,7 +5420,7 @@ static void M_ChoosePlayer(INT32 choice) { char *skin1,*skin2; INT32 skinnum; - boolean ultmode = (ultimate_selectable && SP_PlayerDef.prevMenu == &SP_LoadDef && saveSlotSelected == NOSAVESLOT); + //boolean ultmode = (ultimate_selectable && SP_PlayerDef.prevMenu == &SP_LoadDef && saveSlotSelected == NOSAVESLOT); // skip this if forcecharacter if (mapheaderinfo[startmap-1] && mapheaderinfo[startmap-1]->forcecharacter[0] == '\0') @@ -5457,7 +5457,7 @@ static void M_ChoosePlayer(INT32 choice) lastmapsaved = 0; gamecomplete = false; - G_DeferedInitNew(ultmode, G_BuildMapName(startmap), (UINT8)skinnum, 0, fromlevelselect); + G_DeferedInitNew(false, G_BuildMapName(startmap), (UINT8)skinnum, 0, fromlevelselect); COM_BufAddText("dummyconsvar 1\n"); // G_DeferedInitNew doesn't do this } @@ -6724,7 +6724,7 @@ static void M_StartServer(INT32 choice) if (ssplayers < 1) { - D_MapChange(cv_nextmap.value, cv_newgametype.value, false, 1, 1, false, false); + D_MapChange(cv_nextmap.value, cv_newgametype.value, (boolean)cv_kartencore.value, 1, 1, false, false); COM_BufAddText("dummyconsvar 1\n"); } else // split screen @@ -6738,7 +6738,7 @@ static void M_StartServer(INT32 choice) SplitScreen_OnChange(); } - D_MapChange(cv_nextmap.value, cv_newgametype.value, false, 1, 1, false, false); + D_MapChange(cv_nextmap.value, cv_newgametype.value, (boolean)cv_kartencore.value, 1, 1, false, false); } M_ClearMenus(true); @@ -6750,7 +6750,7 @@ static void M_DrawLevelSelectOnly(boolean leftfade, boolean rightfade) patch_t *PictureOfLevel; INT32 x, y, w, i, oldval, trans, dupadjust = ((vid.width/vid.dupx) - BASEVIDWIDTH)>>1; const char *mapname = G_BuildMapName(cv_nextmap.value); - boolean doencore = (cv_kartencore.value && cv_newgametype.value == GT_RACE); + //boolean doencore = (cv_kartencore.value && cv_newgametype.value == GT_RACE); // A 160x100 image of the level as entry MAPxxP lumpnum = W_CheckNumForName(va("%sP", mapname)); @@ -6772,15 +6772,22 @@ static void M_DrawLevelSelectOnly(boolean leftfade, boolean rightfade) V_DrawFill(x-1, y-1, w+2, i+2, trans); // variable reuse... - if (!doencore) + if (!cv_kartencore.value || cv_newgametype.value != GT_RACE) V_DrawSmallScaledPatch(x, y, 0, PictureOfLevel); else { - UINT8 *mappingforencore = NULL; + /*UINT8 *mappingforencore = NULL; if ((lumpnum = W_CheckNumForName(va("%sE", mapname))) != LUMPERROR) - mappingforencore = W_CachePatchNum(lumpnum, PU_CACHE); + mappingforencore = W_CachePatchNum(lumpnum, PU_CACHE);*/ - V_DrawFixedPatch((x+w)<>ANGLETOFINESHIFT); + V_DrawFixedPatch((x+w/2)< horizspac-dupadjust); x = (BASEVIDWIDTH + w)/2 + horizspac; i = cv_nextmap.value - 1; trans = (rightfade ? V_TRANSLUCENT : 0); - if (doencore) - trans |= V_FLIP; while (x < BASEVIDWIDTH+dupadjust-horizspac) { @@ -6864,16 +6858,7 @@ static void M_DrawLevelSelectOnly(boolean leftfade, boolean rightfade) else PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); - if (!doencore) - V_DrawTinyScaledPatch(x, y, trans, PictureOfLevel); - else - { - UINT8 *mappingforencore = NULL; - if ((lumpnum = W_CheckNumForName(va("%sE", mapname))) != LUMPERROR) - mappingforencore = W_CachePatchNum(lumpnum, PU_CACHE); - - V_DrawFixedPatch((x+(w/2))<countdown = 0; DEH_WriteUndoline("PALLETE", va("%u", mapheaderinfo[num]->palette), UNDO_NONE); mapheaderinfo[num]->palette = UINT16_MAX; + DEH_WriteUndoline("ENCOREPAL", va("%u", mapheaderinfo[num]->encorepal), UNDO_NONE); + mapheaderinfo[num]->encorepal = UINT16_MAX; DEH_WriteUndoline("NUMLAPS", va("%u", mapheaderinfo[num]->numlaps), UNDO_NONE); mapheaderinfo[num]->numlaps = NUMLAPS_DEFAULT; DEH_WriteUndoline("UNLOCKABLE", va("%s", mapheaderinfo[num]->unlockrequired), UNDO_NONE); @@ -2247,28 +2247,19 @@ static void P_LevelInitStuff(void) players[i].pflags &= ~PF_TRANSFERTOCLOSEST; } - prevencoremode = ((wipegamestate == GS_TITLESCREEN) ? false : encoremode); - // SRB2Kart: map load variables if (modeattacking) // Just play it safe and set everything { gamespeed = 2; - encoremode = false; franticitems = false; comeback = true; } else { if (G_BattleGametype()) - { gamespeed = 0; - encoremode = false; - } else - { gamespeed = (UINT8)cv_kartspeed.value; - encoremode = (boolean)cv_kartencore.value; - } franticitems = (boolean)cv_kartfrantic.value; comeback = (boolean)cv_kartcomeback.value; } diff --git a/src/p_tick.c b/src/p_tick.c index b9aaccf7d..bf0777aa0 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -744,7 +744,7 @@ void P_Ticker(boolean run) if (mapreset > 1 && --mapreset <= 1 && server) // Remember: server uses it for mapchange, but EVERYONE ticks down for the animation - D_MapChange(gamemap, gametype, ultimatemode, true, 0, false, false); + D_MapChange(gamemap, gametype, encoremode, true, 0, false, false); } P_MapEnd(); diff --git a/src/r_data.c b/src/r_data.c index 1e2bc628b..e3d23dd7e 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -112,7 +112,8 @@ INT32 *texturetranslation; sprcache_t *spritecachedinfo; lighttable_t *colormaps; -lighttable_t *encoremap; +UINT8 *encoremap; +UINT8 invertmap[256]; // for debugging/info purposes static size_t flatmemory, spritememory, texturememory; @@ -1019,6 +1020,7 @@ static void R_InitColormaps(void) // Init Boom colormaps. R_ClearColormaps(); //R_InitExtraColormaps(); + R_MakeInvertmap(); // this isn't the BEST place to do it the first time, but whatever } void R_ReInitColormaps(UINT16 num, lumpnum_t newencoremap) @@ -1301,6 +1303,14 @@ void R_MakeColormaps(void) colormapFixingArray[i][2]); } +void R_MakeInvertmap(void) +{ + size_t i; + + for (i = 0; i < 256; i++) + invertmap[i] = NearestColor(256 - pLocalPalette[i].s.red, 256 - pLocalPalette[i].s.green, 256 - pLocalPalette[i].s.blue); +} + void R_CreateColormap2(char *p1, char *p2, char *p3) { double cmaskr, cmaskg, cmaskb, cdestr, cdestg, cdestb; diff --git a/src/r_data.h b/src/r_data.h index fb8756dfc..4cc6f2060 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -95,6 +95,7 @@ INT32 R_ColormapNumForName(char *name); INT32 R_CreateColormap(char *p1, char *p2, char *p3); void R_CreateColormap2(char *p1, char *p2, char *p3); void R_MakeColormaps(void); +void R_MakeInvertmap(void); const char *R_ColormapNameForNum(INT32 num); extern INT32 numtextures; diff --git a/src/r_state.h b/src/r_state.h index a651bda71..88a38f251 100644 --- a/src/r_state.h +++ b/src/r_state.h @@ -38,7 +38,8 @@ typedef struct extern sprcache_t *spritecachedinfo; extern lighttable_t *colormaps; -extern lighttable_t *encoremap; +extern UINT8 *encoremap; +extern UINT8 invertmap[256]; // Boom colormaps. // Had to put a limit on colormaps :( diff --git a/src/v_video.c b/src/v_video.c index 8013ae82e..6f9ff219d 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -207,7 +207,7 @@ const char *R_GetPalname(UINT16 num) const char *GetPalette(void) { if (gamestate == GS_LEVEL) - return R_GetPalname(mapheaderinfo[gamemap-1]->palette); + return R_GetPalname((encoremode ? mapheaderinfo[gamemap-1]->encorepal : mapheaderinfo[gamemap-1]->palette)); return "PLAYPAL"; } @@ -248,6 +248,7 @@ void V_SetPaletteLump(const char *pal) #endif if (rendermode != render_none) I_SetPalette(pLocalPalette); + R_MakeInvertmap(); } static void CV_usegamma_OnChange(void) diff --git a/src/y_inter.c b/src/y_inter.c index 14421ad74..d34e5d595 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -126,6 +126,7 @@ typedef struct UINT8 gtc; const char *gts; patch_t *pic; + boolean encore; } y_votelvlinfo; // Clientside & splitscreen player info. @@ -156,6 +157,7 @@ static patch_t *cursor2 = NULL; static patch_t *cursor3 = NULL; static patch_t *cursor4 = NULL; static patch_t *randomlvl = NULL; +static patch_t *rubyicon = NULL; static void Y_UnloadVoteData(void); @@ -930,6 +932,7 @@ void Y_VoteDrawer(void) { INT32 i, x, y = 0, height = 0; UINT8 selected[4]; + fixed_t rubyheight = 0; if (rendermode == render_none) return; @@ -940,6 +943,11 @@ void Y_VoteDrawer(void) if (!voteclient.loaded) return; + { + angle_t rubyfloattime = (ANGLE_MAX/NEWTICRATE)*(votetic % NEWTICRATE); + rubyheight = FINESINE(rubyfloattime>>ANGLETOFINESHIFT); + } + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); if (widebgpatch && rendermode == render_soft && vid.width / vid.dupx > 320) @@ -974,19 +982,18 @@ void Y_VoteDrawer(void) y = (200-height)/2; for (i = 0; i < 4; i++) { - char str[40]; + const char *str; patch_t *pic; UINT8 j, color; if (i == 3) { - snprintf(str, sizeof str, "%.32s", "RANDOM"); - str[sizeof str - 1] = '\0'; + str = "RANDOM"; pic = randomlvl; } else { - strcpy(str, levelinfo[i].str); + str = levelinfo[i].str; pic = levelinfo[i].pic; } @@ -1051,7 +1058,14 @@ void Y_VoteDrawer(void) sizeadd--; } - V_DrawSmallScaledPatch(BASEVIDWIDTH-100, y, V_SNAPTORIGHT, pic); + if (!levelinfo[i].encore) + V_DrawSmallScaledPatch(BASEVIDWIDTH-100, y, V_SNAPTORIGHT, pic); + else + { + V_DrawFixedPatch((BASEVIDWIDTH-20)<zonttl) > 0) + // set up the levelstring + if (mapheaderinfo[votelevels[i][0]]->levelflags & LF_NOZONE || !mapheaderinfo[votelevels[i][0]]->zonttl[0]) { - if (strlen(mapheaderinfo[votelevels[i][0]]->actnum) > 0) + if (mapheaderinfo[votelevels[i][0]]->actnum[0]) snprintf(levelinfo[i].str, sizeof levelinfo[i].str, - "%.32s %.32s %s", + "%s %s", + mapheaderinfo[prevmap]->lvlttl, mapheaderinfo[votelevels[i][0]]->actnum); + else + snprintf(levelinfo[i].str, + sizeof levelinfo[i].str, + "%s", + mapheaderinfo[votelevels[i][0]]->lvlttl); + } + else + { + if (mapheaderinfo[votelevels[i][0]]->actnum[0]) + snprintf(levelinfo[i].str, + sizeof levelinfo[i].str, + "%s %s %s", mapheaderinfo[votelevels[i][0]]->lvlttl, mapheaderinfo[votelevels[i][0]]->zonttl, mapheaderinfo[votelevels[i][0]]->actnum); else snprintf(levelinfo[i].str, sizeof levelinfo[i].str, - "%.32s %.32s", + "%s %s", mapheaderinfo[votelevels[i][0]]->lvlttl, mapheaderinfo[votelevels[i][0]]->zonttl); } - else - { - if (strlen(mapheaderinfo[votelevels[i][0]]->actnum) > 0) - snprintf(levelinfo[i].str, - sizeof levelinfo[i].str, - "%.32s %s", - mapheaderinfo[votelevels[i][0]]->lvlttl, mapheaderinfo[votelevels[i][0]]->actnum); - else - snprintf(levelinfo[i].str, - sizeof levelinfo[i].str, - "%.32s", - mapheaderinfo[votelevels[i][0]]->lvlttl); - } levelinfo[i].str[sizeof levelinfo[i].str - 1] = '\0'; } @@ -1493,6 +1529,7 @@ static void Y_UnloadVoteData(void) UNLOAD(cursor3); UNLOAD(cursor4); UNLOAD(randomlvl); + UNLOAD(rubyicon); UNLOAD(levelinfo[4].pic); UNLOAD(levelinfo[3].pic); From a6f8b021b0a906270be277100820409c205dc47f Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 11 Aug 2018 22:51:11 +0100 Subject: [PATCH 008/146] Encore mapload linedef executor (number 328), as requested by Oni. --- src/p_spec.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/p_spec.c b/src/p_spec.c index d1ee7e7cc..90166104b 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1940,6 +1940,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller || specialtype == 318 // Unlockable trigger - Once || specialtype == 320 // Unlockable - Once || specialtype == 321 || specialtype == 322 // Trigger on X calls - Continuous + Each Time + || specialtype == 328 // Encore Load || specialtype == 399) // Level Load triggerline->special = 0; // Clear it out @@ -1975,6 +1976,7 @@ void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller) // "No More Enemies" and "Level Load" take care of themselves. if (lines[masterline].special == 313 || lines[masterline].special == 399 + || lines[masterline].special == 328 // Each-time executors handle themselves, too || lines[masterline].special == 301 // Each time || lines[masterline].special == 306 // Character ability - Each time @@ -5561,7 +5563,7 @@ static void P_RunLevelLoadExecutors(void) for (i = 0; i < numlines; i++) { - if (lines[i].special == 399) + if (lines[i].special == 399 || lines[i].special == 328) P_RunTriggerLinedef(&lines[i], NULL, NULL); } } @@ -6452,6 +6454,12 @@ void P_SpawnSpecials(INT32 fromnetsave) } break; + case 328: // Encore-only linedef execute on map load + if (!encoremode) + lines[i].special = 0; + // This is handled in P_RunLevelLoadExecutors. + break; + case 399: // Linedef execute on map load // This is handled in P_RunLevelLoadExecutors. break; From 0b65b7a009c2099fd8008e09428583cf054f9be6 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 12 Aug 2018 11:20:53 +0100 Subject: [PATCH 009/146] Fixed Encore remappings not being loaded when joining mid-netgame. --- src/p_saveg.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 8f4e12d42..d9f430008 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -3207,6 +3207,8 @@ static void P_NetArchiveMisc(void) WRITEUINT32(save_p, tokenlist); + WRITEUINT8(save_p, encoremode); + WRITEUINT32(save_p, leveltime); WRITEUINT32(save_p, totalrings); WRITEINT16(save_p, lastmap); @@ -3256,7 +3258,6 @@ static void P_NetArchiveMisc(void) WRITEINT32(save_p, numgotboxes); WRITEUINT8(save_p, gamespeed); - WRITEUINT8(save_p, encoremode); WRITEUINT8(save_p, franticitems); WRITEUINT8(save_p, comeback); @@ -3308,6 +3309,8 @@ static inline boolean P_NetUnArchiveMisc(void) tokenlist = READUINT32(save_p); + encoremode = (boolean)READUINT8(save_p); + if (!P_SetupLevel(true)) return false; @@ -3361,7 +3364,6 @@ static inline boolean P_NetUnArchiveMisc(void) numgotboxes = READINT32(save_p); gamespeed = READUINT8(save_p); - encoremode = (boolean)READUINT8(save_p); franticitems = (boolean)READUINT8(save_p); comeback = (boolean)READUINT8(save_p); From 66092d76e75bd07bea351c7ddbf9661469a8a9aa Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 12 Aug 2018 15:10:47 +0100 Subject: [PATCH 010/146] Bugfix for "Blue Mountain 0", "Green Hills K". Also, minor tweak. --- src/st_stuff.c | 2 +- src/y_inter.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/st_stuff.c b/src/st_stuff.c index ac3391de5..72266ba2f 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -770,7 +770,7 @@ static void ST_drawLevelTitle(void) lvlw = V_LevelNameWidth(lvlttl); - if (strlen(actnum) > 0) + if (actnum[0]) lvlttlxpos = ((BASEVIDWIDTH/2) - (lvlw/2)) - V_LevelNameWidth(actnum); else lvlttlxpos = ((BASEVIDWIDTH/2) - (lvlw/2)); diff --git a/src/y_inter.c b/src/y_inter.c index d34e5d595..d88f3d340 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -1460,7 +1460,7 @@ void Y_StartVote(void) snprintf(levelinfo[i].str, sizeof levelinfo[i].str, "%s %s", - mapheaderinfo[prevmap]->lvlttl, mapheaderinfo[votelevels[i][0]]->actnum); + mapheaderinfo[votelevels[i][0]]->lvlttl, mapheaderinfo[votelevels[i][0]]->actnum); else snprintf(levelinfo[i].str, sizeof levelinfo[i].str, From bb3bb48fe669d3d43388aaefb6165d983c5107d9 Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 14 Aug 2018 15:32:17 +0100 Subject: [PATCH 011/146] * Disable inverting on encore level select pictures at unanimous request of last night's netgame. * Also, correct their alignment in y_inter.c. --- src/m_menu.c | 2 +- src/r_data.c | 6 ++++++ src/r_data.h | 2 ++ src/r_state.h | 2 ++ src/v_video.c | 2 ++ src/y_inter.c | 12 ++++++------ 6 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 5d557f89c..ae46549c7 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6780,7 +6780,7 @@ static void M_DrawLevelSelectOnly(boolean leftfade, boolean rightfade) if ((lumpnum = W_CheckNumForName(va("%sE", mapname))) != LUMPERROR) mappingforencore = W_CachePatchNum(lumpnum, PU_CACHE);*/ - V_DrawFixedPatch((x+w)< Date: Wed, 15 Aug 2018 16:12:36 +0100 Subject: [PATCH 012/146] Added "Random" to the level selection list, for those days when you know you *want* to race but don't have any idea what to do. --- src/command.c | 8 ++---- src/g_game.c | 16 ++++++++++- src/m_menu.c | 79 +++++++++++++++++++++++++++++++++------------------ 3 files changed, 69 insertions(+), 34 deletions(-) diff --git a/src/command.c b/src/command.c index 54406adeb..03c8869d8 100644 --- a/src/command.c +++ b/src/command.c @@ -1482,14 +1482,12 @@ void CV_AddValue(consvar_t *var, INT32 increment) { if(increment > 0) // Going up! { - newvalue++; - if (newvalue == NUMMAPS) - newvalue = 0; + if (++newvalue == NUMMAPS) + newvalue = -1; } else // Going down! { - newvalue--; - if (newvalue == -1) + if (--newvalue == -2) newvalue = NUMMAPS-1; } diff --git a/src/g_game.c b/src/g_game.c index d60ca57bd..6f5c5e69d 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -765,9 +765,20 @@ const char *G_BuildMapName(INT32 map) { static char mapname[10] = "MAPXX"; // internal map name (wad resource name) - I_Assert(map > 0); + I_Assert(map >= 0); I_Assert(map <= NUMMAPS); + if (map == 0) // hack??? + { + if (gamestate == GS_TITLESCREEN) + map = -1; + else if (gamestate == GS_LEVEL) + map = gamemap; + else + map = prevmap; + map = G_RandMap(G_TOLFlag(cv_newgametype.value), map, false, false, 0, false); + } + if (map < 100) sprintf(&mapname[3], "%.2d", map); else @@ -4260,6 +4271,9 @@ char *G_BuildMapTitle(INT32 mapnum) { char *title = NULL; + if (mapnum == 0) + return Z_StrDup("Random"); + if (strcmp(mapheaderinfo[mapnum-1]->lvlttl, "")) { size_t len = 1; diff --git a/src/m_menu.c b/src/m_menu.c index ae46549c7..910076e54 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -383,7 +383,7 @@ static void Dummystaff_OnChange(void); // ========================================================================== static CV_PossibleValue_t map_cons_t[] = { - {1,"MIN"}, + {0,"MIN"}, {NUMMAPS, "MAX"}, {0, NULL} }; @@ -2147,9 +2147,9 @@ static void Dummystaff_OnChange(void) // Newgametype. Used for gametype changes. static void Newgametype_OnChange(void) { - if (menuactive) + if (cv_nextmap.value && menuactive) { - if(!mapheaderinfo[cv_nextmap.value-1]) + if (!mapheaderinfo[cv_nextmap.value-1]) P_AllocMapHeader((INT16)(cv_nextmap.value-1)); if ((cv_newgametype.value == GT_RACE && !(mapheaderinfo[cv_nextmap.value-1]->typeoflevel & TOL_RACE)) || // SRB2kart @@ -3852,6 +3852,10 @@ static void M_PrepareLevelSelect(void) // boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt) { + // Random map! + if (mapnum == -1) + return (gamestate != GS_TIMEATTACK && !modeattacking); + // Does the map exist? if (!mapheaderinfo[mapnum]) return false; @@ -5874,11 +5878,16 @@ static void M_TimeAttack(INT32 choice) M_PrepareLevelSelect(); M_SetupNextMenu(&SP_TimeAttackDef); - Nextmap_OnChange(); + + G_SetGamestate(GS_TIMEATTACK); + + if (cv_nextmap.value) + Nextmap_OnChange(); + else + CV_AddValue(&cv_nextmap, 1); itemOn = tastart; // "Start" is selected. - G_SetGamestate(GS_TIMEATTACK); S_ChangeMusicInternal("racent", true); } @@ -6689,8 +6698,11 @@ static INT32 M_FindFirstMap(INT32 gtype) for (i = 0; i < NUMMAPS; i++) { - if (mapheaderinfo[i] && (mapheaderinfo[i]->typeoflevel & gtype)) - return i + 1; + if (!mapheaderinfo[i]) + continue; + if (!(mapheaderinfo[i]->typeoflevel & gtype)) + continue; + return i + 1; } return 1; @@ -6722,6 +6734,9 @@ static void M_StartServer(INT32 choice) if (metalrecording) G_StopMetalDemo(); + if (!cv_nextmap.value) + CV_SetValue(&cv_nextmap, G_RandMap(G_TOLFlag(cv_newgametype.value), -1, false, false, 0, false)); + if (ssplayers < 1) { D_MapChange(cv_nextmap.value, cv_newgametype.value, (boolean)cv_kartencore.value, 1, 1, false, false); @@ -6749,16 +6764,18 @@ static void M_DrawLevelSelectOnly(boolean leftfade, boolean rightfade) lumpnum_t lumpnum; patch_t *PictureOfLevel; INT32 x, y, w, i, oldval, trans, dupadjust = ((vid.width/vid.dupx) - BASEVIDWIDTH)>>1; - const char *mapname = G_BuildMapName(cv_nextmap.value); - //boolean doencore = (cv_kartencore.value && cv_newgametype.value == GT_RACE); // A 160x100 image of the level as entry MAPxxP - lumpnum = W_CheckNumForName(va("%sP", mapname)); - - if (lumpnum != LUMPERROR) - PictureOfLevel = W_CachePatchNum(lumpnum, PU_CACHE); + if (cv_nextmap.value) + { + lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(cv_nextmap.value))); + if (lumpnum != LUMPERROR) + PictureOfLevel = W_CachePatchNum(lumpnum, PU_CACHE); + else + PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); + } else - PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); + PictureOfLevel = W_CachePatchName("RANDOMLV", PU_CACHE); w = SHORT(PictureOfLevel->width)/2; i = SHORT(PictureOfLevel->height)/2; @@ -6803,7 +6820,7 @@ static void M_DrawLevelSelectOnly(boolean leftfade, boolean rightfade) do { i--; - if (i == -1) + if (i == -2) i = NUMMAPS-1; if (i == oldval) @@ -6815,13 +6832,16 @@ static void M_DrawLevelSelectOnly(boolean leftfade, boolean rightfade) } while (!M_CanShowLevelInList(i, cv_newgametype.value)); // A 160x100 image of the level as entry MAPxxP - mapname = G_BuildMapName(i+1); - lumpnum = W_CheckNumForName(va("%sP", mapname)); - - if (lumpnum != LUMPERROR) - PictureOfLevel = W_CachePatchNum(lumpnum, PU_CACHE); + if (i+1) + { + lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(i+1))); + if (lumpnum != LUMPERROR) + PictureOfLevel = W_CachePatchNum(lumpnum, PU_CACHE); + else + PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); + } else - PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); + PictureOfLevel = W_CachePatchName("RANDOMLV", PU_CACHE); x -= horizspac + w/2; @@ -6839,7 +6859,7 @@ static void M_DrawLevelSelectOnly(boolean leftfade, boolean rightfade) { i++; if (i == NUMMAPS) - i = 0; + i = -1; if (i == oldval) return; @@ -6850,13 +6870,16 @@ static void M_DrawLevelSelectOnly(boolean leftfade, boolean rightfade) } while (!M_CanShowLevelInList(i, cv_newgametype.value)); // A 160x100 image of the level as entry MAPxxP - mapname = G_BuildMapName(i+1); - lumpnum = W_CheckNumForName(va("%sP", mapname)); - - if (lumpnum != LUMPERROR) - PictureOfLevel = W_CachePatchNum(lumpnum, PU_CACHE); + if (i+1) + { + lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(i+1))); + if (lumpnum != LUMPERROR) + PictureOfLevel = W_CachePatchNum(lumpnum, PU_CACHE); + else + PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); + } else - PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); + PictureOfLevel = W_CachePatchName("RANDOMLV", PU_CACHE); V_DrawTinyScaledPatch(x, y, trans, PictureOfLevel); From 2b9068378f7c67038f1b2cceb6c976c501b554cf Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 15 Aug 2018 16:56:26 +0100 Subject: [PATCH 013/146] Correct minor issue with random map name selection. --- src/g_game.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 6f5c5e69d..15c9bab29 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -773,10 +773,10 @@ const char *G_BuildMapName(INT32 map) if (gamestate == GS_TITLESCREEN) map = -1; else if (gamestate == GS_LEVEL) - map = gamemap; + map = gamemap-1; else map = prevmap; - map = G_RandMap(G_TOLFlag(cv_newgametype.value), map, false, false, 0, false); + map = G_RandMap(G_TOLFlag(cv_newgametype.value), map, false, false, 0, false)+1; } if (map < 100) From b637ae3d730b7d1f871973f418957da11db135f9 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 15 Aug 2018 16:59:28 +0100 Subject: [PATCH 014/146] Additional oversight corrected. --- src/m_menu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index 83e285942..82e6ac2f8 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6737,7 +6737,7 @@ static void M_StartServer(INT32 choice) G_StopMetalDemo(); if (!cv_nextmap.value) - CV_SetValue(&cv_nextmap, G_RandMap(G_TOLFlag(cv_newgametype.value), -1, false, false, 0, false)); + CV_SetValue(&cv_nextmap, G_RandMap(G_TOLFlag(cv_newgametype.value), -1, false, false, 0, false)+1); if (ssplayers < 1) { From 95c11ef732d9d08cbcfb40f2f1dd28624ebeaafb Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 16 Aug 2018 15:29:34 +0100 Subject: [PATCH 015/146] Realised I'd forgotten to stop the item explosion from being encoremapped. --- src/info.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/info.c b/src/info.c index 66b6bb4b2..1652fb88f 100644 --- a/src/info.c +++ b/src/info.c @@ -13303,7 +13303,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY|MF_SCENERY|MF_SLIDEME, // flags + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, From f2b73e15b41c9a9db15373c5aaa9a6b56431a8eb Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 26 Aug 2018 15:15:03 +0100 Subject: [PATCH 016/146] * Exempt drop shadows from encore remapping. * Make MT_GHOST's encoremapping depend on whether the source was encoremapped. * Revamp how sector typegroup 2, type 15 inverts the encoremapping (so planes don't get awkwardly desynchronised). --- src/info.c | 4 ++-- src/p_user.c | 3 +++ src/r_bsp.c | 11 +++++++---- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/info.c b/src/info.c index 1652fb88f..464c41663 100644 --- a/src/info.c +++ b/src/info.c @@ -13114,7 +13114,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 1000, // mass 8, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_SCENERY, // flags + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_SCENERY|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -16599,7 +16599,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_NOGRAVITY|MF_SCENERY, // flags + MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, diff --git a/src/p_user.c b/src/p_user.c index a4d624c19..ba7cb80b3 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1599,6 +1599,9 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj) if (mobj->flags2 & MF2_OBJECTFLIP) ghost->flags |= MF2_OBJECTFLIP; + if (!(mobj->flags & MF_DONTENCOREMAP)) + mobj->flags &= ~MF_DONTENCOREMAP; + return ghost; } diff --git a/src/r_bsp.c b/src/r_bsp.c index 981d0b56e..34b082caf 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -39,7 +39,7 @@ INT32 doorclosed; static boolean R_NoEncore(sector_t *sector, boolean ceiling) { - boolean invertencore = (GETSECSPECIAL(sector->special, 2) != 15); + boolean invertencore = (GETSECSPECIAL(sector->special, 2) == 15); #if 0 // perfect implementation INT32 val = GETSECSPECIAL(sector->special, 3); if (val != 1 && val != 3 // spring panel @@ -47,11 +47,14 @@ static boolean R_NoEncore(sector_t *sector, boolean ceiling) if ((!(sector->special & (1<<8)) || (sector->special & ((4|8)<<8))) // spring panel #endif && GETSECSPECIAL(sector->special, 4) != 6) // sneaker panel - return !invertencore; + return invertencore; + + if (invertencore) + return false; if (ceiling) - return ((boolean)(sector->flags & SF_FLIPSPECIAL_CEILING) == invertencore); - return ((boolean)(sector->flags & SF_FLIPSPECIAL_FLOOR) == invertencore); + return ((boolean)(sector->flags & SF_FLIPSPECIAL_CEILING)); + return ((boolean)(sector->flags & SF_FLIPSPECIAL_FLOOR)); } // From 98ccb96938232e35f5d0369942a98c5719425608 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 26 Aug 2018 16:23:50 +0100 Subject: [PATCH 017/146] Real time reordering of intermission rankings as rank counts up! Also features jittering of the intermission elements because I thought it'd be fun, plus some better handling of players leaving (and then new ones joining) mid-intermission. --- src/y_inter.c | 64 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 42 insertions(+), 22 deletions(-) diff --git a/src/y_inter.c b/src/y_inter.c index 43bbf6bfc..562457e1a 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -89,8 +89,9 @@ typedef union INT32 numplayers; // Number of players being displayed char levelstring[64]; // holds levelnames up to 64 characters // SRB2kart - UINT8 increase[MAXPLAYERS]; //how much did the score increase by? - UINT32 val[MAXPLAYERS]; //Gametype-specific value + UINT8 increase[MAXPLAYERS]; // how much did the score increase by? + UINT8 jitter[MAXPLAYERS]; // wiggle + UINT32 val[MAXPLAYERS]; // Gametype-specific value UINT8 pos[MAXPLAYERS]; // player positions. used for ties boolean rankingsmode; // rankings mode boolean encore; // encore mode @@ -191,22 +192,28 @@ static void Y_CompareBattle(INT32 i) static void Y_CompareRank(INT32 i) { - if (!(data.match.val[data.match.numplayers] == UINT32_MAX || players[i].score > data.match.val[data.match.numplayers])) + UINT8 increase = ((data.match.increase[i] == UINT8_MAX) ? 0 : data.match.increase[i]); + if (!(data.match.val[data.match.numplayers] == UINT32_MAX || (players[i].score - increase) > data.match.val[data.match.numplayers])) return; - data.match.val[data.match.numplayers] = players[i].score; + data.match.val[data.match.numplayers] = (players[i].score - increase); data.match.num[data.match.numplayers] = i; } -static void Y_CalculateMatchData(boolean rankingsmode, void (*comparison)(INT32)) +static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32)) { INT32 i, j; boolean completed[MAXPLAYERS]; INT32 numplayersingame = 0; // Initialize variables - if ((data.match.rankingsmode = rankingsmode)) + if (rankingsmode > 1) + ; + else if ((data.match.rankingsmode = (boolean)rankingsmode)) + { sprintf(data.match.levelstring, "* Total Rankings *"); + data.match.encore = false; + } else { // set up the levelstring @@ -239,18 +246,24 @@ static void Y_CalculateMatchData(boolean rankingsmode, void (*comparison)(INT32) } data.match.levelstring[sizeof data.match.levelstring - 1] = '\0'; - } - data.match.encore = (!rankingsmode && encoremode); + data.match.encore = encoremode; + + memset(data.match.jitter, 0, sizeof (data.match.jitter)); + } for (i = 0; i < MAXPLAYERS; i++) { data.match.val[i] = UINT32_MAX; - if (!rankingsmode) - data.match.increase[i] = UINT8_MAX; if (!playeringame[i] || players[i].spectator) + { + data.match.increase[i] = UINT8_MAX; continue; + } + + if (!rankingsmode) + data.match.increase[i] = UINT8_MAX; numplayersingame++; } @@ -432,10 +445,16 @@ void Y_IntermissionDrawer(void) for (i = 0; i < data.match.numplayers; i++) { + boolean dojitter = data.match.jitter[data.match.num[i]]; + data.match.jitter[data.match.num[i]] = 0; + if (data.match.num[i] != MAXPLAYERS && playeringame[data.match.num[i]] && !players[data.match.num[i]].spectator) { char strtime[MAXPLAYERNAME+1]; + if (dojitter) + y--; + V_DrawCenteredString(x+6, y, 0, va("%d", data.match.pos[i])); if (data.match.color[i] == 0) @@ -470,11 +489,9 @@ void Y_IntermissionDrawer(void) V_DrawRightAlignedString(x+120, y, 0, strtime); else V_DrawRightAlignedString(x+120+BASEVIDWIDTH/2, y, 0, strtime); - - snprintf(strtime, sizeof strtime, "%d", data.match.val[i]-data.match.increase[data.match.num[i]]); } - else - snprintf(strtime, sizeof strtime, "%d", data.match.val[i]); + + snprintf(strtime, sizeof strtime, "%d", data.match.val[i]); if (data.match.numplayers > 8) V_DrawRightAlignedString(x+152, y, 0, strtime); @@ -512,12 +529,12 @@ void Y_IntermissionDrawer(void) } } } + + if (dojitter) + y++; } else - { - data.match.increase[data.match.num[i]] = 0; data.match.num[i] = MAXPLAYERS; // this should be the only field setting in this function - } y += 16; @@ -598,7 +615,7 @@ void Y_Ticker(void) else { if (!data.match.rankingsmode && (intertic >= sorttic + 8)) - Y_CalculateMatchData(true, Y_CompareRank); + Y_CalculateMatchData(1, Y_CompareRank); if (data.match.rankingsmode && intertic > sorttic+(2*TICRATE)) { @@ -612,14 +629,17 @@ void Y_Ticker(void) || data.match.increase[data.match.num[q]] == UINT8_MAX) continue; - data.match.increase[data.match.num[q]]--; r++; - if (data.match.increase[data.match.num[q]]) + data.match.jitter[data.match.num[q]] = 1; + if (--data.match.increase[data.match.num[q]]) kaching = false; } if (r) + { S_StartSound(NULL, (kaching ? sfx_chchng : sfx_ptally)); + Y_CalculateMatchData(2, Y_CompareRank); + } else endtic = intertic + 3*TICRATE; // 3 second pause after end of tally } @@ -762,7 +782,7 @@ void Y_StartIntermission(void) case int_match: { // Calculate who won - Y_CalculateMatchData(false, Y_CompareBattle); + Y_CalculateMatchData(0, Y_CompareBattle); if (cv_inttime.value > 0) S_ChangeMusicInternal("racent", true); // loop it break; @@ -785,7 +805,7 @@ void Y_StartIntermission(void) } // Calculate who won - Y_CalculateMatchData(false, Y_CompareRace); + Y_CalculateMatchData(0, Y_CompareRace); break; } From dec11f37ff941b2544ba3ded0b32dbb4a2a59eea Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 26 Aug 2018 17:31:04 +0100 Subject: [PATCH 018/146] Increase the amount of time between the switch to the Rankings half of intermission and ranking is calculated a tad. Turns out it wasn't taking the length of the level-to-rankings switch animation into account! --- src/y_inter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/y_inter.c b/src/y_inter.c index 562457e1a..636b2d239 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -617,7 +617,7 @@ void Y_Ticker(void) if (!data.match.rankingsmode && (intertic >= sorttic + 8)) Y_CalculateMatchData(1, Y_CompareRank); - if (data.match.rankingsmode && intertic > sorttic+(2*TICRATE)) + if (data.match.rankingsmode && intertic > sorttic+16+(2*TICRATE)) { INT32 q=0,r=0; boolean kaching = true; From 798cf3c8ae0cdeba112452c8f93d5b2cca73bd6f Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sun, 26 Aug 2018 14:58:21 -0400 Subject: [PATCH 019/146] Rebalance Battle items in response to last night's netgame --- src/k_kart.c | 62 +++++++++++++++++++++++++++------------------------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index da085225e..3e1b119ec 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -490,29 +490,29 @@ static INT32 K_KartItemOddsRace[NUMKARTRESULTS][9] = static INT32 K_KartItemOddsBattle[NUMKARTRESULTS][6] = { - //P-Odds 0 1 2 3 - /*Sneaker*/ { 2, 2, 2, 2 }, // Sneaker - /*Rocket Sneaker*/ { 0, 0, 0, 0 }, // Rocket Sneaker - /*Invincibility*/ { 4, 2, 1, 2 }, // Invincibility - /*Banana*/ { 0, 0, 2, 0 }, // Banana - /*Eggman Monitor*/ { 0, 0, 1, 0 }, // Eggman Monitor - /*Orbinaut*/ { 0, 1, 5, 0 }, // Orbinaut - /*Jawz*/ { 1, 3, 2, 2 }, // Jawz - /*Mine*/ { 1, 3, 2, 2 }, // Mine - /*Ballhog*/ { 1, 2, 1, 2 }, // Ballhog - /*Self-Propelled Bomb*/ { 0, 0, 0, 0 }, // Self-Propelled Bomb - /*Grow*/ { 4, 2, 0, 2 }, // Grow - /*Shrink*/ { 0, 0, 0, 0 }, // Shrink - /*Thunder Shield*/ { 0, 0, 0, 0 }, // Thunder Shield - /*Hyudoro*/ { 0, 0, 1, 0 }, // Hyudoro - /*Pogo Spring*/ { 0, 0, 1, 0 }, // Pogo Spring - /*Kitchen Sink*/ { 0, 0, 0, 0 }, // Kitchen Sink - /*Sneaker x3*/ { 2, 0, 0, 2 }, // Sneaker x3 - /*Banana x3*/ { 0, 1, 1, 1 }, // Banana x3 - /*Banana x10*/ { 1, 0, 0, 1 }, // Banana x10 - /*Orbinaut x3*/ { 0, 1, 1, 1 }, // Orbinaut x3 - /*Orbinaut x4*/ { 1, 1, 0, 1 }, // Orbinaut x4 - /*Jawz x2*/ { 3, 2, 0, 2 } // Jawz x2 + //P-Odds 0 1 2 3 4 5 + /*Sneaker*/ { 2, 2, 2, 1, 0, 2 }, // Sneaker + /*Rocket Sneaker*/ { 0, 0, 0, 0, 0, 0 }, // Rocket Sneaker + /*Invincibility*/ { 1, 1, 2, 4, 5, 2 }, // Invincibility + /*Banana*/ { 2, 1, 0, 0, 0, 0 }, // Banana + /*Eggman Monitor*/ { 2, 1, 0, 0, 0, 0 }, // Eggman Monitor + /*Orbinaut*/ { 4, 2, 1, 0, 0, 0 }, // Orbinaut + /*Jawz*/ { 2, 3, 2, 1, 0, 2 }, // Jawz + /*Mine*/ { 2, 3, 2, 1, 0, 2 }, // Mine + /*Ballhog*/ { 1, 2, 2, 1, 0, 2 }, // Ballhog + /*Self-Propelled Bomb*/ { 0, 0, 0, 0, 0, 0 }, // Self-Propelled Bomb + /*Grow*/ { 0, 1, 2, 4, 5, 2 }, // Grow + /*Shrink*/ { 0, 0, 0, 0, 0, 0 }, // Shrink + /*Thunder Shield*/ { 0, 0, 0, 0, 0, 0 }, // Thunder Shield + /*Hyudoro*/ { 1, 1, 0, 0, 0, 0 }, // Hyudoro + /*Pogo Spring*/ { 1, 1, 0, 0, 0, 0 }, // Pogo Spring + /*Kitchen Sink*/ { 0, 0, 0, 0, 0, 0 }, // Kitchen Sink + /*Sneaker x3*/ { 0, 0, 0, 2, 4, 2 }, // Sneaker x3 + /*Banana x3*/ { 1, 1, 2, 0, 0, 0 }, // Banana x3 + /*Banana x10*/ { 0, 0, 1, 1, 0, 2 }, // Banana x10 + /*Orbinaut x3*/ { 1, 1, 2, 0, 0, 0 }, // Orbinaut x3 + /*Orbinaut x4*/ { 0, 0, 1, 3, 4, 2 }, // Orbinaut x4 + /*Jawz x2*/ { 0, 0, 1, 2, 4, 2 } // Jawz x2 }; /** \brief Item Roulette for Kart @@ -851,19 +851,21 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) if (oddsvalid[0]) SETUPDISTTABLE(0,1); if (oddsvalid[1]) SETUPDISTTABLE(1,1); if (oddsvalid[2]) SETUPDISTTABLE(2,1); + if (oddsvalid[3]) SETUPDISTTABLE(3,1); + if (oddsvalid[4]) SETUPDISTTABLE(4,1); - if (player->kartstuff[k_roulettetype] == 1 && oddsvalid[3]) // Player-controlled "Karma" items - useodds = 3; + if (player->kartstuff[k_roulettetype] == 1 && oddsvalid[5]) // 5 is the extreme odds of player-controlled "Karma" items + useodds = 5; else { - SINT8 wantedpos = (player->kartstuff[k_bumper]-bestbumper)+2; // 0 is two bumpers below best player's bumper count, 2 is best player's bumper count + SINT8 wantedpos = (bestbumper-player->kartstuff[k_bumper]); // 0 is the best player's bumper count, 1 is a bumper below best, 2 is two bumpers below, etc if (K_IsPlayerWanted(player)) wantedpos--; - if (wantedpos > 2) - wantedpos = 2; - if (wantedpos < 0) + if (wantedpos > 4) // Don't run off into karma items + wantedpos = 4; + if (wantedpos < 0) // Don't go below somehow wantedpos = 0; - useodds = disttable[(wantedpos * distlen) / 3]; + useodds = disttable[(wantedpos * distlen) / 5]; } } else From 844fbbfc4cb1e82c36b45338a3ec92df116e93b0 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sun, 26 Aug 2018 15:17:55 -0400 Subject: [PATCH 020/146] Good catch --- src/k_kart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index 3e1b119ec..ecc27b6f4 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -860,7 +860,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) { SINT8 wantedpos = (bestbumper-player->kartstuff[k_bumper]); // 0 is the best player's bumper count, 1 is a bumper below best, 2 is two bumpers below, etc if (K_IsPlayerWanted(player)) - wantedpos--; + wantedpos++; if (wantedpos > 4) // Don't run off into karma items wantedpos = 4; if (wantedpos < 0) // Don't go below somehow From 5498b63ccaedac43fa5639c4fde0f49fa249bc73 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sun, 26 Aug 2018 19:55:31 -0400 Subject: [PATCH 021/146] Adjustments made to address the netgame Less grow, less invinc, less ballhog, just a teensy bit less triple orbinaut, and SPB odds no longer scale with lower player counts like other power items do --- src/k_kart.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index ecc27b6f4..fe76186d7 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -491,26 +491,26 @@ static INT32 K_KartItemOddsRace[NUMKARTRESULTS][9] = static INT32 K_KartItemOddsBattle[NUMKARTRESULTS][6] = { //P-Odds 0 1 2 3 4 5 - /*Sneaker*/ { 2, 2, 2, 1, 0, 2 }, // Sneaker + /*Sneaker*/ { 3, 2, 2, 2, 0, 2 }, // Sneaker /*Rocket Sneaker*/ { 0, 0, 0, 0, 0, 0 }, // Rocket Sneaker - /*Invincibility*/ { 1, 1, 2, 4, 5, 2 }, // Invincibility + /*Invincibility*/ { 0, 1, 2, 3, 4, 2 }, // Invincibility /*Banana*/ { 2, 1, 0, 0, 0, 0 }, // Banana - /*Eggman Monitor*/ { 2, 1, 0, 0, 0, 0 }, // Eggman Monitor - /*Orbinaut*/ { 4, 2, 1, 0, 0, 0 }, // Orbinaut - /*Jawz*/ { 2, 3, 2, 1, 0, 2 }, // Jawz - /*Mine*/ { 2, 3, 2, 1, 0, 2 }, // Mine - /*Ballhog*/ { 1, 2, 2, 1, 0, 2 }, // Ballhog + /*Eggman Monitor*/ { 1, 1, 0, 0, 0, 0 }, // Eggman Monitor + /*Orbinaut*/ { 6, 2, 1, 0, 0, 0 }, // Orbinaut + /*Jawz*/ { 3, 3, 3, 2, 0, 2 }, // Jawz + /*Mine*/ { 2, 3, 3, 1, 0, 2 }, // Mine + /*Ballhog*/ { 0, 1, 2, 1, 0, 2 }, // Ballhog /*Self-Propelled Bomb*/ { 0, 0, 0, 0, 0, 0 }, // Self-Propelled Bomb - /*Grow*/ { 0, 1, 2, 4, 5, 2 }, // Grow + /*Grow*/ { 0, 0, 1, 2, 4, 2 }, // Grow /*Shrink*/ { 0, 0, 0, 0, 0, 0 }, // Shrink /*Thunder Shield*/ { 0, 0, 0, 0, 0, 0 }, // Thunder Shield /*Hyudoro*/ { 1, 1, 0, 0, 0, 0 }, // Hyudoro /*Pogo Spring*/ { 1, 1, 0, 0, 0, 0 }, // Pogo Spring /*Kitchen Sink*/ { 0, 0, 0, 0, 0, 0 }, // Kitchen Sink /*Sneaker x3*/ { 0, 0, 0, 2, 4, 2 }, // Sneaker x3 - /*Banana x3*/ { 1, 1, 2, 0, 0, 0 }, // Banana x3 + /*Banana x3*/ { 1, 2, 1, 0, 0, 0 }, // Banana x3 /*Banana x10*/ { 0, 0, 1, 1, 0, 2 }, // Banana x10 - /*Orbinaut x3*/ { 1, 1, 2, 0, 0, 0 }, // Orbinaut x3 + /*Orbinaut x3*/ { 0, 1, 2, 1, 0, 0 }, // Orbinaut x3 /*Orbinaut x4*/ { 0, 0, 1, 3, 4, 2 }, // Orbinaut x4 /*Jawz x2*/ { 0, 0, 1, 2, 4, 2 } // Jawz x2 }; @@ -668,7 +668,7 @@ static INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed) if (!cv_ballhog.value) newodds = 0; break; case KITEM_SPB: - POWERITEMODDS(newodds); + //POWERITEMODDS(newodds); if ((!cv_selfpropelledbomb.value) || (indirectitemcooldown > 0) || (pexiting > 0) From 82e018eb998cf84c9084be73feea43b3ee274083 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Mon, 27 Aug 2018 01:07:44 -0400 Subject: [PATCH 022/146] Correct remaining instances where step up/down scales with the object instead of the map --- src/p_map.c | 4 ++-- src/p_mobj.c | 2 +- src/p_user.c | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index 5c3e7177c..03a4dc346 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -2793,7 +2793,7 @@ boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y) if (!(thing->flags & MF_NOCLIP)) { - const fixed_t maxstep = MAXSTEPMOVE; + const fixed_t maxstep = FixedMul(MAXSTEPMOVE, mapheaderinfo[gamemap-1]->mobj_scale); if (tmceilingz - tmfloorz < thing->height) return false; // doesn't fit @@ -3276,7 +3276,7 @@ static boolean PTR_SlideTraverse(intercept_t *in) if (opentop - slidemo->z < slidemo->height) goto isblocking; // mobj is too high - if (openbottom - slidemo->z > FixedMul(MAXSTEPMOVE, slidemo->scale)) + if (openbottom - slidemo->z > FixedMul(MAXSTEPMOVE, mapheaderinfo[gamemap-1]->mobj_scale)) goto isblocking; // too big a step up // this line doesn't block movement diff --git a/src/p_mobj.c b/src/p_mobj.c index 6b01f0a84..1db178da0 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7913,7 +7913,7 @@ void P_MobjThinker(mobj_t *mobj) else { mobj->flags &= ~MF_NOGRAVITY; - if (mobj->z > mobj->watertop && mobj->z - mobj->watertop < FixedMul(MAXSTEPMOVE, mobj->scale)) + if (mobj->z > mobj->watertop && mobj->z - mobj->watertop < FixedMul(MAXSTEPMOVE, mapheaderinfo[gamemap-1]->mobj_scale)) mobj->z = mobj->watertop; } break; diff --git a/src/p_user.c b/src/p_user.c index 53faf8f3f..fabce7efc 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2978,7 +2978,7 @@ static fixed_t teeteryl, teeteryh; static boolean PIT_CheckSolidsTeeter(mobj_t *thing) // SRB2kart - unused. { fixed_t blockdist; - fixed_t tiptop = FixedMul(MAXSTEPMOVE, teeterer->scale); + fixed_t tiptop = FixedMul(MAXSTEPMOVE, mapheaderinfo[gamemap-1]->mobj_scale); fixed_t thingtop = thing->z + thing->height; fixed_t teeterertop = teeterer->z + teeterer->height; @@ -3095,7 +3095,7 @@ static void P_DoTeeter(player_t *player) // SRB2kart - unused. boolean roverfloor; // solid 3d floors? fixed_t floorheight, ceilingheight; fixed_t topheight, bottomheight; // for 3d floor usage - const fixed_t tiptop = FixedMul(MAXSTEPMOVE, player->mo->scale); // Distance you have to be above the ground in order to teeter. + const fixed_t tiptop = FixedMul(MAXSTEPMOVE, mapheaderinfo[gamemap-1]->mobj_scale); // Distance you have to be above the ground in order to teeter. if (player->mo->standingslope && player->mo->standingslope->zdelta >= (FRACUNIT/2)) // Always teeter if the slope is too steep. teeter = true; @@ -7765,8 +7765,8 @@ boolean P_LookForEnemies(player_t *player) if (mo->type == MT_DETON) // Don't be STUPID, Sonic! continue; - if (((mo->z > player->mo->z+FixedMul(MAXSTEPMOVE, player->mo->scale)) && !(player->mo->eflags & MFE_VERTICALFLIP)) - || ((mo->z+mo->height < player->mo->z+player->mo->height-FixedMul(MAXSTEPMOVE, player->mo->scale)) && (player->mo->eflags & MFE_VERTICALFLIP))) // Reverse gravity check - Flame. + if (((mo->z > player->mo->z+FixedMul(MAXSTEPMOVE, mapheaderinfo[gamemap-1]->mobj_scale)) && !(player->mo->eflags & MFE_VERTICALFLIP)) + || ((mo->z+mo->height < player->mo->z+player->mo->height-FixedMul(MAXSTEPMOVE, mapheaderinfo[gamemap-1]->mobj_scale)) && (player->mo->eflags & MFE_VERTICALFLIP))) // Reverse gravity check - Flame. continue; // Don't home upwards! if (P_AproxDistance(P_AproxDistance(player->mo->x-mo->x, player->mo->y-mo->y), From 8f790957f1bcecc92ea0c851a51cea8b3ffe1318 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Mon, 27 Aug 2018 18:09:32 -0400 Subject: [PATCH 023/146] Last touches for smk maps - different min/max on capped spring pads - turn the normally almost-useless "non-ramp sector" type into "wall sector", which disables both stepup AND stepdown instead of just stepdown --- src/k_kart.c | 4 ++-- src/p_map.c | 4 ++++ src/p_spec.c | 12 ++++++------ 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index fe76186d7..22d8124e9 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1585,9 +1585,9 @@ fixed_t K_3dKartMovement(player_t *player, boolean onground, fixed_t forwardmove if (player->kartstuff[k_pogospring]) // Pogo Spring minimum/maximum thrust { - const fixed_t hscale = mapheaderinfo[gamemap-1]->mobj_scale + (mapheaderinfo[gamemap-1]->mobj_scale - player->mo->scale); + const fixed_t hscale = mapheaderinfo[gamemap-1]->mobj_scale /*+ (mapheaderinfo[gamemap-1]->mobj_scale - player->mo->scale)*/; const fixed_t minspeed = 24*hscale; - const fixed_t maxspeed = 36*hscale; + const fixed_t maxspeed = 32*hscale; if (newspeed > maxspeed && player->kartstuff[k_pogospring] == 2) newspeed = maxspeed; diff --git a/src/p_map.c b/src/p_map.c index 03a4dc346..d5fb5ef35 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -2587,6 +2587,10 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) if (P_PlayerTouchingSectorSpecial(thing->player, 1, 13) || GETSECSPECIAL(R_PointInSubsector(x, y)->sector->special, 1) == 13) maxstep <<= 1; + // If using type Section1:14, no maxstep. For ledges you want the player to LAND on, not climb! (see: SMK VL2) + else if (P_PlayerTouchingSectorSpecial(thing->player, 1, 14) + || GETSECSPECIAL(R_PointInSubsector(x, y)->sector->special, 1) == 14) + maxstep = 0; // Don't 'step up' while springing, // Only step up "if needed". diff --git a/src/p_spec.c b/src/p_spec.c index 87894d059..f493f7b95 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3621,7 +3621,7 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers player->powers[pw_spacetime] = spacetimetics + 1; break; case 13: // Ramp Sector (Increase step-up/down) - case 14: // Non-Ramp Sector (Don't step-down) + case 14: // Non-Ramp Sector (Don't step-up/down) case 15: // Bouncy Sector (FOF Control Only) break; } @@ -3756,8 +3756,8 @@ DoneSection2: case 1: // SRB2kart: Spring Panel if (roversector || P_MobjReadyToTrigger(player->mo, sector)) { - const fixed_t scale = mapheaderinfo[gamemap-1]->mobj_scale + abs(player->mo->scale - mapheaderinfo[gamemap-1]->mobj_scale); - const fixed_t minspeed = 24*scale; + const fixed_t hscale = mapheaderinfo[gamemap-1]->mobj_scale + (mapheaderinfo[gamemap-1]->mobj_scale - player->mo->scale); + const fixed_t minspeed = 24*hscale; if (player->mo->eflags & MFE_SPRUNG) break; @@ -3776,9 +3776,9 @@ DoneSection2: case 3: // SRB2kart: Spring Panel (capped speed) if (roversector || P_MobjReadyToTrigger(player->mo, sector)) { - const fixed_t scale = mapheaderinfo[gamemap-1]->mobj_scale + abs(player->mo->scale - mapheaderinfo[gamemap-1]->mobj_scale); - const fixed_t minspeed = 24*scale; - const fixed_t maxspeed = 36*scale; + const fixed_t hscale = mapheaderinfo[gamemap-1]->mobj_scale + (mapheaderinfo[gamemap-1]->mobj_scale - player->mo->scale); + const fixed_t minspeed = 24*hscale; + const fixed_t maxspeed = 32*hscale; if (player->mo->eflags & MFE_SPRUNG) break; From 20cfe7e4a15a4c1be1691fdfdf922ef840943c8f Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 28 Aug 2018 23:06:31 -0400 Subject: [PATCH 024/146] Make the low player count distributions slightly more extreme Scales below 8 players instead of 6 players. The distance multipler in 4P is now x1.14 instead of x1.07. --- src/k_kart.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 22d8124e9..b390ceaef 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -615,8 +615,8 @@ static INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed) players[first].mo->z - players[second].mo->z) / mapheaderinfo[gamemap-1]->mobj_scale; if (franticitems) secondist = (15*secondist/14); - if (pingame < 6 && !G_BattleGametype()) - secondist = ((28+(6-pingame))*secondist/28); + if (pingame < 8 && !G_BattleGametype()) + secondist = ((28+(8-pingame))*secondist/28); } // POWERITEMODDS handles all of the "frantic item" related functionality, for all of our powerful items. @@ -628,8 +628,8 @@ static INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed) #define POWERITEMODDS(odds) \ if (franticitems) \ odds *= 2; \ - if (pingame < 6 && !G_BattleGametype()) \ - odds = FixedMul(odds*FRACUNIT, FRACUNIT+min((6-pingame)*(FRACUNIT/25), FRACUNIT))/FRACUNIT; \ + if (pingame < 8 && !G_BattleGametype()) \ + odds = FixedMul(odds*FRACUNIT, FRACUNIT+min((8-pingame)*(FRACUNIT/25), FRACUNIT))/FRACUNIT; \ if (mashed > 0) \ odds = FixedDiv(odds*FRACUNIT, mashed+FRACUNIT)/FRACUNIT \ @@ -881,8 +881,8 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) if (franticitems) // Frantic items make the distances between everyone artifically higher, for crazier items pdis = (15*pdis/14); - if (pingame < 6 && !G_BattleGametype()) - pdis = ((28+(6-pingame))*pdis/28); + if (pingame < 8 && !G_BattleGametype()) + pdis = ((28+(8-pingame))*pdis/28); if (pingame == 1 && oddsvalid[0]) // Record Attack, or just alone useodds = 0; From d443650c2669d9ad76f9a05182805457c6b7a7e9 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Wed, 29 Aug 2018 14:28:28 -0400 Subject: [PATCH 025/146] Item distribution debugger, and oversight pointed out by this Item distribution debugger is a netvar that enables cheats, so no exploiting! --- src/d_netcmd.c | 4 +- src/d_netcmd.h | 3 +- src/k_kart.c | 280 ++++++++++++++++++++++++++++++++----------------- 3 files changed, 189 insertions(+), 98 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 9b635cb0e..cb5523bac 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -365,8 +365,10 @@ static CV_PossibleValue_t kartdebugitem_cons_t[] = {{-1, "MIN"}, {NUMKARTITEMS-1 consvar_t cv_kartdebugitem = {"kartdebugitem", "0", CV_NETVAR|CV_CHEAT, kartdebugitem_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; static CV_PossibleValue_t kartdebugamount_cons_t[] = {{1, "MIN"}, {255, "MAX"}, {0, NULL}}; consvar_t cv_kartdebugamount = {"kartdebugamount", "1", CV_NETVAR|CV_CHEAT, kartdebugamount_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_kartdebugcheckpoint = {"kartdebugcheckpoint", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_kartdebugshrink = {"kartdebugshrink", "Off", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_kartdebugdistribution = {"kartdebugdistribution", "Off", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; + +consvar_t cv_kartdebugcheckpoint = {"kartdebugcheckpoint", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; static CV_PossibleValue_t votetime_cons_t[] = {{10, "MIN"}, {3600, "MAX"}, {0, NULL}}; consvar_t cv_votetime = {"votetime", "20", CV_NETVAR, votetime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; diff --git a/src/d_netcmd.h b/src/d_netcmd.h index b2a57bc01..a8fd66b96 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -132,7 +132,8 @@ extern consvar_t cv_karteliminatelast; extern consvar_t cv_votetime; -extern consvar_t cv_kartdebugitem, cv_kartdebugamount, cv_kartdebugcheckpoint, cv_kartdebugshrink; +extern consvar_t cv_kartdebugitem, cv_kartdebugamount, cv_kartdebugshrink, cv_kartdebugdistribution; +extern consvar_t cv_kartdebugcheckpoint; extern consvar_t cv_itemfinder; diff --git a/src/k_kart.c b/src/k_kart.c index b390ceaef..54a5be532 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -409,8 +409,10 @@ void K_RegisterKartStuff(void) CV_RegisterVar(&cv_kartdebugitem); CV_RegisterVar(&cv_kartdebugamount); - CV_RegisterVar(&cv_kartdebugcheckpoint); CV_RegisterVar(&cv_kartdebugshrink); + CV_RegisterVar(&cv_kartdebugdistribution); + + CV_RegisterVar(&cv_kartdebugcheckpoint); } //} @@ -733,81 +735,14 @@ static INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed) //{ SRB2kart Roulette Code - Distance Based, no waypoints -static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) +static INT32 K_FindUseodds(player_t *player, fixed_t mashed, INT32 pingame, INT32 bestbumper) { const INT32 distvar = (64*14); INT32 i; - UINT8 pingame = 0; - UINT8 roulettestop; INT32 pdis = 0, useodds = 0; - INT32 spawnchance[NUMKARTRESULTS * NUMKARTODDS]; - INT32 chance = 0, numchoices = 0; - INT32 bestbumper = 0; - boolean oddsvalid[9]; UINT8 disttable[14]; UINT8 distlen = 0; - fixed_t mashed = 0; - - // This makes the roulette cycle through items - if this is 0, you shouldn't be here. - if (player->kartstuff[k_itemroulette]) - player->kartstuff[k_itemroulette]++; - else - return; - - // Gotta check how many players are active at this moment. - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i] || players[i].spectator) - continue; - pingame++; - if (players[i].kartstuff[k_bumper] > bestbumper) - bestbumper = players[i].kartstuff[k_bumper]; - } - - // This makes the roulette produce the random noises. - if ((player->kartstuff[k_itemroulette] % 3) == 1 && P_IsLocalPlayer(player)) - S_StartSound(NULL, sfx_mkitm1 + ((player->kartstuff[k_itemroulette] / 3) % 8)); - - roulettestop = (TICRATE*1) + (3*(pingame - player->kartstuff[k_position])); - - // If the roulette finishes or the player presses BT_ATTACK, stop the roulette and calculate the item. - // I'm returning via the exact opposite, however, to forgo having another bracket embed. Same result either way, I think. - // Finally, if you get past this check, now you can actually start calculating what item you get. - if ((cmd->buttons & BT_ATTACK) && !(player->kartstuff[k_eggmanheld] || player->kartstuff[k_itemheld]) && player->kartstuff[k_itemroulette] >= roulettestop) - { - // Mashing reduces your chances for the good items - mashed = FixedDiv((player->kartstuff[k_itemroulette])*FRACUNIT, ((TICRATE*3)+roulettestop)*FRACUNIT) - FRACUNIT; - } - else if (!(player->kartstuff[k_itemroulette] >= (TICRATE*3))) - return; - - if (cmd->buttons & BT_ATTACK) - player->pflags |= PF_ATTACKDOWN; - - if (player->kartstuff[k_roulettetype] == 2) // Fake items - { - player->kartstuff[k_eggmanexplode] = 4*TICRATE; - player->kartstuff[k_itemroulette] = 0; - player->kartstuff[k_roulettetype] = 0; - if (P_IsLocalPlayer(player)) - S_StartSound(NULL, sfx_mkitmE); - return; - } - - if (cv_kartdebugitem.value != 0) - { - K_KartGetItemResult(player, cv_kartdebugitem.value); - player->kartstuff[k_itemamount] = cv_kartdebugamount.value; - player->kartstuff[k_itemroulette] = 0; - player->kartstuff[k_roulettetype] = 0; - if (P_IsLocalPlayer(player)) - S_StartSound(NULL, sfx_dbgsal); - return; - } - - // Initializes existing spawnchance values - for (i = 0; i < (NUMKARTRESULTS * NUMKARTODDS); i++) - spawnchance[i] = 0; + boolean oddsvalid[9]; for (i = 0; i < 9; i++) { @@ -892,7 +827,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) useodds = disttable[distlen-1]; else { - for (i = 1; i < 12; i++) + for (i = 1; i < 13; i++) { if (pdis <= distvar * ((i * distlen) / 14)) { @@ -907,33 +842,90 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) //CONS_Printf("Got useodds %d. (position: %d, distance: %d)\n", useodds, player->kartstuff[k_position], pdis); -#define SETITEMRESULT(pos, itemnum) \ - for (chance = 0; chance < K_KartGetItemOdds(pos, itemnum, mashed); chance++) \ + return useodds; +} + +static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) +{ + INT32 i; + UINT8 pingame = 0; + UINT8 roulettestop; + INT32 useodds = 0; + INT32 spawnchance[NUMKARTRESULTS * NUMKARTODDS]; + INT32 chance = 0, numchoices = 0; + INT32 bestbumper = 0; + fixed_t mashed = 0; + + // This makes the roulette cycle through items - if this is 0, you shouldn't be here. + if (player->kartstuff[k_itemroulette]) + player->kartstuff[k_itemroulette]++; + else + return; + + // Gotta check how many players are active at this moment. + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator) + continue; + pingame++; + if (players[i].kartstuff[k_bumper] > bestbumper) + bestbumper = players[i].kartstuff[k_bumper]; + } + + // This makes the roulette produce the random noises. + if ((player->kartstuff[k_itemroulette] % 3) == 1 && P_IsLocalPlayer(player)) + S_StartSound(NULL, sfx_mkitm1 + ((player->kartstuff[k_itemroulette] / 3) % 8)); + + roulettestop = (TICRATE*1) + (3*(pingame - player->kartstuff[k_position])); + + // If the roulette finishes or the player presses BT_ATTACK, stop the roulette and calculate the item. + // I'm returning via the exact opposite, however, to forgo having another bracket embed. Same result either way, I think. + // Finally, if you get past this check, now you can actually start calculating what item you get. + if ((cmd->buttons & BT_ATTACK) && !(player->kartstuff[k_eggmanheld] || player->kartstuff[k_itemheld]) && player->kartstuff[k_itemroulette] >= roulettestop) + { + // Mashing reduces your chances for the good items + mashed = FixedDiv((player->kartstuff[k_itemroulette])*FRACUNIT, ((TICRATE*3)+roulettestop)*FRACUNIT) - FRACUNIT; + } + else if (!(player->kartstuff[k_itemroulette] >= (TICRATE*3))) + return; + + if (cmd->buttons & BT_ATTACK) + player->pflags |= PF_ATTACKDOWN; + + if (player->kartstuff[k_roulettetype] == 2) // Fake items + { + player->kartstuff[k_eggmanexplode] = 4*TICRATE; + player->kartstuff[k_itemroulette] = 0; + player->kartstuff[k_roulettetype] = 0; + if (P_IsLocalPlayer(player)) + S_StartSound(NULL, sfx_mkitmE); + return; + } + + if (cv_kartdebugitem.value != 0) + { + K_KartGetItemResult(player, cv_kartdebugitem.value); + player->kartstuff[k_itemamount] = cv_kartdebugamount.value; + player->kartstuff[k_itemroulette] = 0; + player->kartstuff[k_roulettetype] = 0; + if (P_IsLocalPlayer(player)) + S_StartSound(NULL, sfx_dbgsal); + return; + } + + // Initializes existing spawnchance values + for (i = 0; i < (NUMKARTRESULTS * NUMKARTODDS); i++) + spawnchance[i] = 0; + + // Split into another function for a debug function below + useodds = K_FindUseodds(player, mashed, pingame, bestbumper); + +#define SETITEMRESULT(itemnum) \ + for (chance = 0; chance < K_KartGetItemOdds(useodds, itemnum, mashed); chance++) \ spawnchance[numchoices++] = itemnum - SETITEMRESULT(useodds, KITEM_SNEAKER); // Sneaker - SETITEMRESULT(useodds, KITEM_ROCKETSNEAKER); // Rocket Sneaker - SETITEMRESULT(useodds, KITEM_INVINCIBILITY); // Invincibility - SETITEMRESULT(useodds, KITEM_BANANA); // Banana - SETITEMRESULT(useodds, KITEM_EGGMAN); // Eggman Monitor - SETITEMRESULT(useodds, KITEM_ORBINAUT); // Orbinaut - SETITEMRESULT(useodds, KITEM_JAWZ); // Jawz - SETITEMRESULT(useodds, KITEM_MINE); // Mine - SETITEMRESULT(useodds, KITEM_BALLHOG); // Ballhog - SETITEMRESULT(useodds, KITEM_SPB); // Self-Propelled Bomb - SETITEMRESULT(useodds, KITEM_GROW); // Grow - SETITEMRESULT(useodds, KITEM_SHRINK); // Shrink - SETITEMRESULT(useodds, KITEM_THUNDERSHIELD); // Thunder Shield - SETITEMRESULT(useodds, KITEM_HYUDORO); // Hyudoro - SETITEMRESULT(useodds, KITEM_POGOSPRING); // Pogo Spring - //SETITEMRESULT(useodds, KITEM_KITCHENSINK); // Kitchen Sink - - SETITEMRESULT(useodds, KRITEM_TRIPLESNEAKER); // Sneaker x3 - SETITEMRESULT(useodds, KRITEM_TRIPLEBANANA); // Banana x3 - SETITEMRESULT(useodds, KRITEM_TENFOLDBANANA); // Banana x10 - SETITEMRESULT(useodds, KRITEM_TRIPLEORBINAUT); // Orbinaut x3 - SETITEMRESULT(useodds, KRITEM_QUADORBINAUT); // Orbinaut x4 - SETITEMRESULT(useodds, KRITEM_DUALJAWZ); // Jawz x2 + for (i = 1; i < NUMKARTRESULTS; i++) + SETITEMRESULT(i); #undef SETITEMRESULT @@ -6399,8 +6391,101 @@ void K_drawKartFreePlay(UINT32 flashtime) LAPS_Y+3, V_SNAPTOBOTTOM|V_SNAPTORIGHT, "FREE PLAY"); } +static void K_drawDistributionDebugger(void) +{ + patch_t *items[NUMKARTRESULTS] = { + kp_sadface[1], + kp_sneaker[1], + kp_rocketsneaker[1], + kp_invincibility[7], + kp_banana[1], + kp_eggman[1], + kp_orbinaut[4], + kp_jawz[1], + kp_mine[1], + kp_ballhog[1], + kp_selfpropelledbomb[1], + kp_grow[1], + kp_shrink[1], + kp_thundershield[1], + kp_hyudoro[1], + kp_pogospring[1], + kp_kitchensink[1], + + kp_sneaker[1], + kp_banana[1], + kp_banana[1], + kp_orbinaut[4], + kp_orbinaut[4], + kp_jawz[1] + }; + INT32 useodds = 0; + INT32 pingame = 0, bestbumper = 0; + INT32 i; + INT32 x = -9, y = -9; + + if (stplyr != &players[displayplayer]) // only for p1 + return; + + // The only code duplication from the Kart, just to avoid the actual item function from calculating pingame twice + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator) + continue; + pingame++; + if (players[i].kartstuff[k_bumper] > bestbumper) + bestbumper = players[i].kartstuff[k_bumper]; + } + + useodds = K_FindUseodds(stplyr, 0, pingame, bestbumper); + + for (i = 1; i < NUMKARTRESULTS; i++) + { + const INT32 itemodds = K_KartGetItemOdds(useodds, i, 0); + if (itemodds <= 0) + continue; + + V_DrawScaledPatch(x, y, V_HUDTRANS|V_SNAPTOTOP, items[i]); + V_DrawThinString(x+11, y+31, V_HUDTRANS|V_SNAPTOTOP, va("%d", itemodds)); + + // Display amount for multi-items + if (i >= NUMKARTITEMS) + { + INT32 amount; + switch (i) + { + case KRITEM_TENFOLDBANANA: + amount = 10; + break; + case KRITEM_QUADORBINAUT: + amount = 4; + break; + case KRITEM_DUALJAWZ: + amount = 2; + break; + default: + amount = 3; + break; + } + V_DrawString(x+24, y+31, V_ALLOWLOWERCASE|V_HUDTRANS|V_SNAPTOTOP, va("x%d", amount)); + } + + x += 32; + if (x >= 297) + { + x = -9; + y += 32; + } + } + + V_DrawString(0, 0, V_HUDTRANS|V_SNAPTOTOP, va("USEODDS %d", useodds)); +} + static void K_drawCheckpointDebugger(void) { + if (stplyr != &players[displayplayer]) // only for p1 + return; + if ((numstarposts/2 + stplyr->starpostnum) >= numstarposts) V_DrawString(8, 184, 0, va("Checkpoint: %d / %d (Can finish)", stplyr->starpostnum, numstarposts)); else @@ -6547,6 +6632,9 @@ void K_drawKartHUD(void) if (isfreeplay && !stplyr->spectator && timeinmap > 113) K_drawKartFreePlay(leveltime); + if (cv_kartdebugdistribution.value) + K_drawDistributionDebugger(); + if (cv_kartdebugcheckpoint.value) K_drawCheckpointDebugger(); } From 79eb4feb74135562a6f7c3d0669a9d6f64106384 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Wed, 29 Aug 2018 14:46:42 -0400 Subject: [PATCH 026/146] Lower capped spring pad max speed even harder, to properly fix BC3 --- src/k_kart.c | 2 +- src/p_spec.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 54a5be532..b515f22d1 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1579,7 +1579,7 @@ fixed_t K_3dKartMovement(player_t *player, boolean onground, fixed_t forwardmove { const fixed_t hscale = mapheaderinfo[gamemap-1]->mobj_scale /*+ (mapheaderinfo[gamemap-1]->mobj_scale - player->mo->scale)*/; const fixed_t minspeed = 24*hscale; - const fixed_t maxspeed = 32*hscale; + const fixed_t maxspeed = 28*hscale; if (newspeed > maxspeed && player->kartstuff[k_pogospring] == 2) newspeed = maxspeed; diff --git a/src/p_spec.c b/src/p_spec.c index f493f7b95..36490918a 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3778,7 +3778,7 @@ DoneSection2: { const fixed_t hscale = mapheaderinfo[gamemap-1]->mobj_scale + (mapheaderinfo[gamemap-1]->mobj_scale - player->mo->scale); const fixed_t minspeed = 24*hscale; - const fixed_t maxspeed = 32*hscale; + const fixed_t maxspeed = 28*hscale; if (player->mo->eflags & MFE_SPRUNG) break; From 1b1f057e82ce43eaf7c98be65a985d8ea99403d7 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 29 Aug 2018 21:37:47 +0100 Subject: [PATCH 027/146] * Prettier record attack screen! * Uses the in-game timer element to draw its times. * This includes showing them time emblems-to-get! * good night sweet prince * Make the emblem time use the same ' and " as the normal time. --- src/k_kart.c | 97 ++++++++++++++++++++++++++++++---------------------- src/k_kart.h | 1 + src/m_menu.c | 21 ++++++++++-- 3 files changed, 77 insertions(+), 42 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 615b89709..b4c1e6ca4 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -5160,78 +5160,90 @@ static void K_drawKartItem(void) V_DrawScaledPatch(ITEM_X+17, ITEM_Y+13, V_HUDTRANS|splitflags, kp_eggnum[min(3, G_TicsToSeconds(stplyr->kartstuff[k_eggmanexplode]))]); } -static void K_drawKartTimestamp(void) +void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT16 emblemmap, boolean playing) { // TIME_X = BASEVIDWIDTH-124; // 196 // TIME_Y = 6; // 6 - INT32 TIME_XB, splitflags = V_HUDTRANS|K_calcSplitFlags(V_SNAPTOTOP|V_SNAPTORIGHT); - tic_t drawtime = stplyr->realtime; + tic_t worktime; - if (cv_timelimit.value && timelimitintics > 0) + INT32 splitflags = 0; + if (playing) { - if (drawtime >= timelimitintics) - drawtime = 0; - else - drawtime = timelimitintics - drawtime; + splitflags = V_HUDTRANS|K_calcSplitFlags(V_SNAPTOTOP|V_SNAPTORIGHT); + if (cv_timelimit.value && timelimitintics > 0) + { + if (drawtime >= timelimitintics) + drawtime = 0; + else + drawtime = timelimitintics - drawtime; + } } - V_DrawScaledPatch(TIME_X, TIME_Y, splitflags, kp_timestickerwide); + V_DrawScaledPatch(TX, TY, splitflags, kp_timestickerwide); - TIME_XB = TIME_X+33; + TX += 33; - if (drawtime/(60*TICRATE) < 100) // 99:99:99 only + worktime = drawtime/(60*TICRATE); + + if (!playing && !drawtime) + V_DrawKartString(TX, TY+3, splitflags, va("--'--\"--")); + else if (worktime < 100) // 99:99:99 only { // zero minute - if (drawtime/(60*TICRATE) < 10) + if (worktime < 10) { - V_DrawKartString(TIME_XB, TIME_Y+3, splitflags, va("0")); + V_DrawKartString(TX, TY+3, splitflags, va("0")); // minutes time 0 __ __ - V_DrawKartString(TIME_XB+12, TIME_Y+3, splitflags, va("%d", drawtime/(60*TICRATE))); + V_DrawKartString(TX+12, TY+3, splitflags, va("%d", worktime)); } // minutes time 0 __ __ else - V_DrawKartString(TIME_XB, TIME_Y+3, splitflags, va("%d", drawtime/(60*TICRATE))); + V_DrawKartString(TX, TY+3, splitflags, va("%d", worktime)); // apostrophe location _'__ __ - V_DrawKartString(TIME_XB+24, TIME_Y+3, splitflags, va("'")); + V_DrawKartString(TX+24, TY+3, splitflags, va("'")); + + worktime = (drawtime/TICRATE % 60); // zero second _ 0_ __ - if ((drawtime/TICRATE % 60) < 10) + if (worktime < 10) { - V_DrawKartString(TIME_XB+36, TIME_Y+3, splitflags, va("0")); + V_DrawKartString(TX+36, TY+3, splitflags, va("0")); // seconds time _ _0 __ - V_DrawKartString(TIME_XB+48, TIME_Y+3, splitflags, va("%d", drawtime/TICRATE % 60)); + V_DrawKartString(TX+48, TY+3, splitflags, va("%d", worktime)); } // zero second _ 00 __ else - V_DrawKartString(TIME_XB+36, TIME_Y+3, splitflags, va("%d", drawtime/TICRATE % 60)); + V_DrawKartString(TX+36, TY+3, splitflags, va("%d", worktime)); // quotation mark location _ __"__ - V_DrawKartString(TIME_XB+60, TIME_Y+3, splitflags, va("\"")); + V_DrawKartString(TX+60, TY+3, splitflags, va("\"")); + + worktime = G_TicsToCentiseconds(drawtime); // zero tick _ __ 0_ - if (G_TicsToCentiseconds(drawtime) < 10) + if (worktime < 10) { - V_DrawKartString(TIME_XB+72, TIME_Y+3, splitflags, va("0")); + V_DrawKartString(TX+72, TY+3, splitflags, va("0")); // tics _ __ _0 - V_DrawKartString(TIME_XB+84, TIME_Y+3, splitflags, va("%d", G_TicsToCentiseconds(drawtime))); + V_DrawKartString(TX+84, TY+3, splitflags, va("%d", worktime)); } // zero tick _ __ 00 - if (G_TicsToCentiseconds(drawtime) >= 10) - V_DrawKartString(TIME_XB+72, TIME_Y+3, splitflags, va("%d", G_TicsToCentiseconds(drawtime))); + else + V_DrawKartString(TX+72, TY+3, splitflags, va("%d", worktime)); } else if ((drawtime/TICRATE) & 1) - V_DrawKartString(TIME_XB, TIME_Y+3, splitflags, va("99'59\"99")); + V_DrawKartString(TX, TY+3, splitflags, va("99'59\"99")); - if (modeattacking) // emblem time! + if (emblemmap && (modeattacking || !playing)) // emblem time! { - INT32 workx = TIME_XB + 96, worky = TIME_Y+18; + INT32 workx = TX + 96, worky = TY+18; SINT8 curemb = 0; patch_t *emblempic[3] = {NULL, NULL, NULL}; UINT8 *emblemcol[3] = {NULL, NULL, NULL}; - emblem_t *emblem = M_GetLevelEmblems(gamemap); + emblem_t *emblem = M_GetLevelEmblems(emblemmap); while (emblem) { char targettext[9]; @@ -5252,22 +5264,25 @@ static void K_drawKartTimestamp(void) goto bademblem; } - snprintf(targettext, 9, "%i:%02i.%02i", + snprintf(targettext, 9, "%i'%02i\"%02i", G_TicsToMinutes(timetoreach, false), G_TicsToSeconds(timetoreach), G_TicsToCentiseconds(timetoreach)); - if (stplyr->realtime > timetoreach) + if (playing) { - splitflags = (splitflags &~ V_HUDTRANS)|V_HUDTRANSHALF; - if (canplaysound) + if (stplyr->realtime > timetoreach) { - S_StartSound(NULL, sfx_s3k72); //sfx_s26d); -- you STOLE fizzy lifting drinks - canplaysound = false; + splitflags = (splitflags &~ V_HUDTRANS)|V_HUDTRANSHALF; + if (canplaysound) + { + S_StartSound(NULL, sfx_s3k72); //sfx_s26d); -- you STOLE fizzy lifting drinks + canplaysound = false; + } } + else if (!canplaysound) + canplaysound = true; } - else if (!canplaysound) - canplaysound = true; targettext[8] = 0; } @@ -5277,7 +5292,7 @@ static void K_drawKartTimestamp(void) } V_DrawRightAlignedString(workx, worky, splitflags, targettext); - workx -= 69; // i SWEAR i wasn't aiming for this + workx -= 72; //69; -- good night sweet prince V_DrawSmallScaledPatch(workx + 4, worky, splitflags, W_CachePatchName("NEEDIT", PU_CACHE)); break; @@ -5286,6 +5301,8 @@ static void K_drawKartTimestamp(void) emblem = M_GetLevelEmblems(-1); } + if (playing) + splitflags = (splitflags &~ V_HUDTRANSHALF)|V_HUDTRANS; while (curemb--) { workx -= 16; @@ -6469,7 +6486,7 @@ void K_drawKartHUD(void) if (!splitscreen) { // Draw the timestamp - K_drawKartTimestamp(); + K_drawKartTimestamp(stplyr->realtime, TIME_X, TIME_Y, gamemap, true); if (!modeattacking) { diff --git a/src/k_kart.h b/src/k_kart.h index 89f1ea7e7..7c7d66fca 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -61,6 +61,7 @@ void K_LoadKartHUDGraphics(void); fixed_t K_FindCheckX(fixed_t px, fixed_t py, angle_t ang, fixed_t mx, fixed_t my); void K_drawKartHUD(void); void K_drawKartFreePlay(UINT32 flashtime); +void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT16 emblemmap, boolean playing); void K_LoadIconGraphics(char *facestr, INT32 skinnum); void K_ReloadSkinIconGraphics(void); diff --git a/src/m_menu.c b/src/m_menu.c index 82e6ac2f8..3bdcc964e 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5705,7 +5705,6 @@ void M_DrawTimeAttackMenu(void) INT32 i, x, y, cursory = 0; UINT16 dispstatus; patch_t *PictureOfUrFace; - char beststr[40]; //S_ChangeMusicInternal("racent", true); // Eww, but needed for when user hits escape during demo playback @@ -5786,6 +5785,24 @@ void M_DrawTimeAttackMenu(void) // Level record list if (cv_nextmap.value) { + INT32 dupadjust = (vid.width/vid.dupx); + tic_t lap = 0, time = 0; + if (mainrecords[cv_nextmap.value-1]) + { + lap = mainrecords[cv_nextmap.value-1]->lap; + time = mainrecords[cv_nextmap.value-1]->time; + } + + V_DrawFill((BASEVIDWIDTH - dupadjust)>>1, 78, dupadjust, 36, 239); + + V_DrawRightAlignedString(149, 80, highlightflags, "BEST LAP:"); + K_drawKartTimestamp(lap, 19, 86, 0, false); + + V_DrawRightAlignedString(292, 80, highlightflags, "BEST TIME:"); + K_drawKartTimestamp(time, 162, 86, cv_nextmap.value, false); + } + /*{ + char beststr[40]; emblem_t *em; if (!mainrecords[cv_nextmap.value-1] || !mainrecords[cv_nextmap.value-1]->time) @@ -5828,7 +5845,7 @@ void M_DrawTimeAttackMenu(void) skipThisOne: em = M_GetLevelEmblems(-1); } - } + }*/ // ALWAYS DRAW player name, level name, skin and color even when not on this menu! if (currentMenu != &SP_TimeAttackDef) From c95e6f01d3f640310c6021f3d80f9eab15e0ec62 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 29 Aug 2018 22:02:42 +0100 Subject: [PATCH 028/146] disable encore ruby/flip on record attack menu with kartencore on --- src/m_menu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index 3bdcc964e..8e83f3a6a 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6808,7 +6808,7 @@ static void M_DrawLevelSelectOnly(boolean leftfade, boolean rightfade) V_DrawFill(x-1, y-1, w+2, i+2, trans); // variable reuse... - if (!cv_kartencore.value || cv_newgametype.value != GT_RACE) + if (!cv_kartencore.value || gamestate == GS_TIMEATTACK || cv_newgametype.value != GT_RACE) V_DrawSmallScaledPatch(x, y, 0, PictureOfLevel); else { From 3bf3d6df334e7ec440f08bf763c8e405f8e86678 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Wed, 29 Aug 2018 18:12:02 -0400 Subject: [PATCH 029/146] - Revamped Jawz targetting for Battle Mode - Cleaned up some redundant code - Halved the speed of backwards thrown missiles (previously PROJSPEED/2, now is PROJSPEED/4) --- src/k_kart.c | 12 ++++----- src/p_enemy.c | 68 +++++++++++++++++++++++++++++++-------------------- 2 files changed, 48 insertions(+), 32 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index b515f22d1..2c6521e0d 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2446,11 +2446,11 @@ static mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t map if (dir == -1) { // Shoot backward - mo = K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + ANGLE_180 - 0x06000000, 0, PROJSPEED/2); - K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + ANGLE_180 - 0x03000000, 0, PROJSPEED/2); - K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + ANGLE_180, 0, PROJSPEED/2); - K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + ANGLE_180 + 0x03000000, 0, PROJSPEED/2); - K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + ANGLE_180 + 0x06000000, 0, PROJSPEED/2); + mo = K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + ANGLE_180 - 0x06000000, 0, PROJSPEED/4); + K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + ANGLE_180 - 0x03000000, 0, PROJSPEED/4); + K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + ANGLE_180, 0, PROJSPEED/4); + K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + ANGLE_180 + 0x03000000, 0, PROJSPEED/4); + K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + ANGLE_180 + 0x06000000, 0, PROJSPEED/4); } else { @@ -2467,7 +2467,7 @@ static mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t map if (dir == -1) { // Shoot backward - mo = K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + ANGLE_180, 0, PROJSPEED/2); + mo = K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + ANGLE_180, 0, PROJSPEED/4); } else { diff --git a/src/p_enemy.c b/src/p_enemy.c index 6bbf00b2b..9bd5a9c79 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -8164,9 +8164,9 @@ void A_ItemPop(mobj_t *actor) void A_JawzChase(mobj_t *actor) { - - INT32 c = 0; INT32 stop; + INT32 bestang = -1, bestdist = -1; + SINT8 wtarg = -1; player_t *player; #ifdef HAVE_BLUA if (LUA_CallAction("A_JawzChase", actor)) @@ -8199,12 +8199,15 @@ void A_JawzChase(mobj_t *actor) { for (; ; actor->lastlook = (actor->lastlook + 1) & PLAYERSMASK) { + if (actor->lastlook == stop) + { + actor->lastlook = -1; + break; + } + if (!playeringame[actor->lastlook]) continue; - if (c++ == 2) - return; - player = &players[actor->lastlook]; if (!player->mo) @@ -8229,41 +8232,54 @@ void A_JawzChase(mobj_t *actor) if (G_RaceGametype()) // Only in races, in match and CTF you should go after any nearby players { // USER TARGET - if (actor->target->player->kartstuff[k_position] != (player->kartstuff[k_position] + 1)) // Jawz only go after the person directly ahead of you -Sryder - continue; + if (actor->target->player->kartstuff[k_position] == (player->kartstuff[k_position] + 1)) // Jawz only go after the person directly ahead of you -Sryder + { + wtarg = player-players; + break; + } } if (G_BattleGametype()) { + angle_t initang; + INT32 thisang; + INT32 thisdist; + if (player->kartstuff[k_bumper] <= 0) continue; - if (P_AproxDistance(P_AproxDistance(player->mo->x-actor->x, - player->mo->y-actor->y), player->mo->z-actor->z) > RING_DIST) + initang = actor->angle - R_PointToAngle2(actor->x, actor->y, player->mo->x, player->mo->y); + if (initang > ANGLE_180) + initang = InvAngle(initang); + thisang = AngleFixed(initang)>>FRACBITS; + thisdist = P_AproxDistance(P_AproxDistance(player->mo->x - actor->x, + player->mo->y - actor->y), player->mo->z - actor->z)>>FRACBITS; + + if (thisdist > RING_DIST>>FRACBITS) continue; + + if ((bestang < 0 || bestdist < 0) + || (thisang < bestang) + || (thisang == bestang && thisdist < bestdist)) + { + wtarg = player-players; + bestang = thisang; + bestdist = thisdist; + } } } - - if ((G_RaceGametype()) || (G_BattleGametype() // If in match etc. only home in when you get close enough, in race etc. home in all the time - && P_AproxDistance(P_AproxDistance(player->mo->x-actor->x, - player->mo->y-actor->y), player->mo->z-actor->z) < RING_DIST - && player->kartstuff[k_bumper] > 0)) - P_SetTarget(&actor->tracer, player->mo); - return; - - // Moved to bottom so it doesn't not check the last player - // done looking - if (actor->lastlook == stop) - { - if (G_RaceGametype()) - actor->lastlook = -2; - return; - } } } - return; + if (wtarg > 0 + && (G_RaceGametype() // Instantly go after in Race + || (G_BattleGametype() && bestdist < RING_DIST>>FRACBITS))) // Wait until you're in distance in Battle + { + CONS_Printf("ang: %d, dist: %d, wtarg: %d\n", bestang, bestdist, wtarg); + P_SetTarget(&actor->tracer, players[wtarg].mo); + } + return; } void A_JawzExplode(mobj_t *actor) From 0fb69a859a3d0515a986eb6bf0189239b58f92a3 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Wed, 29 Aug 2018 18:12:18 -0400 Subject: [PATCH 030/146] Foolish --- src/p_enemy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 9bd5a9c79..9489693b5 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -8275,7 +8275,7 @@ void A_JawzChase(mobj_t *actor) && (G_RaceGametype() // Instantly go after in Race || (G_BattleGametype() && bestdist < RING_DIST>>FRACBITS))) // Wait until you're in distance in Battle { - CONS_Printf("ang: %d, dist: %d, wtarg: %d\n", bestang, bestdist, wtarg); + //CONS_Printf("ang: %d, dist: %d, wtarg: %d\n", bestang, bestdist, wtarg); P_SetTarget(&actor->tracer, players[wtarg].mo); } From 5a1e52ba334cfc14cc8fd627c534d95b6836c0a9 Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 30 Aug 2018 13:13:25 +0100 Subject: [PATCH 031/146] Overlays and rings now properly handle encore-ness, in that they are sans encore (most of the time). ... :V --- src/info.c | 4 ++-- src/p_mobj.c | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/info.c b/src/info.c index 464c41663..0e6d5abdb 100644 --- a/src/info.c +++ b/src/info.c @@ -5054,7 +5054,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_SLIDEME|MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags + MF_SLIDEME|MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -13141,7 +13141,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 1000, // mass 8, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_SCENERY, // flags + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_SCENERY|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, diff --git a/src/p_mobj.c b/src/p_mobj.c index 102f99d46..129ea3331 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6212,6 +6212,9 @@ void P_RunOverlays(void) mo->scale = mo->destscale = mo->target->scale; mo->angle = mo->target->angle; + if ((mo->flags & MF_DONTENCOREMAP) != (mo->target->flags & MF_DONTENCOREMAP)) + mo->flags ^= MF_DONTENCOREMAP; + if (!(mo->state->frame & FF_ANIMATE)) zoffs = FixedMul(((signed)mo->state->var2)*FRACUNIT, mo->scale); // if you're using FF_ANIMATE on an overlay, From 56e74678af7899bbd4648da68e03745ea1ec2f5c Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 30 Aug 2018 15:30:27 -0400 Subject: [PATCH 032/146] More fundamental Jawz changes. 1.) Instead of prioritizing best angle above all else, it averages both distance and angle to figure out which is the best overall target. 2.) Jawz will completely cut out angles higher than 45 degrees, preventing instances where someone behind you is considered a better target than who you're looking at. 3.) Jawz does the 45 degree angle checking in Race as well, meaning that they will ignore racers that are neck & neck with you, even if they're technically the next place above you, so that Jawz doesn't take a hard left into a wall. --- src/p_enemy.c | 134 +++++++++++++++++++++++--------------------------- 1 file changed, 62 insertions(+), 72 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 9489693b5..f5f834054 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -8164,8 +8164,7 @@ void A_ItemPop(mobj_t *actor) void A_JawzChase(mobj_t *actor) { - INT32 stop; - INT32 bestang = -1, bestdist = -1; + fixed_t best = -1; SINT8 wtarg = -1; player_t *player; #ifdef HAVE_BLUA @@ -8176,109 +8175,100 @@ void A_JawzChase(mobj_t *actor) if (actor->tracer) { if (!actor->tracer->health) - { P_SetTarget(&actor->tracer, NULL); - } - if (actor->tracer && (actor->tracer->health)) + if (actor->tracer && actor->tracer->health) { P_Thrust(actor, R_PointToAngle2(actor->x, actor->y, actor->tracer->x, actor->tracer->y), actor->info->speed); return; } } - // first time init, this allow minimum lastlook changes - if (actor->lastlook == -1) - actor->lastlook = P_RandomFixed(); + if (actor->extravalue1) // Disable looking by setting this + return; - actor->lastlook %= MAXPLAYERS; - - stop = (actor->lastlook - 1) & PLAYERSMASK; - - if (actor->lastlook >= 0) + for (actor->lastlook = 0; actor->lastlook < MAXPLAYERS; actor->lastlook++) { - for (; ; actor->lastlook = (actor->lastlook + 1) & PLAYERSMASK) + if (!playeringame[actor->lastlook]) + continue; + + player = &players[actor->lastlook]; + + if (player->spectator) + continue; // spectator + + if (!player->mo) + continue; + + if (player->mo->health <= 0) + continue; // dead + + if (actor->target && actor->target->player) { - if (actor->lastlook == stop) - { - actor->lastlook = -1; - break; - } + angle_t thisang; - if (!playeringame[actor->lastlook]) + if (player->mo == actor->target) continue; - player = &players[actor->lastlook]; - - if (!player->mo) + // Don't home in on teammates. + if (G_GametypeHasTeams() && actor->target->player->ctfteam == player->ctfteam) continue; - if (player->mo->health <= 0) - continue; // dead + // Find the angle, see who's got the best. + thisang = actor->angle - R_PointToAngle2(actor->x, actor->y, player->mo->x, player->mo->y); + if (thisang > ANGLE_180) + thisang = InvAngle(thisang); - if ((netgame || multiplayer) && player->spectator) - continue; // spectator + if (thisang > ANGLE_45) // Don't go for people who are behind you + continue; - if (actor->target && actor->target->player) + // Jawz only go after the person directly ahead of you in race... sort of literally now! + if (G_RaceGametype()) { - if (player->mo == actor->target) + if (player->kartstuff[k_position] >= actor->target->player->kartstuff[k_position]) // Don't pay attention to people behind you continue; - - // Don't home in on teammates. - if (gametype == GT_CTF - && actor->target->player->ctfteam == player->ctfteam) - continue; - - if (G_RaceGametype()) // Only in races, in match and CTF you should go after any nearby players + if ((best == -1) || (player->kartstuff[k_position] > best)) { - // USER TARGET - if (actor->target->player->kartstuff[k_position] == (player->kartstuff[k_position] + 1)) // Jawz only go after the person directly ahead of you -Sryder - { - wtarg = player-players; - break; - } + wtarg = actor->lastlook; + best = player->kartstuff[k_position]; } + } + else + { + fixed_t thisdist; + fixed_t thisavg; - if (G_BattleGametype()) + if (player->kartstuff[k_bumper] <= 0) + continue; + + thisdist = P_AproxDistance(P_AproxDistance(player->mo->x - (actor->x + actor->momx), + player->mo->y - (actor->y + actor->momy)), player->mo->z - (actor->z + actor->momz)); + + if (thisdist > RING_DIST) // Don't go for people who are too far away + continue; + + thisavg = (AngleFixed(thisang) + thisdist) / 2; + + //CONS_Printf("got avg %d from player # %d\n", thisavg>>FRACBITS, actor->lastlook); + + if ((best == -1) || (thisavg < best)) { - angle_t initang; - INT32 thisang; - INT32 thisdist; - - if (player->kartstuff[k_bumper] <= 0) - continue; - - initang = actor->angle - R_PointToAngle2(actor->x, actor->y, player->mo->x, player->mo->y); - if (initang > ANGLE_180) - initang = InvAngle(initang); - thisang = AngleFixed(initang)>>FRACBITS; - thisdist = P_AproxDistance(P_AproxDistance(player->mo->x - actor->x, - player->mo->y - actor->y), player->mo->z - actor->z)>>FRACBITS; - - if (thisdist > RING_DIST>>FRACBITS) - continue; - - if ((bestang < 0 || bestdist < 0) - || (thisang < bestang) - || (thisang == bestang && thisdist < bestdist)) - { - wtarg = player-players; - bestang = thisang; - bestdist = thisdist; - } + wtarg = actor->lastlook; + best = thisavg; } } } } - if (wtarg > 0 - && (G_RaceGametype() // Instantly go after in Race - || (G_BattleGametype() && bestdist < RING_DIST>>FRACBITS))) // Wait until you're in distance in Battle + if (wtarg != -1) { - //CONS_Printf("ang: %d, dist: %d, wtarg: %d\n", bestang, bestdist, wtarg); + //CONS_Printf("best: %d, final target: %d\n", best, wtarg); P_SetTarget(&actor->tracer, players[wtarg].mo); } + if (G_RaceGametype()) // Stop looking after first tic in race + actor->extravalue1 = 1; + return; } From 85ee66f64adbbf520cd2b60ce92d8608c16795db Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 30 Aug 2018 16:10:25 -0400 Subject: [PATCH 033/146] Held Orbinaut & Jawz radius+scaling animation on spawn --- src/k_kart.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 2c6521e0d..9bc1cd1be 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2927,6 +2927,11 @@ static void K_MoveHeldObjects(player_t *player) cur->angle -= ANGLE_90; cur->angle += FixedAngle(cur->info->speed); + if (cur->extravalue1 < radius) + cur->extravalue1 += FixedMul(P_AproxDistance(cur->extravalue1, radius), FRACUNIT/12); + if (cur->extravalue1 > radius) + cur->extravalue1 = radius; + // If the player is on the ceiling, then flip your items as well. if (player && player->mo->eflags & MFE_VERTICALFLIP) cur->eflags |= MFE_VERTICALFLIP; @@ -2934,7 +2939,7 @@ static void K_MoveHeldObjects(player_t *player) cur->eflags &= ~MFE_VERTICALFLIP; // Shrink your items if the player shrunk too. - P_SetScale(cur, (cur->destscale = player->mo->scale)); + P_SetScale(cur, (cur->destscale = FixedMul(FixedDiv(cur->extravalue1, radius), player->mo->scale))); if (P_MobjFlip(cur) > 0) z = player->mo->z; @@ -2943,8 +2948,8 @@ static void K_MoveHeldObjects(player_t *player) cur->flags |= MF_NOCLIPTHING; // temporarily make them noclip other objects so they can't hit anyone while in the player P_TeleportMove(cur, player->mo->x, player->mo->y, z); - cur->momx = FixedMul(FINECOSINE(cur->angle>>ANGLETOFINESHIFT), radius); - cur->momy = FixedMul(FINESINE(cur->angle>>ANGLETOFINESHIFT), radius); + cur->momx = FixedMul(FINECOSINE(cur->angle>>ANGLETOFINESHIFT), cur->extravalue1); + cur->momy = FixedMul(FINESINE(cur->angle>>ANGLETOFINESHIFT), cur->extravalue1); cur->flags &= ~MF_NOCLIPTHING; if (!P_TryMove(cur, player->mo->x + cur->momx, player->mo->y + cur->momy, true)) P_SlideMove(cur, true); @@ -3874,8 +3879,6 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) { angle_t newangle; - fixed_t newx; - fixed_t newy; INT32 moloop; mobj_t *mo = NULL; mobj_t *prev = player->mo; @@ -3887,9 +3890,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) for (moloop = 0; moloop < player->kartstuff[k_itemamount]; moloop++) { newangle = FixedAngle(((360/player->kartstuff[k_itemamount])*moloop)*FRACUNIT) + ANGLE_90; - newx = player->mo->x + P_ReturnThrustX(player->mo, newangle, 64*FRACUNIT); - newy = player->mo->y + P_ReturnThrustY(player->mo, newangle, 64*FRACUNIT); - mo = P_SpawnMobj(newx, newy, player->mo->z, MT_ORBINAUT_SHIELD); + mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_ORBINAUT_SHIELD); if (!mo) { player->kartstuff[k_itemamount] = moloop; @@ -3919,8 +3920,6 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) { angle_t newangle; - fixed_t newx; - fixed_t newy; INT32 moloop; mobj_t *mo = NULL; mobj_t *prev = player->mo; @@ -3932,9 +3931,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) for (moloop = 0; moloop < player->kartstuff[k_itemamount]; moloop++) { newangle = FixedAngle(((360/player->kartstuff[k_itemamount])*moloop)*FRACUNIT) + ANGLE_90; - newx = player->mo->x + P_ReturnThrustX(player->mo, newangle, 64*FRACUNIT); - newy = player->mo->y + P_ReturnThrustY(player->mo, newangle, 64*FRACUNIT); - mo = P_SpawnMobj(newx, newy, player->mo->z, MT_JAWZ_SHIELD); + mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_JAWZ_SHIELD); if (!mo) { player->kartstuff[k_itemamount] = moloop; From 4b38c3e48e21ad195a1cecb633ee0ad69421863f Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 30 Aug 2018 16:28:01 -0400 Subject: [PATCH 034/146] Put on player's center during this animation --- src/k_kart.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/k_kart.c b/src/k_kart.c index 9bc1cd1be..2923b1878 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2966,6 +2966,10 @@ static void K_MoveHeldObjects(player_t *player) z = cur->ceilingz - cur->height; } } + + // Center it during the scale up animation + z += (FixedMul(mobjinfo[cur->type].height, player->mo->scale - cur->scale)>>1) * P_MobjFlip(cur); + cur->z = z; cur->momx = cur->momy = 0; cur->angle += ANGLE_90; From bd3b346f32ef477c8e9c936c38113de32e6110e4 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 30 Aug 2018 16:36:46 -0400 Subject: [PATCH 035/146] Apply to bananas, eggmen, and mines also --- src/k_kart.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 2923b1878..86ab61f93 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3004,7 +3004,7 @@ static void K_MoveHeldObjects(player_t *player) fixed_t targy; fixed_t targz; fixed_t speed; - fixed_t dist = radius/2; + fixed_t dist; cur->flags &= ~MF_NOCLIPTHING; @@ -3014,15 +3014,25 @@ static void K_MoveHeldObjects(player_t *player) continue; } + if (cur->extravalue1 < radius) + cur->extravalue1 += FixedMul(P_AproxDistance(cur->extravalue1, radius), FRACUNIT/12); + if (cur->extravalue1 > radius) + cur->extravalue1 = radius; + if (cur != player->mo->hnext) { targ = cur->hprev; - dist = radius/4; + dist = cur->extravalue1/4; } + else + dist = cur->extravalue1/2; if (!targ || P_MobjWasRemoved(targ)) continue; + // Shrink your items if the player shrunk too. + P_SetScale(cur, (cur->destscale = FixedMul(FixedDiv(cur->extravalue1, radius), player->mo->scale))); + ang = targ->angle; targx = targ->x + P_ReturnThrustX(cur, ang + ANGLE_180, dist); targy = targ->y + P_ReturnThrustY(cur, ang + ANGLE_180, dist); From f54920572121826beeff6696e7fd4a15e9968192 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 30 Aug 2018 17:12:35 -0400 Subject: [PATCH 036/146] Halved radius of MT_CHOMPER --- src/info.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/info.c b/src/info.c index c642b67e5..281fe10f1 100644 --- a/src/info.c +++ b/src/info.c @@ -16215,8 +16215,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_pop, // deathsound 6, // speed - 3145728, // radius - 3145728, // height + 24*FRACUNIT, // radius + 48*FRACUNIT, // height 0, // display offset 100, // mass 0, // damage From 4018301434fc129b73d314f975701e324a041228 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 30 Aug 2018 17:50:47 -0400 Subject: [PATCH 037/146] Remove use of a duplicated sound --- src/p_map.c | 4 ++-- src/sounds.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index d5fb5ef35..77f9653d3 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -698,7 +698,7 @@ static boolean PIT_CheckThing(mobj_t *thing) K_KartBouncing(thing, tmthing, false, false); if (tmthing->type == MT_ORBINAUT || tmthing->type == MT_JAWZ || tmthing->type == MT_JAWZ_DUD) - S_StartSound(thing, sfx_shelit); + S_StartSound(thing, sfx_s3k7b); // This Item Damage if (tmthing->eflags & MFE_VERTICALFLIP) @@ -981,7 +981,7 @@ static boolean PIT_CheckThing(mobj_t *thing) K_KartBouncing(tmthing, thing, false, false); if (thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD) - S_StartSound(tmthing, sfx_shelit); + S_StartSound(tmthing, sfx_s3k7b); // Other Item Damage if (thing->eflags & MFE_VERTICALFLIP) diff --git a/src/sounds.c b/src/sounds.c index 991941e00..a7e674ab0 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -438,7 +438,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"s3k59", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3k5a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3k5b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k5c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"s3k5c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Kart Mine tick {"s3k5d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3k5e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3k5f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, @@ -469,7 +469,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"s3k78", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3k79", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3k7a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k7b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"s3k7b", false, 64, 16, -1, NULL, 0, -1, -1, LUMPERROR}, // Kart successful hit {"s3k7c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3k7d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3k7e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, @@ -645,7 +645,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"cdfm36", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"cdfm37", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"cdfm38", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm39", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // SS Mine deployed + {"cdfm39", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // Mine deployed {"cdfm40", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"cdfm41", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"cdfm42", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, From 2f7563a5b09734b025f71fd5ce0a3515c3c17aa3 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 30 Aug 2018 17:53:25 -0400 Subject: [PATCH 038/146] Ignore texture on horizon lines when in OGL Before: https://cdn.discordapp.com/attachments/300531341957529602/484842910475354124/kart0110.png After: https://cdn.discordapp.com/attachments/270211093761097728/484841628771680258/kart0109.png Not a solution, but better than the previous. --- src/hardware/hw_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index e67ede234..9dbf37dcc 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -2041,7 +2041,8 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) { // Single sided line... Deal only with the middletexture (if one exists) gr_midtexture = R_GetTextureNum(gr_sidedef->midtexture); - if (gr_midtexture) + if (gr_midtexture + && gr_linedef->special != 41) // Ignore horizon line for OGL { if (drawtextured) { From 5fa2ffd26e8aaa450afb1a30320825c118e287cf Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 30 Aug 2018 19:24:22 -0400 Subject: [PATCH 039/146] Jawz reticule --- src/d_player.h | 1 + src/dehacked.c | 6 ++- src/info.c | 33 ++++++++++++-- src/info.h | 5 +++ src/k_kart.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++++ src/k_kart.h | 1 + src/p_enemy.c | 90 +++++--------------------------------- src/p_mobj.c | 8 ++++ src/sounds.c | 2 +- 9 files changed, 175 insertions(+), 85 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 95d703ef5..9a3ba707c 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -321,6 +321,7 @@ typedef enum k_eggmanheld, // Eggman monitor held, separate from k_itemheld so it doesn't stop you from getting items k_eggmanexplode, // Fake item recieved, explode in a few seconds k_eggmanblame, // Fake item recieved, who set this fake + k_lastjawztarget, // Last person you target with jawz, for playing the target switch sfx k_bananadrag, // After a second of holding a banana behind you, you start to slow down k_spinouttimer, // Spin-out from a banana peel or oil slick (was "pw_bananacam") k_wipeoutslow, // Timer before you slowdown when getting wiped out diff --git a/src/dehacked.c b/src/dehacked.c index 28f203327..be17998ca 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -6362,6 +6362,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_JAWZ_DEAD2", //} + "S_PLAYERRETICULE", // Player reticule + // Special Stage Mine "S_SSMINE1", "S_SSMINE2", @@ -7226,6 +7228,8 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_JAWZ_DUD", "MT_JAWZ_SHIELD", + "MT_PLAYERRETICULE", // Jawz reticule + "MT_SSMINE_SHIELD", // Special Stage Mine stuff "MT_SSMINE", "MT_MINEEXPLOSION", @@ -7683,7 +7687,6 @@ static const char *const KARTSTUFF_LIST[] = { "ITEMAMOUNT", "ITEMHELD", - //"THUNDERANIM", "CURSHIELD", "HYUDOROTIMER", "STEALINGTIMER", @@ -7697,6 +7700,7 @@ static const char *const KARTSTUFF_LIST[] = { "EGGMANHELD", "EGGMANEXPLODE", "EGGMANBLAME", + "LASTJAWZTARGET", "BANANADRAG", "SPINOUTTIMER", "WIPEOUTSLOW", diff --git a/src/info.c b/src/info.c index 281fe10f1..76c535d70 100644 --- a/src/info.c +++ b/src/info.c @@ -60,7 +60,7 @@ char sprnames[NUMSPRITES + 1][5] = "THNS","SINK","SITR","KBLN","DEZL","POKE","AUDI","DECO","DOOD","SNES", "GBAS","SPRS","BUZB","CHOM","SACO","CRAB","SHAD","BRNG","BUMP","FLEN", "CLAS","PSHW","ISTA","ISTB","ARRO","ITEM","ITMO","ITMI","ITMN","WANT", - "PBOM","VIEW" + "PBOM","RETI","VIEW" }; // Doesn't work with g++, needs actionf_p1 (don't modify this comment) @@ -2684,6 +2684,8 @@ state_t states[NUMSTATES] = {SPR_JAWZ, 5, 175, {NULL}, 0, 0, S_JAWZ_DEAD2}, // S_JAWZ_DEAD1 {SPR_NULL, 0, 1, {A_JawzExplode}, 0, 0, S_NULL}, // S_JAWZ_DEAD2 + {SPR_RETI, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_PLAYERRETICULE + {SPR_SSMN, 0, 30, {NULL}, 0, 0, S_SSMINE2}, // S_SSMINE1 {SPR_SSMN, 3, 3, {NULL}, 0, 0, S_SSMINE3}, // S_SSMINE2 {SPR_SSMN, 2, 3, {NULL}, 0, 0, S_SSMINE4}, // S_SSMINE3 @@ -2894,7 +2896,6 @@ state_t states[NUMSTATES] = {SPR_BRNG, 10, 2, {NULL}, 0, 0, S_BIGRING12}, // S_BIGRING11 {SPR_BRNG, 11, 2, {NULL}, 0, 0, S_BIGRING01}, // S_BIGRING12 - {SPR_SNES, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SNES_DONUTBUSH1 {SPR_SNES, 1, -1, {NULL}, 0, 0, S_NULL}, // S_SNES_DONUTBUSH2 {SPR_SNES, 2, -1, {NULL}, 0, 0, S_NULL}, // S_SNES_DONUTBUSH3 @@ -2991,7 +2992,6 @@ state_t states[NUMSTATES] = {SPR_WANT, FF_FULLBRIGHT|4, 3, {NULL}, 0, 0, S_PLAYERARROW_WANTED6}, // S_PLAYERARROW_WANTED5 {SPR_WANT, FF_FULLBRIGHT|5, 1, {NULL}, 0, 0, S_PLAYERARROW_WANTED7}, // S_PLAYERARROW_WANTED6 {SPR_WANT, FF_FULLBRIGHT|6, 3, {NULL}, 0, 0, S_PLAYERARROW_WANTED1}, // S_PLAYERARROW_WANTED7 - {SPR_PBOM, FF_ANIMATE, -1, {NULL}, 3, 3, S_NULL}, // S_PLAYERBOMB {SPR_RNDM, FF_ANIMATE, -1, {NULL}, 23, 3, S_NULL}, // S_PLAYERITEM @@ -14794,6 +14794,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_PLAYERRETICULE + -1, // doomednum + S_PLAYERRETICULE, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 8, // speed + 16*FRACUNIT, // radius + 56*FRACUNIT, // height + 2, // display offset + 16, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + { // MT_SSMINE -1, // doomednum S_SSMINE_AIR1, // spawnstate diff --git a/src/info.h b/src/info.h index 98d628b39..202094162 100644 --- a/src/info.h +++ b/src/info.h @@ -637,6 +637,7 @@ typedef enum sprite SPR_WANT, SPR_PBOM, // player bomb + SPR_RETI, // player reticule SPR_VIEW, // First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw! @@ -3206,6 +3207,8 @@ typedef enum state S_JAWZ_DEAD2, //} + S_PLAYERRETICULE, // Player reticule + // Special Stage Mine S_SSMINE1, S_SSMINE2, @@ -4087,6 +4090,8 @@ typedef enum mobj_type MT_JAWZ_DUD, MT_JAWZ_SHIELD, + MT_PLAYERRETICULE, // Jawz reticule + MT_SSMINE, // Mine stuff MT_SSMINE_SHIELD, MT_MINEEXPLOSION, diff --git a/src/k_kart.c b/src/k_kart.c index 86ab61f93..9dce3dee0 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3069,6 +3069,87 @@ static void K_MoveHeldObjects(player_t *player) } } +player_t *K_FindJawzTarget(mobj_t *actor, player_t *source) +{ + fixed_t best = -1; + player_t *wtarg = NULL; + INT32 i; + + for (i = 0; i < MAXPLAYERS; i++) + { + angle_t thisang; + player_t *player; + + if (!playeringame[i]) + continue; + + player = &players[i]; + + if (player->spectator) + continue; // spectator + + if (!player->mo) + continue; + + if (player->mo->health <= 0) + continue; // dead + + // Don't target yourself, stupid. + if (player == source) + continue; + + // Don't home in on teammates. + if (G_GametypeHasTeams() && source->ctfteam == player->ctfteam) + continue; + + // Find the angle, see who's got the best. + thisang = actor->angle - R_PointToAngle2(actor->x, actor->y, player->mo->x, player->mo->y); + if (thisang > ANGLE_180) + thisang = InvAngle(thisang); + + if (thisang > ANGLE_45) // Don't go for people who are behind you + continue; + + // Jawz only go after the person directly ahead of you in race... sort of literally now! + if (G_RaceGametype()) + { + if (player->kartstuff[k_position] >= source->kartstuff[k_position]) // Don't pay attention to people behind you + continue; + if ((best == -1) || (player->kartstuff[k_position] > best)) + { + wtarg = player; + best = player->kartstuff[k_position]; + } + } + else + { + fixed_t thisdist; + fixed_t thisavg; + + if (player->kartstuff[k_bumper] <= 0) + continue; + + thisdist = P_AproxDistance(P_AproxDistance(player->mo->x - (actor->x + actor->momx), + player->mo->y - (actor->y + actor->momy)), player->mo->z - (actor->z + actor->momz)); + + if (thisdist > RING_DIST) // Don't go for people who are too far away + continue; + + thisavg = (AngleFixed(thisang) + thisdist) / 2; + + //CONS_Printf("got avg %d from player # %d\n", thisavg>>FRACBITS, i); + + if ((best == -1) || (thisavg < best)) + { + wtarg = player; + best = thisavg; + } + } + } + + return wtarg; +} + /** \brief Decreases various kart timers and powers per frame. Called in P_PlayerThink in p_user.c \param player player object passed from P_PlayerThink @@ -3362,6 +3443,39 @@ void K_KartPlayerAfterThink(player_t *player) // Move held objects (Bananas, Orbinaut, etc) K_MoveHeldObjects(player); + + // Jawz reticule (seeking) + if (player->kartstuff[k_itemtype] == KITEM_JAWZ && player->kartstuff[k_itemheld]) + { + player_t *targ = K_FindJawzTarget(player->mo, player); + mobj_t *ret; + + if (!targ) + { + player->kartstuff[k_lastjawztarget] = -1; + return; + } + + ret = P_SpawnMobj(targ->mo->x, targ->mo->y, targ->mo->z, MT_PLAYERRETICULE); + P_SetTarget(&ret->target, targ->mo); + ret->frame |= ((leveltime % 10) / 2); + ret->tics = 1; + ret->color = player->skincolor; + + if (targ-players != player->kartstuff[k_lastjawztarget]) + { + if (P_IsLocalPlayer(player) || P_IsLocalPlayer(targ)) + S_StartSound(NULL, sfx_s3k89); + else + S_StartSound(targ->mo, sfx_s3k89); + + player->kartstuff[k_lastjawztarget] = targ-players; + } + } + else + { + player->kartstuff[k_lastjawztarget] = -1; + } } // Returns false if this player being placed here causes them to collide with any other player diff --git a/src/k_kart.h b/src/k_kart.h index 89f1ea7e7..58f2cc179 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -42,6 +42,7 @@ void K_KillBananaChain(mobj_t *banana, mobj_t *inflictor, mobj_t *source); void K_CleanHnextList(mobj_t *work); void K_UpdateHnextList(player_t *player); void K_RepairOrbitChain(mobj_t *orbit); +player_t *K_FindJawzTarget(mobj_t *actor, player_t *source); boolean K_CheckPlayersRespawnColliding(INT32 playernum, fixed_t x, fixed_t y); INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue); fixed_t K_GetKartDriftSparkValue(player_t *player); diff --git a/src/p_enemy.c b/src/p_enemy.c index f5f834054..830116745 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -8164,8 +8164,6 @@ void A_ItemPop(mobj_t *actor) void A_JawzChase(mobj_t *actor) { - fixed_t best = -1; - SINT8 wtarg = -1; player_t *player; #ifdef HAVE_BLUA if (LUA_CallAction("A_JawzChase", actor)) @@ -8179,6 +8177,13 @@ void A_JawzChase(mobj_t *actor) if (actor->tracer && actor->tracer->health) { + mobj_t *ret; + + ret = P_SpawnMobj(actor->tracer->x, actor->tracer->y, actor->tracer->z, MT_PLAYERRETICULE); + P_SetTarget(&ret->target, actor->tracer); + ret->frame |= ((leveltime % 10) / 2) + 5; + ret->color = actor->target->player->skincolor; + P_Thrust(actor, R_PointToAngle2(actor->x, actor->y, actor->tracer->x, actor->tracer->y), actor->info->speed); return; } @@ -8187,84 +8192,9 @@ void A_JawzChase(mobj_t *actor) if (actor->extravalue1) // Disable looking by setting this return; - for (actor->lastlook = 0; actor->lastlook < MAXPLAYERS; actor->lastlook++) - { - if (!playeringame[actor->lastlook]) - continue; - - player = &players[actor->lastlook]; - - if (player->spectator) - continue; // spectator - - if (!player->mo) - continue; - - if (player->mo->health <= 0) - continue; // dead - - if (actor->target && actor->target->player) - { - angle_t thisang; - - if (player->mo == actor->target) - continue; - - // Don't home in on teammates. - if (G_GametypeHasTeams() && actor->target->player->ctfteam == player->ctfteam) - continue; - - // Find the angle, see who's got the best. - thisang = actor->angle - R_PointToAngle2(actor->x, actor->y, player->mo->x, player->mo->y); - if (thisang > ANGLE_180) - thisang = InvAngle(thisang); - - if (thisang > ANGLE_45) // Don't go for people who are behind you - continue; - - // Jawz only go after the person directly ahead of you in race... sort of literally now! - if (G_RaceGametype()) - { - if (player->kartstuff[k_position] >= actor->target->player->kartstuff[k_position]) // Don't pay attention to people behind you - continue; - if ((best == -1) || (player->kartstuff[k_position] > best)) - { - wtarg = actor->lastlook; - best = player->kartstuff[k_position]; - } - } - else - { - fixed_t thisdist; - fixed_t thisavg; - - if (player->kartstuff[k_bumper] <= 0) - continue; - - thisdist = P_AproxDistance(P_AproxDistance(player->mo->x - (actor->x + actor->momx), - player->mo->y - (actor->y + actor->momy)), player->mo->z - (actor->z + actor->momz)); - - if (thisdist > RING_DIST) // Don't go for people who are too far away - continue; - - thisavg = (AngleFixed(thisang) + thisdist) / 2; - - //CONS_Printf("got avg %d from player # %d\n", thisavg>>FRACBITS, actor->lastlook); - - if ((best == -1) || (thisavg < best)) - { - wtarg = actor->lastlook; - best = thisavg; - } - } - } - } - - if (wtarg != -1) - { - //CONS_Printf("best: %d, final target: %d\n", best, wtarg); - P_SetTarget(&actor->tracer, players[wtarg].mo); - } + player = K_FindJawzTarget(actor, actor->target->player); + if (player) + P_SetTarget(&actor->tracer, player->mo); if (G_RaceGametype()) // Stop looking after first tic in race actor->extravalue1 = 1; diff --git a/src/p_mobj.c b/src/p_mobj.c index b6ebcd690..e1db00ccf 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8242,6 +8242,14 @@ void P_MobjThinker(mobj_t *mobj) } P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z); break; + case MT_PLAYERRETICULE: + if (!mobj->target || !mobj->target->health) + { + P_RemoveMobj(mobj); + return; + } + P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z); + break; case MT_INSTASHIELDB: if (leveltime & 1) mobj->flags2 |= MF2_DONTDRAW; diff --git a/src/sounds.c b/src/sounds.c index a7e674ab0..6e9562609 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -483,7 +483,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"s3k86", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3k87", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3k88", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k89", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"s3k89", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Kart Jawz target {"s3k8a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3k8b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3k8c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, From 9f6c132629b71db15d1a70f5883e6ff1f37d49eb Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 30 Aug 2018 21:32:24 -0400 Subject: [PATCH 040/146] Karma players can bump again --- src/p_map.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index 77f9653d3..2234534b3 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -1491,10 +1491,15 @@ static boolean PIT_CheckThing(mobj_t *thing) if (thing->player->kartstuff[k_squishedtimer] || thing->player->kartstuff[k_hyudorotimer] || thing->player->kartstuff[k_justbumped] || thing->scale > tmthing->scale + (FRACUNIT/8) - || (G_BattleGametype() && thing->player->kartstuff[k_bumper] <= 0) || tmthing->player->kartstuff[k_squishedtimer] || tmthing->player->kartstuff[k_hyudorotimer] - || tmthing->player->kartstuff[k_justbumped] || tmthing->scale > thing->scale + (FRACUNIT/8) - || (G_BattleGametype() && tmthing->player->kartstuff[k_bumper] <= 0)) + || tmthing->player->kartstuff[k_justbumped] || tmthing->scale > thing->scale + (FRACUNIT/8)) + { + return true; + } + + if (G_BattleGametype() + && ((thing->player->kartstuff[k_bumper] && !tmthing->player->kartstuff[k_bumper]) + || (tmthing->player->kartstuff[k_bumper] && !thing->player->kartstuff[k_bumper]))) { return true; } From 5c9e1a7d68a629f925a2eae6861035cfec679704 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 30 Aug 2018 21:51:27 -0400 Subject: [PATCH 041/146] Grow no longer sets flashing tics Just causes a bunch of other, really dumb side-effects, and nothing else I could test suffers from it --- src/k_kart.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 9dce3dee0..1214fb0ac 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -4309,8 +4309,8 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } } - if (player->kartstuff[k_growshrinktimer] > 1) - player->powers[pw_flashing] = 2; + /*if (player->kartstuff[k_growshrinktimer] > 1) + player->powers[pw_flashing] = 2;*/ // Friction if (player->speed > 0 && cmd->forwardmove == 0 && player->mo->friction == 59392) From 2e809548e43782fdd1af20c748516d242c30da7e Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 30 Aug 2018 22:27:18 -0400 Subject: [PATCH 042/146] separate var for dashpad cooldown - no longer has weirdness with pw_flashing - can now have an SA1-style effect for it --- src/d_player.h | 1 + src/dehacked.c | 1 + src/k_kart.c | 32 +++++++++++++++++++++----------- src/p_spec.c | 10 +++++----- 4 files changed, 28 insertions(+), 16 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 9a3ba707c..49fa6de84 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -297,6 +297,7 @@ typedef enum k_pogospring, // Pogo spring bounce effect k_brakestop, // Wait until you've made a complete stop for a few tics before letting brake go in reverse. k_waterskip, // Water skipping counter + k_dashpadcooldown, // Separate the vanilla SA-style dash pads from using pw_flashing k_itemroulette, // Used for the roulette when deciding what item to give you (was "pw_kartitem") k_roulettetype, // Used for the roulette, for deciding type (currently only used for Battle, to give you better items from Karma items) diff --git a/src/dehacked.c b/src/dehacked.c index be17998ca..2cffc6333 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -7679,6 +7679,7 @@ static const char *const KARTSTUFF_LIST[] = { "POGOSPRING", "BRAKESTOP", "WATERSKIP", + "DASHPADCOOLDOWN", "ITEMROULETTE", "ROULETTETYPE", diff --git a/src/k_kart.c b/src/k_kart.c index 1214fb0ac..bcdc7dd0f 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3161,16 +3161,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) { K_UpdateOffroad(player); - // setting players to use the star colormap and spawning afterimages - if (player->kartstuff[k_invincibilitytimer]) - { - mobj_t *ghost; - player->mo->colorized = true; - ghost = P_SpawnGhostMobj(player->mo); - ghost->fuse = 4; - ghost->frame |= FF_FULLBRIGHT; - } - else if (player->kartstuff[k_eggmanexplode]) + if (player->kartstuff[k_eggmanexplode]) // You're gonna diiiiie { const INT32 flashtime = 4<<(player->kartstuff[k_eggmanexplode]/TICRATE); if (player->kartstuff[k_eggmanexplode] == 1 || (player->kartstuff[k_eggmanexplode] % (flashtime/2) != 0)) @@ -3189,7 +3180,15 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->mo->color = SKINCOLOR_CRIMSON; } } - else if (player->kartstuff[k_growshrinktimer]) + else if (player->kartstuff[k_invincibilitytimer]) // setting players to use the star colormap and spawning afterimages + { + mobj_t *ghost; + player->mo->colorized = true; + ghost = P_SpawnGhostMobj(player->mo); + ghost->fuse = 4; + ghost->frame |= FF_FULLBRIGHT; + } + else if (player->kartstuff[k_growshrinktimer]) // Ditto, for grow/shrink { if (player->kartstuff[k_growshrinktimer] % 5 == 0) { @@ -3207,6 +3206,17 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->mo->colorized = false; } + if (player->kartstuff[k_dashpadcooldown]) // Twinkle Circuit inspired afterimages + { + mobj_t *ghost; + ghost = P_SpawnGhostMobj(player->mo); + ghost->fuse = player->kartstuff[k_dashpadcooldown]+1; + ghost->momx = player->mo->momx / (player->kartstuff[k_dashpadcooldown]+1); + ghost->momy = player->mo->momy / (player->kartstuff[k_dashpadcooldown]+1); + ghost->momz = player->mo->momz / (player->kartstuff[k_dashpadcooldown]+1); + player->kartstuff[k_dashpadcooldown]--; + } + if (player->kartstuff[k_spinouttimer]) { if ((P_IsObjectOnGround(player->mo) || player->kartstuff[k_spinouttype] == 1) diff --git a/src/p_spec.c b/src/p_spec.c index 36490918a..57f5659a6 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3798,7 +3798,7 @@ DoneSection2: case 5: // Speed pad w/o spin case 6: // Speed pad w/ spin - if (player->powers[pw_flashing] != 0 && player->powers[pw_flashing] < TICRATE/2) + if (player->kartstuff[k_dashpadcooldown] != 0) break; i = P_FindSpecialLineFromTag(4, sector->tag, -1); @@ -3843,15 +3843,15 @@ DoneSection2: P_InstaThrust(player->mo, player->mo->angle, linespeed); - if (GETSECSPECIAL(sector->special, 3) == 6 && (player->charability2 == CA2_SPINDASH)) + /*if (GETSECSPECIAL(sector->special, 3) == 6 && (player->charability2 == CA2_SPINDASH)) // SRB2kart { if (!(player->pflags & PF_SPINNING)) player->pflags |= PF_SPINNING; - //P_SetPlayerMobjState(player->mo, S_PLAY_ATK1); // SRB2kart - } + //P_SetPlayerMobjState(player->mo, S_PLAY_ATK1); + }*/ - player->powers[pw_flashing] = TICRATE/3; + player->kartstuff[k_dashpadcooldown] = TICRATE/3; S_StartSound(player->mo, sfx_spdpad); } break; From 1be9b16f3a4fd697dfc6ed12ec815f7bdaa3036e Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Fri, 31 Aug 2018 00:05:46 -0400 Subject: [PATCH 043/146] Scale the speed of SA dash pads with higher scales Also, added a define for GROWNEVERMISSES, which fixes every single jump with Grow but with feels terrible. --- src/p_slopes.c | 14 ++++++++++++++ src/p_spec.c | 5 +++++ 2 files changed, 19 insertions(+) diff --git a/src/p_slopes.c b/src/p_slopes.c index dd737204c..a9706eb9e 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -778,6 +778,10 @@ void P_ReverseQuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope) slope->zangle = InvAngle(slope->zangle); } +// SRB2Kart: This fixes all slope-based jumps for different scales in Kart automatically without map tweaking. +// However, they will always feel off every single time... see for yourself: https://cdn.discordapp.com/attachments/270211093761097728/484924392128774165/kart0181.gif +//#define GROWNEVERMISSES + // // P_SlopeLaunch // @@ -786,6 +790,10 @@ void P_SlopeLaunch(mobj_t *mo) { if (!(mo->standingslope->flags & SL_NOPHYSICS)) // If there's physics, time for launching. { +#ifdef GROWNEVERMISSES + const fixed_t xyscale = mapheaderinfo[gamemap-1]->mobj_scale + (mapheaderinfo[gamemap-1]->mobj_scale - mo->scale); + const fixed_t zscale = mapheaderinfo[gamemap-1]->mobj_scale + (mapheaderinfo[gamemap-1]->mobj_scale - mo->scale); +#endif // Double the pre-rotation Z, then halve the post-rotation Z. This reduces the // vertical launch given from slopes while increasing the horizontal launch // given. Good for SRB2's gravity and horizontal speeds. @@ -795,9 +803,15 @@ void P_SlopeLaunch(mobj_t *mo) slopemom.z = mo->momz; P_QuantizeMomentumToSlope(&slopemom, mo->standingslope); +#ifdef GROWNEVERMISSES + mo->momx = FixedMul(slopemom.x, xyscale); + mo->momy = FixedMul(slopemom.y, xyscale); + mo->momz = FixedMul(slopemom.z, zscale); +#else mo->momx = slopemom.x; mo->momy = slopemom.y; mo->momz = slopemom.z; +#endif } //CONS_Printf("Launched off of slope.\n"); diff --git a/src/p_spec.c b/src/p_spec.c index 57f5659a6..3ad529c41 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3813,6 +3813,11 @@ DoneSection2: player->mo->angle = lineangle; + // SRB2Kart: Scale the speed you get from them! + // This is scaled differently from other horizontal speed boosts from stuff like springs, because of how this is used for some ramp jumps. + if (player->mo->scale > mapheaderinfo[gamemap-1]->mobj_scale) + linespeed = FixedMul(linespeed, mapheaderinfo[gamemap-1]->mobj_scale + (player->mo->scale - mapheaderinfo[gamemap-1]->mobj_scale)); + if (!demoplayback || P_AnalogMove(player)) { if (player == &players[consoleplayer]) From 043d0581a6ad8dc7e05587473434ce7a7a4a4197 Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Fri, 31 Aug 2018 13:30:40 +0200 Subject: [PATCH 044/146] Coloured names for chat --- src/hu_stuff.c | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 36b2812e8..b82ffe267 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -757,8 +757,37 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) } else if (target == 0) // To everyone { - fmt = "\3%s\x83<%s%s%s\x83>\x80 %s\n"; - fmt2 = "%s\x83<%s%s%s\x83>\x80 %s"; + + + /* 31/8/18: Lat': Exclusive to kart, use a CLOSE ENOUGH colour to the player's for text (we're quite limited with our options, + drawstring really should be able to remap to any palette index........*/ + + // there's a lot of fucking colors wtf + INT32 color = players[playernum].mo->color; + if (color >= SKINCOLOR_IVORY && color <= SKINCOLOR_SILVER) + prefix = "\x80"; + else if ((color >= SKINCOLOR_CLOUDY && color <= SKINCOLOR_BLACK) || color == SKINCOLOR_JET) // jet is more black than blue so it goes here. + prefix = "\x86"; + else if (color >= SKINCOLOR_SALMON && color <= SKINCOLOR_CRIMSON) + prefix = "\x85"; + else if (color >= SKINCOLOR_DAWN && color <= SKINCOLOR_CARAMEL) + prefix = "\x87"; + else if (color >= SKINCOLOR_TANGERINE && color <= SKINCOLOR_CANARY) + prefix = "\x82"; + else if (color >= SKINCOLOR_OLIVE && color <= SKINCOLOR_SWAMP) + prefix = "\x83"; + else if ((color >= SKINCOLOR_AQUA && color <= SKINCOLOR_STEEL) || color == SKINCOLOR_SAPPHIRE) // toaster wanted that specific one too shrug + prefix = "\x88"; + else if (color >= SKINCOLOR_PERIWINKLE && color <= SKINCOLOR_NAVY) + prefix = "\x84"; + else if (color >= SKINCOLOR_DUSK && color <= SKINCOLOR_LILAC) + prefix = "\x81"; + else + prefix = "\x83"; + + strcat(cstart, prefix); + fmt = "\3%s<%s%s%s>\x80 %s\n"; + fmt2 = "%s<%s%s%s>\x80 %s"; } else if (target-1 == consoleplayer) // To you { @@ -793,6 +822,7 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) } + HU_AddChatText(va(fmt2, prefix, cstart, dispname, cend, msg)); // add it reguardless, in case we decide to change our mind about our chat type. if OLDCHAT From 7e68741a42e2871ce01dd3d43c06a4e6b77fd97e Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 31 Aug 2018 12:37:15 +0100 Subject: [PATCH 045/146] Improve intermission drawer further. * Change `MM:SS.MS` to `MM'SS"MS' to match all other recorded instances of time in-game. * Add a full stop to NO CONTEST to scrounge up an extra four pixels to match the increased width of above. * Make it such that the number of players per column will never be desynced with future code changes by tying it to a local #define. * Other minor code improvements. --- src/y_inter.c | 41 ++++++++++++----------------------------- 1 file changed, 12 insertions(+), 29 deletions(-) diff --git a/src/y_inter.c b/src/y_inter.c index 636b2d239..77cea21f1 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -413,7 +413,8 @@ void Y_IntermissionDrawer(void) } else*/ if (intertype == int_race || intertype == int_match) { - INT32 y = 48; +#define NUMFORNEWCOLUMN 8 + INT32 y = 48, gutter = ((data.match.numplayers > NUMFORNEWCOLUMN) ? 0 : (BASEVIDWIDTH/2)); const char *timeheader; if (data.match.rankingsmode) @@ -428,7 +429,7 @@ void Y_IntermissionDrawer(void) if (data.match.encore) V_DrawCenteredString(-4 + x + BASEVIDWIDTH/2, 20-8, hilicol, "ENCORE MODE"); - if (data.match.numplayers > 8) + if (!gutter) { V_DrawFill(x+156, 32, 1, 152, 0); @@ -465,7 +466,7 @@ void Y_IntermissionDrawer(void) V_DrawSmallMappedPatch(x+16, y-4, 0,faceprefix[*data.match.character[i]], colormap); } - if (data.match.numplayers > 8) + if (!gutter) strlcpy(strtime, data.match.name[i], 6); else STRBUFCPY(strtime, data.match.name[i]); @@ -485,48 +486,29 @@ void Y_IntermissionDrawer(void) else snprintf(strtime, sizeof strtime, "(+ %d)", data.match.increase[data.match.num[i]]); - if (data.match.numplayers > 8) - V_DrawRightAlignedString(x+120, y, 0, strtime); - else - V_DrawRightAlignedString(x+120+BASEVIDWIDTH/2, y, 0, strtime); + V_DrawRightAlignedString(x+120+gutter, y, 0, strtime); } snprintf(strtime, sizeof strtime, "%d", data.match.val[i]); - if (data.match.numplayers > 8) - V_DrawRightAlignedString(x+152, y, 0, strtime); - else - V_DrawRightAlignedString(x+152+BASEVIDWIDTH/2, y, 0, strtime); + V_DrawRightAlignedString(x+152+gutter, y, 0, strtime); } else { if (data.match.val[i] == (UINT32_MAX-1)) - { - if (data.match.numplayers > 8) - V_DrawRightAlignedThinString(x+152, y-1, 0, "NO CONTEST"); - else - V_DrawRightAlignedThinString(x+152+BASEVIDWIDTH/2, y-1, 0, "NO CONTEST"); - } + V_DrawRightAlignedThinString(x+152+gutter, y-1, 0, "NO CONTEST."); else { if (intertype == int_race) { - snprintf(strtime, sizeof strtime, "%i:%02i.%02i", G_TicsToMinutes(data.match.val[i], true), + snprintf(strtime, sizeof strtime, "%i'%02i\"%02i", G_TicsToMinutes(data.match.val[i], true), G_TicsToSeconds(data.match.val[i]), G_TicsToCentiseconds(data.match.val[i])); strtime[sizeof strtime - 1] = '\0'; - if (data.match.numplayers > 8) - V_DrawRightAlignedString(x+152, y, 0, strtime); - else - V_DrawRightAlignedString(x+152+BASEVIDWIDTH/2, y, 0, strtime); + V_DrawRightAlignedString(x+152+gutter, y, 0, strtime); } else - { - if (data.match.numplayers > 8) - V_DrawRightAlignedString(x+152, y, 0, va("%i", data.match.val[i])); - else - V_DrawRightAlignedString(x+152+BASEVIDWIDTH/2, y, 0, va("%i", data.match.val[i])); - } + V_DrawRightAlignedString(x+152+gutter, y, 0, va("%i", data.match.val[i])); } } @@ -538,11 +520,12 @@ void Y_IntermissionDrawer(void) y += 16; - if (i == 7) + if (i == NUMFORNEWCOLUMN-1) { y = 48; x += BASEVIDWIDTH/2; } +#undef NUMFORNEWCOLUMN } } From 313c8b27a656979ed081e064f58a53dd70f50756 Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Fri, 31 Aug 2018 13:52:53 +0200 Subject: [PATCH 046/146] Cleaned up a little, courtesy of toaster --- src/hu_stuff.c | 42 ++++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index b82ffe267..4eeaa79ce 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -763,28 +763,26 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) drawstring really should be able to remap to any palette index........*/ // there's a lot of fucking colors wtf - INT32 color = players[playernum].mo->color; - if (color >= SKINCOLOR_IVORY && color <= SKINCOLOR_SILVER) - prefix = "\x80"; - else if ((color >= SKINCOLOR_CLOUDY && color <= SKINCOLOR_BLACK) || color == SKINCOLOR_JET) // jet is more black than blue so it goes here. - prefix = "\x86"; - else if (color >= SKINCOLOR_SALMON && color <= SKINCOLOR_CRIMSON) - prefix = "\x85"; - else if (color >= SKINCOLOR_DAWN && color <= SKINCOLOR_CARAMEL) - prefix = "\x87"; - else if (color >= SKINCOLOR_TANGERINE && color <= SKINCOLOR_CANARY) - prefix = "\x82"; - else if (color >= SKINCOLOR_OLIVE && color <= SKINCOLOR_SWAMP) - prefix = "\x83"; - else if ((color >= SKINCOLOR_AQUA && color <= SKINCOLOR_STEEL) || color == SKINCOLOR_SAPPHIRE) // toaster wanted that specific one too shrug - prefix = "\x88"; - else if (color >= SKINCOLOR_PERIWINKLE && color <= SKINCOLOR_NAVY) - prefix = "\x84"; - else if (color >= SKINCOLOR_DUSK && color <= SKINCOLOR_LILAC) - prefix = "\x81"; - else - prefix = "\x83"; - + const UINT8 color = players[playernum].skincolor; + if (color <= SKINCOLOR_SILVER) + prefix = "\x80"; + else if (color <= SKINCOLOR_BLACK || color == SKINCOLOR_JET) // jet is more black than blue so it goes here. + prefix = "\x86"; + else if (color <= SKINCOLOR_CRIMSON) + prefix = "\x85"; + else if (color <= SKINCOLOR_CARAMEL) + prefix = "\x87"; + else if (color <= SKINCOLOR_CANARY) + prefix = "\x82"; + else if (color <= SKINCOLOR_SWAMP) + prefix = "\x83"; + else if (color <= SKINCOLOR_STEEL || color == SKINCOLOR_SAPPHIRE) // toaster wanted that specific one too shrug + prefix = "\x88"; + else if (color <= SKINCOLOR_NAVY) + prefix = "\x84"; + else + prefix = "\x81"; + strcat(cstart, prefix); fmt = "\3%s<%s%s%s>\x80 %s\n"; fmt2 = "%s<%s%s%s>\x80 %s"; From b100112a70e7d732e13038c14e7911fb38553426 Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Fri, 31 Aug 2018 13:56:11 +0200 Subject: [PATCH 047/146] Removed that one empty space thing --- src/hu_stuff.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 4eeaa79ce..e66505930 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -820,7 +820,6 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) } - HU_AddChatText(va(fmt2, prefix, cstart, dispname, cend, msg)); // add it reguardless, in case we decide to change our mind about our chat type. if OLDCHAT From 3145c7a9125a100eea0ccf4bd27e84f834b2234d Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Fri, 31 Aug 2018 15:02:48 +0200 Subject: [PATCH 048/146] Cleanup + coloured text for spectators / PMs --- src/hu_stuff.c | 99 ++++++++++++++++++++++---------------------------- 1 file changed, 44 insertions(+), 55 deletions(-) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index e66505930..293031571 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -713,24 +713,41 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) || target == 0 // To everyone || consoleplayer == target-1) // To you { - const char *prefix = "", *cstart = "", *cend = "", *adminchar = "\x82~\x83", *remotechar = "\x82@\x83", *fmt, *fmt2; + const char *prefix = "", *cstart = "", *cend = "", *adminchar = "\x82~\x83", *remotechar = "\x82@\x83", *fmt, *fmt2, *textcolor = "\x80"; char *tempchar = NULL; - // In CTF and team match, color the player's name. - if (G_GametypeHasTeams()) - { - cend = ""; - if (players[playernum].ctfteam == 1) // red - cstart = "\x85"; - else if (players[playernum].ctfteam == 2) // blue - cstart = "\x84"; - - } - // player is a spectator? - if (players[playernum].spectator) - cstart = "\x86"; // grey name - + if (players[playernum].spectator) + { + cstart = "\x86"; // grey name + textcolor = "\x86"; + } + else + { + const UINT8 color = players[playernum].skincolor; + if (color >= SKINCOLOR_IVORY && color <= SKINCOLOR_SILVER) + cstart = "\x80"; + else if ((color >= SKINCOLOR_CLOUDY && color <= SKINCOLOR_BLACK) || color == SKINCOLOR_JET) // jet is more black than blue so it goes here. + cstart = "\x86"; + else if (color >= SKINCOLOR_SALMON && color <= SKINCOLOR_CRIMSON) + cstart = "\x85"; + else if (color >= SKINCOLOR_DAWN && color <= SKINCOLOR_CARAMEL) + cstart = "\x87"; + else if (color >= SKINCOLOR_TANGERINE && color <= SKINCOLOR_CANARY) + cstart = "\x82"; + else if (color >= SKINCOLOR_OLIVE && color <= SKINCOLOR_SWAMP) + cstart = "\x83"; + else if ((color >= SKINCOLOR_AQUA && color <= SKINCOLOR_STEEL) || color == SKINCOLOR_SAPPHIRE) // toaster wanted that specific one too shrug + cstart = "\x88"; + else if (color >= SKINCOLOR_PERIWINKLE && color <= SKINCOLOR_NAVY) + cstart = "\x84"; + else if (color >= SKINCOLOR_DUSK && color <= SKINCOLOR_LILAC) + cstart = "\x81"; + else + cstart = "\x83"; + } + prefix = cstart; + // Give admins and remote admins their symbols. if (playernum == serverplayer) tempchar = (char *)Z_Calloc(strlen(cstart) + strlen(adminchar) + 1, PU_STATIC, NULL); @@ -757,53 +774,25 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) } else if (target == 0) // To everyone { - - - /* 31/8/18: Lat': Exclusive to kart, use a CLOSE ENOUGH colour to the player's for text (we're quite limited with our options, - drawstring really should be able to remap to any palette index........*/ - - // there's a lot of fucking colors wtf - const UINT8 color = players[playernum].skincolor; - if (color <= SKINCOLOR_SILVER) - prefix = "\x80"; - else if (color <= SKINCOLOR_BLACK || color == SKINCOLOR_JET) // jet is more black than blue so it goes here. - prefix = "\x86"; - else if (color <= SKINCOLOR_CRIMSON) - prefix = "\x85"; - else if (color <= SKINCOLOR_CARAMEL) - prefix = "\x87"; - else if (color <= SKINCOLOR_CANARY) - prefix = "\x82"; - else if (color <= SKINCOLOR_SWAMP) - prefix = "\x83"; - else if (color <= SKINCOLOR_STEEL || color == SKINCOLOR_SAPPHIRE) // toaster wanted that specific one too shrug - prefix = "\x88"; - else if (color <= SKINCOLOR_NAVY) - prefix = "\x84"; - else - prefix = "\x81"; - - strcat(cstart, prefix); - fmt = "\3%s<%s%s%s>\x80 %s\n"; - fmt2 = "%s<%s%s%s>\x80 %s"; + fmt = "\3%s<%s%s%s>\x80 %s%s\n"; + fmt2 = "%s<%s%s%s>\x80 %s%s"; } else if (target-1 == consoleplayer) // To you { prefix = "\x82[PM]"; cstart = "\x82"; - fmt = "\4%s<%s%s>%s\x80 %s\n"; // make this yellow, however. - fmt2 = "%s<%s%s>%s\x80 %s"; + textcolor = "\x82"; + fmt = "\4%s<%s%s>%s\x80 %s%s\n"; // make this yellow, however. + fmt2 = "%s<%s%s>%s\x80 %s%s"; } else if (target > 0) // By you, to another player { // Use target's name. dispname = player_names[target-1]; - /*fmt = "\3\x82[TO]\x80%s%s%s* %s\n"; - fmt2 = "\x82[TO]\x80%s%s%s* %s";*/ prefix = "\x82[TO]"; cstart = "\x82"; - fmt = "\4%s<%s%s>%s\x80 %s\n"; // make this yellow, however. - fmt2 = "%s<%s%s>%s\x80 %s"; + fmt = "\4%s<%s%s>%s\x80 %s%s\n"; // make this yellow, however. + fmt2 = "%s<%s%s>%s\x80 %s%s"; } else // To your team @@ -815,17 +804,17 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) else prefix = "\x83"; // makes sure this doesn't implode if you sayteam on non-team gamemodes - fmt = "\3%s<%s%s>\x80%s %s\n"; - fmt2 = "%s<%s%s>\x80%s %s"; + fmt = "\3%s<%s%s>\x80%s %s%s\n"; + fmt2 = "%s<%s%s>\x80%s %s%s"; } - HU_AddChatText(va(fmt2, prefix, cstart, dispname, cend, msg)); // add it reguardless, in case we decide to change our mind about our chat type. + HU_AddChatText(va(fmt2, prefix, cstart, dispname, cend, textcolor, msg)); // add it reguardless, in case we decide to change our mind about our chat type. if OLDCHAT - CONS_Printf(fmt, prefix, cstart, dispname, cend, msg); + CONS_Printf(fmt, prefix, cstart, dispname, cend, textcolor, msg); else - CON_LogMessage(va(fmt, prefix, cstart, dispname, cend, msg)); // save to log.txt + CON_LogMessage(va(fmt, prefix, cstart, dispname, cend, textcolor, msg)); // save to log.txt if (tempchar) Z_Free(tempchar); From af0035aabac2ff28377ee93fef3de89a819bfe4a Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Fri, 31 Aug 2018 13:18:19 -0400 Subject: [PATCH 049/146] Toggles for kitchen sink, ten banana, & quad orbinaut, and a screen that they can fit on --- src/d_netcmd.c | 3 + src/d_netcmd.h | 5 +- src/k_kart.c | 59 ++++++++++- src/k_kart.h | 1 + src/m_menu.c | 272 ++++++++++++++++++++++++++++++++++++++++--------- 5 files changed, 285 insertions(+), 55 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index cb5523bac..a32542661 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -335,10 +335,13 @@ consvar_t cv_shrink = {"shrink", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NUL consvar_t cv_thundershield = {"thundershield", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_hyudoro = {"hyudoro", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_pogospring = {"pogospring", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_kitchensink = {"kitchensink", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_triplesneaker = {"triplesneaker", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_triplebanana = {"triplebanana", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_decabanana = {"decabanana", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_tripleorbinaut = {"tripleorbinaut", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_quadorbinaut = {"quadorbinaut", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_dualjawz = {"dualjawz", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_karthud = {"karthud", "Default", CV_SAVE|CV_CALL, karthud_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; diff --git a/src/d_netcmd.h b/src/d_netcmd.h index a8fd66b96..3f118944e 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -112,9 +112,10 @@ extern consvar_t cv_recycler;*/ extern consvar_t cv_sneaker, cv_rocketsneaker, cv_invincibility, cv_banana; extern consvar_t cv_eggmanmonitor, cv_orbinaut, cv_jawz, cv_mine; extern consvar_t cv_ballhog, cv_selfpropelledbomb, cv_grow, cv_shrink; -extern consvar_t cv_thundershield, cv_hyudoro, cv_pogospring; +extern consvar_t cv_thundershield, cv_hyudoro, cv_pogospring, cv_kitchensink; -extern consvar_t cv_triplesneaker, cv_triplebanana, cv_tripleorbinaut, cv_dualjawz; +extern consvar_t cv_triplesneaker, cv_triplebanana, cv_decabanana; +extern consvar_t cv_tripleorbinaut, cv_quadorbinaut, cv_dualjawz; extern consvar_t cv_karthud; extern consvar_t cv_kartminimap; diff --git a/src/k_kart.c b/src/k_kart.c index bcdc7dd0f..f00bca5f4 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -388,10 +388,13 @@ void K_RegisterKartStuff(void) CV_RegisterVar(&cv_thundershield); CV_RegisterVar(&cv_hyudoro); CV_RegisterVar(&cv_pogospring); + CV_RegisterVar(&cv_kitchensink); CV_RegisterVar(&cv_triplesneaker); CV_RegisterVar(&cv_triplebanana); + CV_RegisterVar(&cv_decabanana); CV_RegisterVar(&cv_tripleorbinaut); + CV_RegisterVar(&cv_quadorbinaut); CV_RegisterVar(&cv_dualjawz); CV_RegisterVar(&cv_kartminimap); @@ -711,7 +714,7 @@ static INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed) break; case KRITEM_TENFOLDBANANA: POWERITEMODDS(newodds); - if (!cv_triplebanana.value) newodds = 0; + if (!cv_decabanana.value) newodds = 0; break; case KRITEM_TRIPLEORBINAUT: POWERITEMODDS(newodds); @@ -719,7 +722,7 @@ static INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed) break; case KRITEM_QUADORBINAUT: POWERITEMODDS(newodds); - if (!cv_tripleorbinaut.value) newodds = 0; + if (!cv_quadorbinaut.value) newodds = 0; break; case KRITEM_DUALJAWZ: POWERITEMODDS(newodds); @@ -2612,7 +2615,7 @@ static void K_DoHyudoroSteal(player_t *player) prandom = P_RandomFixed(); S_StartSound(player->mo, sfx_s3k92); - if (sink && numplayers > 0) // BEHOLD THE KITCHEN SINK + if (sink && numplayers > 0 && cv_kitchensink.value) // BEHOLD THE KITCHEN SINK { player->kartstuff[k_hyudorotimer] = hyudorotime; player->kartstuff[k_stealingtimer] = stealtime; @@ -4952,6 +4955,56 @@ void K_LoadKartHUDGraphics(void) kp_lapanim_emblem = (patch_t *) W_CachePatchName("K_LAPE00", PU_HUDGFX); } +// For the item toggle menu +const char *K_GetItemPatch(UINT8 item, boolean small) +{ + switch (item) + { + case KITEM_SNEAKER: + case KRITEM_TRIPLESNEAKER: + return (small ? "K_ISSHOE" : "K_ITSHOE"); + case KITEM_ROCKETSNEAKER: + return (small ? "K_ISRSHE" : "K_ITRSHE"); + case KITEM_INVINCIBILITY: + return (small ? "K_ISINV1" : "K_ITINV1"); + case KITEM_BANANA: + case KRITEM_TRIPLEBANANA: + case KRITEM_TENFOLDBANANA: + return (small ? "K_ISBANA" : "K_ITBANA"); + case KITEM_EGGMAN: + return (small ? "K_ISEGGM" : "K_ITEGGM"); + case KITEM_ORBINAUT: + return (small ? "K_ISORBN" : "K_ITORB1"); + case KITEM_JAWZ: + case KRITEM_DUALJAWZ: + return (small ? "K_ISJAWZ" : "K_ITJAWZ"); + case KITEM_MINE: + return (small ? "K_ISMINE" : "K_ITMINE"); + case KITEM_BALLHOG: + return (small ? "K_ISBHOG" : "K_ITBHOG"); + case KITEM_SPB: + return (small ? "K_ISSPB" : "K_ITSPB"); + case KITEM_GROW: + return (small ? "K_ISGROW" : "K_ITGROW"); + case KITEM_SHRINK: + return (small ? "K_ISSHRK" : "K_ITSHRK"); + case KITEM_THUNDERSHIELD: + return (small ? "K_ISTHNS" : "K_ITTHNS"); + case KITEM_HYUDORO: + return (small ? "K_ISHYUD" : "K_ITHYUD"); + case KITEM_POGOSPRING: + return (small ? "K_ISPOGO" : "K_ITPOGO"); + case KITEM_KITCHENSINK: + return (small ? "K_ISSINK" : "K_ITSINK"); + case KRITEM_TRIPLEORBINAUT: + return (small ? "K_ISORBN" : "K_ITORB3"); + case KRITEM_QUADORBINAUT: + return (small ? "K_ISORBN" : "K_ITORB4"); + default: + return (small ? "K_ISSAD" : "K_ITSAD"); + } +} + //} INT32 ITEM_X, ITEM_Y; // Item Window diff --git a/src/k_kart.h b/src/k_kart.h index 58f2cc179..9865d3734 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -57,6 +57,7 @@ void K_CalculateBattleWanted(void); void K_CheckBumpers(void); void K_CheckSpectateStatus(void); +const char *K_GetItemPatch(UINT8 item, boolean small); INT32 K_calcSplitFlags(INT32 snapflags); void K_LoadKartHUDGraphics(void); fixed_t K_FindCheckX(fixed_t px, fixed_t py, angle_t ang, fixed_t mx, fixed_t my); diff --git a/src/m_menu.c b/src/m_menu.c index eb8123e9c..7ea5b6428 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -54,6 +54,7 @@ #include "st_stuff.h" #include "i_sound.h" #include "k_kart.h" // SRB2kart +#include "d_player.h" // KITEM_ constants // Condition Sets #include "m_cond.h" @@ -340,7 +341,7 @@ static void M_DrawControl(void); static void M_DrawVideoMenu(void); static void M_DrawHUDOptions(void); static void M_DrawVideoMode(void); -//static void M_DrawMonitorToggles(void); +static void M_DrawMonitorToggles(void); #ifdef HWRENDER static void M_OGL_DrawFogMenu(void); static void M_OGL_DrawColorMenu(void); @@ -371,6 +372,7 @@ static void M_HandleSetupMultiPlayer(INT32 choice); static void M_HandleFogColor(INT32 choice); #endif static void M_HandleVideoMode(INT32 choice); +static void M_HandleMonitorToggles(INT32 choice); // Consvar onchange functions static void Nextmap_OnChange(void); @@ -1519,27 +1521,30 @@ static menuitem_t OP_ServerOptionsMenu[] = static menuitem_t OP_MonitorToggleMenu[] = { - // Printing handled by drawing function + // Mostly handled by the drawing function. // Instead of using this for dumb monitors, lets use the new item bools we have :V - {IT_STRING | IT_CVAR, NULL, "Sneakers", &cv_sneaker, 10}, - {IT_STRING | IT_CVAR, NULL, "Sneakers x3", &cv_triplesneaker, 18}, - {IT_STRING | IT_CVAR, NULL, "Rocket Sneakers", &cv_rocketsneaker, 26}, - {IT_STRING | IT_CVAR, NULL, "Invinciblity", &cv_invincibility, 34}, - {IT_STRING | IT_CVAR, NULL, "Bananas", &cv_banana, 42}, - {IT_STRING | IT_CVAR, NULL, "Bananas x3", &cv_triplebanana, 50}, - {IT_STRING | IT_CVAR, NULL, "Eggman Monitors", &cv_eggmanmonitor, 58}, - {IT_STRING | IT_CVAR, NULL, "Orbinauts", &cv_orbinaut, 66}, - {IT_STRING | IT_CVAR, NULL, "Orbinauts x3", &cv_tripleorbinaut, 74}, - {IT_STRING | IT_CVAR, NULL, "Jawz", &cv_jawz, 82}, - {IT_STRING | IT_CVAR, NULL, "Jawz x2", &cv_dualjawz, 90}, - {IT_STRING | IT_CVAR, NULL, "Mines", &cv_mine, 98}, - {IT_STRING | IT_CVAR, NULL, "Ballhogs", &cv_ballhog, 106}, - {IT_STRING | IT_CVAR, NULL, "Self-Propelled Bombs",&cv_selfpropelledbomb,114}, - {IT_STRING | IT_CVAR, NULL, "Grow", &cv_grow, 122}, - {IT_STRING | IT_CVAR, NULL, "Shrink", &cv_shrink, 130}, - {IT_STRING | IT_CVAR, NULL, "Thunder Shields", &cv_thundershield, 138}, - {IT_STRING | IT_CVAR, NULL, "Hyudoros", &cv_hyudoro, 146}, - {IT_STRING | IT_CVAR, NULL, "Pogo Springs", &cv_pogospring, 154}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Sneakers", M_HandleMonitorToggles, KITEM_SNEAKER}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Sneakers x3", M_HandleMonitorToggles, KRITEM_TRIPLESNEAKER}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Rocket Sneakers", M_HandleMonitorToggles, KITEM_ROCKETSNEAKER}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Invinciblity", M_HandleMonitorToggles, KITEM_INVINCIBILITY}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Bananas", M_HandleMonitorToggles, KITEM_BANANA}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Bananas x3", M_HandleMonitorToggles, KRITEM_TRIPLEBANANA}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Bananas x10", M_HandleMonitorToggles, KRITEM_TENFOLDBANANA}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Eggman Monitors", M_HandleMonitorToggles, KITEM_EGGMAN}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Orbinauts", M_HandleMonitorToggles, KITEM_ORBINAUT}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Orbinauts x3", M_HandleMonitorToggles, KRITEM_TRIPLEORBINAUT}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Orbinauts x4", M_HandleMonitorToggles, KRITEM_QUADORBINAUT}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Mines", M_HandleMonitorToggles, KITEM_MINE}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Jawz", M_HandleMonitorToggles, KITEM_JAWZ}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Jawz x2", M_HandleMonitorToggles, KRITEM_DUALJAWZ}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Ballhogs", M_HandleMonitorToggles, KITEM_BALLHOG}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Self-Propelled Bombs", M_HandleMonitorToggles, KITEM_SPB}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Grow", M_HandleMonitorToggles, KITEM_GROW}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Shrink", M_HandleMonitorToggles, KITEM_SHRINK}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Thunder Shields", M_HandleMonitorToggles, KITEM_THUNDERSHIELD}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Hyudoros", M_HandleMonitorToggles, KITEM_HYUDORO}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Pogo Springs", M_HandleMonitorToggles, KITEM_POGOSPRING}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Kitchen Sinks", M_HandleMonitorToggles, KITEM_KITCHENSINK}, }; // ========================================================================== @@ -1961,18 +1966,17 @@ menu_t OP_ServerOptionsDef = DEFAULTMENUSTYLE("M_SERVER", OP_ServerOptionsMenu, //menu_t OP_NetgameOptionsDef = DEFAULTMENUSTYLE("M_SERVER", OP_NetgameOptionsMenu, &OP_ServerOptionsDef, 30, 30); //menu_t OP_GametypeOptionsDef = DEFAULTMENUSTYLE("M_SERVER", OP_GametypeOptionsMenu, &OP_ServerOptionsDef, 30, 30); -menu_t OP_MonitorToggleDef = DEFAULTMENUSTYLE("M_GAME", OP_MonitorToggleMenu, &OP_GameOptionsDef, 30, 30); -/*menu_t OP_MonitorToggleDef = +menu_t OP_MonitorToggleDef = { - "M_SERVER", + "M_GAME", sizeof (OP_MonitorToggleMenu)/sizeof (menuitem_t), - &OP_ServerOptionsDef, + &OP_GameOptionsDef, OP_MonitorToggleMenu, M_DrawMonitorToggles, - 30, 30, + 47, 30, 0, NULL -};*/ +}; #ifdef HWRENDER menu_t OP_OpenGLOptionsDef = DEFAULTMENUSTYLE("M_VIDEO", OP_OpenGLOptionsMenu, &OP_VideoOptionsDef, 30, 30); @@ -8422,41 +8426,209 @@ static void M_HandleVideoMode(INT32 ch) // =============== // Monitor Toggles // =============== -/*static void M_DrawMonitorToggles(void) +static consvar_t *kartitemcvs[NUMKARTRESULTS-1] = { + &cv_sneaker, + &cv_rocketsneaker, + &cv_invincibility, + &cv_banana, + &cv_eggmanmonitor, + &cv_orbinaut, + &cv_jawz, + &cv_mine, + &cv_ballhog, + &cv_selfpropelledbomb, + &cv_grow, + &cv_shrink, + &cv_thundershield, + &cv_hyudoro, + &cv_pogospring, + &cv_kitchensink, + &cv_triplesneaker, + &cv_triplebanana, + &cv_decabanana, + &cv_tripleorbinaut, + &cv_quadorbinaut, + &cv_dualjawz +}; + +static void M_DrawMonitorToggles(void) { - INT32 i, y; - INT32 sum = 0; + const INT32 edges = 4; + const INT32 height = 4; + const INT32 spacing = 35; + const INT32 column = itemOn/height; + //const INT32 row = itemOn%height; + INT32 leftdraw, rightdraw, totaldraw; + INT32 x = currentMenu->x, y = currentMenu->y+(spacing/4); consvar_t *cv; - boolean cheating = false; + INT32 i; - M_DrawGenericMenu(); + M_DrawMenuTitle(); - // Assumes all are cvar type. - for (i = 0; i < currentMenu->numitems; ++i) + // Find the available space around column + leftdraw = rightdraw = column; + totaldraw = 0; + for (i = 0; (totaldraw < edges*2 && i < edges*4); i++) { - cv = (consvar_t *)currentMenu->menuitems[i].itemaction; - sum += cv->value; - - if (!CV_IsSetToDefault(cv)) - cheating = true; + if (rightdraw+1 < (currentMenu->numitems/height)+1) + { + rightdraw++; + totaldraw++; + } + if (leftdraw-1 >= 0) + { + leftdraw--; + totaldraw++; + } } - for (i = 0; i < currentMenu->numitems; ++i) + for (i = leftdraw; i <= rightdraw; i++) { - cv = (consvar_t *)currentMenu->menuitems[i].itemaction; - y = currentMenu->y + currentMenu->menuitems[i].alphaKey; + INT32 j; - M_DrawSlider(currentMenu->x + 20, y, cv, (i == itemOn)); + for (j = 0; j < height; j++) + { + const INT32 thisitem = (i*height)+j; + const boolean selected = (thisitem == itemOn); + INT32 drawnum = 0; + INT32 translucent = 0; - if (!cv->value) - V_DrawRightAlignedString(312, y, V_OLDSPACING|((i == itemOn) ? highlightflags : 0), "None"); - else - V_DrawRightAlignedString(312, y, V_OLDSPACING|((i == itemOn) ? highlightflags : 0), va("%3d%%", (cv->value*100)/sum)); + if (thisitem >= currentMenu->numitems) + continue; + + cv = kartitemcvs[currentMenu->menuitems[thisitem].alphaKey-1]; + translucent = (cv->value ? 0 : V_TRANSLUCENT); + + switch (currentMenu->menuitems[thisitem].alphaKey) + { + case KRITEM_DUALJAWZ: + drawnum = 2; + break; + case KRITEM_TRIPLESNEAKER: + case KRITEM_TRIPLEBANANA: + drawnum = 3; + break; + case KRITEM_TRIPLEORBINAUT: + if (!selected) + drawnum = 3; + break; + case KRITEM_QUADORBINAUT: + if (!selected) + drawnum = 4; + break; + case KRITEM_TENFOLDBANANA: + drawnum = 10; + break; + default: + break; + } + + if (selected) + { + if (cv->value) + V_DrawScaledPatch(x-1, y-2, 0, W_CachePatchName("K_ITBG", PU_CACHE)); + else + V_DrawScaledPatch(x-1, y-2, 0, W_CachePatchName("K_ITBGD", PU_CACHE)); + + if (drawnum != 0) + { + V_DrawScaledPatch(x-1, y-2, 0, W_CachePatchName("K_ITMUL", PU_CACHE)); + V_DrawScaledPatch(x-1, y-2, translucent, W_CachePatchName(K_GetItemPatch(currentMenu->menuitems[thisitem].alphaKey, !selected), PU_CACHE)); + V_DrawScaledPatch(x+27, y+39, 0, W_CachePatchName("K_ITX", PU_CACHE)); + V_DrawKartString(x+37, y+34, translucent, va("%d", drawnum)); + } + else + V_DrawScaledPatch(x-1, y-2, translucent, W_CachePatchName(K_GetItemPatch(currentMenu->menuitems[thisitem].alphaKey, !selected), PU_CACHE)); + } + else + { + if (cv->value) + V_DrawScaledPatch(x, y, 0, W_CachePatchName("K_ISBG", PU_CACHE)); + else + V_DrawScaledPatch(x, y, 0, W_CachePatchName("K_ISBGD", PU_CACHE)); + + if (drawnum != 0) + { + V_DrawScaledPatch(x, y, 0, W_CachePatchName("K_ISMUL", PU_CACHE)); + V_DrawScaledPatch(x, y, translucent, W_CachePatchName(K_GetItemPatch(currentMenu->menuitems[thisitem].alphaKey, !selected), PU_CACHE)); + V_DrawString(x+24, y+31, V_ALLOWLOWERCASE|translucent, va("x%d", drawnum)); + } + else + V_DrawScaledPatch(x, y, translucent, W_CachePatchName(K_GetItemPatch(currentMenu->menuitems[thisitem].alphaKey, !selected), PU_CACHE)); + } + + y += spacing; + } + + x += spacing; + y = currentMenu->y+(spacing/4); } - if (cheating) - V_DrawCenteredString(BASEVIDWIDTH/2, currentMenu->y, warningflags, "* MODIFIED, CHEATS ENABLED *"); -}*/ + V_DrawCenteredString(BASEVIDWIDTH/2, currentMenu->y, highlightflags, va("* %s *", currentMenu->menuitems[itemOn].text)); +} + +static void M_HandleMonitorToggles(INT32 choice) +{ + const INT32 width = 6, height = 4; + INT32 column = itemOn/height, row = itemOn%height; + INT16 next; + consvar_t *cv = kartitemcvs[currentMenu->menuitems[itemOn].alphaKey-1]; + + switch (choice) + { + case KEY_RIGHTARROW: + S_StartSound(NULL, sfx_menu1); + column++; + if (((column*height)+row) >= currentMenu->numitems) + column = 0; + next = min(((column*height)+row), currentMenu->numitems-1); + itemOn = next; + break; + + case KEY_LEFTARROW: + S_StartSound(NULL, sfx_menu1); + column--; + if (column < 0) + column = width-1; + if (((column*height)+row) >= currentMenu->numitems) + column--; + next = max(((column*height)+row), 0); + if (next >= currentMenu->numitems) + next = currentMenu->numitems-1; + itemOn = next; + break; + + case KEY_DOWNARROW: + S_StartSound(NULL, sfx_menu1); + row = (row+1) % height; + if (((column*height)+row) >= currentMenu->numitems) + row = 0; + next = min(((column*height)+row), currentMenu->numitems-1); + itemOn = next; + break; + + case KEY_UPARROW: + S_StartSound(NULL, sfx_menu1); + row = (row-1) % height; + if (row < 0) + row = height-1; + if (((column*height)+row) >= currentMenu->numitems) + row--; + next = max(((column*height)+row), 0); + if (next >= currentMenu->numitems) + next = currentMenu->numitems-1; + itemOn = next; + break; + + case KEY_ENTER: + CV_AddValue(cv,1); + break; + + case KEY_ESCAPE: + M_ClearMenus(true); + break; + } +} // ========= // Quit Game From 27f7e5bb4a4244e8b6663910a4999ce2270b449c Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Fri, 31 Aug 2018 13:23:05 -0400 Subject: [PATCH 050/146] Small fix --- src/m_menu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index 7ea5b6428..2458097f7 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -8534,7 +8534,7 @@ static void M_DrawMonitorToggles(void) { V_DrawScaledPatch(x-1, y-2, 0, W_CachePatchName("K_ITMUL", PU_CACHE)); V_DrawScaledPatch(x-1, y-2, translucent, W_CachePatchName(K_GetItemPatch(currentMenu->menuitems[thisitem].alphaKey, !selected), PU_CACHE)); - V_DrawScaledPatch(x+27, y+39, 0, W_CachePatchName("K_ITX", PU_CACHE)); + V_DrawScaledPatch(x+27, y+39, translucent, W_CachePatchName("K_ITX", PU_CACHE)); V_DrawKartString(x+37, y+34, translucent, va("%d", drawnum)); } else From b26c30156b6d72cdf72c9f50a937f07692acaa75 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Fri, 31 Aug 2018 14:41:37 -0400 Subject: [PATCH 051/146] Toggle All option --- src/m_menu.c | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 2458097f7..8b15ead0f 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1526,7 +1526,7 @@ static menuitem_t OP_MonitorToggleMenu[] = {IT_KEYHANDLER | IT_NOTHING, NULL, "Sneakers", M_HandleMonitorToggles, KITEM_SNEAKER}, {IT_KEYHANDLER | IT_NOTHING, NULL, "Sneakers x3", M_HandleMonitorToggles, KRITEM_TRIPLESNEAKER}, {IT_KEYHANDLER | IT_NOTHING, NULL, "Rocket Sneakers", M_HandleMonitorToggles, KITEM_ROCKETSNEAKER}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Invinciblity", M_HandleMonitorToggles, KITEM_INVINCIBILITY}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Toggle All", M_HandleMonitorToggles, 0}, {IT_KEYHANDLER | IT_NOTHING, NULL, "Bananas", M_HandleMonitorToggles, KITEM_BANANA}, {IT_KEYHANDLER | IT_NOTHING, NULL, "Bananas x3", M_HandleMonitorToggles, KRITEM_TRIPLEBANANA}, {IT_KEYHANDLER | IT_NOTHING, NULL, "Bananas x10", M_HandleMonitorToggles, KRITEM_TENFOLDBANANA}, @@ -1539,6 +1539,7 @@ static menuitem_t OP_MonitorToggleMenu[] = {IT_KEYHANDLER | IT_NOTHING, NULL, "Jawz x2", M_HandleMonitorToggles, KRITEM_DUALJAWZ}, {IT_KEYHANDLER | IT_NOTHING, NULL, "Ballhogs", M_HandleMonitorToggles, KITEM_BALLHOG}, {IT_KEYHANDLER | IT_NOTHING, NULL, "Self-Propelled Bombs", M_HandleMonitorToggles, KITEM_SPB}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Invinciblity", M_HandleMonitorToggles, KITEM_INVINCIBILITY}, {IT_KEYHANDLER | IT_NOTHING, NULL, "Grow", M_HandleMonitorToggles, KITEM_GROW}, {IT_KEYHANDLER | IT_NOTHING, NULL, "Shrink", M_HandleMonitorToggles, KITEM_SHRINK}, {IT_KEYHANDLER | IT_NOTHING, NULL, "Thunder Shields", M_HandleMonitorToggles, KITEM_THUNDERSHIELD}, @@ -8496,6 +8497,21 @@ static void M_DrawMonitorToggles(void) if (thisitem >= currentMenu->numitems) continue; + if (currentMenu->menuitems[thisitem].alphaKey == 0) + { + if (selected) + { + V_DrawScaledPatch(x-1, y-2, 0, W_CachePatchName("K_ITBG", PU_CACHE)); + V_DrawScaledPatch(x-1, y-2, 0, W_CachePatchName("K_ITTOGL", PU_CACHE)); + } + else + { + V_DrawScaledPatch(x, y, 0, W_CachePatchName("K_ISBG", PU_CACHE)); + V_DrawScaledPatch(x, y, 0, W_CachePatchName("K_ISTOGL", PU_CACHE)); + } + continue; + } + cv = kartitemcvs[currentMenu->menuitems[thisitem].alphaKey-1]; translucent = (cv->value ? 0 : V_TRANSLUCENT); @@ -8572,7 +8588,7 @@ static void M_HandleMonitorToggles(INT32 choice) const INT32 width = 6, height = 4; INT32 column = itemOn/height, row = itemOn%height; INT16 next; - consvar_t *cv = kartitemcvs[currentMenu->menuitems[itemOn].alphaKey-1]; + UINT8 i; switch (choice) { @@ -8621,7 +8637,21 @@ static void M_HandleMonitorToggles(INT32 choice) break; case KEY_ENTER: - CV_AddValue(cv,1); + if (currentMenu->menuitems[itemOn].alphaKey == 0) + { + INT32 v = cv_sneaker.value; + S_StartSound(NULL, sfx_s1b4); + for (i = 0; i < NUMKARTRESULTS-1; i++) + { + if (kartitemcvs[i]->value == v) + CV_AddValue(kartitemcvs[i], 1); + } + } + else + { + S_StartSound(NULL, sfx_s1ba); + CV_AddValue(kartitemcvs[currentMenu->menuitems[itemOn].alphaKey-1], 1); + } break; case KEY_ESCAPE: From 1dfe7e3da41d40eec906009d2059452356ad4995 Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 31 Aug 2018 22:38:56 +0100 Subject: [PATCH 052/146] Update arrow rendering to use simple character function rather than overkill string function. --- src/m_menu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 8e83f3a6a..1c4e9015e 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5519,7 +5519,7 @@ static void M_DrawStatsMaps(int location) boolean dotopname = true, dobottomarrow = (location < statsMax); if (location) - V_DrawString(10, y-(skullAnimCounter/5), highlightflags, "\x1A"); + V_DrawCharacter(10, y-(skullAnimCounter/5), '\x1A' | highlightflags, false); while (statsMapList[++i] != -1) { @@ -5601,7 +5601,7 @@ static void M_DrawStatsMaps(int location) } bottomarrow: if (dobottomarrow) - V_DrawString(10, y-8 + (skullAnimCounter/5), highlightflags, "\x1B"); + V_DrawCharacter(10, y-8 + (skullAnimCounter/5), '\x1B' | highlightflags, false); } static void M_DrawLevelStats(void) From 5c73357dee2ef4b4918816c760223a078afed4cf Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sun, 2 Sep 2018 20:50:22 -0400 Subject: [PATCH 053/146] Remove an #ifdef here --- src/p_slopes.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/p_slopes.c b/src/p_slopes.c index a9706eb9e..c516fa970 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -790,10 +790,6 @@ void P_SlopeLaunch(mobj_t *mo) { if (!(mo->standingslope->flags & SL_NOPHYSICS)) // If there's physics, time for launching. { -#ifdef GROWNEVERMISSES - const fixed_t xyscale = mapheaderinfo[gamemap-1]->mobj_scale + (mapheaderinfo[gamemap-1]->mobj_scale - mo->scale); - const fixed_t zscale = mapheaderinfo[gamemap-1]->mobj_scale + (mapheaderinfo[gamemap-1]->mobj_scale - mo->scale); -#endif // Double the pre-rotation Z, then halve the post-rotation Z. This reduces the // vertical launch given from slopes while increasing the horizontal launch // given. Good for SRB2's gravity and horizontal speeds. @@ -804,9 +800,13 @@ void P_SlopeLaunch(mobj_t *mo) P_QuantizeMomentumToSlope(&slopemom, mo->standingslope); #ifdef GROWNEVERMISSES - mo->momx = FixedMul(slopemom.x, xyscale); - mo->momy = FixedMul(slopemom.y, xyscale); - mo->momz = FixedMul(slopemom.z, zscale); + { + const fixed_t xyscale = mapheaderinfo[gamemap-1]->mobj_scale + (mapheaderinfo[gamemap-1]->mobj_scale - mo->scale); + const fixed_t zscale = mapheaderinfo[gamemap-1]->mobj_scale + (mapheaderinfo[gamemap-1]->mobj_scale - mo->scale); + mo->momx = FixedMul(slopemom.x, xyscale); + mo->momy = FixedMul(slopemom.y, xyscale); + mo->momz = FixedMul(slopemom.z, zscale); + } #else mo->momx = slopemom.x; mo->momy = slopemom.y; From 79c49550c1d7e84323cbf7f1c65a7a1bef3c64b5 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sun, 2 Sep 2018 20:57:40 -0400 Subject: [PATCH 054/146] Move wall sector type to from Section1:14 to Section1:12 The SMK maps will probably need an update --- src/p_map.c | 6 +++--- src/p_spec.c | 7 ++----- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index 2234534b3..88045a3e1 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -2592,9 +2592,9 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) if (P_PlayerTouchingSectorSpecial(thing->player, 1, 13) || GETSECSPECIAL(R_PointInSubsector(x, y)->sector->special, 1) == 13) maxstep <<= 1; - // If using type Section1:14, no maxstep. For ledges you want the player to LAND on, not climb! (see: SMK VL2) - else if (P_PlayerTouchingSectorSpecial(thing->player, 1, 14) - || GETSECSPECIAL(R_PointInSubsector(x, y)->sector->special, 1) == 14) + // If using type Section1:12, no maxstep. For ledges you don't want the player to climb! (see: Egg Zeppelin & SMK port walls) + else if (P_PlayerTouchingSectorSpecial(thing->player, 1, 12) + || GETSECSPECIAL(R_PointInSubsector(x, y)->sector->special, 1) == 12) maxstep = 0; // Don't 'step up' while springing, diff --git a/src/p_spec.c b/src/p_spec.c index 3ad529c41..9e3393aca 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3616,12 +3616,9 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers if (gametype == GT_CTF && player->gotflag & (GF_REDFLAG|GF_BLUEFLAG)) P_PlayerFlagBurst(player, false); break; - case 12: // Space Countdown - if ((player->powers[pw_shield] & SH_NOSTACK) != SH_ELEMENTAL && !player->powers[pw_spacetime]) - player->powers[pw_spacetime] = spacetimetics + 1; - break; + case 12: // Wall Sector (Don't step-up/down) case 13: // Ramp Sector (Increase step-up/down) - case 14: // Non-Ramp Sector (Don't step-up/down) + case 14: // Non-Ramp Sector (Don't step-down) case 15: // Bouncy Sector (FOF Control Only) break; } From e4a4ef83c15238ed275652aae36c2dd05cbade05 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sun, 2 Sep 2018 22:53:40 -0400 Subject: [PATCH 055/146] Vote screen uses the font's intended character spacing --- src/v_video.c | 16 ++++++++++------ src/y_inter.c | 2 +- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/v_video.c b/src/v_video.c index e39663a74..58115e020 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -1755,8 +1755,9 @@ void V_DrawThinString(INT32 x, INT32 y, INT32 option, const char *string) case V_OLDSPACING: charwidth = 5; break; - case V_6WIDTHSPACE: - spacewidth = 3; + // Out of video flags, so we're reusing this for alternate charwidth instead + /*case V_6WIDTHSPACE: + spacewidth = 3;*/ default: break; } @@ -1798,7 +1799,8 @@ void V_DrawThinString(INT32 x, INT32 y, INT32 option, const char *string) if (charwidth) w = charwidth * dupx; else - w = (SHORT(tny_font[c]->width) * dupx); + w = ((option & V_6WIDTHSPACE ? max(1, SHORT(tny_font[c]->width)-1) // Reuse this flag for the alternate bunched-up spacing + : SHORT(tny_font[c]->width)) * dupx); if (cx > scrwidth) break; @@ -2220,8 +2222,9 @@ INT32 V_ThinStringWidth(const char *string, INT32 option) case V_OLDSPACING: charwidth = 5; break; - case V_6WIDTHSPACE: - spacewidth = 3; + // Out of video flags, so we're reusing this for alternate charwidth instead + /*case V_6WIDTHSPACE: + spacewidth = 3;*/ default: break; } @@ -2236,7 +2239,8 @@ INT32 V_ThinStringWidth(const char *string, INT32 option) if (c < 0 || c >= HU_FONTSIZE || !tny_font[c]) w += spacewidth; else - w += (charwidth ? charwidth : SHORT(tny_font[c]->width)); + w += (charwidth ? charwidth + : (option & V_6WIDTHSPACE ? max(1, SHORT(tny_font[c]->width)-1) : SHORT(tny_font[c]->width))); // Reuse this flag for the alternate bunched-up spacing } return w; diff --git a/src/y_inter.c b/src/y_inter.c index 9416211a0..e0d903275 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -1048,7 +1048,7 @@ void Y_VoteDrawer(void) } V_DrawSmallScaledPatch(BASEVIDWIDTH-100, y, V_SNAPTORIGHT, pic); - V_DrawRightAlignedThinString(BASEVIDWIDTH-20, 40+y, V_SNAPTORIGHT, str); + V_DrawRightAlignedThinString(BASEVIDWIDTH-22, 40+y, V_SNAPTORIGHT|V_6WIDTHSPACE, str); if (levelinfo[i].gts) { INT32 w = V_ThinStringWidth(levelinfo[i].gts, V_SNAPTORIGHT)+1; From 8fa9fef15d1d1e024cd1f8dd29daf899b894c5a8 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Mon, 3 Sep 2018 00:06:17 -0400 Subject: [PATCH 056/146] Redone stat graph --- src/m_menu.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index 8b15ead0f..f7fe1e84f 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -7128,6 +7128,8 @@ static void M_DrawSetupMultiPlayerMenu(void) spritedef_t *sprdef; spriteframe_t *sprframe; patch_t *statbg = W_CachePatchName("K_STATBG", PU_CACHE); + patch_t *statlr = W_CachePatchName("K_STATLR", PU_CACHE); + patch_t *statud = W_CachePatchName("K_STATUD", PU_CACHE); patch_t *statdot = W_CachePatchName("K_SDOT0", PU_CACHE); patch_t *patch; UINT8 frame; @@ -7135,10 +7137,14 @@ static void M_DrawSetupMultiPlayerMenu(void) UINT8 weight; UINT8 i; const UINT8 *flashcol = V_GetStringColormap(highlightflags); + INT32 statx, staty; mx = MP_PlayerSetupDef.x; my = MP_PlayerSetupDef.y; + statx = (BASEVIDWIDTH - mx - 118); + staty = (my+62); + // use generic drawer for cursor, items and title M_DrawGenericMenu(); @@ -7176,7 +7182,16 @@ static void M_DrawSetupMultiPlayerMenu(void) } // SRB2Kart: draw the stat backer - V_DrawFixedPatch((BASEVIDWIDTH - mx - 117)< Date: Mon, 3 Sep 2018 20:40:46 -0400 Subject: [PATCH 057/146] Camera now sticks close behind you, only the angle is lagged --- src/p_user.c | 334 ++++++++++++--------------------------------------- 1 file changed, 77 insertions(+), 257 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index fabce7efc..9ba70c45a 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2939,17 +2939,14 @@ static void P_DoClimbing(player_t *player) // SRB2kart - unused P_InstaThrust(player->mo, player->mo->angle, FixedMul(-4*FRACUNIT, player->mo->scale)); } - if (!demoplayback || P_AnalogMove(player)) - { - if (player == &players[consoleplayer]) - localangle = player->mo->angle; - else if (player == &players[secondarydisplayplayer]) - localangle2 = player->mo->angle; - else if (player == &players[thirddisplayplayer]) - localangle3 = player->mo->angle; - else if (player == &players[fourthdisplayplayer]) - localangle4 = player->mo->angle; - } + if (player == &players[consoleplayer]) + localangle = player->mo->angle; + else if (player == &players[secondarydisplayplayer]) + localangle2 = player->mo->angle; + else if (player == &players[thirddisplayplayer]) + localangle3 = player->mo->angle; + else if (player == &players[fourthdisplayplayer]) + localangle4 = player->mo->angle; if (player->climbing == 0) P_SetPlayerMobjState(player->mo, S_PLAY_ATK1); @@ -3772,17 +3769,14 @@ void P_DoJump(player_t *player, boolean soundandstate) player->mo->angle = player->mo->angle - ANGLE_180; // Turn around from the wall you were climbing. - if (!demoplayback || P_AnalogMove(player)) - { - if (player == &players[consoleplayer]) - localangle = player->mo->angle; // Adjust the local control angle. - else if (player == &players[secondarydisplayplayer]) - localangle2 = player->mo->angle; - else if (player == &players[thirddisplayplayer]) - localangle3 = player->mo->angle; - else if (player == &players[fourthdisplayplayer]) - localangle4 = player->mo->angle; - } + if (player == &players[consoleplayer]) + localangle = player->mo->angle; // Adjust the local control angle. + else if (player == &players[secondarydisplayplayer]) + localangle2 = player->mo->angle; + else if (player == &players[thirddisplayplayer]) + localangle3 = player->mo->angle; + else if (player == &players[fourthdisplayplayer]) + localangle4 = player->mo->angle; player->climbing = 0; // Stop climbing, duh! P_InstaThrust(player->mo, player->mo->angle, FixedMul(6*FRACUNIT, player->mo->scale)); // Jump off the wall. @@ -7820,7 +7814,7 @@ void P_HomingAttack(mobj_t *source, mobj_t *enemy) // Home in on your target // change angle source->angle = R_PointToAngle2(source->x, source->y, enemy->x, enemy->y); - if (source->player && (!demoplayback || P_AnalogMove(source->player))) + if (source->player) { if (source->player == &players[consoleplayer]) localangle = source->angle; @@ -8337,54 +8331,40 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall camspeed = FRACUNIT; } -#ifdef REDSANALOG - if (P_AnalogMove(player) && (player->cmd.buttons & (BT_FORWARD|BT_BACKWARD)) == (BT_FORWARD|BT_BACKWARD)) { - camstill = true; - if (camspeed < 4*FRACUNIT/5) - camspeed = 4*FRACUNIT/5; - } -#endif // REDSANALOG - if (mo->eflags & MFE_VERTICALFLIP) camheight += thiscam->height; - if (twodlevel || (mo->flags2 & MF2_TWOD)) - angle = ANGLE_90; - else if (camstill || resetcalled || player->playerstate == PST_DEAD) + if (camstill || resetcalled || player->playerstate == PST_DEAD) angle = thiscam->angle; - else if (player->pflags & PF_NIGHTSMODE) // NiGHTS Level - { - if ((player->pflags & PF_TRANSFERTOCLOSEST) && player->axis1 && player->axis2) - { - angle = R_PointToAngle2(player->axis1->x, player->axis1->y, player->axis2->x, player->axis2->y); - angle += ANGLE_90; - } - else if (player->mo->target) - { - if (player->mo->target->flags2 & MF2_AMBUSH) - angle = R_PointToAngle2(player->mo->target->x, player->mo->target->y, player->mo->x, player->mo->y); - else - angle = R_PointToAngle2(player->mo->x, player->mo->y, player->mo->target->x, player->mo->target->y); - } - } - else if (P_AnalogMove(player)) // Analog - angle = R_PointToAngle2(thiscam->x, thiscam->y, mo->x, mo->y); - else if (demoplayback && leveltime > starttime) + else if (leveltime < starttime) + angle = focusangle + FixedAngle(camrotate*FRACUNIT); + else if (demoplayback) { angle = focusangle; focusangle = R_PointToAngle2(thiscam->x, thiscam->y, mo->x, mo->y); if (player == &players[consoleplayer]) { if (focusangle >= localangle) - localangle += abs((signed)(focusangle - localangle))>>5; + localangle += abs((signed)(focusangle - localangle))>>3; else - localangle -= abs((signed)(focusangle - localangle))>>5; + localangle -= abs((signed)(focusangle - localangle))>>3; } } else - angle = focusangle + FixedAngle(camrotate*FRACUNIT); + { + angle_t input = focusangle + FixedAngle(camrotate<angle; + boolean invert = (input > ANGLE_180); + if (invert) + input = InvAngle(input); - if (!resetcalled && (leveltime > starttime) && (cv_analog.value || demoplayback) + input = FixedAngle(FixedMul(AngleFixed(input), camspeed)); + if (invert) + input = InvAngle(input); + + angle = thiscam->angle + input; + } + + if (!resetcalled && (leveltime > starttime) && ((thiscam == &camera && t_cam_rotate != -42) || (thiscam == &camera2 && t_cam2_rotate != -42) || (thiscam == &camera3 && t_cam3_rotate != -42) @@ -8394,73 +8374,21 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall thiscam->angle = angle; } - /* // SRB2kart - camera controls are disabled... for now. - if (!objectplacing && !(twodlevel || (mo->flags2 & MF2_TWOD)) && !(player->pflags & PF_NIGHTSMODE) && displayplayer == consoleplayer) - { -#ifdef REDSANALOG - if ((player->cmd.buttons & (BT_FORWARD|BT_BACKWARD)) == (BT_FORWARD|BT_BACKWARD)); else -#endif - if (player->cmd.buttons & BT_FORWARD) - { - if (thiscam == &camera) - { - if (cv_analog.value || demoplayback) - angle -= FixedAngle(cv_cam_rotspeed.value*FRACUNIT); - else - CV_SetValue(&cv_cam_rotate, camrotate == 0 ? 358 - : camrotate - 2); - } - else - { - if (cv_analog2.value) - angle -= FixedAngle(cv_cam2_rotspeed.value*FRACUNIT); - else - CV_SetValue(&cv_cam2_rotate, camrotate == 0 ? 358 - : camrotate - 2); - } - } - else if (player->cmd.buttons & BT_BACKWARD) - { - if (thiscam == &camera) - { - if (cv_analog.value || demoplayback) - angle += FixedAngle(cv_cam_rotspeed.value*FRACUNIT); - else - CV_SetValue(&cv_cam_rotate, camrotate + 2); - } - else - { - if (cv_analog2.value) - angle += FixedAngle(cv_cam2_rotspeed.value*FRACUNIT); - else - CV_SetValue(&cv_cam2_rotate, camrotate + 2); - } - } - } - */ - height = camheight; // sets ideal cam pos - if (twodlevel || (mo->flags2 & MF2_TWOD)) - dist = 480<pflags & PF_NIGHTSMODE) - dist = 320<climbing || player->exiting || player->playerstate == PST_DEAD || (player->pflags & (PF_MACESPIN|PF_ITEMHANG|PF_ROPEHANG))) - dist <<= 1; + dist = FixedMul(dist, 3*FRACUNIT/2); + height = FixedMul(height, 3*FRACUNIT/2); } + if (player->climbing || player->playerstate == PST_DEAD || (player->pflags & (PF_MACESPIN|PF_ITEMHANG|PF_ROPEHANG))) + dist <<= 1; + checkdist = dist; if (checkdist < 128*FRACUNIT) @@ -8469,38 +8397,6 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall x = mo->x - FixedMul(FINECOSINE((angle>>ANGLETOFINESHIFT) & FINEMASK), dist); y = mo->y - FixedMul(FINESINE((angle>>ANGLETOFINESHIFT) & FINEMASK), dist); -#if 0 - if (twodlevel || (mo->flags2 & MF2_TWOD)) - { - // Camera doesn't ALWAYS need to move, only when running... - if (abs(player->mo->momx) > 10) - { - // Move the camera all smooth-like, not jerk it around... - if (mo->momx > 0) - { - if (thiscam->relativex < MAXCAMERADIST) - thiscam->relativex += 4*FRACUNIT; - } - else if (mo->momx < 0) - { - if (thiscam->relativex > -MAXCAMERADIST) - thiscam->relativex -= 4*FRACUNIT; - } - } - else // If speed is less than required, start moving the camera back. - { - if (thiscam->relativex > 0) - thiscam->relativex -= 4*FRACUNIT; - else if (thiscam->relativex < 0) - thiscam->relativex += 4*FRACUNIT; - } - - // Add the relative x to the global x - x += thiscam->relativex; - y += mo->momy << 1; - } -#endif // bad 2D camera code - pviewheight = FixedMul(32<scale); if (mo->eflags & MFE_VERTICALFLIP) @@ -8677,7 +8573,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall for (rover = newsubsec->sector->ffloors; rover; rover = rover->next) { fixed_t topheight, bottomheight; - if ((rover->flags & FF_BLOCKOTHERS) && (rover->flags & FF_RENDERALL) && (rover->flags & FF_EXISTS) && GETSECSPECIAL(rover->master->frontsector->special, 4) != 12) + if ((rover->flags & FF_BLOCKOTHERS) && (rover->flags & FF_RENDERALL) && (rover->flags & FF_EXISTS) && GETSECSPECIAL(rover->master->frontsector->special, 4) == 12) { topheight = P_CameraGetFOFTopZ(thiscam, newsubsec->sector, rover, midx, midy, NULL); bottomheight = P_CameraGetFOFBottomZ(thiscam, newsubsec->sector, rover, midx, midy, NULL); @@ -8703,15 +8599,12 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall } } - if (mo->type == MT_EGGTRAP) - z = mo->z + 128*FRACUNIT + pviewheight + camheight; - if (thiscam->z < thiscam->floorz && !cameranoclip) thiscam->z = thiscam->floorz; // point viewed by the camera // this point is just 64 unit forward the player - dist = FixedMul(64 << FRACBITS, mapheaderinfo[gamemap-1]->mobj_scale); + dist = 64*mapheaderinfo[gamemap-1]->mobj_scale; viewpointx = mo->x + FixedMul(FINECOSINE((angle>>ANGLETOFINESHIFT) & FINEMASK), dist); viewpointy = mo->y + FixedMul(FINESINE((angle>>ANGLETOFINESHIFT) & FINEMASK), dist); @@ -8721,52 +8614,28 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall viewpointx = mo->x + FixedMul(FINECOSINE((angle>>ANGLETOFINESHIFT) & FINEMASK), dist); viewpointy = mo->y + FixedMul(FINESINE((angle>>ANGLETOFINESHIFT) & FINEMASK), dist); -/* - if (twodlevel || (mo->flags2 & MF2_TWOD)) - thiscam->angle = angle; -*/ - // follow the player - /*if (player->playerstate != PST_DEAD && (camspeed) != 0) - { - if (P_AproxDistance(mo->x - thiscam->x, mo->y - thiscam->y) > (checkdist + P_AproxDistance(mo->momx, mo->momy)) * 4 - || abs(mo->z - thiscam->z) > checkdist * 3) - { - if (!resetcalled) - P_ResetCamera(player, thiscam); - return true; - } - }*/ - if (player->exiting) { thiscam->momx = 0; thiscam->momy = 0; thiscam->momz = 0; } + else if (leveltime < starttime) + { + thiscam->momx = FixedMul(x - thiscam->x, FRACUNIT/4); + thiscam->momy = FixedMul(y - thiscam->y, FRACUNIT/4); + thiscam->momz = FixedMul(z - thiscam->z, FRACUNIT/4); + } else { - if (twodlevel || (mo->flags2 & MF2_TWOD)) - { - thiscam->momx = x-thiscam->x; - thiscam->momy = y-thiscam->y; - thiscam->momz = z-thiscam->z; - } + thiscam->momx = x-thiscam->x; + thiscam->momy = y-thiscam->y; +#if 1 + if (player->kartstuff[k_pogospring]) // SRB2Kart: don't follow while bouncing, experimental + thiscam->momz = 0; else - { - thiscam->momx = FixedMul(x - thiscam->x, camspeed); - thiscam->momy = FixedMul(y - thiscam->y, camspeed); - - if ((GETSECSPECIAL(thiscam->subsector->sector->special, 1) == 6 - && thiscam->z < thiscam->subsector->sector->floorheight + 256*FRACUNIT - && FixedMul(z - thiscam->z, camspeed) < 0) -#if 0 - || player->kartstuff[k_pogospring] // SRB2Kart: don't follow while bouncing, experimental #endif - ) - thiscam->momz = 0; // Don't go down a death pit - else - thiscam->momz = FixedMul(z - thiscam->z, camspeed); - } + thiscam->momz = z-thiscam->z; } // compute aming to look the viewed point @@ -8778,6 +8647,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall angle = R_PointToAngle2(0, thiscam->z + thiscam->height, dist, mo->z + mo->height - P_GetPlayerHeight(player)); else angle = R_PointToAngle2(0, thiscam->z, dist, mo->z + P_GetPlayerHeight(player)); + if (player->playerstate != PST_DEAD && !(player->pflags & PF_NIGHTSMODE && player->exiting)) angle += (focusaiming < ANGLE_180 ? focusaiming/2 : InvAngle(InvAngle(focusaiming)/2)); // overcomplicated version of '((signed)focusaiming)/2;' @@ -8788,40 +8658,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall thiscam->aiming -= (dist>>3); } - // Make player translucent if camera is too close (only in single player). - /*if (!(multiplayer || netgame) && !splitscreen) - { - fixed_t vx = 0, vy = 0; - if (player->awayviewtics) { - vx = player->awayviewmobj->x; - vy = player->awayviewmobj->y; - } - else - { - vx = thiscam->x; - vy = thiscam->y; - } - - if (P_AproxDistance(vx - player->mo->x, vy - player->mo->y) < FixedMul(48*FRACUNIT, mo->scale)) - player->mo->flags2 |= MF2_SHADOW; - else - player->mo->flags2 &= ~MF2_SHADOW; - } - else - player->mo->flags2 &= ~MF2_SHADOW;*/ - -/* if (!resetcalled && (player->pflags & PF_NIGHTSMODE && player->exiting)) - { - // Don't let the camera match your movement. - thiscam->momz = 0; - - // Only let the camera go a little bit upwards. - if (mo->eflags & MFE_VERTICALFLIP && thiscam->aiming < ANGLE_315 && thiscam->aiming > ANGLE_180) - thiscam->aiming = ANGLE_315; - else if (!(mo->eflags & MFE_VERTICALFLIP) && thiscam->aiming > ANGLE_45 && thiscam->aiming < ANGLE_180) - thiscam->aiming = ANGLE_45; - } - else */if (!resetcalled && (player->playerstate == PST_DEAD || player->playerstate == PST_REBORN)) + if (!resetcalled && (player->playerstate == PST_DEAD || player->playerstate == PST_REBORN)) { // Don't let the camera match your movement. thiscam->momz = 0; @@ -8833,17 +8670,6 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall thiscam->aiming = ANGLE_22h; } -#if 0 - // SRB2Kart: keep camera the same distance away from the player, while maintaining its angle - { - fixed_t xlen = (thiscam->x+thiscam->momx) - (mo->x+mo->momx); - fixed_t ylen = (thiscam->y+thiscam->momy) - (mo->y+mo->momy); - fixed_t xydist = P_AproxDistance(xlen, ylen); - thiscam->momx = FixedMul(dist, FixedDiv(xlen, xydist)); - thiscam->momy = FixedMul(dist, FixedDiv(ylen, xydist)); - } -#endif - return (x == thiscam->x && y == thiscam->y && z == thiscam->z && angle == thiscam->aiming); } @@ -9886,17 +9712,14 @@ void P_PlayerAfterThink(player_t *player) { player->mo->angle = player->mo->tracer->angle; - if (!demoplayback || P_AnalogMove(player)) - { - if (player == &players[consoleplayer]) - localangle = player->mo->angle; - else if (player == &players[secondarydisplayplayer]) - localangle2 = player->mo->angle; - else if (player == &players[thirddisplayplayer]) - localangle3 = player->mo->angle; - else if (player == &players[fourthdisplayplayer]) - localangle4 = player->mo->angle; - } + if (player == &players[consoleplayer]) + localangle = player->mo->angle; + else if (player == &players[secondarydisplayplayer]) + localangle2 = player->mo->angle; + else if (player == &players[thirddisplayplayer]) + localangle3 = player->mo->angle; + else if (player == &players[fourthdisplayplayer]) + localangle4 = player->mo->angle; } if (P_AproxDistance(player->mo->x - player->mo->tracer->x, player->mo->y - player->mo->tracer->y) > player->mo->radius) @@ -9963,17 +9786,14 @@ void P_PlayerAfterThink(player_t *player) player->mo->tracer->target->health += cmd->sidemove; player->mo->angle += cmd->sidemove< ANGLE_MAX - if (!demoplayback || P_AnalogMove(player)) - { - if (player == &players[consoleplayer]) - localangle = player->mo->angle; // Adjust the local control angle. - else if (player == &players[secondarydisplayplayer]) - localangle2 = player->mo->angle; - else if (player == &players[thirddisplayplayer]) - localangle3 = player->mo->angle; - else if (player == &players[fourthdisplayplayer]) - localangle4 = player->mo->angle; - } + if (player == &players[consoleplayer]) + localangle = player->mo->angle; // Adjust the local control angle. + else if (player == &players[secondarydisplayplayer]) + localangle2 = player->mo->angle; + else if (player == &players[thirddisplayplayer]) + localangle3 = player->mo->angle; + else if (player == &players[fourthdisplayplayer]) + localangle4 = player->mo->angle; } } From 95d9725ade6c1bdec53b3e20ce22ff27320cb110 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Mon, 3 Sep 2018 21:21:40 -0400 Subject: [PATCH 058/146] This was not meant to be commited --- src/p_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_user.c b/src/p_user.c index 9ba70c45a..37af26378 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8630,7 +8630,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall { thiscam->momx = x-thiscam->x; thiscam->momy = y-thiscam->y; -#if 1 +#if 0 if (player->kartstuff[k_pogospring]) // SRB2Kart: don't follow while bouncing, experimental thiscam->momz = 0; else From f7f70e5f107f73660c6b6f3f480c883b5f8c7108 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 4 Sep 2018 02:51:00 -0400 Subject: [PATCH 059/146] Z pos smoothing --- src/p_user.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index 37af26378..99c43bd82 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8622,20 +8622,15 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall } else if (leveltime < starttime) { - thiscam->momx = FixedMul(x - thiscam->x, FRACUNIT/4); - thiscam->momy = FixedMul(y - thiscam->y, FRACUNIT/4); - thiscam->momz = FixedMul(z - thiscam->z, FRACUNIT/4); + thiscam->momx = FixedMul(x - thiscam->x, camspeed); + thiscam->momy = FixedMul(y - thiscam->y, camspeed); + thiscam->momz = FixedMul(z - thiscam->z, camspeed); } else { thiscam->momx = x-thiscam->x; thiscam->momy = y-thiscam->y; -#if 0 - if (player->kartstuff[k_pogospring]) // SRB2Kart: don't follow while bouncing, experimental - thiscam->momz = 0; - else -#endif - thiscam->momz = z-thiscam->z; + thiscam->momz = FixedMul(z - thiscam->z, camspeed/2); } // compute aming to look the viewed point From 2864c4b272e2055500158cd957935c77929a3911 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 4 Sep 2018 15:11:14 -0400 Subject: [PATCH 060/146] Camera outrunning --- src/d_player.h | 4 ++- src/dehacked.c | 2 ++ src/k_kart.c | 93 ++++++++++++++++++++++++++------------------------ src/p_user.c | 7 ++-- 4 files changed, 58 insertions(+), 48 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 49fa6de84..c038f1d85 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -298,6 +298,8 @@ typedef enum k_brakestop, // Wait until you've made a complete stop for a few tics before letting brake go in reverse. k_waterskip, // Water skipping counter k_dashpadcooldown, // Separate the vanilla SA-style dash pads from using pw_flashing + k_speedboost, // Boost value smoothing for max speed + k_accelboost, // Boost value smoothing for acceleration k_itemroulette, // Used for the roulette when deciding what item to give you (was "pw_kartitem") k_roulettetype, // Used for the roulette, for deciding type (currently only used for Battle, to give you better items from Karma items) @@ -323,7 +325,7 @@ typedef enum k_eggmanexplode, // Fake item recieved, explode in a few seconds k_eggmanblame, // Fake item recieved, who set this fake k_lastjawztarget, // Last person you target with jawz, for playing the target switch sfx - k_bananadrag, // After a second of holding a banana behind you, you start to slow down + k_bananadrag, // After a second of holding a banana behind you, you start to slow down k_spinouttimer, // Spin-out from a banana peel or oil slick (was "pw_bananacam") k_wipeoutslow, // Timer before you slowdown when getting wiped out k_justbumped, // Prevent players from endlessly bumping into each other diff --git a/src/dehacked.c b/src/dehacked.c index 2cffc6333..9d0459ae8 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -7680,6 +7680,8 @@ static const char *const KARTSTUFF_LIST[] = { "BRAKESTOP", "WATERSKIP", "DASHPADCOOLDOWN", + "SPEEDBOOST", + "ACCELBOOST", "ITEMROULETTE", "ROULETTETYPE", diff --git a/src/k_kart.c b/src/k_kart.c index f00bca5f4..3cfbed2c7 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1443,67 +1443,69 @@ void K_MomentumToFacing(player_t *player) } // if speed is true it gets the speed boost power, otherwise it gets the acceleration -static fixed_t K_GetKartBoostPower(player_t *player, boolean speed) +static void K_GetKartBoostPower(player_t *player) { fixed_t boostpower = FRACUNIT; - fixed_t boostvalue = 0; + fixed_t speedboost = 0, accelboost = 0; if (player->kartstuff[k_spinouttimer] && player->kartstuff[k_wipeoutslow] == 1) // Slow down after you've been bumped - return 0; + { + player->kartstuff[k_speedboost] = player->kartstuff[k_accelboost] = 0; + return; + } // Offroad is separate, it's difficult to factor it in with a variable value anyway. if (!(player->kartstuff[k_invincibilitytimer] || player->kartstuff[k_hyudorotimer] || player->kartstuff[k_sneakertimer]) - && player->kartstuff[k_offroad] >= 0 && speed) + && player->kartstuff[k_offroad] >= 0) boostpower = FixedDiv(boostpower, player->kartstuff[k_offroad] + FRACUNIT); if (player->kartstuff[k_bananadrag] > TICRATE) boostpower = 4*boostpower/5; - if (player->kartstuff[k_growshrinktimer] > 0) - { // Grow - if (speed) + if (player->kartstuff[k_growshrinktimer] > 0) // Grow + { + speedboost = max(speedboost, FRACUNIT/5); // + 20% + } + + if (player->kartstuff[k_invincibilitytimer]) // Invincibility + { + speedboost = max(speedboost, 3*(FRACUNIT/8)); // + 37.5% + accelboost = max(accelboost, 3*FRACUNIT); // + 600% + } + + if (player->kartstuff[k_driftboost]) // Drift Boost + { + speedboost = max(speedboost, FRACUNIT/4); // + 25% + accelboost = max(accelboost, 4*FRACUNIT); // + 400% + } + + if (player->kartstuff[k_sneakertimer]) // Sneaker + { + switch (gamespeed) { - boostvalue = max(boostvalue, FRACUNIT/5); // + 20% + case 0: + speedboost = max(speedboost, 53740+768); + break; + case 2: + speedboost = max(speedboost, 17294+768); + break; + default: + speedboost = max(speedboost, 32768); + break; } + accelboost = max(accelboost, 8*FRACUNIT); // + 800% } - if (player->kartstuff[k_invincibilitytimer]) - { // Invincibility - if (speed) - boostvalue = max(boostvalue, 3*(FRACUNIT/8)); // + 37.5% - else - boostvalue = max(boostvalue, 3*FRACUNIT); // + 600% - } - if (player->kartstuff[k_driftboost]) - { // Drift Boost - if (speed) - boostvalue = max(boostvalue, FRACUNIT/4); // + 25% - else - boostvalue = max(boostvalue, 4*FRACUNIT); // + 400% - } - if (player->kartstuff[k_sneakertimer]) - { // Sneaker - if (speed) - { - switch (gamespeed) - { - case 0: - boostvalue = max(boostvalue, 53740+768); - break; - case 2: - boostvalue = max(boostvalue, 17294+768); - break; - default: - boostvalue = max(boostvalue, 32768); - break; - } - } - else - boostvalue = max(boostvalue, 8*FRACUNIT); // + 800% - } + // don't average them anymore, this would make a small boost and a high boost less useful // just take the highest we want instead - return boostpower + boostvalue; + if (boostpower + speedboost > player->kartstuff[k_speedboost]) + player->kartstuff[k_speedboost] += ((boostpower+speedboost) - player->kartstuff[k_speedboost])/(TICRATE/2); // Quick increase if higher + else + player->kartstuff[k_speedboost] += ((boostpower+speedboost) - player->kartstuff[k_speedboost])/TICRATE; // Smoothly decrease if lower + + // Accel isn't affected by boostpower, hence the FRACUNIT. Probably for making acceleration feel consistent in offroad. + player->kartstuff[k_accelboost] = FRACUNIT+accelboost; } fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower) @@ -1538,7 +1540,7 @@ fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower) finalspeed = FixedMul(FixedMul(k_speed<<14, g_cc), player->mo->scale); if (doboostpower) - return FixedMul(finalspeed, K_GetKartBoostPower(player, true)); + return FixedMul(finalspeed, player->kartstuff[k_speedboost]); return finalspeed; } @@ -1553,7 +1555,7 @@ fixed_t K_GetKartAccel(player_t *player) //k_accel += 3 * (9 - kartspeed); // 36 - 60 k_accel += 4 * (9 - kartspeed); // 32 - 64 - return FixedMul(k_accel, K_GetKartBoostPower(player, false)); + return FixedMul(k_accel, player->kartstuff[k_accelboost]); } UINT16 K_GetKartFlashing(player_t *player) @@ -3163,6 +3165,7 @@ player_t *K_FindJawzTarget(mobj_t *actor, player_t *source) void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) { K_UpdateOffroad(player); + K_GetKartBoostPower(player); if (player->kartstuff[k_eggmanexplode]) // You're gonna diiiiie { diff --git a/src/p_user.c b/src/p_user.c index 99c43bd82..1f0d2092c 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8379,6 +8379,9 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall // sets ideal cam pos dist = camdist; + if (player->speed > K_GetKartSpeed(player, false)) + dist += 3*(player->speed - K_GetKartSpeed(player, false)); + // in splitscreen modes, mess with the camera distances to make it feel proportional to how it feels normally if (splitscreen == 1) // widescreen splits should get x1.5 distance { @@ -8628,8 +8631,8 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall } else { - thiscam->momx = x-thiscam->x; - thiscam->momy = y-thiscam->y; + thiscam->momx = x - thiscam->x; + thiscam->momy = y - thiscam->y; thiscam->momz = FixedMul(z - thiscam->z, camspeed/2); } From cb126527be249ae8c267601d0d7a6d1bc111a7eb Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 4 Sep 2018 16:08:37 -0400 Subject: [PATCH 061/146] Camera panning for drifts --- src/p_local.h | 3 +++ src/p_user.c | 43 +++++++++++++++++++++++++++++-------------- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/src/p_local.h b/src/p_local.h index 7d7342bc7..51676a2c3 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -107,6 +107,9 @@ typedef struct camera_s // Momentums, used to update position. fixed_t momx, momy, momz; + + // SRB2Kart: camera pans while drifting + fixed_t pan; } camera_t; extern camera_t camera, camera2, camera3, camera4; diff --git a/src/p_user.c b/src/p_user.c index 1f0d2092c..524d5f5cd 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8162,7 +8162,8 @@ void P_ResetCamera(player_t *player, camera_t *thiscam) boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcalled) { angle_t angle = 0, focusangle = 0, focusaiming = 0; - fixed_t x, y, z, dist, height, checkdist, viewpointx, viewpointy, camspeed, camdist, camheight, pviewheight; + fixed_t x, y, z, dist, height, viewpointx, viewpointy, camspeed, camdist, camheight, pviewheight; + fixed_t pan, xpan, ypan; INT32 camrotate; boolean camstill, cameranoclip, lookback; mobj_t *mo; @@ -8379,9 +8380,6 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall // sets ideal cam pos dist = camdist; - if (player->speed > K_GetKartSpeed(player, false)) - dist += 3*(player->speed - K_GetKartSpeed(player, false)); - // in splitscreen modes, mess with the camera distances to make it feel proportional to how it feels normally if (splitscreen == 1) // widescreen splits should get x1.5 distance { @@ -8389,18 +8387,36 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall height = FixedMul(height, 3*FRACUNIT/2); } + if (player->kartstuff[k_drift] != 0) + { + fixed_t panmax = (dist/5); + pan = min(player->kartstuff[k_driftcharge], K_GetKartDriftSparkValue(player)) * panmax / K_GetKartDriftSparkValue(player); + if (pan > panmax) + pan = panmax; + if (player->kartstuff[k_drift] < 0) + pan *= -1; + } + else + pan = 0; + + if (player->speed > K_GetKartSpeed(player, false)) + dist += 3*(player->speed - K_GetKartSpeed(player, false)); + if (player->climbing || player->playerstate == PST_DEAD || (player->pflags & (PF_MACESPIN|PF_ITEMHANG|PF_ROPEHANG))) dist <<= 1; - checkdist = dist; - - if (checkdist < 128*FRACUNIT) - checkdist = 128*FRACUNIT; - x = mo->x - FixedMul(FINECOSINE((angle>>ANGLETOFINESHIFT) & FINEMASK), dist); y = mo->y - FixedMul(FINESINE((angle>>ANGLETOFINESHIFT) & FINEMASK), dist); pviewheight = FixedMul(32<scale); + pan = thiscam->pan + FixedMul(pan - thiscam->pan, camspeed/4); + + xpan = FixedMul(FINECOSINE(((angle+ANGLE_90)>>ANGLETOFINESHIFT) & FINEMASK), pan); + ypan = FixedMul(FINESINE(((angle+ANGLE_90)>>ANGLETOFINESHIFT) & FINEMASK), pan); + + x += xpan; + y += ypan; + if (mo->eflags & MFE_VERTICALFLIP) z = mo->z + mo->height - pviewheight - camheight; @@ -8608,15 +8624,12 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall // point viewed by the camera // this point is just 64 unit forward the player dist = 64*mapheaderinfo[gamemap-1]->mobj_scale; - viewpointx = mo->x + FixedMul(FINECOSINE((angle>>ANGLETOFINESHIFT) & FINEMASK), dist); - viewpointy = mo->y + FixedMul(FINESINE((angle>>ANGLETOFINESHIFT) & FINEMASK), dist); + viewpointx = mo->x + FixedMul(FINECOSINE((angle>>ANGLETOFINESHIFT) & FINEMASK), dist) + xpan; + viewpointy = mo->y + FixedMul(FINESINE((angle>>ANGLETOFINESHIFT) & FINEMASK), dist) + ypan; if (!camstill && !resetcalled && !paused) thiscam->angle = R_PointToAngle2(thiscam->x, thiscam->y, viewpointx, viewpointy); - viewpointx = mo->x + FixedMul(FINECOSINE((angle>>ANGLETOFINESHIFT) & FINEMASK), dist); - viewpointy = mo->y + FixedMul(FINESINE((angle>>ANGLETOFINESHIFT) & FINEMASK), dist); - if (player->exiting) { thiscam->momx = 0; @@ -8636,6 +8649,8 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall thiscam->momz = FixedMul(z - thiscam->z, camspeed/2); } + thiscam->pan = pan; + // compute aming to look the viewed point f1 = viewpointx-thiscam->x; f2 = viewpointy-thiscam->y; From 25410d82bf4ddbb035bd1e182bb42fa8d60ee353 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 4 Sep 2018 16:10:59 -0400 Subject: [PATCH 062/146] Misc camera fixes - Fixed remaining instances where camera position would scale with the player instead of the level; the camera should almost 100% certainly not change now when you get Grown/Shrunk - Reset camera when switching viewpoint, to make it not look *as* weird when switching after you've finished (needs tested) --- src/g_game.c | 1 + src/p_user.c | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index db686873a..cacc12a9b 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1857,6 +1857,7 @@ boolean G_Responder(event_t *ev) // tell who's the view CONS_Printf(M_GetText("Viewpoint: %s\n"), player_names[displayplayer]); + P_ResetCamera(&players[displayplayer], &camera); return true; } diff --git a/src/p_user.c b/src/p_user.c index 524d5f5cd..136473135 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8233,8 +8233,8 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall mo = player->mo; - thiscam->radius = FixedMul(20*FRACUNIT, mo->scale); - thiscam->height = FixedMul(16*FRACUNIT, mo->scale); + thiscam->radius = FixedMul(20*FRACUNIT, mapheaderinfo[gamemap-1]->mobj_scale); + thiscam->height = FixedMul(16*FRACUNIT, mapheaderinfo[gamemap-1]->mobj_scale); if (!mo) return true; @@ -8408,7 +8408,6 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall x = mo->x - FixedMul(FINECOSINE((angle>>ANGLETOFINESHIFT) & FINEMASK), dist); y = mo->y - FixedMul(FINESINE((angle>>ANGLETOFINESHIFT) & FINEMASK), dist); - pviewheight = FixedMul(32<scale); pan = thiscam->pan + FixedMul(pan - thiscam->pan, camspeed/4); xpan = FixedMul(FINECOSINE(((angle+ANGLE_90)>>ANGLETOFINESHIFT) & FINEMASK), pan); @@ -8417,9 +8416,10 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall x += xpan; y += ypan; + pviewheight = FixedMul(32<mobj_scale); if (mo->eflags & MFE_VERTICALFLIP) - z = mo->z + mo->height - pviewheight - camheight; + z = mo->z + mobjinfo[mo->type].height - pviewheight - camheight; else z = mo->z + pviewheight + camheight; From 23efd60910c3037648f819fff158f581937adadd Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 4 Sep 2018 17:07:53 -0400 Subject: [PATCH 063/146] Revert a few of the changes from last commit Ended up not liking them --- src/p_user.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index 136473135..7c1f9df80 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8416,10 +8416,10 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall x += xpan; y += ypan; - pviewheight = FixedMul(32<mobj_scale); + pviewheight = FixedMul(32<scale); if (mo->eflags & MFE_VERTICALFLIP) - z = mo->z + mobjinfo[mo->type].height - pviewheight - camheight; + z = mo->z + mo->height - pviewheight - camheight; else z = mo->z + pviewheight + camheight; From 3d1617952426797e7530b9b819ff2b6d460d329d Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 4 Sep 2018 18:21:55 -0400 Subject: [PATCH 064/146] Alternate demo replay camera Not good, but less bad than before :V --- src/p_user.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index 7c1f9df80..a8923d373 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8339,18 +8339,6 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall angle = thiscam->angle; else if (leveltime < starttime) angle = focusangle + FixedAngle(camrotate*FRACUNIT); - else if (demoplayback) - { - angle = focusangle; - focusangle = R_PointToAngle2(thiscam->x, thiscam->y, mo->x, mo->y); - if (player == &players[consoleplayer]) - { - if (focusangle >= localangle) - localangle += abs((signed)(focusangle - localangle))>>3; - else - localangle -= abs((signed)(focusangle - localangle))>>3; - } - } else { angle_t input = focusangle + FixedAngle(camrotate<angle; @@ -8363,6 +8351,9 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall input = InvAngle(input); angle = thiscam->angle + input; + + if (demoplayback && player == &players[consoleplayer]) + localangle = angle; } if (!resetcalled && (leveltime > starttime) From be92535dba6bb6b052836e40c3e778645c31e223 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 4 Sep 2018 18:27:36 -0400 Subject: [PATCH 065/146] Splitscreen fix Just changed order of operations --- src/p_user.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index a8923d373..fdbc4c9e7 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8371,6 +8371,12 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall // sets ideal cam pos dist = camdist; + if (player->speed > K_GetKartSpeed(player, false)) + dist += 3*(player->speed - K_GetKartSpeed(player, false)); + + if (player->climbing || player->playerstate == PST_DEAD || (player->pflags & (PF_MACESPIN|PF_ITEMHANG|PF_ROPEHANG))) + dist <<= 1; + // in splitscreen modes, mess with the camera distances to make it feel proportional to how it feels normally if (splitscreen == 1) // widescreen splits should get x1.5 distance { @@ -8378,9 +8384,13 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall height = FixedMul(height, 3*FRACUNIT/2); } + x = mo->x - FixedMul(FINECOSINE((angle>>ANGLETOFINESHIFT) & FINEMASK), dist); + y = mo->y - FixedMul(FINESINE((angle>>ANGLETOFINESHIFT) & FINEMASK), dist); + + // SRB2Kart: set camera panning if (player->kartstuff[k_drift] != 0) { - fixed_t panmax = (dist/5); + fixed_t panmax = (camdist/5); pan = min(player->kartstuff[k_driftcharge], K_GetKartDriftSparkValue(player)) * panmax / K_GetKartDriftSparkValue(player); if (pan > panmax) pan = panmax; @@ -8390,15 +8400,6 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall else pan = 0; - if (player->speed > K_GetKartSpeed(player, false)) - dist += 3*(player->speed - K_GetKartSpeed(player, false)); - - if (player->climbing || player->playerstate == PST_DEAD || (player->pflags & (PF_MACESPIN|PF_ITEMHANG|PF_ROPEHANG))) - dist <<= 1; - - x = mo->x - FixedMul(FINECOSINE((angle>>ANGLETOFINESHIFT) & FINEMASK), dist); - y = mo->y - FixedMul(FINESINE((angle>>ANGLETOFINESHIFT) & FINEMASK), dist); - pan = thiscam->pan + FixedMul(pan - thiscam->pan, camspeed/4); xpan = FixedMul(FINECOSINE(((angle+ANGLE_90)>>ANGLETOFINESHIFT) & FINEMASK), pan); From c46bf86bf3a919de413d847d0b6509a68b94bbf9 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 4 Sep 2018 18:47:30 -0400 Subject: [PATCH 066/146] Jawz ignores targets too high/low --- src/k_kart.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 3cfbed2c7..1463ce03e 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3107,6 +3107,14 @@ player_t *K_FindJawzTarget(mobj_t *actor, player_t *source) if (G_GametypeHasTeams() && source->ctfteam == player->ctfteam) continue; + // Invisible, don't bother + if (player->kartstuff[k_hyudorotimer]) + continue; + + // Z pos too high/low + if (abs(player->mo->z - (actor->z + actor->momz)) > 48<angle - R_PointToAngle2(actor->x, actor->y, player->mo->x, player->mo->y); if (thisang > ANGLE_180) @@ -3134,8 +3142,7 @@ player_t *K_FindJawzTarget(mobj_t *actor, player_t *source) if (player->kartstuff[k_bumper] <= 0) continue; - thisdist = P_AproxDistance(P_AproxDistance(player->mo->x - (actor->x + actor->momx), - player->mo->y - (actor->y + actor->momy)), player->mo->z - (actor->z + actor->momz)); + thisdist = P_AproxDistance(player->mo->x - (actor->x + actor->momx), player->mo->y - (actor->y + actor->momy)); if (thisdist > RING_DIST) // Don't go for people who are too far away continue; From 7012d94f15d1c21aeb3dc6cae42a5c0c7c901158 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 4 Sep 2018 19:14:44 -0400 Subject: [PATCH 067/146] Ghost sink "shield" Sink shield that makes it double-press to use, gives the trailing item slowdown, and shows other people that you have it, but doesn't have any collision --- src/dehacked.c | 2 ++ src/info.c | 36 ++++++++++++++++++++++++++++++++---- src/info.h | 2 ++ src/k_kart.c | 18 ++++++++++++++++++ src/p_inter.c | 3 ++- src/p_mobj.c | 1 + 6 files changed, 57 insertions(+), 5 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 9d0459ae8..8ef369935 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -6481,6 +6481,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit // The legend "S_SINK", + "S_SINK_SHIELD", "S_SINKTRAIL1", "S_SINKTRAIL2", "S_SINKTRAIL3", @@ -7249,6 +7250,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_THUNDERSHIELD", // Thunder Shield stuff "MT_SINK", // Kitchen Sink Stuff + "MT_SINK_SHIELD", "MT_SINKTRAIL", "MT_BATTLEBUMPER", // Battle Mode bumper diff --git a/src/info.c b/src/info.c index 76c535d70..60cac109d 100644 --- a/src/info.c +++ b/src/info.c @@ -2795,10 +2795,11 @@ state_t states[NUMSTATES] = {SPR_THNS, 10, 2, {NULL}, 0, 0, S_THUNDERSHIELD24}, // S_THUNDERSHIELD23 {SPR_THNS, 11, 2, {NULL}, 0, 0, S_THUNDERSHIELD1}, // S_THUNDERSHIELD24 - {SPR_SINK, 0, 4, {A_SmokeTrailer}, MT_SINKTRAIL, 0, S_SINK}, // S_SINK - {SPR_SITR, 0, 1, {NULL}, 0, 0, S_SINKTRAIL2}, // S_SINKTRAIL1 - {SPR_SITR, 1, 5, {NULL}, 0, 0, S_SINKTRAIL3}, // S_SINKTRAIL2 - {SPR_SITR, 2, 3, {NULL}, 0, 0, S_NULL}, // S_SINKTRAIL3 + {SPR_SINK, 0, 4, {A_SmokeTrailer}, MT_SINKTRAIL, 0, S_SINK}, // S_SINK + {SPR_SINK, 0|FF_TRANS80|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_SINK_SHIELD}, // S_SINK_SHIELD + {SPR_SITR, 0, 1, {NULL}, 0, 0, S_SINKTRAIL2}, // S_SINKTRAIL1 + {SPR_SITR, 1, 5, {NULL}, 0, 0, S_SINKTRAIL3}, // S_SINKTRAIL2 + {SPR_SITR, 2, 3, {NULL}, 0, 0, S_NULL}, // S_SINKTRAIL3 {SPR_KBLN, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_BATTLEBUMPER1}, // S_BATTLEBUMPER1 {SPR_KBLN, FF_FULLBRIGHT|1, -1, {NULL}, 0, 0, S_BATTLEBUMPER2}, // S_BATTLEBUMPER2 @@ -15199,6 +15200,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_SINK_SHIELD + -1, // doomednum + S_SINK_SHIELD, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 100, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 24*FRACUNIT, // height + 0, // display offset + 100, // mass + 1, // damage + sfx_None, // activesound + MF_NOGRAVITY|MF_SCENERY, // flags + S_NULL // raisestate + }, + { // MT_SINKTRAIL -1, // doomednum S_SINKTRAIL1, // spawnstate diff --git a/src/info.h b/src/info.h index 202094162..736fdfdee 100644 --- a/src/info.h +++ b/src/info.h @@ -3326,6 +3326,7 @@ typedef enum state // The legend S_SINK, + S_SINK_SHIELD, S_SINKTRAIL1, S_SINKTRAIL2, S_SINKTRAIL3, @@ -4111,6 +4112,7 @@ typedef enum mobj_type MT_THUNDERSHIELD, // Thunder Shield stuff MT_SINK, // Kitchen Sink Stuff + MT_SINK_SHIELD, MT_SINKTRAIL, MT_BATTLEBUMPER, // Battle Mode bumpers diff --git a/src/k_kart.c b/src/k_kart.c index 1463ce03e..8d5bb02ea 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2986,6 +2986,7 @@ static void K_MoveHeldObjects(player_t *player) case MT_BANANA_SHIELD: // Kart trailing items case MT_SSMINE_SHIELD: case MT_FAKESHIELD: + case MT_SINK_SHIELD: { mobj_t *cur = player->mo->hnext; mobj_t *targ = player->mo; @@ -4239,11 +4240,28 @@ void K_MoveKartPlayer(player_t *player, boolean onground) break; case KITEM_KITCHENSINK: if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) + { + mobj_t *mo; + player->kartstuff[k_itemheld] = 1; + S_StartSound(player->mo, sfx_s254); + mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_SINK_SHIELD); + if (mo) + { + mo->flags |= MF_NOCLIPTHING; + mo->threshold = 10; + mo->movecount = 1; + mo->movedir = 1; + P_SetTarget(&mo->target, player->mo); + P_SetTarget(&player->mo->hnext, mo); + } + } + else if (ATTACK_IS_DOWN && HOLDING_ITEM && player->kartstuff[k_itemheld]) // Sink thrown { K_ThrowKartItem(player, false, MT_SINK, 1, true); K_PlayTauntSound(player->mo); player->kartstuff[k_itemamount]--; player->kartstuff[k_itemheld] = 0; + K_CleanHnextList(player->mo); } break; case KITEM_SAD: diff --git a/src/p_inter.c b/src/p_inter.c index f980e70d1..ca9330699 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2219,7 +2219,8 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source) if (target->target->player->kartstuff[k_itemheld]) { if ((target->type == MT_BANANA_SHIELD && target->target->player->kartstuff[k_itemtype] == KITEM_BANANA) // trail items - || (target->type == MT_SSMINE_SHIELD && target->target->player->kartstuff[k_itemtype] == KITEM_MINE)) + || (target->type == MT_SSMINE_SHIELD && target->target->player->kartstuff[k_itemtype] == KITEM_MINE) + || (target->type == MT_SINK_SHIELD && target->target->player->kartstuff[k_itemtype] == KITEM_KITCHENSINK)) { if (target->movedir != 0 && target->movedir < (UINT16)target->target->player->kartstuff[k_itemamount]) { diff --git a/src/p_mobj.c b/src/p_mobj.c index e1db00ccf..d22ce3e7c 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6720,6 +6720,7 @@ void P_MobjThinker(mobj_t *mobj) case MT_BANANA_SHIELD: case MT_SSMINE_SHIELD: case MT_FAKESHIELD: + case MT_SINK_SHIELD: /*if (mobj->health > 0 && mobj->target && mobj->target->player && mobj->target->player->health > 0 && !mobj->target->player->spectator) { From 147f4520eca6c4143287abba2c5ccb588b0a4467 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 4 Sep 2018 19:58:20 -0400 Subject: [PATCH 068/146] Addressed some of Chrome's thoughts - Don't drag - Shield isn't visible to anyone but yourself - Projectile is twice as heavy --- src/k_kart.c | 76 +++++++++++++++++++++++++++++++--------------------- src/p_mobj.c | 5 +++- 2 files changed, 49 insertions(+), 32 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 8d5bb02ea..930223b36 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2402,7 +2402,7 @@ static mobj_t *K_FindLastTrailMobj(player_t *player) return trail; } -static mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t mapthing, INT32 defaultDir, boolean minethrow) +static mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t mapthing, INT32 defaultDir, INT32 altthrow) { mobj_t *mo; INT32 dir, PROJSPEED; @@ -2427,14 +2427,26 @@ static mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t map break; } - if (minethrow) + if (altthrow) { - if (player->kartstuff[k_throwdir] == 1) - dir = 2; - else if (player->kartstuff[k_throwdir] == -1 && mapthing != MT_SINK) - dir = -1; + if (altthrow == 2) // Kitchen sink throwing + { + if (player->kartstuff[k_throwdir] == 1) + dir = 3; + else if (player->kartstuff[k_throwdir] == -1) + dir = 1; + else + dir = 2; + } else - dir = 1; + { + if (player->kartstuff[k_throwdir] == 1) + dir = 2; + else if (player->kartstuff[k_throwdir] == -1) + dir = -1; + else + dir = 1; + } } else { @@ -2485,7 +2497,7 @@ static mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t map { player->kartstuff[k_bananadrag] = 0; // RESET timer, for multiple bananas - if (dir == 1 || dir == 2) + if (dir > 0) { // Shoot forward mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + player->mo->height/2, mapthing); @@ -2498,15 +2510,10 @@ static mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t map if (mo) { angle_t fa = player->mo->angle>>ANGLETOFINESHIFT; - INT32 HEIGHT; + INT32 HEIGHT = (20 + (dir*10))*(mapheaderinfo[gamemap-1]->mobj_scale) + player->mo->momz; - if (dir == 2) - HEIGHT = 40*(mapheaderinfo[gamemap-1]->mobj_scale) + player->mo->momz; - else - HEIGHT = 30*(mapheaderinfo[gamemap-1]->mobj_scale) + player->mo->momz; - - mo->momx = player->mo->momx + FixedMul(FINECOSINE(fa), PROJSPEED); - mo->momy = player->mo->momy + FixedMul(FINESINE(fa), PROJSPEED); + mo->momx = player->mo->momx + FixedMul(FINECOSINE(fa), (altthrow == 2 ? 2*PROJSPEED/3 : PROJSPEED)); + mo->momy = player->mo->momy + FixedMul(FINESINE(fa), (altthrow == 2 ? 2*PROJSPEED/3 : PROJSPEED)); mo->momz = P_MobjFlip(player->mo) * HEIGHT; if (player->mo->eflags & MFE_VERTICALFLIP) @@ -2991,7 +2998,8 @@ static void K_MoveHeldObjects(player_t *player) mobj_t *cur = player->mo->hnext; mobj_t *targ = player->mo; - if (P_IsObjectOnGround(player->mo) && player->speed > 0) + if (P_IsObjectOnGround(player->mo) && player->speed > 0 + && player->mo->hnext->type != MT_SINK_SHIELD) // Sink ignores debuff, and is only visible to the owner. More of a HUD indicator than an actual shield. { player->kartstuff[k_bananadrag]++; if (player->kartstuff[k_bananadrag] > TICRATE) @@ -3006,14 +3014,19 @@ static void K_MoveHeldObjects(player_t *player) { const fixed_t radius = FixedHypot(targ->radius, targ->radius) + FixedHypot(cur->radius, cur->radius); angle_t ang; - fixed_t targx; - fixed_t targy; - fixed_t targz; - fixed_t speed; - fixed_t dist; + fixed_t targx, targy, targz; + fixed_t speed, dist; cur->flags &= ~MF_NOCLIPTHING; + if (cur->type == MT_SINK_SHIELD) + { + if (P_IsLocalPlayer(player)) + cur->flags2 &= ~MF2_DONTDRAW; + else + cur->flags2 |= MF2_DONTDRAW; + } + if (!cur->health) { cur = cur->hnext; @@ -3915,7 +3928,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) // Eggman Monitor throwing else if (ATTACK_IS_DOWN && player->kartstuff[k_eggmanheld]) { - K_ThrowKartItem(player, false, MT_FAKEITEM, -1, false); + K_ThrowKartItem(player, false, MT_FAKEITEM, -1, 0); K_PlayTauntSound(player->mo); player->kartstuff[k_eggmanheld] = 0; K_CleanHnextList(player->mo); @@ -4002,7 +4015,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } else if (ATTACK_IS_DOWN && player->kartstuff[k_itemheld]) // Banana x3 thrown { - K_ThrowKartItem(player, false, MT_BANANA, -1, false); + K_ThrowKartItem(player, false, MT_BANANA, -1, 0); K_PlayTauntSound(player->mo); player->kartstuff[k_itemamount]--; K_UpdateHnextList(player); @@ -4062,7 +4075,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } else if (ATTACK_IS_DOWN && player->kartstuff[k_itemheld]) // Orbinaut x3 thrown { - K_ThrowKartItem(player, true, MT_ORBINAUT, 1, false); + K_ThrowKartItem(player, true, MT_ORBINAUT, 1, 0); K_PlayTauntSound(player->mo); player->kartstuff[k_itemamount]--; K_UpdateHnextList(player); @@ -4103,9 +4116,9 @@ void K_MoveKartPlayer(player_t *player, boolean onground) else if (ATTACK_IS_DOWN && HOLDING_ITEM && player->kartstuff[k_itemheld]) // Jawz thrown { if (player->kartstuff[k_throwdir] == 1 || player->kartstuff[k_throwdir] == 0) - K_ThrowKartItem(player, true, MT_JAWZ, 1, false); + K_ThrowKartItem(player, true, MT_JAWZ, 1, 0); else if (player->kartstuff[k_throwdir] == -1) // Throwing backward gives you a dud that doesn't home in - K_ThrowKartItem(player, true, MT_JAWZ_DUD, -1, false); + K_ThrowKartItem(player, true, MT_JAWZ_DUD, -1, 0); K_PlayTauntSound(player->mo); player->kartstuff[k_itemamount]--; K_UpdateHnextList(player); @@ -4130,7 +4143,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } else if (ATTACK_IS_DOWN && player->kartstuff[k_itemheld]) { - K_ThrowKartItem(player, false, MT_SSMINE, 1, true); + K_ThrowKartItem(player, false, MT_SSMINE, 1, 1); K_PlayTauntSound(player->mo); player->kartstuff[k_itemamount]--; player->kartstuff[k_itemheld] = 0; @@ -4141,7 +4154,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) { player->kartstuff[k_itemamount]--; - K_ThrowKartItem(player, true, MT_BALLHOG, 1, false); + K_ThrowKartItem(player, true, MT_BALLHOG, 1, 0); S_StartSound(player->mo, sfx_mario7); K_PlayTauntSound(player->mo); } @@ -4243,7 +4256,8 @@ void K_MoveKartPlayer(player_t *player, boolean onground) { mobj_t *mo; player->kartstuff[k_itemheld] = 1; - S_StartSound(player->mo, sfx_s254); + if (P_IsLocalPlayer(player)) + S_StartSound(player->mo, sfx_s254); mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_SINK_SHIELD); if (mo) { @@ -4257,7 +4271,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } else if (ATTACK_IS_DOWN && HOLDING_ITEM && player->kartstuff[k_itemheld]) // Sink thrown { - K_ThrowKartItem(player, false, MT_SINK, 1, true); + K_ThrowKartItem(player, false, MT_SINK, 1, 2); K_PlayTauntSound(player->mo); player->kartstuff[k_itemamount]--; player->kartstuff[k_itemheld] = 0; diff --git a/src/p_mobj.c b/src/p_mobj.c index d22ce3e7c..fb6eed541 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1404,8 +1404,11 @@ fixed_t P_GetMobjGravity(mobj_t *mo) case MT_BANANA: case MT_FAKEITEM: case MT_SSMINE: - case MT_SINK: gravityadd = FixedMul(gravityadd, 5*FRACUNIT/2); + break; + case MT_SINK: + gravityadd = FixedMul(gravityadd, 5*FRACUNIT); // Double gravity + break; default: break; } From 1ecb8c5c8b80e0f85bb785cad100b06ca6455005 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 4 Sep 2018 20:16:42 -0400 Subject: [PATCH 069/146] If the game would normally end in a bomb kill, then always switch their places --- src/k_kart.c | 6 ++++-- src/p_inter.c | 16 ++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 930223b36..ecee1416f 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -4490,7 +4490,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) void K_CalculateBattleWanted(void) { - UINT8 numingame = 0, numwanted = 0; + UINT8 numingame = 0, numplaying = 0, numwanted = 0; SINT8 bestbumperplayer = -1, bestbumper = -1; SINT8 camppos[MAXPLAYERS]; // who is the biggest camper UINT8 ties = 0, nextcamppos = 0; @@ -4519,6 +4519,8 @@ void K_CalculateBattleWanted(void) if (players[i].exiting) // We're done, don't calculate. return; + numplaying++; + if (players[i].kartstuff[k_bumper] <= 0) // Not alive, so don't do anything else continue; @@ -4554,7 +4556,7 @@ void K_CalculateBattleWanted(void) camppos[position] = i; } - if (numingame <= 2) + if (numplaying <= 2 || (numingame <= 2 && bestbumper == 1)) // In 1v1s then there's no need for WANTED. In bigger netgames, don't show anyone as WANTED when they're equally matched. numwanted = 0; else numwanted = min(4, 1 + ((numingame-2) / 4)); diff --git a/src/p_inter.c b/src/p_inter.c index ca9330699..7e35731aa 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -516,6 +516,22 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) boom->color = SKINCOLOR_RED; S_StartSound(boom, special->info->attacksound); + if (player->kartstuff[k_bumper] == 1) // If you have only one bumper left, and see if it's a 1v1 + { + INT32 numingame = 0; + INT32 i; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator || players[i].kartstuff[k_bumper] <= 0) + continue; + numingame++; + } + + if (numingame <= 2) // If so, then an extra karma point so they are 100% certain to switch places; it's annoying to end matches with a bomb kill + special->target->player->kartstuff[k_comebackpoints]++; + } + special->target->player->kartstuff[k_comebackpoints] += 2 * (K_IsPlayerWanted(player) ? 2 : 1); if (netgame && cv_hazardlog.value) CONS_Printf(M_GetText("%s bombed %s!\n"), player_names[special->target->player-players], player_names[player-players]); From 4a7399b62d45a11cd717f3df826896a7abd9b2e6 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 4 Sep 2018 20:51:16 -0400 Subject: [PATCH 070/146] Heavy as shit now --- src/k_kart.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index ecee1416f..5c1563f77 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1459,7 +1459,9 @@ static void K_GetKartBoostPower(player_t *player) && player->kartstuff[k_offroad] >= 0) boostpower = FixedDiv(boostpower, player->kartstuff[k_offroad] + FRACUNIT); - if (player->kartstuff[k_bananadrag] > TICRATE) + if (player->kartstuff[k_itemtype] == KITEM_KITCHENSINK) + boostpower = max((TICRATE/2), (5*TICRATE)-player->kartstuff[k_bananadrag])*boostpower/(5*TICRATE); + else if (player->kartstuff[k_bananadrag] > TICRATE) boostpower = 4*boostpower/5; if (player->kartstuff[k_growshrinktimer] > 0) // Grow @@ -2998,8 +3000,7 @@ static void K_MoveHeldObjects(player_t *player) mobj_t *cur = player->mo->hnext; mobj_t *targ = player->mo; - if (P_IsObjectOnGround(player->mo) && player->speed > 0 - && player->mo->hnext->type != MT_SINK_SHIELD) // Sink ignores debuff, and is only visible to the owner. More of a HUD indicator than an actual shield. + if (P_IsObjectOnGround(player->mo) && player->speed > 0) { player->kartstuff[k_bananadrag]++; if (player->kartstuff[k_bananadrag] > TICRATE) @@ -3019,14 +3020,6 @@ static void K_MoveHeldObjects(player_t *player) cur->flags &= ~MF_NOCLIPTHING; - if (cur->type == MT_SINK_SHIELD) - { - if (P_IsLocalPlayer(player)) - cur->flags2 &= ~MF2_DONTDRAW; - else - cur->flags2 |= MF2_DONTDRAW; - } - if (!cur->health) { cur = cur->hnext; @@ -4256,8 +4249,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) { mobj_t *mo; player->kartstuff[k_itemheld] = 1; - if (P_IsLocalPlayer(player)) - S_StartSound(player->mo, sfx_s254); + S_StartSound(player->mo, sfx_s254); mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_SINK_SHIELD); if (mo) { From b53bdc9e679e1a2a31c19624ab9152332fd9f3ae Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 4 Sep 2018 21:14:42 -0400 Subject: [PATCH 071/146] Lowest speed happens slower --- src/k_kart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index 5c1563f77..2a431af8d 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1460,7 +1460,7 @@ static void K_GetKartBoostPower(player_t *player) boostpower = FixedDiv(boostpower, player->kartstuff[k_offroad] + FRACUNIT); if (player->kartstuff[k_itemtype] == KITEM_KITCHENSINK) - boostpower = max((TICRATE/2), (5*TICRATE)-player->kartstuff[k_bananadrag])*boostpower/(5*TICRATE); + boostpower = max((TICRATE/2), (5*TICRATE)-(player->kartstuff[k_bananadrag]/2))*boostpower/(5*TICRATE); else if (player->kartstuff[k_bananadrag] > TICRATE) boostpower = 4*boostpower/5; From 9514d51684b50a3542b1a0a7dd3ea43f58b79bdf Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 4 Sep 2018 21:18:20 -0400 Subject: [PATCH 072/146] Change a few cvar defaults --- src/d_netcmd.c | 4 ++-- src/p_user.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index a32542661..8e046d928 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -247,7 +247,7 @@ consvar_t cv_competitionboxes = {"competitionboxes", "Random", CV_NETVAR|CV_CHEA #ifdef SEENAMES static CV_PossibleValue_t seenames_cons_t[] = {{0, "Off"}, {1, "Colorless"}, {2, "Team"}, {3, "Ally/Foe"}, {0, NULL}}; consvar_t cv_seenames = {"seenames", "Off", CV_SAVE, seenames_cons_t, 0, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_allowseenames = {"allowseenames", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_allowseenames = {"allowseenames", "No", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; #endif // these are just meant to be saved to the config @@ -383,7 +383,7 @@ consvar_t cv_gravity = {"gravity", "0.8", CV_RESTRICT|CV_FLOAT|CV_CALL, NULL, Gr consvar_t cv_soundtest = {"soundtest", "0", CV_CALL, NULL, SoundTest_OnChange, 0, NULL, NULL, 0, 0, NULL}; static CV_PossibleValue_t minitimelimit_cons_t[] = {{15, "MIN"}, {9999, "MAX"}, {0, NULL}}; -consvar_t cv_countdowntime = {"countdowntime", "60", CV_NETVAR|CV_CHEAT, minitimelimit_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_countdowntime = {"countdowntime", "30", CV_NETVAR|CV_CHEAT, minitimelimit_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_touchtag = {"touchtag", "Off", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_hidetime = {"hidetime", "30", CV_NETVAR|CV_CALL, minitimelimit_cons_t, Hidetime_OnChange, 0, NULL, NULL, 0, 0, NULL}; diff --git a/src/p_user.c b/src/p_user.c index fdbc4c9e7..0b78ef0e7 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8080,25 +8080,25 @@ static CV_PossibleValue_t CV_CamRotate[] = {{-720, "MIN"}, {720, "MAX"}, {0, NUL consvar_t cv_cam_dist = {"cam_dist", "160", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam_height = {"cam_height", "50", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam_still = {"cam_still", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_cam_speed = {"cam_speed", "0.45", CV_FLOAT|CV_SAVE, CV_CamSpeed, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_cam_speed = {"cam_speed", "0.4", CV_FLOAT|CV_SAVE, CV_CamSpeed, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam_rotate = {"cam_rotate", "0", CV_CALL|CV_NOINIT, CV_CamRotate, CV_CamRotate_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam_rotspeed = {"cam_rotspeed", "10", CV_SAVE, rotation_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam2_dist = {"cam2_dist", "160", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam2_height = {"cam2_height", "50", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam2_still = {"cam2_still", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_cam2_speed = {"cam2_speed", "0.45", CV_FLOAT|CV_SAVE, CV_CamSpeed, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_cam2_speed = {"cam2_speed", "0.4", CV_FLOAT|CV_SAVE, CV_CamSpeed, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam2_rotate = {"cam2_rotate", "0", CV_CALL|CV_NOINIT, CV_CamRotate, CV_CamRotate2_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam2_rotspeed = {"cam2_rotspeed", "10", CV_SAVE, rotation_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam3_dist = {"cam3_dist", "160", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam3_height = {"cam3_height", "50", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam3_still = {"cam3_still", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_cam3_speed = {"cam3_speed", "0.45", CV_FLOAT|CV_SAVE, CV_CamSpeed, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_cam3_speed = {"cam3_speed", "0.4", CV_FLOAT|CV_SAVE, CV_CamSpeed, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam3_rotate = {"cam3_rotate", "0", CV_CALL|CV_NOINIT, CV_CamRotate, CV_CamRotate3_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam3_rotspeed = {"cam3_rotspeed", "10", CV_SAVE, rotation_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam4_dist = {"cam4_dist", "160", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam4_height = {"cam4_height", "50", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam4_still = {"cam4_still", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_cam4_speed = {"cam4_speed", "0.45", CV_FLOAT|CV_SAVE, CV_CamSpeed, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_cam4_speed = {"cam4_speed", "0.4", CV_FLOAT|CV_SAVE, CV_CamSpeed, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam4_rotate = {"cam4_rotate", "0", CV_CALL|CV_NOINIT, CV_CamRotate, CV_CamRotate4_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam4_rotspeed = {"cam4_rotspeed", "10", CV_SAVE, rotation_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; From 8f11dca31435dffe897474b04317c577c64c3882 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Wed, 5 Sep 2018 11:19:00 -0400 Subject: [PATCH 073/146] Boost cam --- src/d_player.h | 2 ++ src/dehacked.c | 2 ++ src/k_kart.c | 32 +++++++++++++++++++++++++++++--- src/p_user.c | 4 +++- 4 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index c038f1d85..3262defa3 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -300,6 +300,8 @@ typedef enum k_dashpadcooldown, // Separate the vanilla SA-style dash pads from using pw_flashing k_speedboost, // Boost value smoothing for max speed k_accelboost, // Boost value smoothing for acceleration + k_boostcam, // Camera push forward on boost + k_destboostcam, // Ditto k_itemroulette, // Used for the roulette when deciding what item to give you (was "pw_kartitem") k_roulettetype, // Used for the roulette, for deciding type (currently only used for Battle, to give you better items from Karma items) diff --git a/src/dehacked.c b/src/dehacked.c index 8ef369935..3473eb87c 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -7684,6 +7684,8 @@ static const char *const KARTSTUFF_LIST[] = { "DASHPADCOOLDOWN", "SPEEDBOOST", "ACCELBOOST", + "BOOSTCAM", + "DESTBOOSTCAM", "ITEMROULETTE", "ROULETTETYPE", diff --git a/src/k_kart.c b/src/k_kart.c index 2a431af8d..409560165 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1502,12 +1502,12 @@ static void K_GetKartBoostPower(player_t *player) // just take the highest we want instead if (boostpower + speedboost > player->kartstuff[k_speedboost]) - player->kartstuff[k_speedboost] += ((boostpower+speedboost) - player->kartstuff[k_speedboost])/(TICRATE/2); // Quick increase if higher + player->kartstuff[k_speedboost] = boostpower + speedboost; // Immediate increase if higher else - player->kartstuff[k_speedboost] += ((boostpower+speedboost) - player->kartstuff[k_speedboost])/TICRATE; // Smoothly decrease if lower + player->kartstuff[k_speedboost] += ((boostpower + speedboost) - player->kartstuff[k_speedboost])/TICRATE; // Smoothly decrease if lower // Accel isn't affected by boostpower, hence the FRACUNIT. Probably for making acceleration feel consistent in offroad. - player->kartstuff[k_accelboost] = FRACUNIT+accelboost; + player->kartstuff[k_accelboost] = FRACUNIT + accelboost; } fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower) @@ -2672,6 +2672,8 @@ static void K_DoHyudoroSteal(player_t *player) void K_DoSneaker(player_t *player, boolean doPFlag) { + const fixed_t prevboost = player->kartstuff[k_speedboost]; + if (!player->kartstuff[k_floorboost] || player->kartstuff[k_floorboost] == 3) S_StartSound(player->mo, sfx_cdfm01); @@ -2681,6 +2683,11 @@ void K_DoSneaker(player_t *player, boolean doPFlag) player->pflags |= PF_ATTACKDOWN; K_PlayTauntSound(player->mo); + + K_GetKartBoostPower(player); + + // Push the camera forward, the amount depending on how much the speed boost increases + player->kartstuff[k_destboostcam] = FixedMul(FRACUNIT, player->kartstuff[k_speedboost]-prevboost); } static void K_DoShrink(player_t *player) @@ -3237,6 +3244,25 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->kartstuff[k_dashpadcooldown]--; } + // DKR style camera for boosting + if (player->kartstuff[k_boostcam] != 0 || player->kartstuff[k_destboostcam] != 0) + { + if (player->kartstuff[k_boostcam] < player->kartstuff[k_destboostcam] + && player->kartstuff[k_destboostcam] != 0) + { + player->kartstuff[k_boostcam] += FRACUNIT/8; + if (player->kartstuff[k_boostcam] >= player->kartstuff[k_destboostcam]) + player->kartstuff[k_destboostcam] = 0; + } + else + { + player->kartstuff[k_boostcam] -= FRACUNIT/8; + if (player->kartstuff[k_boostcam] < player->kartstuff[k_destboostcam]) + player->kartstuff[k_boostcam] = player->kartstuff[k_destboostcam] = 0; + } + //CONS_Printf("cam: %d, dest: %d\n", player->kartstuff[k_boostcam], player->kartstuff[k_destboostcam]); + } + if (player->kartstuff[k_spinouttimer]) { if ((P_IsObjectOnGround(player->mo) || player->kartstuff[k_spinouttype] == 1) diff --git a/src/p_user.c b/src/p_user.c index 0b78ef0e7..d2631010d 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8372,7 +8372,9 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall dist = camdist; if (player->speed > K_GetKartSpeed(player, false)) - dist += 3*(player->speed - K_GetKartSpeed(player, false)); + dist += 4*(player->speed - K_GetKartSpeed(player, false)); + if (player->kartstuff[k_boostcam]) + dist -= FixedMul(dist/2, player->kartstuff[k_boostcam]); if (player->climbing || player->playerstate == PST_DEAD || (player->pflags & (PF_MACESPIN|PF_ITEMHANG|PF_ROPEHANG))) dist <<= 1; From 4a597b7ef46c7bcf0cdb8492599a1d09f80d4cee Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 6 Sep 2018 11:49:58 -0400 Subject: [PATCH 074/146] Wrote a new function for MT_SOLID object bumping A lot more similar to the code used for player wall bumping, and is much less likely for you to just... pass through the object if you keep trying hard enough. Also, falling rocks get pushed aside by invinicible players with no resistance. --- src/k_kart.c | 99 +++++++++++++++++++++++++++++++++++++++++++---- src/k_kart.h | 3 +- src/lua_baselib.c | 35 +++++++++++++++-- src/p_map.c | 20 ++++------ 4 files changed, 132 insertions(+), 25 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 409560165..8d206bf44 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -966,6 +966,16 @@ static fixed_t K_GetMobjWeight(mobj_t *mobj, mobj_t *against) else weight = (mobj->player->kartweight)<player) + { + if (against->player->kartstuff[k_invincibilitytimer] + || against->player->kartstuff[k_growshrinktimer] > 0) + weight = 0; + else + weight = (against->player->kartweight)<player) @@ -986,7 +996,7 @@ static fixed_t K_GetMobjWeight(mobj_t *mobj, mobj_t *against) return weight; } -void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid) +void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce) { mobj_t *fx; fixed_t momdifx, momdify; @@ -1021,11 +1031,7 @@ void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid) } mass1 = K_GetMobjWeight(mobj1, mobj2); - - if (solid == true && mass1 > 0) - mass2 = mass1; - else - mass2 = K_GetMobjWeight(mobj2, mobj1); + mass2 = K_GetMobjWeight(mobj2, mobj1); momdifx = mobj1->momx - mobj2->momx; momdify = mobj1->momy - mobj2->momy; @@ -1077,7 +1083,7 @@ void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid) fixed_t newz = mobj1->momz; if (mass2 > 0) mobj1->momz = mobj2->momz; - if (mass1 > 0 && solid == false) + if (mass1 > 0) mobj2->momz = newz; } @@ -1087,7 +1093,7 @@ void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid) mobj1->momy = mobj1->momy - FixedMul(FixedMul(FixedDiv(2*mass2, mass1 + mass2), p), disty); } - if (mass1 > 0 && solid == false) + if (mass1 > 0) { mobj2->momx = mobj2->momx - FixedMul(FixedMul(FixedDiv(2*mass1, mass1 + mass2), p), -distx); mobj2->momy = mobj2->momy - FixedMul(FixedMul(FixedDiv(2*mass1, mass1 + mass2), p), -disty); @@ -1131,6 +1137,83 @@ void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid) } } +// Alternate version for solid objects; always pushes away from the solid object, doesn't take anything else into account. + +void K_KartSolidBouncing(mobj_t *solid, mobj_t *mo) +{ + fixed_t mmomx = 0, mmomy = 0; + + if (!solid || !mo) + return; + + // Don't bump when you're being reborn + if (mo->player && mo->player->playerstate != PST_LIVE) + return; + + if (mo->player && mo->player->kartstuff[k_respawn]) + return; + + if (mo->eflags & MFE_JUSTBOUNCEDWALL) + { + P_SlideMove(mo, true); + return; + } + + mmomx = mo->player->rmomx; + mmomy = mo->player->rmomy; + + if (mo->player->kartstuff[k_drift] != 0) // SRB2kart + { + mo->player->kartstuff[k_drift] = 0; + mo->player->kartstuff[k_driftcharge] = 0; + } + else + { + mmomx = mo->momx; + mmomy = mo->momy; + } + + mmomx = FixedMul(mmomx, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3))); + mmomy = FixedMul(mmomy, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3))); + + { + mobj_t *fx = P_SpawnMobj(mo->x, mo->y, mo->z, MT_BUMP); + if (mo->eflags & MFE_VERTICALFLIP) + fx->eflags |= MFE_VERTICALFLIP; + else + fx->eflags &= ~MFE_VERTICALFLIP; + fx->scale = mo->scale; + + S_StartSound(mo, sfx_s3k49); + } + + { + angle_t pushangle; + fixed_t movelen; + + pushangle = R_PointToAngle2(solid->x, solid->y, mo->x, mo->y); + + pushangle >>= ANGLETOFINESHIFT; + + movelen = P_AproxDistance(mmomx, mmomy); + + if (mo->player && movelen < (15*mapheaderinfo[gamemap-1]->mobj_scale)) + movelen = (15*mapheaderinfo[gamemap-1]->mobj_scale); + + mmomx += FixedMul(movelen, FINECOSINE(pushangle)); + mmomy += FixedMul(movelen, FINESINE(pushangle)); + } + + mo->eflags |= MFE_JUSTBOUNCEDWALL; + + mo->momx = mmomx; + mo->momy = mmomy; + mo->player->cmomx = mmomx; + mo->player->cmomy = mmomy; + + P_TryMove(mo, mo->x + mmomx, mo->y + mmomy, true); +} + /** \brief Checks that the player is on an offroad subsector for realsies \param mo player mobj object diff --git a/src/k_kart.h b/src/k_kart.h index 9865d3734..8989e58ee 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -20,7 +20,8 @@ void K_RegisterKartStuff(void); boolean K_IsPlayerLosing(player_t *player); boolean K_IsPlayerWanted(player_t *player); -void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid); +void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce); +void K_KartSolidBouncing(mobj_t *solid, mobj_t *mo); void K_RespawnChecker(player_t *player); void K_KartMoveAnimation(player_t *player); void K_KartPlayerThink(player_t *player, ticcmd_t *cmd); diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 7c44c7962..5ae801a96 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -2081,13 +2081,25 @@ static int lib_kKartBouncing(lua_State *L) mobj_t *mobj1 = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *mobj2 = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); boolean bounce = luaL_checkboolean(L, 3); - boolean solid = luaL_checkboolean(L, 4); NOHUD if (!mobj1) return LUA_ErrInvalid(L, "mobj_t"); if (!mobj2) return LUA_ErrInvalid(L, "mobj_t"); - K_KartBouncing(mobj1, mobj2, bounce, solid); + K_KartBouncing(mobj1, mobj2, bounce); + return 0; +} + +static int lib_kKartSolidBouncing(lua_State *L) +{ + mobj_t *solid = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); + NOHUD + if (!solid) + return LUA_ErrInvalid(L, "mobj_t"); + if (!mo) + return LUA_ErrInvalid(L, "mobj_t"); + K_KartSolidBouncing(solid, mo); return 0; } @@ -2242,8 +2254,8 @@ static int lib_kDoPogoSpring(lua_State *L) static int lib_kKillBananaChain(lua_State *L) { mobj_t *banana = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); - mobj_t *inflictor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); - mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + mobj_t *inflictor = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); + mobj_t *source = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); NOHUD if (!banana) return LUA_ErrInvalid(L, "mobj_t"); @@ -2265,6 +2277,19 @@ static int lib_kRepairOrbitChain(lua_State *L) return 0; } +static int lib_kFindJawzTarget(lua_State *L) +{ + mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + player_t *source = *((player_t **)luaL_checkudata(L, 2, META_PLAYER)); + NOHUD // HUDSAFE? + if (!actor) + return LUA_ErrInvalid(L, "mobj_t"); + if (!source) + return LUA_ErrInvalid(L, "player_t"); + LUA_PushUserdata(L, K_FindJawzTarget(actor, source), META_PLAYER); + return 0; +} + static int lib_kMomentumToFacing(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); @@ -2487,6 +2512,7 @@ static luaL_Reg lib[] = { {"K_IsPlayerLosing",lib_kIsPlayerLosing}, {"K_IsPlayerWanted",lib_kIsPlayerWanted}, {"K_KartBouncing",lib_kKartBouncing}, + {"K_KartSolidBouncing",lib_kKartSolidBouncing}, {"K_DoInstashield",lib_kDoInstashield}, {"K_SpinPlayer",lib_kSpinPlayer}, {"K_SquishPlayer",lib_kSquishPlayer}, @@ -2501,6 +2527,7 @@ static luaL_Reg lib[] = { {"K_DoPogoSpring",lib_kDoPogoSpring}, {"K_KillBananaChain",lib_kKillBananaChain}, {"K_RepairOrbitChain",lib_kRepairOrbitChain}, + {"K_FindJawzTarget",lib_kFindJawzTarget}, {"K_MomentumToFacing",lib_kMomentumToFacing}, {"K_GetKartSpeed",lib_kGetKartSpeed}, {"K_GetKartAccel",lib_kGetKartAccel}, diff --git a/src/p_map.c b/src/p_map.c index 88045a3e1..6e8bd8bb7 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -695,7 +695,7 @@ static boolean PIT_CheckThing(mobj_t *thing) { // Player Damage P_DamageMobj(thing, tmthing, tmthing->target, 1); - K_KartBouncing(thing, tmthing, false, false); + K_KartBouncing(thing, tmthing, false); if (tmthing->type == MT_ORBINAUT || tmthing->type == MT_JAWZ || tmthing->type == MT_JAWZ_DUD) S_StartSound(thing, sfx_s3k7b); @@ -978,7 +978,7 @@ static boolean PIT_CheckThing(mobj_t *thing) // Player Damage P_DamageMobj(tmthing, thing, thing->target, 1); - K_KartBouncing(tmthing, thing, false, false); + K_KartBouncing(tmthing, thing, false); if (thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD) S_StartSound(tmthing, sfx_s3k7b); @@ -1084,7 +1084,7 @@ static boolean PIT_CheckThing(mobj_t *thing) return true; // overhead if (tmthing->z + tmthing->height < thing->z) return true; // underneath - K_KartBouncing(thing, tmthing, false, false); + K_KartBouncing(thing, tmthing, false); } if ((thing->type == MT_SPRINGSHELL || thing->type == MT_YELLOWSHELL) && thing->health > 0 @@ -1506,7 +1506,7 @@ static boolean PIT_CheckThing(mobj_t *thing) if (P_IsObjectOnGround(thing) && tmthing->momz < 0) { - K_KartBouncing(tmthing, thing, true, false); + K_KartBouncing(tmthing, thing, true); if (G_BattleGametype() && tmthing->player->kartstuff[k_pogospring]) { K_StealBumper(tmthing->player, thing->player, false); @@ -1515,7 +1515,7 @@ static boolean PIT_CheckThing(mobj_t *thing) } else if (P_IsObjectOnGround(tmthing) && thing->momz < 0) { - K_KartBouncing(thing, tmthing, true, false); + K_KartBouncing(thing, tmthing, true); if (G_BattleGametype() && thing->player->kartstuff[k_pogospring]) { K_StealBumper(thing->player, tmthing->player, false); @@ -1523,7 +1523,7 @@ static boolean PIT_CheckThing(mobj_t *thing) } } else - K_KartBouncing(tmthing, thing, false, false); + K_KartBouncing(tmthing, thing, false); if (G_BattleGametype()) { @@ -1549,12 +1549,8 @@ static boolean PIT_CheckThing(mobj_t *thing) if (tmthing->z + tmthing->height < thing->z) return true; // underneath - if (P_IsObjectOnGround(thing) && tmthing->momz < 0) - K_KartBouncing(tmthing, thing, true, true); - else - K_KartBouncing(tmthing, thing, false, true); - - return true; + K_KartSolidBouncing(thing, tmthing); + return false; } // Are you touching the side of the object you're interacting with? else if (thing->z - FixedMul(FRACUNIT, thing->scale) <= tmthing->z + tmthing->height From 84d4efe5f18a07194665bb790ee8712daba2491f Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 6 Sep 2018 13:02:08 -0400 Subject: [PATCH 075/146] Boost tweaks Fix offroad not affecting you as soon as it did before, and tweaking boost cam to be stronger --- src/d_player.h | 1 + src/dehacked.c | 1 + src/k_kart.c | 29 +++++++++++++++-------------- src/p_user.c | 4 ++++ 4 files changed, 21 insertions(+), 14 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 3262defa3..34eb385ca 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -298,6 +298,7 @@ typedef enum k_brakestop, // Wait until you've made a complete stop for a few tics before letting brake go in reverse. k_waterskip, // Water skipping counter k_dashpadcooldown, // Separate the vanilla SA-style dash pads from using pw_flashing + k_boostpower, // Base boost value, for offroad k_speedboost, // Boost value smoothing for max speed k_accelboost, // Boost value smoothing for acceleration k_boostcam, // Camera push forward on boost diff --git a/src/dehacked.c b/src/dehacked.c index 3473eb87c..39188f9eb 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -7682,6 +7682,7 @@ static const char *const KARTSTUFF_LIST[] = { "BRAKESTOP", "WATERSKIP", "DASHPADCOOLDOWN", + "BOOSTPOWER", "SPEEDBOOST", "ACCELBOOST", "BOOSTCAM", diff --git a/src/k_kart.c b/src/k_kart.c index 8d206bf44..dcb7aa26d 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1533,7 +1533,7 @@ static void K_GetKartBoostPower(player_t *player) if (player->kartstuff[k_spinouttimer] && player->kartstuff[k_wipeoutslow] == 1) // Slow down after you've been bumped { - player->kartstuff[k_speedboost] = player->kartstuff[k_accelboost] = 0; + player->kartstuff[k_boostpower] = player->kartstuff[k_speedboost] = player->kartstuff[k_accelboost] = 0; return; } @@ -1584,13 +1584,15 @@ static void K_GetKartBoostPower(player_t *player) // don't average them anymore, this would make a small boost and a high boost less useful // just take the highest we want instead - if (boostpower + speedboost > player->kartstuff[k_speedboost]) - player->kartstuff[k_speedboost] = boostpower + speedboost; // Immediate increase if higher - else - player->kartstuff[k_speedboost] += ((boostpower + speedboost) - player->kartstuff[k_speedboost])/TICRATE; // Smoothly decrease if lower + player->kartstuff[k_boostpower] = boostpower; - // Accel isn't affected by boostpower, hence the FRACUNIT. Probably for making acceleration feel consistent in offroad. - player->kartstuff[k_accelboost] = FRACUNIT + accelboost; + // value smoothing + if (speedboost > player->kartstuff[k_speedboost]) + player->kartstuff[k_speedboost] = speedboost; + else + player->kartstuff[k_speedboost] += (speedboost - player->kartstuff[k_speedboost])/(TICRATE/2); + + player->kartstuff[k_accelboost] = accelboost; } fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower) @@ -1625,7 +1627,7 @@ fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower) finalspeed = FixedMul(FixedMul(k_speed<<14, g_cc), player->mo->scale); if (doboostpower) - return FixedMul(finalspeed, player->kartstuff[k_speedboost]); + return FixedMul(finalspeed, player->kartstuff[k_boostpower]+player->kartstuff[k_speedboost]); return finalspeed; } @@ -1640,7 +1642,7 @@ fixed_t K_GetKartAccel(player_t *player) //k_accel += 3 * (9 - kartspeed); // 36 - 60 k_accel += 4 * (9 - kartspeed); // 32 - 64 - return FixedMul(k_accel, player->kartstuff[k_accelboost]); + return FixedMul(k_accel, FRACUNIT+player->kartstuff[k_accelboost]); } UINT16 K_GetKartFlashing(player_t *player) @@ -2768,9 +2770,8 @@ void K_DoSneaker(player_t *player, boolean doPFlag) K_PlayTauntSound(player->mo); K_GetKartBoostPower(player); - - // Push the camera forward, the amount depending on how much the speed boost increases - player->kartstuff[k_destboostcam] = FixedMul(FRACUNIT, player->kartstuff[k_speedboost]-prevboost); + if (player->kartstuff[k_speedboost] > prevboost) + player->kartstuff[k_destboostcam] = FRACUNIT; } static void K_DoShrink(player_t *player) @@ -3333,13 +3334,13 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->kartstuff[k_boostcam] < player->kartstuff[k_destboostcam] && player->kartstuff[k_destboostcam] != 0) { - player->kartstuff[k_boostcam] += FRACUNIT/8; + player->kartstuff[k_boostcam] += FRACUNIT/5; if (player->kartstuff[k_boostcam] >= player->kartstuff[k_destboostcam]) player->kartstuff[k_destboostcam] = 0; } else { - player->kartstuff[k_boostcam] -= FRACUNIT/8; + player->kartstuff[k_boostcam] -= FRACUNIT/5; if (player->kartstuff[k_boostcam] < player->kartstuff[k_destboostcam]) player->kartstuff[k_boostcam] = player->kartstuff[k_destboostcam] = 0; } diff --git a/src/p_user.c b/src/p_user.c index d2631010d..30370dc81 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8373,8 +8373,12 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if (player->speed > K_GetKartSpeed(player, false)) dist += 4*(player->speed - K_GetKartSpeed(player, false)); + if (player->kartstuff[k_boostcam]) + { dist -= FixedMul(dist/2, player->kartstuff[k_boostcam]); + height -= FixedMul(height, player->kartstuff[k_boostcam]); + } if (player->climbing || player->playerstate == PST_DEAD || (player->pflags & (PF_MACESPIN|PF_ITEMHANG|PF_ROPEHANG))) dist <<= 1; From 8866bd9818162734c191a05e7cd5830dad677a0b Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 6 Sep 2018 15:52:27 -0400 Subject: [PATCH 076/146] Sink bug fix Sink would only spawn its trail ever if you threw it on a tic that was (leveltime % 4 == 0), because it called its action every 4 tics instead of every tic --- src/info.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/info.c b/src/info.c index 60cac109d..0ea7f13a0 100644 --- a/src/info.c +++ b/src/info.c @@ -2795,7 +2795,7 @@ state_t states[NUMSTATES] = {SPR_THNS, 10, 2, {NULL}, 0, 0, S_THUNDERSHIELD24}, // S_THUNDERSHIELD23 {SPR_THNS, 11, 2, {NULL}, 0, 0, S_THUNDERSHIELD1}, // S_THUNDERSHIELD24 - {SPR_SINK, 0, 4, {A_SmokeTrailer}, MT_SINKTRAIL, 0, S_SINK}, // S_SINK + {SPR_SINK, 0, 1, {A_SmokeTrailer}, MT_SINKTRAIL, 0, S_SINK}, // S_SINK {SPR_SINK, 0|FF_TRANS80|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_SINK_SHIELD}, // S_SINK_SHIELD {SPR_SITR, 0, 1, {NULL}, 0, 0, S_SINKTRAIL2}, // S_SINKTRAIL1 {SPR_SITR, 1, 5, {NULL}, 0, 0, S_SINKTRAIL3}, // S_SINKTRAIL2 From 0d5aaa65c63dc844c506f0ebc31d6a876ccae398 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 6 Sep 2018 16:05:57 -0400 Subject: [PATCH 077/146] More Jawz tweaking - Z pos checking is Battle-only now - Made the Z pos limit much higher - Increased its range in Battle --- src/k_kart.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index dcb7aa26d..d62183066 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3209,10 +3209,6 @@ player_t *K_FindJawzTarget(mobj_t *actor, player_t *source) if (player->kartstuff[k_hyudorotimer]) continue; - // Z pos too high/low - if (abs(player->mo->z - (actor->z + actor->momz)) > 48<angle - R_PointToAngle2(actor->x, actor->y, player->mo->x, player->mo->y); if (thisang > ANGLE_180) @@ -3240,9 +3236,13 @@ player_t *K_FindJawzTarget(mobj_t *actor, player_t *source) if (player->kartstuff[k_bumper] <= 0) continue; + // Z pos too high/low + if (abs(player->mo->z - (actor->z + actor->momz)) > RING_DIST/8) + continue; + thisdist = P_AproxDistance(player->mo->x - (actor->x + actor->momx), player->mo->y - (actor->y + actor->momy)); - if (thisdist > RING_DIST) // Don't go for people who are too far away + if (thisdist > 2*RING_DIST) // Don't go for people who are too far away continue; thisavg = (AngleFixed(thisang) + thisdist) / 2; From 50f8186651b1a397d5d7bc1f7614edb581273c35 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 6 Sep 2018 16:06:37 -0400 Subject: [PATCH 078/146] Player arrows can show x10 Requires new patch.kart --- src/p_mobj.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index fb6eed541..4ff2c2dc6 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7033,7 +7033,7 @@ void P_MobjThinker(mobj_t *mobj) mobj->tracer->destscale = scale; if (mobj->target->player->kartstuff[k_itemamount] >= numberdisplaymin - && mobj->target->player->kartstuff[k_itemamount] < 10) // Meh, too difficult to support greater than this; convert this to a decent HUD object and then maybe :V + && mobj->target->player->kartstuff[k_itemamount] <= 10) // Meh, too difficult to support greater than this; convert this to a decent HUD object and then maybe :V { mobj_t *number = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_OVERLAY); mobj_t *numx = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_OVERLAY); From 81af98fd916fa5042d28fa79c893c652e258a8ee Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 6 Sep 2018 16:09:17 -0400 Subject: [PATCH 079/146] Forgot this --- src/info.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/info.c b/src/info.c index 0ea7f13a0..493baf443 100644 --- a/src/info.c +++ b/src/info.c @@ -2985,7 +2985,7 @@ state_t states[NUMSTATES] = {SPR_ARRO, FF_FULLBRIGHT|1, -1, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW_BOX {SPR_ITEM, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW_ITEM {SPR_ITMN, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW_NUMBER - {SPR_ITMN, FF_FULLBRIGHT|10, 2, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW_X + {SPR_ITMN, FF_FULLBRIGHT|11, 2, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW_X {SPR_WANT, FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_PLAYERARROW_WANTED2}, // S_PLAYERARROW_WANTED1 {SPR_WANT, FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_PLAYERARROW_WANTED3}, // S_PLAYERARROW_WANTED2 {SPR_WANT, FF_FULLBRIGHT|2, 3, {NULL}, 0, 0, S_PLAYERARROW_WANTED4}, // S_PLAYERARROW_WANTED3 From 04aa1289fc6621e1b5bf192a1132f0f9bf03497c Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 6 Sep 2018 19:27:07 -0400 Subject: [PATCH 080/146] Revert "Wrote a new function for MT_SOLID object bumping" This reverts commit 4a597b7ef46c7bcf0cdb8492599a1d09f80d4cee. --- src/k_kart.c | 99 ++++------------------------------------------- src/k_kart.h | 3 +- src/lua_baselib.c | 35 ++--------------- src/p_map.c | 20 ++++++---- 4 files changed, 25 insertions(+), 132 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index d62183066..57b05c50c 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -966,16 +966,6 @@ static fixed_t K_GetMobjWeight(mobj_t *mobj, mobj_t *against) else weight = (mobj->player->kartweight)<player) - { - if (against->player->kartstuff[k_invincibilitytimer] - || against->player->kartstuff[k_growshrinktimer] > 0) - weight = 0; - else - weight = (against->player->kartweight)<player) @@ -996,7 +986,7 @@ static fixed_t K_GetMobjWeight(mobj_t *mobj, mobj_t *against) return weight; } -void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce) +void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid) { mobj_t *fx; fixed_t momdifx, momdify; @@ -1031,7 +1021,11 @@ void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce) } mass1 = K_GetMobjWeight(mobj1, mobj2); - mass2 = K_GetMobjWeight(mobj2, mobj1); + + if (solid == true && mass1 > 0) + mass2 = mass1; + else + mass2 = K_GetMobjWeight(mobj2, mobj1); momdifx = mobj1->momx - mobj2->momx; momdify = mobj1->momy - mobj2->momy; @@ -1083,7 +1077,7 @@ void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce) fixed_t newz = mobj1->momz; if (mass2 > 0) mobj1->momz = mobj2->momz; - if (mass1 > 0) + if (mass1 > 0 && solid == false) mobj2->momz = newz; } @@ -1093,7 +1087,7 @@ void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce) mobj1->momy = mobj1->momy - FixedMul(FixedMul(FixedDiv(2*mass2, mass1 + mass2), p), disty); } - if (mass1 > 0) + if (mass1 > 0 && solid == false) { mobj2->momx = mobj2->momx - FixedMul(FixedMul(FixedDiv(2*mass1, mass1 + mass2), p), -distx); mobj2->momy = mobj2->momy - FixedMul(FixedMul(FixedDiv(2*mass1, mass1 + mass2), p), -disty); @@ -1137,83 +1131,6 @@ void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce) } } -// Alternate version for solid objects; always pushes away from the solid object, doesn't take anything else into account. - -void K_KartSolidBouncing(mobj_t *solid, mobj_t *mo) -{ - fixed_t mmomx = 0, mmomy = 0; - - if (!solid || !mo) - return; - - // Don't bump when you're being reborn - if (mo->player && mo->player->playerstate != PST_LIVE) - return; - - if (mo->player && mo->player->kartstuff[k_respawn]) - return; - - if (mo->eflags & MFE_JUSTBOUNCEDWALL) - { - P_SlideMove(mo, true); - return; - } - - mmomx = mo->player->rmomx; - mmomy = mo->player->rmomy; - - if (mo->player->kartstuff[k_drift] != 0) // SRB2kart - { - mo->player->kartstuff[k_drift] = 0; - mo->player->kartstuff[k_driftcharge] = 0; - } - else - { - mmomx = mo->momx; - mmomy = mo->momy; - } - - mmomx = FixedMul(mmomx, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3))); - mmomy = FixedMul(mmomy, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3))); - - { - mobj_t *fx = P_SpawnMobj(mo->x, mo->y, mo->z, MT_BUMP); - if (mo->eflags & MFE_VERTICALFLIP) - fx->eflags |= MFE_VERTICALFLIP; - else - fx->eflags &= ~MFE_VERTICALFLIP; - fx->scale = mo->scale; - - S_StartSound(mo, sfx_s3k49); - } - - { - angle_t pushangle; - fixed_t movelen; - - pushangle = R_PointToAngle2(solid->x, solid->y, mo->x, mo->y); - - pushangle >>= ANGLETOFINESHIFT; - - movelen = P_AproxDistance(mmomx, mmomy); - - if (mo->player && movelen < (15*mapheaderinfo[gamemap-1]->mobj_scale)) - movelen = (15*mapheaderinfo[gamemap-1]->mobj_scale); - - mmomx += FixedMul(movelen, FINECOSINE(pushangle)); - mmomy += FixedMul(movelen, FINESINE(pushangle)); - } - - mo->eflags |= MFE_JUSTBOUNCEDWALL; - - mo->momx = mmomx; - mo->momy = mmomy; - mo->player->cmomx = mmomx; - mo->player->cmomy = mmomy; - - P_TryMove(mo, mo->x + mmomx, mo->y + mmomy, true); -} - /** \brief Checks that the player is on an offroad subsector for realsies \param mo player mobj object diff --git a/src/k_kart.h b/src/k_kart.h index 8989e58ee..9865d3734 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -20,8 +20,7 @@ void K_RegisterKartStuff(void); boolean K_IsPlayerLosing(player_t *player); boolean K_IsPlayerWanted(player_t *player); -void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce); -void K_KartSolidBouncing(mobj_t *solid, mobj_t *mo); +void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid); void K_RespawnChecker(player_t *player); void K_KartMoveAnimation(player_t *player); void K_KartPlayerThink(player_t *player, ticcmd_t *cmd); diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 5ae801a96..7c44c7962 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -2081,25 +2081,13 @@ static int lib_kKartBouncing(lua_State *L) mobj_t *mobj1 = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *mobj2 = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); boolean bounce = luaL_checkboolean(L, 3); + boolean solid = luaL_checkboolean(L, 4); NOHUD if (!mobj1) return LUA_ErrInvalid(L, "mobj_t"); if (!mobj2) return LUA_ErrInvalid(L, "mobj_t"); - K_KartBouncing(mobj1, mobj2, bounce); - return 0; -} - -static int lib_kKartSolidBouncing(lua_State *L) -{ - mobj_t *solid = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); - mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); - NOHUD - if (!solid) - return LUA_ErrInvalid(L, "mobj_t"); - if (!mo) - return LUA_ErrInvalid(L, "mobj_t"); - K_KartSolidBouncing(solid, mo); + K_KartBouncing(mobj1, mobj2, bounce, solid); return 0; } @@ -2254,8 +2242,8 @@ static int lib_kDoPogoSpring(lua_State *L) static int lib_kKillBananaChain(lua_State *L) { mobj_t *banana = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); - mobj_t *inflictor = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); - mobj_t *source = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); + mobj_t *inflictor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); NOHUD if (!banana) return LUA_ErrInvalid(L, "mobj_t"); @@ -2277,19 +2265,6 @@ static int lib_kRepairOrbitChain(lua_State *L) return 0; } -static int lib_kFindJawzTarget(lua_State *L) -{ - mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); - player_t *source = *((player_t **)luaL_checkudata(L, 2, META_PLAYER)); - NOHUD // HUDSAFE? - if (!actor) - return LUA_ErrInvalid(L, "mobj_t"); - if (!source) - return LUA_ErrInvalid(L, "player_t"); - LUA_PushUserdata(L, K_FindJawzTarget(actor, source), META_PLAYER); - return 0; -} - static int lib_kMomentumToFacing(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); @@ -2512,7 +2487,6 @@ static luaL_Reg lib[] = { {"K_IsPlayerLosing",lib_kIsPlayerLosing}, {"K_IsPlayerWanted",lib_kIsPlayerWanted}, {"K_KartBouncing",lib_kKartBouncing}, - {"K_KartSolidBouncing",lib_kKartSolidBouncing}, {"K_DoInstashield",lib_kDoInstashield}, {"K_SpinPlayer",lib_kSpinPlayer}, {"K_SquishPlayer",lib_kSquishPlayer}, @@ -2527,7 +2501,6 @@ static luaL_Reg lib[] = { {"K_DoPogoSpring",lib_kDoPogoSpring}, {"K_KillBananaChain",lib_kKillBananaChain}, {"K_RepairOrbitChain",lib_kRepairOrbitChain}, - {"K_FindJawzTarget",lib_kFindJawzTarget}, {"K_MomentumToFacing",lib_kMomentumToFacing}, {"K_GetKartSpeed",lib_kGetKartSpeed}, {"K_GetKartAccel",lib_kGetKartAccel}, diff --git a/src/p_map.c b/src/p_map.c index 6e8bd8bb7..88045a3e1 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -695,7 +695,7 @@ static boolean PIT_CheckThing(mobj_t *thing) { // Player Damage P_DamageMobj(thing, tmthing, tmthing->target, 1); - K_KartBouncing(thing, tmthing, false); + K_KartBouncing(thing, tmthing, false, false); if (tmthing->type == MT_ORBINAUT || tmthing->type == MT_JAWZ || tmthing->type == MT_JAWZ_DUD) S_StartSound(thing, sfx_s3k7b); @@ -978,7 +978,7 @@ static boolean PIT_CheckThing(mobj_t *thing) // Player Damage P_DamageMobj(tmthing, thing, thing->target, 1); - K_KartBouncing(tmthing, thing, false); + K_KartBouncing(tmthing, thing, false, false); if (thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD) S_StartSound(tmthing, sfx_s3k7b); @@ -1084,7 +1084,7 @@ static boolean PIT_CheckThing(mobj_t *thing) return true; // overhead if (tmthing->z + tmthing->height < thing->z) return true; // underneath - K_KartBouncing(thing, tmthing, false); + K_KartBouncing(thing, tmthing, false, false); } if ((thing->type == MT_SPRINGSHELL || thing->type == MT_YELLOWSHELL) && thing->health > 0 @@ -1506,7 +1506,7 @@ static boolean PIT_CheckThing(mobj_t *thing) if (P_IsObjectOnGround(thing) && tmthing->momz < 0) { - K_KartBouncing(tmthing, thing, true); + K_KartBouncing(tmthing, thing, true, false); if (G_BattleGametype() && tmthing->player->kartstuff[k_pogospring]) { K_StealBumper(tmthing->player, thing->player, false); @@ -1515,7 +1515,7 @@ static boolean PIT_CheckThing(mobj_t *thing) } else if (P_IsObjectOnGround(tmthing) && thing->momz < 0) { - K_KartBouncing(thing, tmthing, true); + K_KartBouncing(thing, tmthing, true, false); if (G_BattleGametype() && thing->player->kartstuff[k_pogospring]) { K_StealBumper(thing->player, tmthing->player, false); @@ -1523,7 +1523,7 @@ static boolean PIT_CheckThing(mobj_t *thing) } } else - K_KartBouncing(tmthing, thing, false); + K_KartBouncing(tmthing, thing, false, false); if (G_BattleGametype()) { @@ -1549,8 +1549,12 @@ static boolean PIT_CheckThing(mobj_t *thing) if (tmthing->z + tmthing->height < thing->z) return true; // underneath - K_KartSolidBouncing(thing, tmthing); - return false; + if (P_IsObjectOnGround(thing) && tmthing->momz < 0) + K_KartBouncing(tmthing, thing, true, true); + else + K_KartBouncing(tmthing, thing, false, true); + + return true; } // Are you touching the side of the object you're interacting with? else if (thing->z - FixedMul(FRACUNIT, thing->scale) <= tmthing->z + tmthing->height From ceacbd180f197079fe0420d742debbb99ad359e7 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 6 Sep 2018 19:31:28 -0400 Subject: [PATCH 081/146] Restore the one good bit --- src/k_kart.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/k_kart.c b/src/k_kart.c index 57b05c50c..43cd22520 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -966,6 +966,16 @@ static fixed_t K_GetMobjWeight(mobj_t *mobj, mobj_t *against) else weight = (mobj->player->kartweight)<player) + { + if (against->player->kartstuff[k_invincibilitytimer] + || against->player->kartstuff[k_growshrinktimer] > 0) + weight = 0; + else + weight = (against->player->kartweight)<player) From 874d088f7726ccf9355096f45257eb4df1c82a3a Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 6 Sep 2018 21:58:23 -0400 Subject: [PATCH 082/146] Tweaked boost cam, again --- src/k_kart.c | 4 ++-- src/p_user.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 43cd22520..2708c92e5 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3261,13 +3261,13 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->kartstuff[k_boostcam] < player->kartstuff[k_destboostcam] && player->kartstuff[k_destboostcam] != 0) { - player->kartstuff[k_boostcam] += FRACUNIT/5; + player->kartstuff[k_boostcam] += FRACUNIT/(TICRATE/4); if (player->kartstuff[k_boostcam] >= player->kartstuff[k_destboostcam]) player->kartstuff[k_destboostcam] = 0; } else { - player->kartstuff[k_boostcam] -= FRACUNIT/5; + player->kartstuff[k_boostcam] -= FRACUNIT/TICRATE; if (player->kartstuff[k_boostcam] < player->kartstuff[k_destboostcam]) player->kartstuff[k_boostcam] = player->kartstuff[k_destboostcam] = 0; } diff --git a/src/p_user.c b/src/p_user.c index 30370dc81..fb327e3a2 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8376,7 +8376,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if (player->kartstuff[k_boostcam]) { - dist -= FixedMul(dist/2, player->kartstuff[k_boostcam]); + dist -= FixedMul(3*dist/4, player->kartstuff[k_boostcam]); height -= FixedMul(height, player->kartstuff[k_boostcam]); } From 1a7a84f614b227852b410c2c7d449c18563f7b30 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 6 Sep 2018 23:49:51 -0400 Subject: [PATCH 083/146] Placeholder boost effect --- src/dehacked.c | 12 ++++++++ src/info.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++---- src/info.h | 14 ++++++++++ src/k_kart.c | 8 ++++++ src/p_mobj.c | 33 ++++++++++++++++++++++ 5 files changed, 137 insertions(+), 6 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 39188f9eb..905e6dc04 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -6249,6 +6249,16 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit // Thunder Shield Burst + // Sneaker boost effect + "S_BOOSTFLAME", + "S_BOOSTSMOKESPAWNER", + "S_BOOSTSMOKE1", + "S_BOOSTSMOKE2", + "S_BOOSTSMOKE3", + "S_BOOSTSMOKE4", + "S_BOOSTSMOKE5", + "S_BOOSTSMOKE6", + // Sneaker Fire Trail "S_KARTFIRE1", "S_KARTFIRE2", @@ -7209,6 +7219,8 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_RANDOMITEM", "MT_RANDOMITEMPOP", + "MT_BOOSTFLAME", + "MT_BOOSTSMOKE", "MT_SNEAKERTRAIL", "MT_SPARKLETRAIL", "MT_INVULNFLASH", diff --git a/src/info.c b/src/info.c index 493baf443..b87e317de 100644 --- a/src/info.c +++ b/src/info.c @@ -55,12 +55,12 @@ char sprnames[NUMSPRITES + 1][5] = "GWLR","SRBA","SRBB","SRBC","SRBD","SRBE","SRBF","SRBG","SRBH","SRBI", "SRBJ","SRBK","SRBL","SRBM","SRBN","SRBO", //SRB2kart Sprites - "SPRG","BSPR","RNDM","RPOP","KFRE","KINV","KINF","WIPD","DRIF","DUST", - "FITM","BANA","ORBN","JAWZ","SSMN","KRBM","BHOG","BHBM","BLIG","LIGH", - "THNS","SINK","SITR","KBLN","DEZL","POKE","AUDI","DECO","DOOD","SNES", - "GBAS","SPRS","BUZB","CHOM","SACO","CRAB","SHAD","BRNG","BUMP","FLEN", - "CLAS","PSHW","ISTA","ISTB","ARRO","ITEM","ITMO","ITMI","ITMN","WANT", - "PBOM","RETI","VIEW" + "SPRG","BSPR","RNDM","RPOP","BOST","BOSM","KFRE","KINV","KINF","WIPD", + "DRIF","DUST","FITM","BANA","ORBN","JAWZ","SSMN","KRBM","BHOG","BHBM", + "BLIG","LIGH","THNS","SINK","SITR","KBLN","DEZL","POKE","AUDI","DECO", + "DOOD","SNES","GBAS","SPRS","BUZB","CHOM","SACO","CRAB","SHAD","BRNG", + "BUMP","FLEN","CLAS","PSHW","ISTA","ISTB","ARRO","ITEM","ITMO","ITMI", + "ITMN","WANT","PBOM","RETI","VIEW" }; // Doesn't work with g++, needs actionf_p1 (don't modify this comment) @@ -2578,6 +2578,16 @@ state_t states[NUMSTATES] = {SPR_DUST, FF_TRANS20|2, 3, {NULL}, 0, 0, S_DRIFTDUST4}, // S_DRIFTDUST3 {SPR_DUST, FF_TRANS20|3, 3, {NULL}, 0, 0, S_NULL}, // S_DRIFTDUST4 + {SPR_BOST, FF_FULLBRIGHT|FF_ANIMATE, TICRATE, {NULL}, 6, 1, S_BOOSTSMOKESPAWNER}, // S_BOOSTFLAME + {SPR_NULL, 0, TICRATE/2, {NULL}, 0, 0, S_NULL}, // S_BOOSTSMOKESPAWNER + + {SPR_BOSM, FF_TRANS50, 3, {NULL}, 0, 0, S_BOOSTSMOKE2}, // S_BOOSTSMOKE1 + {SPR_BOSM, FF_TRANS50|1, 3, {NULL}, 0, 0, S_BOOSTSMOKE3}, // S_BOOSTSMOKE2 + {SPR_BOSM, FF_TRANS50|2, 3, {NULL}, 0, 0, S_BOOSTSMOKE4}, // S_BOOSTSMOKE3 + {SPR_BOSM, FF_TRANS50|3, 3, {NULL}, 0, 0, S_BOOSTSMOKE5}, // S_BOOSTSMOKE4 + {SPR_BOSM, FF_TRANS50|4, 3, {NULL}, 0, 0, S_BOOSTSMOKE6}, // S_BOOSTSMOKE5 + {SPR_BOSM, FF_TRANS50|5, 3, {NULL}, 0, 0, S_NULL}, // S_BOOSTSMOKE6 + {SPR_NULL, 0, 10, {NULL}, 0, 0, S_KARTFIRE2}, // S_KARTFIRE1 {SPR_KFRE, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_KARTFIRE3}, // S_KARTFIRE2 {SPR_KFRE, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_KARTFIRE4}, // S_KARTFIRE3 @@ -14390,6 +14400,60 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_BOOSTFLAME + -1, // doomednum + S_BOOSTFLAME, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 8, // speed + 8*FRACUNIT, // radius + 8*FRACUNIT, // height + 1, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_BOOSTSMOKE + -1, // doomednum + S_BOOSTSMOKE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 8, // speed + 8*FRACUNIT, // radius + 8*FRACUNIT, // height + 1, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags + S_NULL // raisestate + }, + { // MT_SNEAKERTRAIL -1, // doomednum S_KARTFIRE1, // spawnstate diff --git a/src/info.h b/src/info.h index 736fdfdee..a1300ca38 100644 --- a/src/info.h +++ b/src/info.h @@ -582,6 +582,8 @@ typedef enum sprite SPR_RNDM, // Random Item Box SPR_RPOP, // Random Item Box Pop + SPR_BOST, // Sneaker booster flame + SPR_BOSM, // Sneaker booster smoke SPR_KFRE, // Sneaker fire trail SPR_KINV, // Invincibility sparkle trail SPR_KINF, // Invincibility flash @@ -3094,6 +3096,16 @@ typedef enum state // Magnet Burst + // Sneaker boost effect + S_BOOSTFLAME, + S_BOOSTSMOKESPAWNER, + S_BOOSTSMOKE1, + S_BOOSTSMOKE2, + S_BOOSTSMOKE3, + S_BOOSTSMOKE4, + S_BOOSTSMOKE5, + S_BOOSTSMOKE6, + // Sneaker Fire Trail S_KARTFIRE1, S_KARTFIRE2, @@ -4071,6 +4083,8 @@ typedef enum mobj_type MT_RANDOMITEM, MT_RANDOMITEMPOP, + MT_BOOSTFLAME, + MT_BOOSTSMOKE, MT_SNEAKERTRAIL, MT_SPARKLETRAIL, MT_INVULNFLASH, diff --git a/src/k_kart.c b/src/k_kart.c index 2708c92e5..8b09e0514 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2689,6 +2689,14 @@ void K_DoSneaker(player_t *player, boolean doPFlag) if (!player->kartstuff[k_floorboost] || player->kartstuff[k_floorboost] == 3) S_StartSound(player->mo, sfx_cdfm01); + if (!player->kartstuff[k_sneakertimer]) + { + mobj_t *overlay = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_BOOSTFLAME); + P_SetTarget(&overlay->target, player->mo); + overlay->destscale = player->mo->scale; + P_SetScale(overlay, player->mo->scale); + } + player->kartstuff[k_sneakertimer] = sneakertime; if (doPFlag) diff --git a/src/p_mobj.c b/src/p_mobj.c index 4ff2c2dc6..04f99accc 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8229,6 +8229,39 @@ void P_MobjThinker(mobj_t *mobj) S_StartSound(mobj, sfx_prloop); mobj->health--; break; + case MT_BOOSTFLAME: + if (!mobj->target || !mobj->target->health) + { + P_RemoveMobj(mobj); + return; + } + + P_TeleportMove(mobj, mobj->target->x + P_ReturnThrustX(mobj, mobj->target->angle+ANGLE_180, mobj->target->radius), + mobj->target->y + P_ReturnThrustY(mobj, mobj->target->angle+ANGLE_180, mobj->target->radius), mobj->target->z); + mobj->angle = mobj->target->angle; + P_SetScale(mobj, mobj->target->scale); + + if (mobj->target->player) + { + if (mobj->target->player->kartstuff[k_sneakertimer] > mobj->movecount) + P_SetMobjState(mobj, S_BOOSTFLAME); + mobj->movecount = mobj->target->player->kartstuff[k_sneakertimer]; + } + + if (mobj->state == &states[S_BOOSTSMOKESPAWNER]) + { + mobj_t *smoke = P_SpawnMobj(mobj->x, mobj->y, mobj->z+(8<target->scale/2); + smoke->destscale = 3*mobj->target->scale/2; + + smoke->momx = mobj->target->momx/2; + smoke->momy = mobj->target->momy/2; + smoke->momz = mobj->target->momz/2; + + P_Thrust(smoke, mobj->target->angle+FixedAngle(P_RandomRange(135, 225)<mobj_scale); + } + break; case MT_SPARKLETRAIL: if (!mobj->target) { From b7e0baad98cb75227c03627efe84af0a8f95e348 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Fri, 7 Sep 2018 22:17:38 -0400 Subject: [PATCH 084/146] Rebalanced odds table again --- src/k_kart.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 8b09e0514..30a47d634 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -469,28 +469,28 @@ boolean K_IsPlayerWanted(player_t *player) static INT32 K_KartItemOddsRace[NUMKARTRESULTS][9] = { //P-Odds 0 1 2 3 4 5 6 7 8 - /*Sneaker*/ {20, 0, 0, 3, 6, 6, 0, 0, 0 }, // Sneaker - /*Rocket Sneaker*/ { 0, 0, 0, 0, 0, 2, 5, 4, 0 }, // Rocket Sneaker + /*Sneaker*/ {20, 0, 0, 3, 6, 5, 0, 0, 0 }, // Sneaker + /*Rocket Sneaker*/ { 0, 0, 0, 0, 0, 2, 6, 5, 0 }, // Rocket Sneaker /*Invincibility*/ { 0, 0, 0, 0, 0, 1, 5, 6,16 }, // Invincibility - /*Banana*/ { 0, 9, 4, 2, 1, 0, 0, 0, 0 }, // Banana + /*Banana*/ { 0, 9, 3, 2, 1, 0, 0, 0, 0 }, // Banana /*Eggman Monitor*/ { 0, 4, 3, 2, 0, 0, 0, 0, 0 }, // Eggman Monitor - /*Orbinaut*/ { 0, 6, 5, 4, 2, 0, 0, 0, 0 }, // Orbinaut + /*Orbinaut*/ { 0, 6, 3, 4, 2, 0, 0, 0, 0 }, // Orbinaut /*Jawz*/ { 0, 0, 3, 2, 2, 1, 0, 0, 0 }, // Jawz /*Mine*/ { 0, 0, 1, 2, 1, 0, 0, 0, 0 }, // Mine - /*Ballhog*/ { 0, 0, 1, 2, 1, 0, 0, 0, 0 }, // Ballhog + /*Ballhog*/ { 0, 0, 2, 2, 1, 0, 0, 0, 0 }, // Ballhog /*Self-Propelled Bomb*/ { 0, 0, 1, 1, 1, 2, 2, 3, 2 }, // Self-Propelled Bomb /*Grow*/ { 0, 0, 0, 0, 0, 1, 3, 6, 4 }, // Grow - /*Shrink*/ { 0, 0, 0, 0, 0, 0, 0, 1, 0 }, // Shrink + /*Shrink*/ { 0, 0, 0, 0, 0, 0, 0, 2, 0 }, // Shrink /*Thunder Shield*/ { 0, 1, 2, 0, 0, 0, 0, 0, 0 }, // Thunder Shield /*Hyudoro*/ { 0, 0, 0, 0, 1, 2, 1, 0, 0 }, // Hyudoro /*Pogo Spring*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Pogo Spring /*Kitchen Sink*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Kitchen Sink - /*Sneaker x3*/ { 0, 0, 0, 0, 3, 6, 5, 3, 0 }, // Sneaker x3 - /*Banana x3*/ { 0, 0, 1, 1, 0, 0, 0, 0, 0 }, // Banana x3 + /*Sneaker x3*/ { 0, 0, 0, 0, 3, 8, 5, 2, 0 }, // Sneaker x3 + /*Banana x3*/ { 0, 0, 2, 1, 0, 0, 0, 0, 0 }, // Banana x3 /*Banana x10*/ { 0, 0, 0, 0, 1, 0, 0, 0, 0 }, // Banana x10 - /*Orbinaut x3*/ { 0, 0, 0, 1, 1, 0, 0, 0, 0 }, // Orbinaut x3 - /*Orbinaut x4*/ { 0, 0, 0, 0, 0, 1, 1, 0, 0 }, // Orbinaut x4 - /*Jawz x2*/ { 0, 0, 0, 1, 1, 0, 0, 0, 0 } // Jawz x2 + /*Orbinaut x3*/ { 0, 0, 0, 1, 0, 0, 0, 0, 0 }, // Orbinaut x3 + /*Orbinaut x4*/ { 0, 0, 0, 0, 1, 0, 0, 0, 0 }, // Orbinaut x4 + /*Jawz x2*/ { 0, 0, 1, 1, 1, 0, 0, 0, 0 } // Jawz x2 }; static INT32 K_KartItemOddsBattle[NUMKARTRESULTS][6] = From c3afcc09cd419ccd06fbf9984c2738e715d943df Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sat, 8 Sep 2018 03:24:32 -0400 Subject: [PATCH 085/146] Critical inconsistency fix --- src/k_kart.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index da085225e..6a7efffc1 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3517,9 +3517,9 @@ static void K_KartDrift(player_t *player, boolean onground) player->kartstuff[k_drift] = 5; if (player->cmd.driftturn > 0) // Inward - driftadditive += (player->cmd.driftturn/800)/8; + driftadditive += abs(player->cmd.driftturn)/100; if (player->cmd.driftturn < 0) // Outward - driftadditive -= (player->cmd.driftturn/800)/8; + driftadditive -= abs(player->cmd.driftturn)/75; } else if (player->kartstuff[k_drift] <= -1) // Drifting to the right { @@ -3528,9 +3528,9 @@ static void K_KartDrift(player_t *player, boolean onground) player->kartstuff[k_drift] = -5; if (player->cmd.driftturn < 0) // Inward - driftadditive += (player->cmd.driftturn/800)/4; + driftadditive += abs(player->cmd.driftturn)/100; if (player->cmd.driftturn > 0) // Outward - driftadditive -= (player->cmd.driftturn/800)/4; + driftadditive -= abs(player->cmd.driftturn)/75; } // This spawns the drift sparks From 051324c25a2dc4e6c81a374183df143668a93083 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sat, 8 Sep 2018 04:04:10 -0400 Subject: [PATCH 086/146] Weight increases with speed Might be a tad weak right now, but we'll see if people want it stronger --- src/k_kart.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/k_kart.c b/src/k_kart.c index 2d6b0aeb5..ba2d03d9f 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -964,7 +964,11 @@ static fixed_t K_GetMobjWeight(mobj_t *mobj, mobj_t *against) if (against->player && !against->player->kartstuff[k_spinouttimer] && mobj->player->kartstuff[k_spinouttimer]) weight = 0; // Do not bump else + { weight = (mobj->player->kartweight)<player->speed > K_GetKartSpeed(mobj->player, false)) + weight += (mobj->player->speed - K_GetKartSpeed(mobj->player, false))/8; + } break; case MT_FALLINGROCK: if (against->player) From e7b53c3c09a725e2059558630d9c88330ab0a7f2 Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 8 Sep 2018 17:02:03 +0100 Subject: [PATCH 087/146] * User manual! * Some visual ordering fixes for the item menu, plus a #define-toggleable option for the bottom right slot to be traversable for ease-of-use purposes (even if it doesn't do anything). --- src/m_menu.c | 222 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 149 insertions(+), 73 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index f7fe1e84f..b0be82bfc 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -224,6 +224,7 @@ menu_t SR_MainDef, SR_UnlockChecklistDef; // Misc. Main Menu static void M_SinglePlayerMenu(INT32 choice); static void M_Options(INT32 choice); +static void M_Manual(INT32 choice); static void M_SelectableClearMenus(INT32 choice); static void M_Retry(INT32 choice); static void M_EndGame(INT32 choice); @@ -625,11 +626,13 @@ static menuitem_t MISC_ChangeLevelMenu[] = static menuitem_t MISC_HelpMenu[] = { - {IT_KEYHANDLER | IT_NOTHING, NULL, "HELPN01", M_HandleImageDef, 0}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "HELPN02", M_HandleImageDef, 0}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "HELPN03", M_HandleImageDef, 0}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "HELPM01", M_HandleImageDef, 0}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "HELPM02", M_HandleImageDef, 0}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL0", M_HandleImageDef, 0}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL1", M_HandleImageDef, 1}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL2", M_HandleImageDef, 1}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL3", M_HandleImageDef, 1}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL4", M_HandleImageDef, 1}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL5", M_HandleImageDef, 1}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL6", M_HandleImageDef, 0}, }; // -------------------------------- @@ -1057,8 +1060,9 @@ static menuitem_t OP_MainMenu[] = {IT_SUBMENU|IT_STRING, NULL, "Gameplay Options...", &OP_GameOptionsDef, 90}, {IT_SUBMENU|IT_STRING, NULL, "Server Options...", &OP_ServerOptionsDef, 100}, - {IT_CALL|IT_STRING, NULL, "Play Credits", M_Credits, 120}, - {IT_SUBMENU|IT_STRING, NULL, "Erase Data...", &OP_EraseDataDef, 130}, + {IT_CALL|IT_STRING, NULL, "User Manual", M_Manual, 120}, + {IT_CALL|IT_STRING, NULL, "Play Credits", M_Credits, 130}, + {IT_SUBMENU|IT_STRING, NULL, "Erase Data...", &OP_EraseDataDef, 140}, }; static menuitem_t OP_ControlsMenu[] = @@ -1519,6 +1523,8 @@ static menuitem_t OP_ServerOptionsMenu[] = {IT_STRING | IT_CVAR, NULL, "Karma Comeback", &cv_kartcomeback, 66}, };*/ +#define ITEMTOGGLEBOTTOMRIGHT + static menuitem_t OP_MonitorToggleMenu[] = { // Mostly handled by the drawing function. @@ -1531,10 +1537,10 @@ static menuitem_t OP_MonitorToggleMenu[] = {IT_KEYHANDLER | IT_NOTHING, NULL, "Bananas x3", M_HandleMonitorToggles, KRITEM_TRIPLEBANANA}, {IT_KEYHANDLER | IT_NOTHING, NULL, "Bananas x10", M_HandleMonitorToggles, KRITEM_TENFOLDBANANA}, {IT_KEYHANDLER | IT_NOTHING, NULL, "Eggman Monitors", M_HandleMonitorToggles, KITEM_EGGMAN}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Orbinauts", M_HandleMonitorToggles, KITEM_ORBINAUT}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Orbinauts", M_HandleMonitorToggles, KITEM_ORBINAUT}, {IT_KEYHANDLER | IT_NOTHING, NULL, "Orbinauts x3", M_HandleMonitorToggles, KRITEM_TRIPLEORBINAUT}, {IT_KEYHANDLER | IT_NOTHING, NULL, "Orbinauts x4", M_HandleMonitorToggles, KRITEM_QUADORBINAUT}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Mines", M_HandleMonitorToggles, KITEM_MINE}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Mines", M_HandleMonitorToggles, KITEM_MINE}, {IT_KEYHANDLER | IT_NOTHING, NULL, "Jawz", M_HandleMonitorToggles, KITEM_JAWZ}, {IT_KEYHANDLER | IT_NOTHING, NULL, "Jawz x2", M_HandleMonitorToggles, KRITEM_DUALJAWZ}, {IT_KEYHANDLER | IT_NOTHING, NULL, "Ballhogs", M_HandleMonitorToggles, KITEM_BALLHOG}, @@ -1545,7 +1551,10 @@ static menuitem_t OP_MonitorToggleMenu[] = {IT_KEYHANDLER | IT_NOTHING, NULL, "Thunder Shields", M_HandleMonitorToggles, KITEM_THUNDERSHIELD}, {IT_KEYHANDLER | IT_NOTHING, NULL, "Hyudoros", M_HandleMonitorToggles, KITEM_HYUDORO}, {IT_KEYHANDLER | IT_NOTHING, NULL, "Pogo Springs", M_HandleMonitorToggles, KITEM_POGOSPRING}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Kitchen Sinks", M_HandleMonitorToggles, KITEM_KITCHENSINK}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Kitchen Sinks", M_HandleMonitorToggles, KITEM_KITCHENSINK}, +#ifdef ITEMTOGGLEBOTTOMRIGHT + {IT_KEYHANDLER | IT_NOTHING, NULL, "---", M_HandleMonitorToggles, 255}, +#endif }; // ========================================================================== @@ -2478,7 +2487,7 @@ boolean M_Responder(event_t *ev) if (modeattacking) return true; M_StartControlPanel(); - currentMenu = &MISC_HelpDef; + M_Manual(INT32_MAX); itemOn = 0; return true; @@ -4166,6 +4175,9 @@ static void M_StopMessage(INT32 choice) // You can even put multiple images in one menu! static void M_DrawImageDef(void) { + // this is probably what the V_DrawFixedPatch screen-fill bullshit was for, right + //V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); -- never mind, screen fade + // Grr. Need to autodetect for pic_ts. pic_t *pictest = (pic_t *)W_CachePatchName(currentMenu->menuitems[itemOn].text,PU_CACHE); if (!pictest->zero) @@ -4179,41 +4191,49 @@ static void M_DrawImageDef(void) V_DrawSmallScaledPatch(0,0,0,patch); } - if (currentMenu->numitems > 1) - V_DrawString(0,192,V_TRANSLUCENT, va("PAGE %d of %hd", itemOn+1, currentMenu->numitems)); + if (currentMenu->menuitems[itemOn].alphaKey) + { + V_DrawString(2,BASEVIDHEIGHT-10, V_YELLOWMAP, va("%d", (itemOn<<1)-1)); // intentionally not highlightflags + V_DrawRightAlignedString(BASEVIDWIDTH-2,BASEVIDHEIGHT-10, V_YELLOWMAP, va("%d", itemOn<<1)); // ditto + } } // Handles the ImageDefs. Just a specialized function that // uses left and right movement. static void M_HandleImageDef(INT32 choice) { + boolean exitmenu = false; + switch (choice) { case KEY_RIGHTARROW: - if (currentMenu->numitems == 1) - break; - - S_StartSound(NULL, sfx_menu1); if (itemOn >= (INT16)(currentMenu->numitems-1)) - itemOn = 0; - else itemOn++; + break; + S_StartSound(NULL, sfx_menu1); + itemOn++; break; case KEY_LEFTARROW: - if (currentMenu->numitems == 1) + if (!itemOn) break; S_StartSound(NULL, sfx_menu1); - if (!itemOn) - itemOn = currentMenu->numitems - 1; - else itemOn--; + itemOn--; break; case KEY_ESCAPE: case KEY_ENTER: - M_ClearMenus(true); + exitmenu = true; break; } + + if (exitmenu) + { + if (currentMenu->prevMenu) + M_SetupNextMenu(currentMenu->prevMenu); + else + M_ClearMenus(true); + } } // ====================== @@ -4329,6 +4349,14 @@ static void M_Options(INT32 choice) M_SetupNextMenu(&OP_MainDef); } +static void M_Manual(INT32 choice) +{ + (void)choice; + + MISC_HelpDef.prevMenu = (choice == INT32_MAX ? NULL : currentMenu); + M_SetupNextMenu(&MISC_HelpDef); +} + static void M_RetryResponse(INT32 ch) { if (ch != 'y' && ch != KEY_ENTER) @@ -8476,8 +8504,9 @@ static void M_DrawMonitorToggles(void) //const INT32 row = itemOn%height; INT32 leftdraw, rightdraw, totaldraw; INT32 x = currentMenu->x, y = currentMenu->y+(spacing/4); + INT32 onx = 0, ony = 0; consvar_t *cv; - INT32 i; + INT32 i, translucent, drawnum; M_DrawMenuTitle(); @@ -8505,25 +8534,30 @@ static void M_DrawMonitorToggles(void) for (j = 0; j < height; j++) { const INT32 thisitem = (i*height)+j; - const boolean selected = (thisitem == itemOn); INT32 drawnum = 0; - INT32 translucent = 0; if (thisitem >= currentMenu->numitems) continue; + if (thisitem == itemOn) + { + onx = x; + ony = y; + y += spacing; + continue; + } + +#ifdef ITEMTOGGLEBOTTOMRIGHT + if (currentMenu->menuitems[thisitem].alphaKey == 255) + { + V_DrawScaledPatch(x, y, V_TRANSLUCENT, W_CachePatchName("K_ISBG", PU_CACHE)); + continue; + } +#endif if (currentMenu->menuitems[thisitem].alphaKey == 0) { - if (selected) - { - V_DrawScaledPatch(x-1, y-2, 0, W_CachePatchName("K_ITBG", PU_CACHE)); - V_DrawScaledPatch(x-1, y-2, 0, W_CachePatchName("K_ITTOGL", PU_CACHE)); - } - else - { - V_DrawScaledPatch(x, y, 0, W_CachePatchName("K_ISBG", PU_CACHE)); - V_DrawScaledPatch(x, y, 0, W_CachePatchName("K_ISTOGL", PU_CACHE)); - } + V_DrawScaledPatch(x, y, 0, W_CachePatchName("K_ISBG", PU_CACHE)); + V_DrawScaledPatch(x, y, 0, W_CachePatchName("K_ISTOGL", PU_CACHE)); continue; } @@ -8540,53 +8574,32 @@ static void M_DrawMonitorToggles(void) drawnum = 3; break; case KRITEM_TRIPLEORBINAUT: - if (!selected) - drawnum = 3; + drawnum = 3; break; case KRITEM_QUADORBINAUT: - if (!selected) - drawnum = 4; + drawnum = 4; break; case KRITEM_TENFOLDBANANA: drawnum = 10; break; default: + drawnum = 0; break; } - if (selected) - { - if (cv->value) - V_DrawScaledPatch(x-1, y-2, 0, W_CachePatchName("K_ITBG", PU_CACHE)); - else - V_DrawScaledPatch(x-1, y-2, 0, W_CachePatchName("K_ITBGD", PU_CACHE)); + if (cv->value) + V_DrawScaledPatch(x, y, 0, W_CachePatchName("K_ISBG", PU_CACHE)); + else + V_DrawScaledPatch(x, y, 0, W_CachePatchName("K_ISBGD", PU_CACHE)); - if (drawnum != 0) - { - V_DrawScaledPatch(x-1, y-2, 0, W_CachePatchName("K_ITMUL", PU_CACHE)); - V_DrawScaledPatch(x-1, y-2, translucent, W_CachePatchName(K_GetItemPatch(currentMenu->menuitems[thisitem].alphaKey, !selected), PU_CACHE)); - V_DrawScaledPatch(x+27, y+39, translucent, W_CachePatchName("K_ITX", PU_CACHE)); - V_DrawKartString(x+37, y+34, translucent, va("%d", drawnum)); - } - else - V_DrawScaledPatch(x-1, y-2, translucent, W_CachePatchName(K_GetItemPatch(currentMenu->menuitems[thisitem].alphaKey, !selected), PU_CACHE)); + if (drawnum != 0) + { + V_DrawScaledPatch(x, y, 0, W_CachePatchName("K_ISMUL", PU_CACHE)); + V_DrawScaledPatch(x, y, translucent, W_CachePatchName(K_GetItemPatch(currentMenu->menuitems[thisitem].alphaKey, true), PU_CACHE)); + V_DrawString(x+24, y+31, V_ALLOWLOWERCASE|translucent, va("x%d", drawnum)); } else - { - if (cv->value) - V_DrawScaledPatch(x, y, 0, W_CachePatchName("K_ISBG", PU_CACHE)); - else - V_DrawScaledPatch(x, y, 0, W_CachePatchName("K_ISBGD", PU_CACHE)); - - if (drawnum != 0) - { - V_DrawScaledPatch(x, y, 0, W_CachePatchName("K_ISMUL", PU_CACHE)); - V_DrawScaledPatch(x, y, translucent, W_CachePatchName(K_GetItemPatch(currentMenu->menuitems[thisitem].alphaKey, !selected), PU_CACHE)); - V_DrawString(x+24, y+31, V_ALLOWLOWERCASE|translucent, va("x%d", drawnum)); - } - else - V_DrawScaledPatch(x, y, translucent, W_CachePatchName(K_GetItemPatch(currentMenu->menuitems[thisitem].alphaKey, !selected), PU_CACHE)); - } + V_DrawScaledPatch(x, y, translucent, W_CachePatchName(K_GetItemPatch(currentMenu->menuitems[thisitem].alphaKey, true), PU_CACHE)); y += spacing; } @@ -8595,6 +8608,56 @@ static void M_DrawMonitorToggles(void) y = currentMenu->y+(spacing/4); } + { +#ifdef ITEMTOGGLEBOTTOMRIGHT + if (currentMenu->menuitems[itemOn].alphaKey == 255) + V_DrawScaledPatch(onx-1, ony-2, V_TRANSLUCENT, W_CachePatchName("K_ITBG", PU_CACHE)); + else +#endif + if (currentMenu->menuitems[itemOn].alphaKey == 0) + { + V_DrawScaledPatch(onx-1, ony-2, 0, W_CachePatchName("K_ITBG", PU_CACHE)); + V_DrawScaledPatch(onx-1, ony-2, 0, W_CachePatchName("K_ITTOGL", PU_CACHE)); + } + else + { + cv = kartitemcvs[currentMenu->menuitems[itemOn].alphaKey-1]; + translucent = (cv->value ? 0 : V_TRANSLUCENT); + + switch (currentMenu->menuitems[itemOn].alphaKey) + { + case KRITEM_DUALJAWZ: + drawnum = 2; + break; + case KRITEM_TRIPLESNEAKER: + case KRITEM_TRIPLEBANANA: + drawnum = 3; + break; + case KRITEM_TENFOLDBANANA: + drawnum = 10; + break; + default: + drawnum = 0; + break; + } + + if (cv->value) + V_DrawScaledPatch(onx-1, ony-2, 0, W_CachePatchName("K_ITBG", PU_CACHE)); + else + V_DrawScaledPatch(onx-1, ony-2, 0, W_CachePatchName("K_ITBGD", PU_CACHE)); + + if (drawnum != 0) + { + V_DrawScaledPatch(onx-1, ony-2, 0, W_CachePatchName("K_ITMUL", PU_CACHE)); + V_DrawScaledPatch(onx-1, ony-2, translucent, W_CachePatchName(K_GetItemPatch(currentMenu->menuitems[itemOn].alphaKey, false), PU_CACHE)); + V_DrawScaledPatch(onx+27, ony+39, translucent, W_CachePatchName("K_ITX", PU_CACHE)); + V_DrawKartString(onx+37, ony+34, translucent, va("%d", drawnum)); + } + else + V_DrawScaledPatch(onx-1, ony-2, translucent, W_CachePatchName(K_GetItemPatch(currentMenu->menuitems[itemOn].alphaKey, false), PU_CACHE)); + } + } + V_DrawCenteredString(BASEVIDWIDTH/2, currentMenu->y, highlightflags, va("* %s *", currentMenu->menuitems[itemOn].text)); } @@ -8604,6 +8667,7 @@ static void M_HandleMonitorToggles(INT32 choice) INT32 column = itemOn/height, row = itemOn%height; INT16 next; UINT8 i; + boolean exitmenu = false; switch (choice) { @@ -8652,6 +8716,11 @@ static void M_HandleMonitorToggles(INT32 choice) break; case KEY_ENTER: +#ifdef ITEMTOGGLEBOTTOMRIGHT + if (currentMenu->menuitems[itemOn].alphaKey == 255) + S_StartSound(NULL, sfx_lose); + else +#endif if (currentMenu->menuitems[itemOn].alphaKey == 0) { INT32 v = cv_sneaker.value; @@ -8670,9 +8739,17 @@ static void M_HandleMonitorToggles(INT32 choice) break; case KEY_ESCAPE: - M_ClearMenus(true); + exitmenu = true; break; } + + if (exitmenu) + { + if (currentMenu->prevMenu) + M_SetupNextMenu(currentMenu->prevMenu); + else + M_ClearMenus(true); + } } // ========= @@ -8790,7 +8867,6 @@ static void M_HandleFogColor(INT32 choice) break; case KEY_ESCAPE: - S_StartSound(NULL, sfx_menu1); exitmenu = true; break; From d0fdd09be574f8f367d499e96fb6e810befd6361 Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 8 Sep 2018 17:50:53 +0100 Subject: [PATCH 088/146] Bugfix a Jawz crash Jeck got a few days ago. Not menu-based, but I guess this branch is misc PLUS menu stuff, not just menu stuff based on sal-misc. --- src/k_kart.c | 25 ++++++++++++++++--------- src/p_enemy.c | 2 +- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index ba2d03d9f..496be1b5a 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2170,16 +2170,23 @@ static mobj_t *K_SpawnKartMissile(mobj_t *source, mobjtype_t type, angle_t angle th->momx = FixedMul(finalspeed, FINECOSINE(an>>ANGLETOFINESHIFT)); th->momy = FixedMul(finalspeed, FINESINE(an>>ANGLETOFINESHIFT)); - if (type == MT_ORBINAUT) + switch (type) { - if (source && source->player) - th->color = source->player->skincolor; - else - th->color = SKINCOLOR_CLOUDY; - } - else if (type == MT_JAWZ || type == MT_JAWZ_DUD) - { - S_StartSound(th, th->info->activesound); + case MT_ORBINAUT: + if (source && source->player) + th->color = source->player->skincolor; + else + th->color = SKINCOLOR_CLOUDY; + break; + case MT_JAWZ: + if (source && source->player) + th->cvmem = source->player->skincolor; + else + th->cvmem = SKINCOLOR_RED; + //fallthrough + case MT_JAWZ_DUD: + S_StartSound(th, th->info->activesound); + break; } x = x + P_ReturnThrustX(source, an, source->radius + th->radius); diff --git a/src/p_enemy.c b/src/p_enemy.c index 830116745..a6c124db2 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -8182,7 +8182,7 @@ void A_JawzChase(mobj_t *actor) ret = P_SpawnMobj(actor->tracer->x, actor->tracer->y, actor->tracer->z, MT_PLAYERRETICULE); P_SetTarget(&ret->target, actor->tracer); ret->frame |= ((leveltime % 10) / 2) + 5; - ret->color = actor->target->player->skincolor; + ret->color = actor->cvmem; P_Thrust(actor, R_PointToAngle2(actor->x, actor->y, actor->tracer->x, actor->tracer->y), actor->info->speed); return; From ca5d5079d527b96820c6d51923de445b71fefc47 Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 8 Sep 2018 17:53:41 +0100 Subject: [PATCH 089/146] Forgot a default case. --- src/k_kart.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/k_kart.c b/src/k_kart.c index 496be1b5a..ed56d9526 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2187,6 +2187,8 @@ static mobj_t *K_SpawnKartMissile(mobj_t *source, mobjtype_t type, angle_t angle case MT_JAWZ_DUD: S_StartSound(th, th->info->activesound); break; + default: + break; } x = x + P_ReturnThrustX(source, an, source->radius + th->radius); From 702e4dda11f1ae6edb4b48602b7feb817f6101c6 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sat, 8 Sep 2018 16:32:39 -0400 Subject: [PATCH 090/146] weaker --- src/k_kart.c | 4 ++-- src/p_user.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index ba2d03d9f..ab13c607b 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3273,13 +3273,13 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->kartstuff[k_boostcam] < player->kartstuff[k_destboostcam] && player->kartstuff[k_destboostcam] != 0) { - player->kartstuff[k_boostcam] += FRACUNIT/(TICRATE/4); + player->kartstuff[k_boostcam] += FRACUNIT/5; if (player->kartstuff[k_boostcam] >= player->kartstuff[k_destboostcam]) player->kartstuff[k_destboostcam] = 0; } else { - player->kartstuff[k_boostcam] -= FRACUNIT/TICRATE; + player->kartstuff[k_boostcam] -= FRACUNIT/20; if (player->kartstuff[k_boostcam] < player->kartstuff[k_destboostcam]) player->kartstuff[k_boostcam] = player->kartstuff[k_destboostcam] = 0; } diff --git a/src/p_user.c b/src/p_user.c index fb327e3a2..ab90fa83b 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8376,7 +8376,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if (player->kartstuff[k_boostcam]) { - dist -= FixedMul(3*dist/4, player->kartstuff[k_boostcam]); + dist -= FixedMul(19*dist/32, player->kartstuff[k_boostcam]); height -= FixedMul(height, player->kartstuff[k_boostcam]); } From cefa21059c119eb57c23c720fb61103bc71b8e9a Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sat, 8 Sep 2018 18:45:57 -0400 Subject: [PATCH 091/146] Camera adjustments - reverted boostcam timing, different max dist - zooms out based on camera momz - drift panning is twice as slow --- src/k_kart.c | 4 ++-- src/p_user.c | 8 +++----- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index ab13c607b..ba2d03d9f 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3273,13 +3273,13 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->kartstuff[k_boostcam] < player->kartstuff[k_destboostcam] && player->kartstuff[k_destboostcam] != 0) { - player->kartstuff[k_boostcam] += FRACUNIT/5; + player->kartstuff[k_boostcam] += FRACUNIT/(TICRATE/4); if (player->kartstuff[k_boostcam] >= player->kartstuff[k_destboostcam]) player->kartstuff[k_destboostcam] = 0; } else { - player->kartstuff[k_boostcam] -= FRACUNIT/20; + player->kartstuff[k_boostcam] -= FRACUNIT/TICRATE; if (player->kartstuff[k_boostcam] < player->kartstuff[k_destboostcam]) player->kartstuff[k_boostcam] = player->kartstuff[k_destboostcam] = 0; } diff --git a/src/p_user.c b/src/p_user.c index ab90fa83b..8c05c629a 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8373,16 +8373,14 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if (player->speed > K_GetKartSpeed(player, false)) dist += 4*(player->speed - K_GetKartSpeed(player, false)); + dist += abs(thiscam->momz)/4; if (player->kartstuff[k_boostcam]) { - dist -= FixedMul(19*dist/32, player->kartstuff[k_boostcam]); + dist -= FixedMul(11*dist/16, player->kartstuff[k_boostcam]); height -= FixedMul(height, player->kartstuff[k_boostcam]); } - if (player->climbing || player->playerstate == PST_DEAD || (player->pflags & (PF_MACESPIN|PF_ITEMHANG|PF_ROPEHANG))) - dist <<= 1; - // in splitscreen modes, mess with the camera distances to make it feel proportional to how it feels normally if (splitscreen == 1) // widescreen splits should get x1.5 distance { @@ -8397,7 +8395,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if (player->kartstuff[k_drift] != 0) { fixed_t panmax = (camdist/5); - pan = min(player->kartstuff[k_driftcharge], K_GetKartDriftSparkValue(player)) * panmax / K_GetKartDriftSparkValue(player); + pan = min(player->kartstuff[k_driftcharge]/2, K_GetKartDriftSparkValue(player)) * panmax / K_GetKartDriftSparkValue(player); if (pan > panmax) pan = panmax; if (player->kartstuff[k_drift] < 0) From 216cc9a5b6c465e02ba943e2162d888d80720d39 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sat, 8 Sep 2018 19:50:31 -0400 Subject: [PATCH 092/146] Revert "Rebalanced odds table again" This reverts commit b7e0baad98cb75227c03627efe84af0a8f95e348. --- src/k_kart.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index ba2d03d9f..c64e4acc8 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -469,28 +469,28 @@ boolean K_IsPlayerWanted(player_t *player) static INT32 K_KartItemOddsRace[NUMKARTRESULTS][9] = { //P-Odds 0 1 2 3 4 5 6 7 8 - /*Sneaker*/ {20, 0, 0, 3, 6, 5, 0, 0, 0 }, // Sneaker - /*Rocket Sneaker*/ { 0, 0, 0, 0, 0, 2, 6, 5, 0 }, // Rocket Sneaker + /*Sneaker*/ {20, 0, 0, 3, 6, 6, 0, 0, 0 }, // Sneaker + /*Rocket Sneaker*/ { 0, 0, 0, 0, 0, 2, 5, 4, 0 }, // Rocket Sneaker /*Invincibility*/ { 0, 0, 0, 0, 0, 1, 5, 6,16 }, // Invincibility - /*Banana*/ { 0, 9, 3, 2, 1, 0, 0, 0, 0 }, // Banana + /*Banana*/ { 0, 9, 4, 2, 1, 0, 0, 0, 0 }, // Banana /*Eggman Monitor*/ { 0, 4, 3, 2, 0, 0, 0, 0, 0 }, // Eggman Monitor - /*Orbinaut*/ { 0, 6, 3, 4, 2, 0, 0, 0, 0 }, // Orbinaut + /*Orbinaut*/ { 0, 6, 5, 4, 2, 0, 0, 0, 0 }, // Orbinaut /*Jawz*/ { 0, 0, 3, 2, 2, 1, 0, 0, 0 }, // Jawz /*Mine*/ { 0, 0, 1, 2, 1, 0, 0, 0, 0 }, // Mine - /*Ballhog*/ { 0, 0, 2, 2, 1, 0, 0, 0, 0 }, // Ballhog + /*Ballhog*/ { 0, 0, 1, 2, 1, 0, 0, 0, 0 }, // Ballhog /*Self-Propelled Bomb*/ { 0, 0, 1, 1, 1, 2, 2, 3, 2 }, // Self-Propelled Bomb /*Grow*/ { 0, 0, 0, 0, 0, 1, 3, 6, 4 }, // Grow - /*Shrink*/ { 0, 0, 0, 0, 0, 0, 0, 2, 0 }, // Shrink + /*Shrink*/ { 0, 0, 0, 0, 0, 0, 0, 1, 0 }, // Shrink /*Thunder Shield*/ { 0, 1, 2, 0, 0, 0, 0, 0, 0 }, // Thunder Shield /*Hyudoro*/ { 0, 0, 0, 0, 1, 2, 1, 0, 0 }, // Hyudoro /*Pogo Spring*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Pogo Spring /*Kitchen Sink*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Kitchen Sink - /*Sneaker x3*/ { 0, 0, 0, 0, 3, 8, 5, 2, 0 }, // Sneaker x3 - /*Banana x3*/ { 0, 0, 2, 1, 0, 0, 0, 0, 0 }, // Banana x3 + /*Sneaker x3*/ { 0, 0, 0, 0, 3, 6, 5, 3, 0 }, // Sneaker x3 + /*Banana x3*/ { 0, 0, 1, 1, 0, 0, 0, 0, 0 }, // Banana x3 /*Banana x10*/ { 0, 0, 0, 0, 1, 0, 0, 0, 0 }, // Banana x10 - /*Orbinaut x3*/ { 0, 0, 0, 1, 0, 0, 0, 0, 0 }, // Orbinaut x3 - /*Orbinaut x4*/ { 0, 0, 0, 0, 1, 0, 0, 0, 0 }, // Orbinaut x4 - /*Jawz x2*/ { 0, 0, 1, 1, 1, 0, 0, 0, 0 } // Jawz x2 + /*Orbinaut x3*/ { 0, 0, 0, 1, 1, 0, 0, 0, 0 }, // Orbinaut x3 + /*Orbinaut x4*/ { 0, 0, 0, 0, 0, 1, 1, 0, 0 }, // Orbinaut x4 + /*Jawz x2*/ { 0, 0, 0, 1, 1, 0, 0, 0, 0 } // Jawz x2 }; static INT32 K_KartItemOddsBattle[NUMKARTRESULTS][6] = From 605224ff085245c2686c54e166811e06b927175b Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 9 Sep 2018 15:44:37 +0100 Subject: [PATCH 093/146] Disable the options you MEANT to disable. --- src/m_menu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index b0be82bfc..f527dd0a4 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4342,8 +4342,8 @@ static void M_Options(INT32 choice) OP_MainMenu[5].status = OP_MainMenu[6].status = (Playing() && !(server || IsPlayerAdmin(consoleplayer))) ? (IT_GRAYEDOUT) : (IT_STRING|IT_SUBMENU); // if the player is playing _at all_, disable the erase data & credits options - OP_MainMenu[7].status = (Playing()) ? (IT_GRAYEDOUT) : (IT_STRING|IT_CALL); - OP_MainMenu[8].status = (Playing()) ? (IT_GRAYEDOUT) : (IT_STRING|IT_SUBMENU); + OP_MainMenu[8].status = (Playing()) ? (IT_GRAYEDOUT) : (IT_STRING|IT_CALL); + OP_MainMenu[9].status = (Playing()) ? (IT_GRAYEDOUT) : (IT_STRING|IT_SUBMENU); OP_MainDef.prevMenu = currentMenu; M_SetupNextMenu(&OP_MainDef); From 7383bb28c70bf947fc6765f31fc846a5eeca835f Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sun, 9 Sep 2018 18:04:35 -0400 Subject: [PATCH 094/146] Revert pan speed Old one was more exciting, and gave that feeling of "you're scraping against the walls" when you try to corner really hard --- src/p_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_user.c b/src/p_user.c index 8c05c629a..7c7253f6f 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8395,7 +8395,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if (player->kartstuff[k_drift] != 0) { fixed_t panmax = (camdist/5); - pan = min(player->kartstuff[k_driftcharge]/2, K_GetKartDriftSparkValue(player)) * panmax / K_GetKartDriftSparkValue(player); + pan = min(player->kartstuff[k_driftcharge], K_GetKartDriftSparkValue(player)) * panmax / K_GetKartDriftSparkValue(player); if (pan > panmax) pan = panmax; if (player->kartstuff[k_drift] < 0) From 77131a30ec0c14e8473eed01f9637fbd641bc3d7 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sun, 9 Sep 2018 18:10:11 -0400 Subject: [PATCH 095/146] Comment ou remaining traces of cv_karthud We've poured so much effort into our own HUD that it doesn't make much sense to have the option to replace it with another game's at this point --- src/command.c | 6 +++--- src/command.h | 2 +- src/d_netcmd.c | 2 +- src/d_netcmd.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/command.c b/src/command.c index 305a5eeeb..a159ebcd7 100644 --- a/src/command.c +++ b/src/command.c @@ -63,9 +63,9 @@ CV_PossibleValue_t CV_Unsigned[] = {{0, "MIN"}, {999999999, "MAX"}, {0, NULL}}; CV_PossibleValue_t CV_Natural[] = {{1, "MIN"}, {999999999, "MAX"}, {0, NULL}}; //SRB2kart -CV_PossibleValue_t karthud_cons_t[] = { - {0, "Off"}, {1, "Default"}, {2, "SNES"}, {3, "MK64"}, - {0, NULL}}; +/*CV_PossibleValue_t karthud_cons_t[] = { + {0, "Off"}, {1, "Default"}, {2, "SMK"}, {3, "MK64"}, + {0, NULL}};*/ CV_PossibleValue_t kartspeed_cons_t[] = { {0, "Easy"}, {1, "Normal"}, {2, "Hard"}, {0, NULL}}; diff --git a/src/command.h b/src/command.h index 513883d4e..0c2ef9120 100644 --- a/src/command.h +++ b/src/command.h @@ -127,7 +127,7 @@ extern CV_PossibleValue_t CV_Unsigned[]; extern CV_PossibleValue_t CV_Natural[]; // SRB2kart -extern CV_PossibleValue_t karthud_cons_t[]; +//extern CV_PossibleValue_t karthud_cons_t[]; extern CV_PossibleValue_t kartspeed_cons_t[]; // register a variable for use at the console diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 8e046d928..fa2d00324 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -344,7 +344,7 @@ consvar_t cv_tripleorbinaut = {"tripleorbinaut", "On", CV_NETVAR|CV_CHEAT, C consvar_t cv_quadorbinaut = {"quadorbinaut", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_dualjawz = {"dualjawz", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_karthud = {"karthud", "Default", CV_SAVE|CV_CALL, karthud_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +//consvar_t cv_karthud = {"karthud", "Default", CV_SAVE|CV_CALL, karthud_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; static CV_PossibleValue_t kartminimap_cons_t[] = {{0, "MIN"}, {10, "MAX"}, {0, NULL}}; consvar_t cv_kartminimap = {"kartminimap", "4", CV_SAVE, kartminimap_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_kartcheck = {"kartcheck", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; diff --git a/src/d_netcmd.h b/src/d_netcmd.h index 3f118944e..66c712c56 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -117,7 +117,7 @@ extern consvar_t cv_thundershield, cv_hyudoro, cv_pogospring, cv_kitchensink; extern consvar_t cv_triplesneaker, cv_triplebanana, cv_decabanana; extern consvar_t cv_tripleorbinaut, cv_quadorbinaut, cv_dualjawz; -extern consvar_t cv_karthud; +//extern consvar_t cv_karthud; extern consvar_t cv_kartminimap; extern consvar_t cv_kartcheck; extern consvar_t cv_kartinvinsfx; From c8f802370b0ef112dc3641ffa0269343c51a8575 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sun, 9 Sep 2018 18:24:09 -0400 Subject: [PATCH 096/146] // we're fucking sick of this Why hasn't SRB2 already done this themselves YEARS ago... --- src/w_wad.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/w_wad.c b/src/w_wad.c index 3a8285593..9df2065fa 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -769,6 +769,24 @@ static size_t W_RawReadLumpHeader(UINT16 wad, UINT16 lump, void *dest, size_t si fseek(handle, (long)(l->position + offset), SEEK_SET); bytesread = fread(dest, 1, size, handle); +#if 1 // we're fucking sick of this + if (bytesread < 67) // http://garethrees.org/2007/11/14/pngcrush/ + return bytesread; + +#define sigcheck ((UINT8 *)dest) + if (sigcheck[0] == 0x89 + && sigcheck[1] == 0x50 + && sigcheck[2] == 0x4e + && sigcheck[3] == 0x47 + && sigcheck[4] == 0x0d + && sigcheck[5] == 0x0a + && sigcheck[6] == 0x1a + && sigcheck[7] == 0x0a) + I_Error("W_Wad: Tried to cache a .PNG - have you tried converting to Doom or Flat (raw) image formats?"); +#undef sigcheck + +#endif + return bytesread; } From 08e101e8f8b6d9bc0f78bdef1dcd3e35f1db063d Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sun, 9 Sep 2018 20:57:54 -0400 Subject: [PATCH 097/146] New gamepad defaults Based on input recieved from Jeck --- src/g_input.c | 53 ++++++++++++++++++--------------------------------- 1 file changed, 19 insertions(+), 34 deletions(-) diff --git a/src/g_input.c b/src/g_input.c index 2822cc294..5b47ccf0d 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -29,7 +29,7 @@ consvar_t cv_mousesens = {"mousesens", "35", CV_SAVE, mousesens_cons_t, NULL, 0, consvar_t cv_mousesens2 = {"mousesens2", "35", CV_SAVE, mousesens_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_mouseysens = {"mouseysens", "35", CV_SAVE, mousesens_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_mouseysens2 = {"mouseysens2", "35", CV_SAVE, mousesens_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_controlperkey = {"controlperkey", "One", CV_SAVE, onecontrolperkey_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_controlperkey = {"controlperkey", "Several", CV_SAVE, onecontrolperkey_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; INT32 mousex, mousey; INT32 mlooky; // like mousey but with a custom sensitivity for mlook @@ -1283,68 +1283,53 @@ void G_Controldefault(void) gamecontrol[gc_fire ][0] = KEY_SPACE; gamecontrol[gc_lookback ][0] = KEY_LSHIFT; - gamecontrol[gc_aimforward ][1] = KEY_HAT1+0; - gamecontrol[gc_aimbackward][1] = KEY_HAT1+1; - gamecontrol[gc_turnleft ][1] = KEY_HAT1+2; - gamecontrol[gc_turnright ][1] = KEY_HAT1+3; gamecontrol[gc_accelerate ][1] = KEY_JOY1+0; // A - gamecontrol[gc_drift ][1] = KEY_JOY1+1; // X + gamecontrol[gc_lookback ][1] = KEY_JOY1+1; // X gamecontrol[gc_brake ][1] = KEY_JOY1+2; // B - gamecontrol[gc_fire ][1] = KEY_JOY1+4; // LB - gamecontrol[gc_lookback ][1] = KEY_JOY1+5; // RB + gamecontrol[gc_fire ][1] = KEY_JOY1+4; // LB + gamecontrol[gc_drift ][1] = KEY_JOY1+5; // RB // Extra controls gamecontrol[gc_pause ][0] = KEY_PAUSE; gamecontrol[gc_console ][0] = KEY_CONSOLE; gamecontrol[gc_talkkey ][0] = 't'; - gamecontrol[gc_teamkey ][0] = 'y'; + //gamecontrol[gc_teamkey ][0] = 'y'; gamecontrol[gc_scores ][0] = KEY_TAB; gamecontrol[gc_spectate ][0] = '\''; - - gamecontrol[gc_scores ][1] = KEY_JOY1+6; // Back - gamecontrol[gc_spectate ][1] = KEY_JOY1+7; // Start (This is sort of like MP's pause...?) - gamecontrol[gc_lookup ][0] = KEY_PGUP; gamecontrol[gc_lookdown ][0] = KEY_PGDN; gamecontrol[gc_centerview ][0] = KEY_END; gamecontrol[gc_camreset ][0] = KEY_HOME; gamecontrol[gc_camtoggle ][0] = KEY_BACKSPACE; + //gamecontrol[gc_viewpoint ][1] = KEY_JOY1+3; // Y + gamecontrol[gc_pause ][1] = KEY_JOY1+6; // Back + //gamecontrol[gc_menu ][1] = KEY_JOY1+7; // Start + gamecontrol[gc_camtoggle ][1] = KEY_HAT1+0; // D-Pad Up + //gamecontrol[gc_screenshot ][1] = KEY_HAT1+1; // D-Pad Down + gamecontrol[gc_talkkey ][1] = KEY_HAT1+2; // D-Pad Left + gamecontrol[gc_scores ][1] = KEY_HAT1+3; // D-Pad Right + // Player 2 controls - gamecontrolbis[gc_aimforward ][0] = KEY_2HAT1+0; - gamecontrolbis[gc_aimbackward][0] = KEY_2HAT1+1; - gamecontrolbis[gc_turnleft ][0] = KEY_2HAT1+2; - gamecontrolbis[gc_turnright ][0] = KEY_2HAT1+3; gamecontrolbis[gc_accelerate ][0] = KEY_2JOY1+0; // A - gamecontrolbis[gc_drift ][0] = KEY_2JOY1+1; // X + gamecontrolbis[gc_lookback ][0] = KEY_2JOY1+1; // X gamecontrolbis[gc_brake ][0] = KEY_2JOY1+2; // B gamecontrolbis[gc_fire ][0] = KEY_2JOY1+4; // LB - gamecontrolbis[gc_lookback ][0] = KEY_2JOY1+5; // RB - gamecontrolbis[gc_spectate ][0] = KEY_2JOY1+7; // Start + gamecontrolbis[gc_drift ][0] = KEY_2JOY1+5; // RB // Player 3 controls - gamecontrol3[gc_aimforward ][0] = KEY_3HAT1+0; - gamecontrol3[gc_aimbackward][0] = KEY_3HAT1+1; - gamecontrol3[gc_turnleft ][0] = KEY_3HAT1+2; - gamecontrol3[gc_turnright ][0] = KEY_3HAT1+3; gamecontrol3[gc_accelerate ][0] = KEY_3JOY1+0; // A - gamecontrol3[gc_drift ][0] = KEY_3JOY1+1; // X + gamecontrol3[gc_lookback ][0] = KEY_3JOY1+1; // X gamecontrol3[gc_brake ][0] = KEY_3JOY1+2; // B gamecontrol3[gc_fire ][0] = KEY_3JOY1+4; // LB - gamecontrol3[gc_lookback ][0] = KEY_3JOY1+5; // RB - gamecontrol3[gc_spectate ][0] = KEY_3JOY1+7; // Start + gamecontrol3[gc_drift ][0] = KEY_3JOY1+5; // RB // Player 4 controls - gamecontrol4[gc_aimforward ][0] = KEY_4HAT1+0; - gamecontrol4[gc_aimbackward][0] = KEY_4HAT1+1; - gamecontrol4[gc_turnleft ][0] = KEY_4HAT1+2; - gamecontrol4[gc_turnright ][0] = KEY_4HAT1+3; gamecontrol4[gc_accelerate ][0] = KEY_4JOY1+0; // A - gamecontrol4[gc_drift ][0] = KEY_4JOY1+1; // X + gamecontrol4[gc_lookback ][0] = KEY_4JOY1+1; // X gamecontrol4[gc_brake ][0] = KEY_4JOY1+2; // B gamecontrol4[gc_fire ][0] = KEY_4JOY1+4; // LB - gamecontrol4[gc_lookback ][0] = KEY_4JOY1+5; // RB - gamecontrol4[gc_spectate ][0] = KEY_4JOY1+7; // Start + gamecontrol4[gc_drift ][0] = KEY_4JOY1+5; // RB } //#endif From 715711cc7ba7b6dc6c422824c31fc96a392a9239 Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Sun, 9 Sep 2018 20:50:33 -0500 Subject: [PATCH 098/146] Change ESC menu override string to "Open/Close Menu (ESC)", adjust menu accordingly --- src/m_menu.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index cea5996dc..a9de402a5 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1090,12 +1090,13 @@ static menuitem_t OP_MoveControlsMenu[] = {IT_CONTROL, NULL, "Talk key", M_ChangeControl, gc_talkkey }, //{IT_CONTROL, NULL, "Team-Talk key", M_ChangeControl, gc_teamkey }, {IT_CONTROL, NULL, "Rankings/Scores", M_ChangeControl, gc_scores }, + {IT_CONTROL, NULL, "Open/Close Menu (ESC)", M_ChangeControl, gc_systemmenu}, {IT_CONTROL, NULL, "Pause", M_ChangeControl, gc_pause }, {IT_CONTROL, NULL, "Console", M_ChangeControl, gc_console }, - {IT_SUBMENU | IT_STRING, NULL, "Gamepad Options...", &OP_Joystick1Def, 112}, - {IT_SUBMENU | IT_STRING, NULL, "Spectator Controls...", &OP_SpectateControlsDef, 120}, - {IT_SUBMENU | IT_STRING, NULL, "Custom Lua Actions...", &OP_CustomControlsDef, 128}, + {IT_SUBMENU | IT_STRING, NULL, "Gamepad Options...", &OP_Joystick1Def, 120}, + {IT_SUBMENU | IT_STRING, NULL, "Spectator Controls...", &OP_SpectateControlsDef, 128}, + {IT_SUBMENU | IT_STRING, NULL, "Custom Lua Actions...", &OP_CustomControlsDef, 136}, }; static menuitem_t OP_SpectateControlsMenu[] = @@ -1146,8 +1147,6 @@ static menuitem_t OP_MiscControlsMenu[] = {IT_CALL | IT_STRING2, NULL, "Custom Action 2", M_ChangeControl, gc_custom2 }, {IT_CALL | IT_STRING2, NULL, "Custom Action 3", M_ChangeControl, gc_custom3 }, - {IT_CALL | IT_STRING2, NULL, "System Menu (ESC)",M_ChangeControl, gc_systemmenu }, - {IT_CALL | IT_STRING2, NULL, "Pause", M_ChangeControl, gc_pause }, {IT_CALL | IT_STRING2, NULL, "Console", M_ChangeControl, gc_console }, From 47dd9e2fc26a219e93f5ab9987f9c27cd1ef7d9f Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Mon, 10 Sep 2018 01:47:23 -0400 Subject: [PATCH 099/146] Drop Dash + alternate start boosts New respawn boost behavior, where you just hold for long enough instead of timing it with hitting the ground. Also much weaker, just gives you enough boost to get going instead of being a free sneaker. Start boosts have been severely changed. The perfect one has an extra tic on its timing window and gets Sneaker boosting special effects, but every other possible boost has been severely nerfed. --- src/d_player.h | 4 +- src/dehacked.c | 2 + src/k_kart.c | 111 +++++++++++++++++++++++++++++++------------------ src/p_user.c | 3 +- src/sounds.c | 1 + src/sounds.h | 1 + 6 files changed, 80 insertions(+), 42 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 34eb385ca..822ea305a 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -276,6 +276,7 @@ typedef enum k_waypoint, // Waypoints. k_starpostwp, // Temporarily stores player waypoint for... some reason. Used when respawning and finishing. k_respawn, // Timer for the DEZ laser respawn effect + k_dropdash, // Charge up for respawn Drop Dash k_throwdir, // Held dir of controls; 1 = forward, 0 = none, -1 = backward (was "player->heldDir") k_lapanimation, // Used to show the lap start wing logo animation @@ -291,7 +292,8 @@ typedef enum k_driftend, // Drift has ended, used to adjust character angle after drift k_driftcharge, // Charge your drift so you can release a burst of speed k_driftboost, // Boost you get from drifting - k_boostcharge, // Charge-up for boosting at the start of the race, or when dropping from respawn + k_boostcharge, // Charge-up for boosting at the start of the race + k_startboost, // Boost you get from start of race or respawn drop dash k_jmp, // In Mario Kart, letting go of the jump button stops the drift k_offroad, // In Super Mario Kart, going offroad has lee-way of about 1 second before you start losing speed k_pogospring, // Pogo spring bounce effect diff --git a/src/dehacked.c b/src/dehacked.c index 905e6dc04..7ad02c1a3 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -7672,6 +7672,7 @@ static const char *const KARTSTUFF_LIST[] = { "WAYPOINT", "STARPOSTWP", "RESPAWN", + "DROPDASH", "THROWDIR", "LAPANIMATION", @@ -7688,6 +7689,7 @@ static const char *const KARTSTUFF_LIST[] = { "DRIFTCHARGE", "DRIFTBOOST", "BOOSTCHARGE", + "STARTBOOST", "JMP", "OFFROAD", "POGOSPRING", diff --git a/src/k_kart.c b/src/k_kart.c index c64e4acc8..d6676ca7c 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1236,7 +1236,7 @@ void K_RespawnChecker(player_t *player) if (player->spectator) return; - if (player->kartstuff[k_respawn] > 3) + if (player->kartstuff[k_respawn] > 1) { player->kartstuff[k_respawn]--; player->mo->momz = 0; @@ -1274,26 +1274,39 @@ void K_RespawnChecker(player_t *player) } } } - - if (player->kartstuff[k_respawn] > 0 && player->kartstuff[k_respawn] <= 3) + else if (player->kartstuff[k_respawn] == 1) { if (!P_IsObjectOnGround(player->mo)) { player->powers[pw_flashing] = 2; - // If you tried to boost while in the air, - // you lose your chance of boosting at all. + + // Sal: That's stupid and prone to accidental usage. + // Let's rip off Mania instead, and turn this into a Drop Dash! + if (cmd->buttons & BT_ACCELERATE) - { - player->powers[pw_flashing] = 0; - player->kartstuff[k_respawn] = 0; - } + player->kartstuff[k_dropdash]++; + else + player->kartstuff[k_dropdash] = 0; + + if (player->kartstuff[k_dropdash] == TICRATE/4) + S_StartSound(player->mo, sfx_ddash); + + if ((player->kartstuff[k_dropdash] >= TICRATE/4) + && (player->kartstuff[k_dropdash] & 1)) + player->mo->colorized = true; + else + player->mo->colorized = false; } else { - player->kartstuff[k_respawn]--; - // Quick! You only have three tics to boost! - if (cmd->buttons & BT_ACCELERATE) - K_DoSneaker(player, true); + if ((cmd->buttons & BT_ACCELERATE) && (player->kartstuff[k_dropdash] >= TICRATE/4)) + { + S_StartSound(player->mo, sfx_s23c); + player->kartstuff[k_startboost] = 50; + } + player->mo->colorized = false; + player->kartstuff[k_dropdash] = 0; + player->kartstuff[k_respawn] = 0; } } } @@ -1478,23 +1491,6 @@ static void K_GetKartBoostPower(player_t *player) else if (player->kartstuff[k_bananadrag] > TICRATE) boostpower = 4*boostpower/5; - if (player->kartstuff[k_growshrinktimer] > 0) // Grow - { - speedboost = max(speedboost, FRACUNIT/5); // + 20% - } - - if (player->kartstuff[k_invincibilitytimer]) // Invincibility - { - speedboost = max(speedboost, 3*(FRACUNIT/8)); // + 37.5% - accelboost = max(accelboost, 3*FRACUNIT); // + 600% - } - - if (player->kartstuff[k_driftboost]) // Drift Boost - { - speedboost = max(speedboost, FRACUNIT/4); // + 25% - accelboost = max(accelboost, 4*FRACUNIT); // + 400% - } - if (player->kartstuff[k_sneakertimer]) // Sneaker { switch (gamespeed) @@ -1512,6 +1508,29 @@ static void K_GetKartBoostPower(player_t *player) accelboost = max(accelboost, 8*FRACUNIT); // + 800% } + if (player->kartstuff[k_invincibilitytimer]) // Invincibility + { + speedboost = max(speedboost, 3*FRACUNIT/8); // + 37.5% + accelboost = max(accelboost, 3*FRACUNIT); // + 300% + } + + if (player->kartstuff[k_growshrinktimer] > 0) // Grow + { + speedboost = max(speedboost, FRACUNIT/5); // + 20% + } + + if (player->kartstuff[k_driftboost]) // Drift Boost + { + speedboost = max(speedboost, FRACUNIT/4); // + 25% + accelboost = max(accelboost, 4*FRACUNIT); // + 400% + } + + if (player->kartstuff[k_startboost]) // Startup Boost + { + speedboost = max(speedboost, FRACUNIT/4); // + 25% + accelboost = max(accelboost, 6*FRACUNIT); // + 300% + } + // don't average them anymore, this would make a small boost and a high boost less useful // just take the highest we want instead @@ -2704,9 +2723,10 @@ void K_DoSneaker(player_t *player, boolean doPFlag) player->kartstuff[k_sneakertimer] = sneakertime; if (doPFlag) + { player->pflags |= PF_ATTACKDOWN; - - K_PlayTauntSound(player->mo); + K_PlayTauntSound(player->mo); + } K_GetKartBoostPower(player); if (player->kartstuff[k_speedboost] > prevboost) @@ -3328,6 +3348,9 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->kartstuff[k_driftboost]) player->kartstuff[k_driftboost]--; + if (player->kartstuff[k_startboost]) + player->kartstuff[k_startboost]--; + if (player->kartstuff[k_invincibilitytimer]) player->kartstuff[k_invincibilitytimer]--; @@ -4505,16 +4528,24 @@ void K_MoveKartPlayer(player_t *player, boolean onground) // Get an instant boost! else if (player->kartstuff[k_boostcharge] <= 50) { - player->kartstuff[k_sneakertimer] = -((21*(player->kartstuff[k_boostcharge]*player->kartstuff[k_boostcharge]))/425)+131; // max time is 70, min time is 7; yay parabooolas - if (!player->kartstuff[k_floorboost] || player->kartstuff[k_floorboost] == 3) + player->kartstuff[k_startboost] = (50-player->kartstuff[k_boostcharge])+20; + + if (player->kartstuff[k_boostcharge] <= 36) { - if (player->kartstuff[k_sneakertimer] >= 70) - S_StartSound(player->mo, sfx_s25f); // Special sound for the perfect start boost! - else if (player->kartstuff[k_sneakertimer] >= sneakertime) - S_StartSound(player->mo, sfx_cdfm01); // Sneaker boost sound for big boost - else - S_StartSound(player->mo, sfx_s23c); // Drift boost sound for small boost + player->kartstuff[k_startboost] = 0; + K_DoSneaker(player, false); + player->kartstuff[k_sneakertimer] = 70; // PERFECT BOOST!! + + if (!player->kartstuff[k_floorboost] || player->kartstuff[k_floorboost] == 3) // Let everyone hear this one + S_StartSound(player->mo, sfx_s25f); } + else if ((!player->kartstuff[k_floorboost] || player->kartstuff[k_floorboost] == 3) && P_IsLocalPlayer(player)) + { + if (player->kartstuff[k_boostcharge] <= 40) + S_StartSound(player->mo, sfx_cdfm01); // You were almost there! + else + S_StartSound(player->mo, sfx_s23c); // Nope, better luck next time. + } } // You overcharged your engine? Those things are expensive!!! else if (player->kartstuff[k_boostcharge] > 50) diff --git a/src/p_user.c b/src/p_user.c index 7c7253f6f..dc7ad252a 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -9285,7 +9285,7 @@ void P_PlayerThink(player_t *player) #if 1 // "Blur" a bit when you have speed shoes and are going fast enough if ((player->powers[pw_super] || player->powers[pw_sneakers] - || player->kartstuff[k_driftboost] || player->kartstuff[k_sneakertimer]) && !player->kartstuff[k_invincibilitytimer] // SRB2kart + || player->kartstuff[k_driftboost] || player->kartstuff[k_sneakertimer] || player->kartstuff[k_startboost]) && !player->kartstuff[k_invincibilitytimer] // SRB2kart && (player->speed + abs(player->mo->momz)) > FixedMul(20*FRACUNIT,player->mo->scale)) { mobj_t *gmobj = P_SpawnGhostMobj(player->mo); @@ -9434,6 +9434,7 @@ void P_PlayerThink(player_t *player) if (!(player->pflags & PF_NIGHTSMODE || player->kartstuff[k_hyudorotimer] // SRB2kart - fixes Hyudoro not flashing when it should. || player->kartstuff[k_growshrinktimer] > 0 // Grow doesn't flash either. + || player->kartstuff[k_respawn] // Respawn timer (for drop dash effect) || (G_BattleGametype() && player->kartstuff[k_bumper] <= 0 && player->kartstuff[k_comebacktimer]) || leveltime < starttime)) // Level intro { diff --git a/src/sounds.c b/src/sounds.c index 6e9562609..ec88786cf 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -811,6 +811,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"noooo1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"noooo2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"hogbom", false, 110, 8, -1, NULL, 0, -1, -1, LUMPERROR}, + {"ddash", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"dbgsal", false, 110, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // SRB2kart - Skin sounds diff --git a/src/sounds.h b/src/sounds.h index 2f0732736..980c097e0 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -883,6 +883,7 @@ typedef enum sfx_noooo1, sfx_noooo2, sfx_hogbom, + sfx_ddash, sfx_dbgsal, sfx_kwin, From cc27612b169aa284b828ffbebe71a0d96522ae86 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Mon, 10 Sep 2018 02:24:21 -0400 Subject: [PATCH 100/146] Camera fixes - Fixed camera panning for higher distances. - Because of this, re-enabled scaling the pan amount based on distance. --- src/p_user.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index dc7ad252a..f499b7ec0 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8394,8 +8394,8 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall // SRB2Kart: set camera panning if (player->kartstuff[k_drift] != 0) { - fixed_t panmax = (camdist/5); - pan = min(player->kartstuff[k_driftcharge], K_GetKartDriftSparkValue(player)) * panmax / K_GetKartDriftSparkValue(player); + fixed_t panmax = (dist/5); + pan = FixedDiv(FixedMul(min((fixed_t)player->kartstuff[k_driftcharge], K_GetKartDriftSparkValue(player)), panmax), K_GetKartDriftSparkValue(player)); if (pan > panmax) pan = panmax; if (player->kartstuff[k_drift] < 0) From 3a34a3f7eaac48fd8fb0611e8a6f6a2c1249b61b Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Mon, 10 Sep 2018 02:48:10 -0400 Subject: [PATCH 101/146] Item stuff - Keep items on death, as long as you haven't used them yet. - Restart the item roulette on spawn if you die during it. - Held items that take up your item box now flash, to be consistent with Rocket Sneaker and Grow. --- src/g_game.c | 20 ++++++++++++++++++++ src/k_kart.c | 3 +++ 2 files changed, 23 insertions(+) diff --git a/src/g_game.c b/src/g_game.c index cacc12a9b..bdc803d8b 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2347,6 +2347,10 @@ void G_PlayerReborn(INT32 player) // SRB2kart INT32 starpostwp; + INT32 itemtype; + INT32 itemamount; + INT32 itemroulette; + INT32 roulettetype; INT32 bumper; INT32 comebackpoints; INT32 wanted; @@ -2405,6 +2409,18 @@ void G_PlayerReborn(INT32 player) // SRB2kart starpostwp = players[player].kartstuff[k_starpostwp]; + itemroulette = (players[player].kartstuff[k_itemroulette] > 0 ? 1 : 0); + roulettetype = players[player].kartstuff[k_roulettetype]; + if (players[player].kartstuff[k_itemheld]) + { + itemtype = 0; + itemamount = 0; + } + else + { + itemtype = players[player].kartstuff[k_itemtype]; + itemamount = players[player].kartstuff[k_itemamount]; + } bumper = players[player].kartstuff[k_bumper]; comebackpoints = players[player].kartstuff[k_comebackpoints]; wanted = players[player].kartstuff[k_wanted]; @@ -2464,6 +2480,10 @@ void G_PlayerReborn(INT32 player) // SRB2kart p->kartstuff[k_starpostwp] = starpostwp; // TODO: get these out of kartstuff, it causes desync + p->kartstuff[k_itemroulette] = itemroulette; + p->kartstuff[k_roulettetype] = roulettetype; + p->kartstuff[k_itemtype] = itemtype; + p->kartstuff[k_itemamount] = itemamount; p->kartstuff[k_bumper] = bumper; p->kartstuff[k_comebackpoints] = comebackpoints; p->kartstuff[k_comebacktimer] = comebacktime; diff --git a/src/k_kart.c b/src/k_kart.c index d6676ca7c..953ba0273 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -5410,6 +5410,9 @@ static void K_drawKartItem(void) case KITEM_SAD: localpatch = kp_sadface[offset]; break; default: return; } + + if (stplyr->kartstuff[k_itemheld] && !(leveltime & 1)) + localpatch = kp_nodraw; } } From dc76eeed31da3e55fed2ba9d10f0bcc6a8258614 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Mon, 10 Sep 2018 03:15:46 -0400 Subject: [PATCH 102/146] Don't let players carry them between levels.......... (In return for not letting anyone experience this silly bug, I made spectators joining before the match starts in Battle spawn with bumpers) --- src/g_game.c | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index bdc803d8b..68127eaa4 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2408,22 +2408,39 @@ void G_PlayerReborn(INT32 player) pity = players[player].pity; // SRB2kart - starpostwp = players[player].kartstuff[k_starpostwp]; - itemroulette = (players[player].kartstuff[k_itemroulette] > 0 ? 1 : 0); - roulettetype = players[player].kartstuff[k_roulettetype]; - if (players[player].kartstuff[k_itemheld]) + if (leveltime <= starttime) { + itemroulette = 0; + roulettetype = 0; itemtype = 0; itemamount = 0; + bumper = (G_BattleGametype() ? cv_kartbumpers.value : 0); + comebackpoints = 0; + wanted = 0; + starpostwp = 0; } else { - itemtype = players[player].kartstuff[k_itemtype]; - itemamount = players[player].kartstuff[k_itemamount]; + starpostwp = players[player].kartstuff[k_starpostwp]; + + itemroulette = (players[player].kartstuff[k_itemroulette] > 0 ? 1 : 0); + roulettetype = players[player].kartstuff[k_roulettetype]; + + if (players[player].kartstuff[k_itemheld]) + { + itemtype = 0; + itemamount = 0; + } + else + { + itemtype = players[player].kartstuff[k_itemtype]; + itemamount = players[player].kartstuff[k_itemamount]; + } + + bumper = players[player].kartstuff[k_bumper]; + comebackpoints = players[player].kartstuff[k_comebackpoints]; + wanted = players[player].kartstuff[k_wanted]; } - bumper = players[player].kartstuff[k_bumper]; - comebackpoints = players[player].kartstuff[k_comebackpoints]; - wanted = players[player].kartstuff[k_wanted]; p = &players[player]; memset(p, 0, sizeof (*p)); From be6d4342b9d4430fc7207f9645ca02c386a60d62 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Mon, 10 Sep 2018 03:17:15 -0400 Subject: [PATCH 103/146] Make Battle arrows consistent w/ the flashing item change earlier Should make Hyudoro even more amazing in Battle, since you can tell which held items are off-limits~ --- src/p_mobj.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 04f99accc..fcd4f4929 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7022,7 +7022,15 @@ void P_MobjThinker(mobj_t *mobj) break; } - mobj->tracer->flags2 &= ~MF2_DONTDRAW; + if (mobj->target->player->kartstuff[k_itemheld]) + { + if (leveltime & 1) + mobj->tracer->flags2 &= ~MF2_DONTDRAW; + else + mobj->tracer->flags2 |= MF2_DONTDRAW; + } + else + mobj->tracer->flags2 &= ~MF2_DONTDRAW; } else { From eb3bfba1ed31ceafeef252a52b7df4a65f89c991 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Mon, 10 Sep 2018 03:27:05 -0400 Subject: [PATCH 104/146] System menu default --- src/g_input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_input.c b/src/g_input.c index d685b8b06..ab33d58e1 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -1305,7 +1305,7 @@ void G_Controldefault(void) //gamecontrol[gc_viewpoint ][1] = KEY_JOY1+3; // Y gamecontrol[gc_pause ][1] = KEY_JOY1+6; // Back - //gamecontrol[gc_menu ][1] = KEY_JOY1+7; // Start + gamecontrol[gc_systemmenu ][1] = KEY_JOY1+7; // Start gamecontrol[gc_camtoggle ][1] = KEY_HAT1+0; // D-Pad Up //gamecontrol[gc_screenshot ][1] = KEY_HAT1+1; // D-Pad Down gamecontrol[gc_talkkey ][1] = KEY_HAT1+2; // D-Pad Left From 42fe27420f42bbbbca6b7747694b7aad4d05b11e Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Mon, 10 Sep 2018 03:35:10 -0400 Subject: [PATCH 105/146] Quick fix No other keys bound to this, it should be 0 --- src/g_input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_input.c b/src/g_input.c index ab33d58e1..279ee56b2 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -1305,7 +1305,7 @@ void G_Controldefault(void) //gamecontrol[gc_viewpoint ][1] = KEY_JOY1+3; // Y gamecontrol[gc_pause ][1] = KEY_JOY1+6; // Back - gamecontrol[gc_systemmenu ][1] = KEY_JOY1+7; // Start + gamecontrol[gc_systemmenu ][0] = KEY_JOY1+7; // Start gamecontrol[gc_camtoggle ][1] = KEY_HAT1+0; // D-Pad Up //gamecontrol[gc_screenshot ][1] = KEY_HAT1+1; // D-Pad Down gamecontrol[gc_talkkey ][1] = KEY_HAT1+2; // D-Pad Left From ea90a6aaa32b238d4ad0f42a043031717dfded1c Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Mon, 10 Sep 2018 04:29:37 -0400 Subject: [PATCH 106/146] Don't allow joining 20 sec into the match --- src/k_kart.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/k_kart.c b/src/k_kart.c index 953ba0273..4edfe0da4 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -4755,6 +4755,8 @@ void K_CheckSpectateStatus(void) return; if (numingame < 2 || leveltime < starttime || mapreset) // Allow if the match hasn't started yet continue; + if (leveltime > 20*TICRATE) // DON'T allow if the match is 20 seconds in + return; if (G_RaceGametype() && players[i].laps) // DON'T allow if the race is at 2 laps return; continue; From e91d9760a20598daaae978deaca6c98d44c07e65 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 10 Sep 2018 12:39:59 +0100 Subject: [PATCH 107/146] More manual pages, plus renaming the option to `Tricks & Secrets (F1)` - PLUS, the magic of a little animated how-to for leafing through the pages. Requires new patch.kart, as I wanted the leading zeroes and Jeck wanted to add more pages without more commits later... --- src/m_menu.c | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index f1e3264ff..efcd715c4 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -626,13 +626,19 @@ static menuitem_t MISC_ChangeLevelMenu[] = static menuitem_t MISC_HelpMenu[] = { - {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL0", M_HandleImageDef, 0}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL1", M_HandleImageDef, 1}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL2", M_HandleImageDef, 1}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL3", M_HandleImageDef, 1}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL4", M_HandleImageDef, 1}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL5", M_HandleImageDef, 1}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL6", M_HandleImageDef, 0}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL00", M_HandleImageDef, 0}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL01", M_HandleImageDef, 1}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL02", M_HandleImageDef, 1}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL03", M_HandleImageDef, 1}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL04", M_HandleImageDef, 1}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL05", M_HandleImageDef, 1}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL06", M_HandleImageDef, 1}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL07", M_HandleImageDef, 1}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL08", M_HandleImageDef, 1}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL09", M_HandleImageDef, 1}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL10", M_HandleImageDef, 1}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL11", M_HandleImageDef, 1}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL12", M_HandleImageDef, 0}, }; // -------------------------------- @@ -1060,7 +1066,7 @@ static menuitem_t OP_MainMenu[] = {IT_SUBMENU|IT_STRING, NULL, "Gameplay Options...", &OP_GameOptionsDef, 90}, {IT_SUBMENU|IT_STRING, NULL, "Server Options...", &OP_ServerOptionsDef, 100}, - {IT_CALL|IT_STRING, NULL, "User Manual", M_Manual, 120}, + {IT_CALL|IT_STRING, NULL, "Tricks & Secrets (F1)", M_Manual, 120}, {IT_CALL|IT_STRING, NULL, "Play Credits", M_Credits, 130}, {IT_SUBMENU|IT_STRING, NULL, "Erase Data...", &OP_EraseDataDef, 140}, }; @@ -4197,9 +4203,19 @@ static void M_DrawImageDef(void) if (currentMenu->menuitems[itemOn].alphaKey) { - V_DrawString(2,BASEVIDHEIGHT-10, V_YELLOWMAP, va("%d", (itemOn<<1)-1)); // intentionally not highlightflags + V_DrawString(2,BASEVIDHEIGHT-10, V_YELLOWMAP, va("%d", (itemOn<<1)-1)); // intentionally not highlightflags, unlike below V_DrawRightAlignedString(BASEVIDWIDTH-2,BASEVIDHEIGHT-10, V_YELLOWMAP, va("%d", itemOn<<1)); // ditto } + else + { + INT32 x = ((itemOn ? 3 : 1)*BASEVIDWIDTH)>>2, y = (BASEVIDHEIGHT>>1) - 4; + V_DrawCenteredString(x, y-10, highlightflags, "USE ARROW KEYS"); + V_DrawCharacter(x - 10 - (skullAnimCounter/5), y, + '\x1C' | highlightflags, false); // left arrow + V_DrawCharacter(x + 2 + (skullAnimCounter/5), y, + '\x1D' | highlightflags, false); // right arrow + V_DrawCenteredString(x, y+10, highlightflags, "TO LEAF THROUGH"); + } } // Handles the ImageDefs. Just a specialized function that From 33ab47dd3a84577e8e89ddaa6bdb0cde531dc966 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 10 Sep 2018 12:41:53 +0100 Subject: [PATCH 108/146] I was getting annoyed by these arrows and their inconsistency, so I made them use the graphics. --- src/hu_stuff.c | 58 +++++++++++++++----------------------------------- src/m_menu.c | 6 ++++-- 2 files changed, 21 insertions(+), 43 deletions(-) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 36b2812e8..36e4621b2 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -1366,54 +1366,24 @@ static void HU_drawMiniChat(void) } -// HU_DrawUpArrow -// You see, we don't have arrow graphics in 2.1 and I'm too lazy to include a 2 bytes file for it. - -static void HU_DrawUpArrow(INT32 x, INT32 y, INT32 options) -{ - // Ok I'm super lazy so let's make this as the worst draw function: - V_DrawFill(x+2, y, 1, 1, 103|options); - V_DrawFill(x+1, y+1, 3, 1, 103|options); - V_DrawFill(x, y+2, 5, 1, 103|options); // that's the yellow part, I swear - - V_DrawFill(x+3, y, 1, 1, 26|options); - V_DrawFill(x+4, y+1, 1, 1, 26|options); - V_DrawFill(x+5, y+2, 1, 1, 26|options); - V_DrawFill(x, y+3, 6, 1, 26|options); // that's the black part. no racism intended. i swear. -} - -// HU_DrawDownArrow -// Should we talk about anime waifus to pass the time? This feels retarded. - -static void HU_DrawDownArrow(INT32 x, INT32 y, INT32 options) -{ - // Ok I'm super lazy so let's make this as the worst draw function: - V_DrawFill(x, y, 6, 1, 26|options); - V_DrawFill(x, y+1, 5, 1, 26|options); - V_DrawFill(x+1, y+2, 3, 1, 26|options); - V_DrawFill(x+2, y+3, 1, 1, 26|options); // that's the black part. no racism intended. i swear. - - V_DrawFill(x, y, 5, 1, 103|options); - V_DrawFill(x+1, y+1, 3, 1, 103|options); - V_DrawFill(x+2, y+2, 1, 1, 103|options); // that's the yellow part, I swear -} - // HU_DrawChatLog // TODO: fix dumb word wrapping issues static void HU_drawChatLog(INT32 offset) { + INT32 charwidth = 4, charheight = 6; + INT32 x = chatx+2, y, dx = 0, dy = 0; + UINT32 i = 0; + INT32 chat_topy, chat_bottomy; + boolean atbottom = false; - // before we do anything, make sure that our scroll position isn't "illegal"; + // make sure that our scroll position isn't "illegal"; if (chat_scroll > chat_maxscroll) chat_scroll = chat_maxscroll; - INT32 charwidth = 4, charheight = 6; - INT32 x = chatx+2, y = chaty - offset*charheight - (chat_scroll*charheight) - cv_chatheight.value*charheight - 12 - (cv_kartspeedometer.value ? 16 : 0), dx = 0, dy = 0; - UINT32 i = 0; - INT32 chat_topy = y + chat_scroll*charheight; - INT32 chat_bottomy = chat_topy + cv_chatheight.value*charheight; - boolean atbottom = false; + y = chaty - offset*charheight - (chat_scroll*charheight) - cv_chatheight.value*charheight - 12 - (cv_kartspeedometer.value ? 16 : 0); + chat_topy = y + chat_scroll*charheight; + chat_bottomy = chat_topy + cv_chatheight.value*charheight; V_DrawFillConsoleMap(chatx, chat_topy, cv_chatwidth.value, cv_chatheight.value*charheight +2, 239|V_SNAPTOBOTTOM|V_SNAPTOLEFT); // log box @@ -1484,9 +1454,15 @@ static void HU_drawChatLog(INT32 offset) // draw arrows to indicate that we can (or not) scroll. if (chat_scroll > 0) - HU_DrawUpArrow(chatx-8, ((justscrolledup) ? (chat_topy-1) : (chat_topy)), V_SNAPTOBOTTOM | V_SNAPTOLEFT); + { + V_DrawCharacter(chatx-9, ((justscrolledup) ? (chat_topy-1) : (chat_topy)), + '\x1A' | V_SNAPTOBOTTOM | V_SNAPTOLEFT, false); // up arrow + } if (chat_scroll < chat_maxscroll) - HU_DrawDownArrow(chatx-8, chat_bottomy-((justscrolleddown) ? 3 : 4), V_SNAPTOBOTTOM | V_SNAPTOLEFT); + { + V_DrawCharacter(chatx-9, chat_bottomy-((justscrolleddown) ? 5 : 6), + '\x1B' | V_SNAPTOBOTTOM | V_SNAPTOLEFT, false); // down arrow + } justscrolleddown = false; justscrolledup = false; diff --git a/src/m_menu.c b/src/m_menu.c index efcd715c4..4f208a2bd 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5564,7 +5564,8 @@ static void M_DrawStatsMaps(int location) boolean dotopname = true, dobottomarrow = (location < statsMax); if (location) - V_DrawString(10, y-(skullAnimCounter/5), highlightflags, "\x1A"); + V_DrawCharacter(10, y-(skullAnimCounter/5), + '\x1A' | highlightflags, false); // up arrow while (statsMapList[++i] != -1) { @@ -5646,7 +5647,8 @@ static void M_DrawStatsMaps(int location) } bottomarrow: if (dobottomarrow) - V_DrawString(10, y-8 + (skullAnimCounter/5), highlightflags, "\x1B"); + V_DrawCharacter(10, y-8 + (skullAnimCounter/5), + '\x1B' | highlightflags, false); // up arrow } static void M_DrawLevelStats(void) From c46fe65a063e2b76c54ad7c45466c2c8e32275ed Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Mon, 10 Sep 2018 15:15:14 -0400 Subject: [PATCH 109/146] .PNG error shows lump name --- src/w_wad.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/w_wad.c b/src/w_wad.c index 9df2065fa..89fdadde6 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -782,7 +782,12 @@ static size_t W_RawReadLumpHeader(UINT16 wad, UINT16 lump, void *dest, size_t si && sigcheck[5] == 0x0a && sigcheck[6] == 0x1a && sigcheck[7] == 0x0a) - I_Error("W_Wad: Tried to cache a .PNG - have you tried converting to Doom or Flat (raw) image formats?"); + { + char pnglump[9]; + strncpy(pnglump, l->name, 8); + pnglump[8] = '\0'; + I_Error("W_Wad: Lump \"%s\" is a .PNG - have you tried converting to Doom or Flat (raw) image formats?", pnglump); + } #undef sigcheck #endif From 8df3e2ffbe7f5fc90878128fd9541f14ca2228ff Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 11 Sep 2018 15:41:41 +0100 Subject: [PATCH 110/146] Do a bunch of major modifications to the voting system's rule change system! * Add `kartvoterulechanges`, or "Voting Rule Changes" on the menu, to allow some user control over event frequency. * "Never" - does what it says on the tin. * "Sometimes" - 1/8 chance of Encore if host has unlocked it, only gametype change when buffer is full * "Frequent" - 1/2 chance of Encore if host has unlocked it, gametype change every 5 maps * "Always" - If host has unlocked Encore, alternates between Encore and Gametype. Otherwise, always a gametype change * There's probably room for a setting between "Sometimes" and "Frequent", but I didn't want to overload the host with options and these were the ones that made sense. * Better handling of buffer refreshes, to prevent two of the same map appearing next to each other in the voting unless there literally aren't that many maps. * Mostly unrelated: Minor bugfix for Y_SetupVoteFinish, preventing music changes/random sounds playing on the You Will Join Next Race screen. (Branch-appropriate, at least.) --- src/d_netcmd.c | 2 ++ src/d_netcmd.h | 1 + src/g_game.c | 78 +++++++++++++++++++++++++++++++++++++++++++------- src/k_kart.c | 1 + src/m_menu.c | 11 +++---- src/y_inter.c | 17 +++++------ 6 files changed, 85 insertions(+), 25 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 28d33be97..cb2ed49d0 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -353,6 +353,8 @@ consvar_t cv_kartbumpers = {"kartbumpers", "3", CV_NETVAR|CV_CHEAT, kartbumpers_ consvar_t cv_kartfrantic = {"kartfrantic", "Off", CV_NETVAR|CV_CHEAT|CV_CALL|CV_NOINIT, CV_OnOff, KartFrantic_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_kartcomeback = {"kartcomeback", "On", CV_NETVAR|CV_CHEAT|CV_CALL|CV_NOINIT, CV_OnOff, KartComeback_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_kartencore = {"kartencore", "Off", CV_NETVAR|CV_CALL|CV_NOINIT, CV_OnOff, KartEncore_OnChange, 0, NULL, NULL, 0, 0, NULL}; +static CV_PossibleValue_t kartvoterulechanges_cons_t[] = {{0, "Never"}, {1, "Sometimes"}, {2, "Frequent"}, {3, "Always"}, {0, NULL}}; +consvar_t cv_kartvoterulechanges = {"kartvoterulechanges", "Frequent", CV_NETVAR, kartvoterulechanges_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; static CV_PossibleValue_t kartspeedometer_cons_t[] = {{0, "Off"}, {1, "Kilometers"}, {2, "Miles"}, {3, "Fracunits"}, {0, NULL}}; consvar_t cv_kartspeedometer = {"kartdisplayspeed", "Off", CV_SAVE, kartspeedometer_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; // use tics in display static CV_PossibleValue_t kartvoices_cons_t[] = {{0, "Never"}, {1, "Tasteful"}, {2, "Meme"}, {0, NULL}}; diff --git a/src/d_netcmd.h b/src/d_netcmd.h index 5238c44e1..5814f2ae5 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -125,6 +125,7 @@ extern consvar_t cv_kartbumpers; extern consvar_t cv_kartfrantic; extern consvar_t cv_kartcomeback; extern consvar_t cv_kartencore; +extern consvar_t cv_kartvoterulechanges; extern consvar_t cv_kartspeedometer; extern consvar_t cv_kartvoices; diff --git a/src/g_game.c b/src/g_game.c index 15c9bab29..00a2828d7 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3113,14 +3113,48 @@ boolean G_BattleGametype(void) // INT16 G_SometimesGetDifferentGametype(void) { - if (randmapbuffer[NUMMAPS] != -1) + boolean encorepossible = (M_SecretUnlocked(SECRET_ENCORE) && G_RaceGametype()); + + if (!cv_kartvoterulechanges.value) // never + return gametype; + + if (randmapbuffer[NUMMAPS] > 0 && (encorepossible || cv_kartvoterulechanges.value != 3)) { - if (M_SecretUnlocked(SECRET_ENCORE) && (M_RandomChance(FRACUNIT/2/*56*/) != cv_kartencore.value) && G_RaceGametype()) - return (gametype|0x80); + if (cv_kartvoterulechanges.value != 1) + randmapbuffer[NUMMAPS]--; + if (encorepossible) + { + switch (cv_kartvoterulechanges.value) + { + case 3: // always + randmapbuffer[NUMMAPS] = 0; // gotta prep this in case it isn't already set + break; + case 2: // frequent + encorepossible = M_RandomChance(FRACUNIT>>1); + break; + case 1: // sometimes + default: + encorepossible = M_RandomChance(FRACUNIT>>3); + break; + } + if (encorepossible != cv_kartencore.value) + return (gametype|0x80); + } return gametype; } - randmapbuffer[NUMMAPS] = gametype; + switch (cv_kartvoterulechanges.value) // okay, we're having a gametype change! when's the next one, luv? + { + case 3: // always + randmapbuffer[NUMMAPS] = 1; // every other vote (or always if !encorepossible) + break; + case 1: // sometimes + default: + // fallthrough - happens when clearing buffer, but needs a reasonable countdown if cvar is modified + case 2: // frequent + randmapbuffer[NUMMAPS] = 5; // per "cup" + break; + } if (gametype == GT_MATCH) return GT_RACE; @@ -3188,6 +3222,7 @@ INT16 G_TOLFlag(INT32 pgametype) return INT16_MAX; } +#ifdef FLUSHMAPBUFFEREARLY static INT32 TOLMaps(INT16 tolflags) { INT32 num = 0; @@ -3205,6 +3240,7 @@ static INT32 TOLMaps(INT16 tolflags) return num; } +#endif /** Select a random map with the given typeoflevel flags. * If no map has those flags, this arbitrarily gives you map 1. @@ -3223,6 +3259,8 @@ INT16 G_RandMap(INT16 tolflags, INT16 pprevmap, boolean dontadd, boolean ignoreb if (!okmaps) okmaps = Z_Malloc(NUMMAPS * sizeof(INT16), PU_STATIC, NULL); +tryagain: + // Find all the maps that are ok and and put them in an array. for (ix = 0; ix < NUMMAPS; ix++) { @@ -3256,12 +3294,28 @@ INT16 G_RandMap(INT16 tolflags, INT16 pprevmap, boolean dontadd, boolean ignoreb okmaps[numokmaps++] = ix; } - if (numokmaps == 0) + if (numokmaps == 0) // If there's no matches... (Goodbye, incredibly silly function chains :V) { if (!ignorebuffer) - return G_RandMap(tolflags, pprevmap, dontadd, true, maphell, callagainsoon); // If there's no matches, (An incredibly silly function chain, buuut... :V) - if (maphell) - return G_RandMap(tolflags, pprevmap, dontadd, true, maphell-1, callagainsoon); + { + if (randmapbuffer[3] == -1) // Is the buffer basically empty? + { + ignorebuffer = true; // This will probably only help in situations where there's very few maps, but it's folly not to at least try it + goto tryagain; //return G_RandMap(tolflags, pprevmap, dontadd, true, maphell, callagainsoon); + } + + for (bufx = 3; bufx < NUMMAPS; bufx++) // Let's clear all but the three most recent maps... + randmapbuffer[bufx] = -1; + if (cv_kartvoterulechanges.value == 1) // sometimes + randmapbuffer[NUMMAPS] = 0; + goto tryagain; //return G_RandMap(tolflags, pprevmap, dontadd, ignorebuffer, maphell, callagainsoon); + } + + if (maphell) // Any wiggle room to loosen our restrictions here? + { + maphell--; + goto tryagain; //return G_RandMap(tolflags, pprevmap, dontadd, true, maphell-1, callagainsoon); + } ix = 0; // Sorry, none match. You get MAP01. for (bufx = 0; bufx < NUMMAPS+1; bufx++) @@ -3423,11 +3477,15 @@ static void G_DoCompleted(void) automapactive = false; - if (randmapbuffer[TOLMaps(G_TOLFlag(gametype))-4] != -1) // we're getting pretty full, so lets clear it +#ifdef FLUSHMAPBUFFEREARLY + if (randmapbuffer[TOLMaps(G_TOLFlag(gametype))-5] != -1) // We're getting pretty full, so! -- no need for this, handled in G_RandMap { - for (i = 0; i < NUMMAPS+1; i++) + for (i = 3; i < NUMMAPS; i++) // Let's clear all but the three most recent maps... randmapbuffer[i] = -1; + if (cv_kartvoterulechanges.value == 1) // sometimes + randmapbuffer[NUMMAPS] = 0; } +#endif if (gametype != GT_COOP) { diff --git a/src/k_kart.c b/src/k_kart.c index b4c1e6ca4..ae09c3baa 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -402,6 +402,7 @@ void K_RegisterKartStuff(void) CV_RegisterVar(&cv_kartfrantic); CV_RegisterVar(&cv_kartcomeback); CV_RegisterVar(&cv_kartencore); + CV_RegisterVar(&cv_kartvoterulechanges); CV_RegisterVar(&cv_kartspeedometer); CV_RegisterVar(&cv_kartvoices); CV_RegisterVar(&cv_karteliminatelast); diff --git a/src/m_menu.c b/src/m_menu.c index 1c4e9015e..536edd20e 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1474,14 +1474,15 @@ static menuitem_t OP_ServerOptionsMenu[] = {IT_STRING | IT_CVAR, NULL, "Intermission Timer", &cv_inttime, 40}, {IT_STRING | IT_CVAR, NULL, "Map Progression", &cv_advancemap, 50}, {IT_STRING | IT_CVAR, NULL, "Voting Timer", &cv_votetime, 60}, + {IT_STRING | IT_CVAR, NULL, "Voting Rule Changes", &cv_kartvoterulechanges, 70}, #ifndef NONET - {IT_STRING | IT_CVAR, NULL, "Max. Player Count", &cv_maxplayers, 80}, - {IT_STRING | IT_CVAR, NULL, "Allow Players to Join", &cv_allownewplayer, 90}, - //{IT_STRING | IT_CVAR, NULL, "Join on Map Change", &cv_joinnextround, 100}, + {IT_STRING | IT_CVAR, NULL, "Max. Player Count", &cv_maxplayers, 90}, + {IT_STRING | IT_CVAR, NULL, "Allow Players to Join", &cv_allownewplayer, 100}, + //{IT_STRING | IT_CVAR, NULL, "Join on Map Change", &cv_joinnextround, 110}, - {IT_STRING | IT_CVAR, NULL, "Allow WAD Downloading", &cv_downloading, 100}, - {IT_STRING | IT_CVAR, NULL, "Attempts to resynchronise", &cv_resynchattempts, 110}, + {IT_STRING | IT_CVAR, NULL, "Allow WAD Downloading", &cv_downloading, 110}, + {IT_STRING | IT_CVAR, NULL, "Attempts to resynchronise", &cv_resynchattempts, 120}, #endif }; diff --git a/src/y_inter.c b/src/y_inter.c index 77cea21f1..f5e1ba6ed 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -1548,13 +1548,13 @@ static void Y_UnloadVoteData(void) // void Y_SetupVoteFinish(SINT8 pick, SINT8 level) { + if (!voteclient.loaded) + return; + if (pick == -1) // No other votes? We gotta get out of here, then! { - if (voteclient.loaded) - { - Y_EndVote(); - Y_FollowIntermission(); - } + Y_EndVote(); + Y_FollowIntermission(); return; } @@ -1600,11 +1600,8 @@ void Y_SetupVoteFinish(SINT8 pick, SINT8 level) } else if (endtype == 0) // Might as well put this here, too. { - if (voteclient.loaded) - { - Y_EndVote(); - Y_FollowIntermission(); - } + Y_EndVote(); + Y_FollowIntermission(); return; } else From 50826ef6344d3ba693689e688ad8fc8cc44d554f Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 11 Sep 2018 19:52:00 -0400 Subject: [PATCH 111/146] New drift sparks --- src/dehacked.c | 14 +++---- src/info.c | 72 +++++++++++++++++----------------- src/info.h | 14 +++---- src/k_kart.c | 96 ++++++++++++++++++++++++++++++++++++++++++++- src/p_inter.c | 1 - src/p_mobj.c | 104 ------------------------------------------------- 6 files changed, 145 insertions(+), 156 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 7ad02c1a3..f05732c0d 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -6234,12 +6234,12 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit //} // Drift Sparks - "S_DRIFTSPARK1", - "S_DRIFTSPARK2", - "S_DRIFTSPARK3", - "S_DRIFTSPARK4", - "S_DRIFTSPARK5", - "S_DRIFTSPARK6", + "S_DRIFTSPARK_A1", + "S_DRIFTSPARK_A2", + "S_DRIFTSPARK_A3", + "S_DRIFTSPARK_B1", + "S_DRIFTSPARK_C1", + "S_DRIFTSPARK_C2", // Drift Smoke "S_DRIFTDUST1", @@ -7225,7 +7225,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_SPARKLETRAIL", "MT_INVULNFLASH", "MT_WIPEOUTTRAIL", - "MT_DRIFT", + "MT_DRIFTSPARK", "MT_DRIFTDUST", "MT_FAKESHIELD", diff --git a/src/info.c b/src/info.c index b87e317de..47b9e2c76 100644 --- a/src/info.c +++ b/src/info.c @@ -2566,12 +2566,14 @@ state_t states[NUMSTATES] = {SPR_RPOP, FF_FULLBRIGHT|2, 5, {NULL}, 0, 0, S_RANDOMITEMPOP4}, // S_RANDOMITEMPOP3 {SPR_RPOP, FF_FULLBRIGHT|3, 5, {NULL}, 0, 0, S_NULL}, // S_RANDOMITEMPOP4 - {SPR_DRIF, 0|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_DRIFTSPARK2}, // S_DRIFTSPARK1 - {SPR_DRIF, 1|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_DRIFTSPARK3}, // S_DRIFTSPARK2 - {SPR_DRIF, 2|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_DRIFTSPARK1}, // S_DRIFTSPARK3 - {SPR_DRIF, 3|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_DRIFTSPARK5}, // S_DRIFTSPARK4 - {SPR_DRIF, 4|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_DRIFTSPARK6}, // S_DRIFTSPARK5 - {SPR_DRIF, 5|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_DRIFTSPARK4}, // S_DRIFTSPARK6 + {SPR_DRIF, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_DRIFTSPARK_A2}, // S_DRIFTSPARK_A1 + {SPR_DRIF, FF_FULLBRIGHT|FF_TRANS20|1, 1, {NULL}, 0, 0, S_DRIFTSPARK_A3}, // S_DRIFTSPARK_A2 + {SPR_DRIF, FF_FULLBRIGHT|FF_TRANS50, 1, {NULL}, 0, 0, S_NULL}, // S_DRIFTSPARK_A3 + + {SPR_DRIF, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_DRIFTSPARK_A2}, // S_DRIFTSPARK_B1 (Loop back to A2) + + {SPR_DRIF, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_DRIFTSPARK_C2}, // S_DRIFTSPARK_C1 + {SPR_DRIF, FF_FULLBRIGHT|FF_TRANS20, 1, {NULL}, 0, 0, S_DRIFTSPARK_A3}, // S_DRIFTSPARK_C2 (Loop back to A3) {SPR_DUST, 0, 3, {NULL}, 0, 0, S_DRIFTDUST2}, // S_DRIFTDUST1 {SPR_DUST, 1, 3, {NULL}, 0, 0, S_DRIFTDUST3}, // S_DRIFTDUST2 @@ -2780,30 +2782,30 @@ state_t states[NUMSTATES] = {SPR_LIGH, 2, 2, {NULL}, 0, 0, S_LIGHTNING4}, // S_LIGHTNING3 {SPR_LIGH, 3, 2, {NULL}, 0, 0, S_NULL}, // S_LIGHTNING4 - {SPR_THNS, 0, 2, {NULL}, 0, 0, S_THUNDERSHIELD2}, // S_THUNDERSHIELD1 - {SPR_THNS, 1, 2, {NULL}, 0, 0, S_THUNDERSHIELD3}, // S_THUNDERSHIELD2 - {SPR_THNS, 2, 2, {NULL}, 0, 0, S_THUNDERSHIELD4}, // S_THUNDERSHIELD3 - {SPR_THNS, 3, 2, {NULL}, 0, 0, S_THUNDERSHIELD5}, // S_THUNDERSHIELD4 - {SPR_THNS, 4, 2, {NULL}, 0, 0, S_THUNDERSHIELD6}, // S_THUNDERSHIELD5 - {SPR_THNS, 5, 2, {NULL}, 0, 0, S_THUNDERSHIELD7}, // S_THUNDERSHIELD6 - {SPR_THNS, 6, 2, {NULL}, 0, 0, S_THUNDERSHIELD8}, // S_THUNDERSHIELD7 - {SPR_THNS, 7, 2, {NULL}, 0, 0, S_THUNDERSHIELD9}, // S_THUNDERSHIELD8 - {SPR_THNS, 8, 2, {NULL}, 0, 0, S_THUNDERSHIELD10}, // S_THUNDERSHIELD9 - {SPR_THNS, 9, 2, {NULL}, 0, 0, S_THUNDERSHIELD11}, // S_THUNDERSHIELD10 - {SPR_THNS, 10, 2, {NULL}, 0, 0, S_THUNDERSHIELD12}, // S_THUNDERSHIELD11 - {SPR_THNS, 11, 2, {NULL}, 0, 0, S_THUNDERSHIELD13}, // S_THUNDERSHIELD12 - {SPR_THNS, 8, 2, {NULL}, 0, 0, S_THUNDERSHIELD14}, // S_THUNDERSHIELD13 - {SPR_THNS, 7, 2, {NULL}, 0, 0, S_THUNDERSHIELD15}, // S_THUNDERSHIELD14 - {SPR_THNS, 6, 2, {NULL}, 0, 0, S_THUNDERSHIELD16}, // S_THUNDERSHIELD15 - {SPR_THNS, 5, 2, {NULL}, 0, 0, S_THUNDERSHIELD17}, // S_THUNDERSHIELD16 - {SPR_THNS, 4, 2, {NULL}, 0, 0, S_THUNDERSHIELD18}, // S_THUNDERSHIELD17 - {SPR_THNS, 3, 2, {NULL}, 0, 0, S_THUNDERSHIELD19}, // S_THUNDERSHIELD18 - {SPR_THNS, 2, 2, {NULL}, 0, 0, S_THUNDERSHIELD20}, // S_THUNDERSHIELD19 - {SPR_THNS, 1, 2, {NULL}, 0, 0, S_THUNDERSHIELD21}, // S_THUNDERSHIELD20 - {SPR_THNS, 0, 2, {NULL}, 0, 0, S_THUNDERSHIELD22}, // S_THUNDERSHIELD21 - {SPR_THNS, 9, 2, {NULL}, 0, 0, S_THUNDERSHIELD23}, // S_THUNDERSHIELD22 - {SPR_THNS, 10, 2, {NULL}, 0, 0, S_THUNDERSHIELD24}, // S_THUNDERSHIELD23 - {SPR_THNS, 11, 2, {NULL}, 0, 0, S_THUNDERSHIELD1}, // S_THUNDERSHIELD24 + {SPR_THNS, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_THUNDERSHIELD2}, // S_THUNDERSHIELD1 + {SPR_THNS, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_THUNDERSHIELD3}, // S_THUNDERSHIELD2 + {SPR_THNS, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_THUNDERSHIELD4}, // S_THUNDERSHIELD3 + {SPR_THNS, FF_FULLBRIGHT|3, 2, {NULL}, 0, 0, S_THUNDERSHIELD5}, // S_THUNDERSHIELD4 + {SPR_THNS, FF_FULLBRIGHT|4, 2, {NULL}, 0, 0, S_THUNDERSHIELD6}, // S_THUNDERSHIELD5 + {SPR_THNS, FF_FULLBRIGHT|5, 2, {NULL}, 0, 0, S_THUNDERSHIELD7}, // S_THUNDERSHIELD6 + {SPR_THNS, FF_FULLBRIGHT|6, 2, {NULL}, 0, 0, S_THUNDERSHIELD8}, // S_THUNDERSHIELD7 + {SPR_THNS, FF_FULLBRIGHT|7, 2, {NULL}, 0, 0, S_THUNDERSHIELD9}, // S_THUNDERSHIELD8 + {SPR_THNS, FF_FULLBRIGHT|8, 2, {NULL}, 0, 0, S_THUNDERSHIELD10}, // S_THUNDERSHIELD9 + {SPR_THNS, FF_FULLBRIGHT|9, 2, {NULL}, 0, 0, S_THUNDERSHIELD11}, // S_THUNDERSHIELD10 + {SPR_THNS, FF_FULLBRIGHT|10, 2, {NULL}, 0, 0, S_THUNDERSHIELD12}, // S_THUNDERSHIELD11 + {SPR_THNS, FF_FULLBRIGHT|11, 2, {NULL}, 0, 0, S_THUNDERSHIELD13}, // S_THUNDERSHIELD12 + {SPR_THNS, FF_FULLBRIGHT|8, 2, {NULL}, 0, 0, S_THUNDERSHIELD14}, // S_THUNDERSHIELD13 + {SPR_THNS, FF_FULLBRIGHT|7, 2, {NULL}, 0, 0, S_THUNDERSHIELD15}, // S_THUNDERSHIELD14 + {SPR_THNS, FF_FULLBRIGHT|6, 2, {NULL}, 0, 0, S_THUNDERSHIELD16}, // S_THUNDERSHIELD15 + {SPR_THNS, FF_FULLBRIGHT|5, 2, {NULL}, 0, 0, S_THUNDERSHIELD17}, // S_THUNDERSHIELD16 + {SPR_THNS, FF_FULLBRIGHT|4, 2, {NULL}, 0, 0, S_THUNDERSHIELD18}, // S_THUNDERSHIELD17 + {SPR_THNS, FF_FULLBRIGHT|3, 2, {NULL}, 0, 0, S_THUNDERSHIELD19}, // S_THUNDERSHIELD18 + {SPR_THNS, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_THUNDERSHIELD20}, // S_THUNDERSHIELD19 + {SPR_THNS, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_THUNDERSHIELD21}, // S_THUNDERSHIELD20 + {SPR_THNS, FF_FULLBRIGHT|0, 2, {NULL}, 0, 0, S_THUNDERSHIELD22}, // S_THUNDERSHIELD21 + {SPR_THNS, FF_FULLBRIGHT|9, 2, {NULL}, 0, 0, S_THUNDERSHIELD23}, // S_THUNDERSHIELD22 + {SPR_THNS, FF_FULLBRIGHT|10, 2, {NULL}, 0, 0, S_THUNDERSHIELD24}, // S_THUNDERSHIELD23 + {SPR_THNS, FF_FULLBRIGHT|11, 2, {NULL}, 0, 0, S_THUNDERSHIELD1}, // S_THUNDERSHIELD24 {SPR_SINK, 0, 1, {A_SmokeTrailer}, MT_SINKTRAIL, 0, S_SINK}, // S_SINK {SPR_SINK, 0|FF_TRANS80|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_SINK_SHIELD}, // S_SINK_SHIELD @@ -14562,9 +14564,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_DRIFT + { // MT_DRIFTSPARK -1, // doomednum - S_DRIFTSPARK1, // spawnstate + S_DRIFTSPARK_B1,// spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -14579,13 +14581,13 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_None, // deathsound 8, // speed - 64*FRACUNIT, // radius - 64*FRACUNIT, // height + 14*FRACUNIT, // radius + 14*FRACUNIT, // height 0, // display offset 16, // mass 0, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY, // flags S_NULL // raisestate }, diff --git a/src/info.h b/src/info.h index a1300ca38..b359bef56 100644 --- a/src/info.h +++ b/src/info.h @@ -3081,12 +3081,12 @@ typedef enum state //} // Drift Sparks - S_DRIFTSPARK1, - S_DRIFTSPARK2, - S_DRIFTSPARK3, - S_DRIFTSPARK4, - S_DRIFTSPARK5, - S_DRIFTSPARK6, + S_DRIFTSPARK_A1, + S_DRIFTSPARK_A2, + S_DRIFTSPARK_A3, + S_DRIFTSPARK_B1, + S_DRIFTSPARK_C1, + S_DRIFTSPARK_C2, // Drift Smoke S_DRIFTDUST1, @@ -4089,7 +4089,7 @@ typedef enum mobj_type MT_SPARKLETRAIL, MT_INVULNFLASH, MT_WIPEOUTTRAIL, - MT_DRIFT, + MT_DRIFTSPARK, MT_DRIFTDUST, MT_FAKESHIELD, diff --git a/src/k_kart.c b/src/k_kart.c index 4edfe0da4..b1438a16c 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2211,6 +2211,98 @@ static mobj_t *K_SpawnKartMissile(mobj_t *source, mobjtype_t type, angle_t angle return NULL; } +static void K_SpawnDriftSparks(player_t *player) +{ + fixed_t newx; + fixed_t newy; + //fixed_t ground; + mobj_t *spark; + angle_t travelangle; + INT32 i; + + I_Assert(player != NULL); + I_Assert(player->mo != NULL); + I_Assert(!P_MobjWasRemoved(player->mo)); + + if (leveltime % 2 == 1) + return; + + if (!P_IsObjectOnGround(player->mo)) + return; + + if (!player->kartstuff[k_drift] || player->kartstuff[k_driftcharge] < K_GetKartDriftSparkValue(player)) + return; + + /*if (player->mo->eflags & MFE_VERTICALFLIP) + ground = player->mo->ceilingz - FixedMul(mobjinfo[MT_DRIFTSPARK].height, player->mo->scale); + else + ground = player->mo->floorz;*/ + + travelangle = player->mo->angle-(ANGLE_45/5)*player->kartstuff[k_drift]; + + for (i = 0; i < 2; i++) + { + newx = player->mo->x + P_ReturnThrustX(player->mo, travelangle + ((i&1) ? -1 : 1)*ANGLE_135, FixedMul(32*FRACUNIT, player->mo->scale)); + newy = player->mo->y + P_ReturnThrustY(player->mo, travelangle + ((i&1) ? -1 : 1)*ANGLE_135, FixedMul(32*FRACUNIT, player->mo->scale)); +/*#ifdef ESLOPE + if (player->mo->standingslope) + { + ground = P_GetZAt(player->mo->standingslope, newx, newy); + if (player->mo->eflags & MFE_VERTICALFLIP) + ground -= FixedMul(mobjinfo[MT_DRIFTSPARK].height, player->mo->scale); + } +#endif*/ + spark = P_SpawnMobj(newx, newy, player->mo->z, MT_DRIFTSPARK); + + P_SetTarget(&spark->target, player->mo); + spark->angle = travelangle-(ANGLE_45/5)*player->kartstuff[k_drift]; + spark->destscale = player->mo->scale; + P_SetScale(spark, player->mo->scale); + + spark->momx = player->mo->momx/2; + spark->momy = player->mo->momy/2; + //spark->momz = player->mo->momz/2; + + if (player->kartstuff[k_driftcharge] >= K_GetKartDriftSparkValue(player)*2) + { + if (player->kartstuff[k_driftcharge] <= (K_GetKartDriftSparkValue(player)*2)+(32*3)) + spark->color = SKINCOLOR_DUSK; // transition + else + spark->color = SKINCOLOR_RUBY; + } + else + spark->color = SKINCOLOR_SAPPHIRE; + + if ((player->kartstuff[k_drift] > 0 && player->cmd.driftturn > 0) // Inward drifts + || (player->kartstuff[k_drift] < 0 && player->cmd.driftturn < 0)) + { + if ((player->kartstuff[k_drift] < 0 && (i & 1)) + || (player->kartstuff[k_drift] > 0 && !(i & 1))) + P_SetMobjState(spark, S_DRIFTSPARK_A1); + else if ((player->kartstuff[k_drift] < 0 && !(i & 1)) + || (player->kartstuff[k_drift] > 0 && (i & 1))) + P_SetMobjState(spark, S_DRIFTSPARK_C1); + } + else if ((player->kartstuff[k_drift] > 0 && player->cmd.driftturn < 0) // Outward drifts + || (player->kartstuff[k_drift] < 0 && player->cmd.driftturn > 0)) + { + if ((player->kartstuff[k_drift] < 0 && (i & 1)) + || (player->kartstuff[k_drift] > 0 && !(i & 1))) + P_SetMobjState(spark, S_DRIFTSPARK_C1); + else if ((player->kartstuff[k_drift] < 0 && !(i & 1)) + || (player->kartstuff[k_drift] > 0 && (i & 1))) + P_SetMobjState(spark, S_DRIFTSPARK_A1); + } + + spark->flags2 = (spark->flags2 & ~MF2_DONTDRAW)|(player->mo->eflags & MF2_DONTDRAW); + spark->eflags = (spark->eflags & ~MFE_VERTICALFLIP)|(player->mo->eflags & MFE_VERTICALFLIP); + spark->eflags = (spark->eflags & ~MFE_DRAWONLYFORP1)|(player->mo->eflags & MFE_DRAWONLYFORP1); + spark->eflags = (spark->eflags & ~MFE_DRAWONLYFORP2)|(player->mo->eflags & MFE_DRAWONLYFORP2); + spark->eflags = (spark->eflags & ~MFE_DRAWONLYFORP3)|(player->mo->eflags & MFE_DRAWONLYFORP3); + spark->eflags = (spark->eflags & ~MFE_DRAWONLYFORP4)|(player->mo->eflags & MFE_DRAWONLYFORP4); + } +} + void K_SpawnBoostTrail(player_t *player) { fixed_t newx; @@ -3763,8 +3855,8 @@ static void K_KartDrift(player_t *player, boolean onground) } // This spawns the drift sparks - if (player->kartstuff[k_driftcharge] < dsone && player->kartstuff[k_driftcharge] + driftadditive >= dsone) - P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_DRIFT)->target = player->mo; + if (player->kartstuff[k_driftcharge] + driftadditive >= dsone) + K_SpawnDriftSparks(player); player->kartstuff[k_driftcharge] += driftadditive; player->kartstuff[k_driftend] = 0; diff --git a/src/p_inter.c b/src/p_inter.c index 7e35731aa..6f3685d60 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1749,7 +1749,6 @@ static void P_HitDeathMessages(player_t *player, mobj_t *inflictor, mobj_t *sour str = M_GetText("%s%s's tagging hand %s %s.\n"); break; case MT_SPINFIRE: - case MT_SNEAKERTRAIL: str = M_GetText("%s%s's elemental fire trail %s %s.\n"); break; case MT_THROWNBOUNCE: diff --git a/src/p_mobj.c b/src/p_mobj.c index fcd4f4929..2c311bee0 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6614,110 +6614,6 @@ void P_MobjThinker(mobj_t *mobj) return; break; //{ SRB2kart mobs - case MT_DRIFT: - { - if (mobj->target && mobj->target->player && mobj->target->player->mo && mobj->target->player->health > 0 && !mobj->target->player->spectator) - { - fixed_t HEIGHT; - fixed_t radius; - - fixed_t dsone = K_GetKartDriftSparkValue(mobj->target->player); - fixed_t dstwo = dsone*2; - - if (mobj->target->player->kartstuff[k_driftcharge] < dsone) - { - P_RemoveMobj(mobj); - return; - } - - if (mobj->target->player->kartstuff[k_hyudorotimer] > 0) - { - if (splitscreen) - { - if (leveltime & 1) - mobj->flags2 |= MF2_DONTDRAW; - else - mobj->flags2 &= ~MF2_DONTDRAW; - - if (mobj->target->player->kartstuff[k_hyudorotimer] >= (1*TICRATE/2) && mobj->target->player->kartstuff[k_hyudorotimer] <= hyudorotime-(1*TICRATE/2)) - { - if (mobj->target->player == &players[secondarydisplayplayer]) - mobj->eflags |= MFE_DRAWONLYFORP2; - else if (mobj->target->player == &players[thirddisplayplayer] && splitscreen > 1) - mobj->eflags |= MFE_DRAWONLYFORP3; - else if (mobj->target->player == &players[fourthdisplayplayer] && splitscreen > 2) - mobj->eflags |= MFE_DRAWONLYFORP4; - else - mobj->eflags |= MFE_DRAWONLYFORP1; - } - else - mobj->eflags &= ~(MFE_DRAWONLYFORP1|MFE_DRAWONLYFORP2|MFE_DRAWONLYFORP3|MFE_DRAWONLYFORP4); - } - else - { - if (mobj->target->player == &players[displayplayer] - || (mobj->target->player != &players[displayplayer] - && (mobj->target->player->kartstuff[k_hyudorotimer] < (1*TICRATE/2) || mobj->target->player->kartstuff[k_hyudorotimer] > hyudorotime-(1*TICRATE/2)))) - { - if (leveltime & 1) - mobj->flags2 |= MF2_DONTDRAW; - else - mobj->flags2 &= ~MF2_DONTDRAW; - } - else - mobj->flags2 |= MF2_DONTDRAW; - } - } - else if (mobj->target->player->kartstuff[k_hyudorotimer] == 0) - { - mobj->flags2 &= ~MF2_DONTDRAW; - mobj->eflags &= ~(MFE_DRAWONLYFORP1|MFE_DRAWONLYFORP2|MFE_DRAWONLYFORP3|MFE_DRAWONLYFORP4); - } - - // Actor's distance from its Target, or Radius. - radius = 7*mobj->target->scale; - - // Switch blue flames to red flames - if (mobj->target->player && mobj->type == MT_DRIFT - && mobj->target->player->kartstuff[k_driftcharge] >= dstwo - && !(mobj->state >= &states[S_DRIFTSPARK4] && mobj->state <= &states[S_DRIFTSPARK6])) - P_SetMobjStateNF(mobj, S_DRIFTSPARK4); - - // Get the angle - if (mobj->target->player) - mobj->angle = ANGLE_180 + mobj->target->player->frameangle; - - // If the player is on the ceiling, then flip - if (mobj->target->eflags & MFE_VERTICALFLIP) - { - mobj->eflags |= MFE_VERTICALFLIP; - HEIGHT = (16<eflags &= ~MFE_VERTICALFLIP; - HEIGHT = 0; - } - - // Shrink if the player shrunk too. - mobj->scale = mobj->target->scale; - - P_UnsetThingPosition(mobj); - { - const angle_t fa = mobj->angle>>ANGLETOFINESHIFT; - mobj->x = mobj->target->x + FixedMul(finecosine[fa],radius); - mobj->y = mobj->target->y + FixedMul(finesine[fa],radius); - mobj->z = mobj->target->z - HEIGHT; - P_SetThingPosition(mobj); - } - } - else - { - P_RemoveMobj(mobj); - return; - } - break; - } case MT_ORBINAUT_SHIELD: // Kart orbit/trail items case MT_JAWZ_SHIELD: case MT_BANANA_SHIELD: From 5708e49c9574dee16c9a63b578a3aa18548d0547 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 13 Sep 2018 02:07:00 -0400 Subject: [PATCH 112/146] Instead of doing productive things, I changed around skincolors again - Renamed Ivory to White, removed Nickel and old White, and improved Silver and Grey. - Improved Pink & Ruby. - Added Ketchup, replaced Canary with Mustard. - Removed Army. --- src/dehacked.c | 96 ++++++++++---------- src/doomdef.h | 8 +- src/k_kart.c | 238 +++++++++++++++++++++++-------------------------- 3 files changed, 164 insertions(+), 178 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index f05732c0d..54d876189 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -7544,55 +7544,55 @@ static const char *const ML_LIST[16] = { // Also includes Super colors static const char *COLOR_ENUMS[] = { // Rejigged for Kart. "NONE", // 00 // SKINCOLOR_NONE - "IVORY", // 01 // SKINCOLOR_IVORY - "WHITE", // 02 // SKINCOLOR_WHITE - "SILVER", // 03 // SKINCOLOR_SILVER - "CLOUDY", // 04 // SKINCOLOR_CLOUDY - "GREY", // 05 // SKINCOLOR_GREY - "NICKEL", // 06 // SKINCOLOR_NICKEL - "BLACK", // 07 // SKINCOLOR_BLACK - "SALMON", // 08 // SKINCOLOR_SALMON - "PINK", // 09 // SKINCOLOR_PINK - "ROSE", // 10 // SKINCOLOR_ROSE - "RASPBERRY", // 11 // SKINCOLOR_RASPBERRY - "RED", // 12 // SKINCOLOR_RED - "RUBY", // 13 // SKINCOLOR_RUBY - "CRIMSON", // 14 // SKINCOLOR_CRIMSON - "DAWN", // 15 // SKINCOLOR_DAWN - "CREAMSICLE", // 16 // SKINCOLOR_CREAMSICLE - "ORANGE", // 17 // SKINCOLOR_ORANGE - "PUMPKIN", // 18 // SKINCOLOR_PUMPKIN - "ROSEWOOD", // 19 // SKINCOLOR_ROSEWOOD - "BURGUNDY", // 20 // SKINCOLOR_BURGUNDY - "BRONZE", // 21 // SKINCOLOR_BRONZE - "SEPIA", // 22 // SKINCOLOR_SEPIA - "BEIGE", // 23 // SKINCOLOR_BEIGE - "BROWN", // 24 // SKINCOLOR_BROWN - "LEATHER", // 25 // SKINCOLOR_LEATHER - "PEACH", // 26 // SKINCOLOR_PEACH - "CARAMEL", // 27 // SKINCOLOR_CARAMEL - "TANGERINE", // 28 // SKINCOLOR_TANGERINE - "GOLD", // 29 // SKINCOLOR_GOLD - "VOMIT", // 30 // SKINCOLOR_VOMIT - "YELLOW", // 31 // SKINCOLOR_YELLOW - "CANARY", // 32 // SKINCOLOR_CANARY - "OLIVE", // 33 // SKINCOLOR_OLIVE - "GARDEN", // 34 // SKINCOLOR_GARDEN - "LIME", // 35 // SKINCOLOR_LIME + "WHITE", // 01 // SKINCOLOR_WHITE + "SILVER", // 02 // SKINCOLOR_SILVER + "CLOUDY", // 03 // SKINCOLOR_CLOUDY + "GREY", // 04 // SKINCOLOR_GREY + "BLACK", // 05 // SKINCOLOR_BLACK + "SALMON", // 06 // SKINCOLOR_SALMON + "PINK", // 07 // SKINCOLOR_PINK + "ROSE", // 08 // SKINCOLOR_ROSE + "RASPBERRY", // 09 // SKINCOLOR_RASPBERRY + "RED", // 10 // SKINCOLOR_RED + "RUBY", // 11 // SKINCOLOR_RUBY + "CRIMSON", // 12 // SKINCOLOR_CRIMSON + "KETCHUP", // 13 // SKINCOLOR_KETCHUP + "DAWN", // 14 // SKINCOLOR_DAWN + "CREAMSICLE", // 15 // SKINCOLOR_CREAMSICLE + "ORANGE", // 16 // SKINCOLOR_ORANGE + "PUMPKIN", // 17 // SKINCOLOR_PUMPKIN + "ROSEWOOD", // 18 // SKINCOLOR_ROSEWOOD + "BURGUNDY", // 19 // SKINCOLOR_BURGUNDY + "BRONZE", // 20 // SKINCOLOR_BRONZE + "SEPIA", // 21 // SKINCOLOR_SEPIA + "BEIGE", // 22 // SKINCOLOR_BEIGE + "BROWN", // 23 // SKINCOLOR_BROWN + "LEATHER", // 24 // SKINCOLOR_LEATHER + "PEACH", // 25 // SKINCOLOR_PEACH + "CARAMEL", // 26 // SKINCOLOR_CARAMEL + "TANGERINE", // 27 // SKINCOLOR_TANGERINE + "GOLD", // 28 // SKINCOLOR_GOLD + "VOMIT", // 29 // SKINCOLOR_VOMIT + "YELLOW", // 30 // SKINCOLOR_YELLOW + "MUSTARD", // 31 // SKINCOLOR_MUSTARD + "OLIVE", // 32 // SKINCOLOR_OLIVE + "GARDEN", // 33 // SKINCOLOR_GARDEN + "LIME", // 34 // SKINCOLOR_LIME + "DREAM", // 35 // SKINCOLOR_DREAM "TEA", // 36 // SKINCOLOR_TEA - "ARMY", // 37 // SKINCOLOR_ARMY - "PISTACHIO", // 38 // SKINCOLOR_PISTACHIO - "MOSS", // 39 // SKINCOLOR_MOSS - "MINT", // 40 // SKINCOLOR_MINT - "GREEN", // 41 // SKINCOLOR_GREEN - "ROBOHOOD", // 42 // SKINCOLOR_ROBOHOOD - "PINETREE", // 43 // SKINCOLOR_PINETREE - "EMERALD", // 44 // SKINCOLOR_EMERALD - "SWAMP", // 45 // SKINCOLOR_SWAMP - "AQUA", // 46 // SKINCOLOR_AQUA - "TEAL", // 47 // SKINCOLOR_TEAL - "CYAN", // 48 // SKINCOLOR_CYAN - "CERULEAN", // 49 // SKINCOLOR_CERULEAN + "PISTACHIO", // 37 // SKINCOLOR_PISTACHIO + "MOSS", // 38 // SKINCOLOR_MOSS + "MINT", // 39 // SKINCOLOR_MINT + "GREEN", // 40 // SKINCOLOR_GREEN + "ROBOHOOD", // 41 // SKINCOLOR_ROBOHOOD + "PINETREE", // 42 // SKINCOLOR_PINETREE + "EMERALD", // 43 // SKINCOLOR_EMERALD + "SWAMP", // 44 // SKINCOLOR_SWAMP + "AQUA", // 45 // SKINCOLOR_AQUA + "TEAL", // 46 // SKINCOLOR_TEAL + "CYAN", // 47 // SKINCOLOR_CYAN + "CERULEAN", // 48 // SKINCOLOR_CERULEAN + "JAWZ", // 49 // SKINCOLOR_JAWZ "SLATE", // 50 // SKINCOLOR_SLATE "STEEL", // 51 // SKINCOLOR_STEEL "PERIWINKLE", // 52 // SKINCOLOR_PERIWINKLE diff --git a/src/doomdef.h b/src/doomdef.h index 2e4f45b25..2e15cb7ec 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -232,12 +232,10 @@ extern FILE *logstream; typedef enum { SKINCOLOR_NONE = 0, - SKINCOLOR_IVORY, SKINCOLOR_WHITE, SKINCOLOR_SILVER, SKINCOLOR_CLOUDY, SKINCOLOR_GREY, - SKINCOLOR_NICKEL, SKINCOLOR_BLACK, SKINCOLOR_SALMON, SKINCOLOR_PINK, @@ -246,6 +244,7 @@ typedef enum SKINCOLOR_RED, SKINCOLOR_RUBY, SKINCOLOR_CRIMSON, + SKINCOLOR_KETCHUP, SKINCOLOR_DAWN, SKINCOLOR_CREAMSICLE, SKINCOLOR_ORANGE, @@ -263,12 +262,12 @@ typedef enum SKINCOLOR_GOLD, SKINCOLOR_VOMIT, SKINCOLOR_YELLOW, - SKINCOLOR_CANARY, + SKINCOLOR_MUSTARD, SKINCOLOR_OLIVE, SKINCOLOR_GARDEN, SKINCOLOR_LIME, + SKINCOLOR_DREAM, SKINCOLOR_TEA, - SKINCOLOR_ARMY, SKINCOLOR_PISTACHIO, SKINCOLOR_MOSS, SKINCOLOR_MINT, @@ -281,6 +280,7 @@ typedef enum SKINCOLOR_TEAL, SKINCOLOR_CYAN, SKINCOLOR_CERULEAN, + SKINCOLOR_JAWZ, // Oni's torment SKINCOLOR_SLATE, SKINCOLOR_STEEL, SKINCOLOR_PERIWINKLE, diff --git a/src/k_kart.c b/src/k_kart.c index b1438a16c..ed4043c5e 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -43,55 +43,55 @@ const char *KartColor_Names[MAXSKINCOLORS] = { "None", // 00 // SKINCOLOR_NONE - "Ivory", // 01 // SKINCOLOR_IVORY - "White", // 02 // SKINCOLOR_WHITE - "Silver", // 03 // SKINCOLOR_SILVER - "Cloudy", // 04 // SKINCOLOR_CLOUDY - "Grey", // 05 // SKINCOLOR_GREY - "Nickel", // 06 // SKINCOLOR_NICKEL - "Black", // 07 // SKINCOLOR_BLACK - "Salmon", // 08 // SKINCOLOR_SALMON - "Pink", // 09 // SKINCOLOR_PINK - "Rose", // 10 // SKINCOLOR_ROSE - "Raspberry", // 11 // SKINCOLOR_RASPBERRY - "Red", // 12 // SKINCOLOR_RED - "Ruby", // 13 // SKINCOLOR_RUBY - "Crimson", // 14 // SKINCOLOR_CRIMSON - "Dawn", // 15 // SKINCOLOR_DAWN - "Creamsicle", // 16 // SKINCOLOR_CREAMSICLE - "Orange", // 17 // SKINCOLOR_ORANGE - "Pumpkin", // 18 // SKINCOLOR_PUMPKIN - "Rosewood", // 19 // SKINCOLOR_ROSEWOOD - "Burgundy", // 20 // SKINCOLOR_BURGUNDY - "Bronze", // 21 // SKINCOLOR_BRONZE - "Sepia", // 22 // SKINCOLOR_SEPIA - "Beige", // 23 // SKINCOLOR_BEIGE - "Brown", // 24 // SKINCOLOR_BROWN - "Leather", // 25 // SKINCOLOR_LEATHER - "Peach", // 26 // SKINCOLOR_PEACH - "Caramel", // 27 // SKINCOLOR_CARAMEL - "Tangerine", // 28 // SKINCOLOR_TANGERINE - "Gold", // 29 // SKINCOLOR_GOLD - "Vomit", // 30 // SKINCOLOR_VOMIT - "Yellow", // 31 // SKINCOLOR_YELLOW - "Canary", // 32 // SKINCOLOR_CANARY - "Olive", // 33 // SKINCOLOR_OLIVE - "Garden", // 34 // SKINCOLOR_GARDEN - "Lime", // 35 // SKINCOLOR_LIME + "White", // 01 // SKINCOLOR_WHITE + "Silver", // 02 // SKINCOLOR_SILVER + "Cloudy", // 03 // SKINCOLOR_CLOUDY + "Grey", // 04 // SKINCOLOR_GREY + "Black", // 05 // SKINCOLOR_BLACK + "Salmon", // 06 // SKINCOLOR_SALMON + "Pink", // 07 // SKINCOLOR_PINK + "Rose", // 08 // SKINCOLOR_ROSE + "Raspberry", // 09 // SKINCOLOR_RASPBERRY + "Red", // 10 // SKINCOLOR_RED + "Ruby", // 11 // SKINCOLOR_RUBY + "Crimson", // 12 // SKINCOLOR_CRIMSON + "Ketchup", // 13 // SKINCOLOR_KETCHUP + "Dawn", // 14 // SKINCOLOR_DAWN + "Creamsicle", // 15 // SKINCOLOR_CREAMSICLE + "Orange", // 16 // SKINCOLOR_ORANGE + "Pumpkin", // 17 // SKINCOLOR_PUMPKIN + "Rosewood", // 18 // SKINCOLOR_ROSEWOOD + "Burgundy", // 19 // SKINCOLOR_BURGUNDY + "Bronze", // 20 // SKINCOLOR_BRONZE + "Sepia", // 21 // SKINCOLOR_SEPIA + "Beige", // 22 // SKINCOLOR_BEIGE + "Brown", // 23 // SKINCOLOR_BROWN + "Leather", // 24 // SKINCOLOR_LEATHER + "Peach", // 25 // SKINCOLOR_PEACH + "Caramel", // 26 // SKINCOLOR_CARAMEL + "Tangerine", // 27 // SKINCOLOR_TANGERINE + "Gold", // 28 // SKINCOLOR_GOLD + "Vomit", // 29 // SKINCOLOR_VOMIT + "Yellow", // 30 // SKINCOLOR_YELLOW + "Mustard", // 31 // SKINCOLOR_MUSTARD + "Olive", // 32 // SKINCOLOR_OLIVE + "Garden", // 33 // SKINCOLOR_GARDEN + "Lime", // 34 // SKINCOLOR_LIME + "Dream", // 35 // SKINCOLOR_DREAM "Tea", // 36 // SKINCOLOR_TEA - "Army", // 37 // SKINCOLOR_ARMY - "Pistachio", // 38 // SKINCOLOR_PISTACHIO - "Moss", // 39 // SKINCOLOR_MOSS - "Mint", // 40 // SKINCOLOR_MINT - "Green", // 41 // SKINCOLOR_GREEN - "Robo-Hood", // 42 // SKINCOLOR_ROBOHOOD - "Pinetree", // 43 // SKINCOLOR_PINETREE - "Emerald", // 44 // SKINCOLOR_EMERALD - "Swamp", // 45 // SKINCOLOR_SWAMP - "Aqua", // 46 // SKINCOLOR_AQUA - "Teal", // 47 // SKINCOLOR_TEAL - "Cyan", // 48 // SKINCOLOR_CYAN - "Cerulean", // 49 // SKINCOLOR_CERULEAN + "Pistachio", // 37 // SKINCOLOR_PISTACHIO + "Moss", // 38 // SKINCOLOR_MOSS + "Mint", // 39 // SKINCOLOR_MINT + "Green", // 40 // SKINCOLOR_GREEN + "Robo-Hood", // 41 // SKINCOLOR_ROBOHOOD + "Pinetree", // 42 // SKINCOLOR_PINETREE + "Emerald", // 43 // SKINCOLOR_EMERALD + "Swamp", // 44 // SKINCOLOR_SWAMP + "Aqua", // 45 // SKINCOLOR_AQUA + "Teal", // 46 // SKINCOLOR_TEAL + "Cyan", // 47 // SKINCOLOR_CYAN + "Cerulean", // 48 // SKINCOLOR_CERULEAN + "Jawz", // 49 // SKINCOLOR_JAWZ "Slate", // 50 // SKINCOLOR_SLATE "Steel", // 51 // SKINCOLOR_STEEL "Periwinkle", // 52 // SKINCOLOR_PERIWINKLE @@ -112,87 +112,86 @@ const char *KartColor_Names[MAXSKINCOLORS] = const UINT8 KartColor_Opposite[MAXSKINCOLORS*2] = { SKINCOLOR_NONE,8, // 00 // SKINCOLOR_NONE - SKINCOLOR_BLACK,8, // 01 // SKINCOLOR_IVORY - SKINCOLOR_NICKEL,8, // 02 // SKINCOLOR_WHITE - SKINCOLOR_GREY,8, // 03 // SKINCOLOR_SILVER - SKINCOLOR_CLOUDY,8, // 04 // SKINCOLOR_CLOUDY - SKINCOLOR_SILVER,8, // 05 // SKINCOLOR_GREY - SKINCOLOR_WHITE,8, // 06 // SKINCOLOR_NICKEL - SKINCOLOR_IVORY,8, // 07 // SKINCOLOR_BLACK - SKINCOLOR_TEA,8, // 08 // SKINCOLOR_SALMON - SKINCOLOR_ARMY,8, // 09 // SKINCOLOR_PINK - SKINCOLOR_MOSS,8, // 10 // SKINCOLOR_ROSE - SKINCOLOR_MINT,10, // 11 // SKINCOLOR_RASPBERRY - SKINCOLOR_GREEN,8, // 12 // SKINCOLOR_RED - SKINCOLOR_EMERALD,6, // 13 // SKINCOLOR_RUBY - SKINCOLOR_PINETREE,6, // 14 // SKINCOLOR_CRIMSON - SKINCOLOR_DUSK,8, // 15 // SKINCOLOR_DAWN - SKINCOLOR_PERIWINKLE,8, // 16 // SKINCOLOR_CREAMSICLE - SKINCOLOR_BLUE,8, // 17 // SKINCOLOR_ORANGE - SKINCOLOR_BLUEBERRY,8, // 18 // SKINCOLOR_PUMPKIN - SKINCOLOR_NAVY,8, // 19 // SKINCOLOR_ROSEWOOD - SKINCOLOR_JET,8, // 20 // SKINCOLOR_BURGUNDY - SKINCOLOR_STEEL,8, // 21 // SKINCOLOR_BRONZE - SKINCOLOR_LEATHER,6, // 22 // SKINCOLOR_SEPIA - SKINCOLOR_BROWN,2, // 23 // SKINCOLOR_BEIGE - SKINCOLOR_BEIGE,8, // 24 // SKINCOLOR_BROWN - SKINCOLOR_SEPIA,8, // 25 // SKINCOLOR_LEATHER - SKINCOLOR_SLATE,8, // 26 // SKINCOLOR_PEACH - SKINCOLOR_TEAL,8, // 27 // SKINCOLOR_CARAMEL - SKINCOLOR_LIME,8, // 28 // SKINCOLOR_TANGERINE - SKINCOLOR_LAVENDER,6, // 29 // SKINCOLOR_GOLD - SKINCOLOR_ROBOHOOD,8, // 30 // SKINCOLOR_VOMIT - SKINCOLOR_BYZANTIUM,8, // 31 // SKINCOLOR_YELLOW - SKINCOLOR_PURPLE,8, // 32 // SKINCOLOR_CANARY - SKINCOLOR_INDIGO,8, // 33 // SKINCOLOR_OLIVE - SKINCOLOR_AQUA,8, // 34 // SKINCOLOR_GARDEN - SKINCOLOR_TANGERINE,8, // 35 // SKINCOLOR_LIME + SKINCOLOR_BLACK,8, // 01 // SKINCOLOR_WHITE + SKINCOLOR_GREY,8, // 02 // SKINCOLOR_SILVER + SKINCOLOR_CLOUDY,8, // 03 // SKINCOLOR_CLOUDY + SKINCOLOR_SILVER,8, // 04 // SKINCOLOR_GREY + SKINCOLOR_WHITE,8, // 05 // SKINCOLOR_BLACK + SKINCOLOR_TEA,8, // 06 // SKINCOLOR_SALMON + SKINCOLOR_PISTACHIO,8, // 07 // SKINCOLOR_PINK + SKINCOLOR_MOSS,8, // 08 // SKINCOLOR_ROSE + SKINCOLOR_MINT,10, // 09 // SKINCOLOR_RASPBERRY + SKINCOLOR_GREEN,8, // 10 // SKINCOLOR_RED + SKINCOLOR_SAPPHIRE,8, // 11 // SKINCOLOR_RUBY + SKINCOLOR_PINETREE,6, // 12 // SKINCOLOR_CRIMSON + SKINCOLOR_MUSTARD,6, // 13 // SKINCOLOR_KETCHUP + SKINCOLOR_DUSK,8, // 14 // SKINCOLOR_DAWN + SKINCOLOR_PERIWINKLE,8, // 15 // SKINCOLOR_CREAMSICLE + SKINCOLOR_BLUE,8, // 16 // SKINCOLOR_ORANGE + SKINCOLOR_BLUEBERRY,8, // 17 // SKINCOLOR_PUMPKIN + SKINCOLOR_NAVY,8, // 18 // SKINCOLOR_ROSEWOOD + SKINCOLOR_JET,8, // 19 // SKINCOLOR_BURGUNDY + SKINCOLOR_AQUA,8, // 20 // SKINCOLOR_BRONZE + SKINCOLOR_LEATHER,6, // 21 // SKINCOLOR_SEPIA + SKINCOLOR_BROWN,2, // 22 // SKINCOLOR_BEIGE + SKINCOLOR_BEIGE,8, // 23 // SKINCOLOR_BROWN + SKINCOLOR_SEPIA,8, // 24 // SKINCOLOR_LEATHER + SKINCOLOR_SLATE,8, // 25 // SKINCOLOR_PEACH + SKINCOLOR_STEEL,8, // 26 // SKINCOLOR_CARAMEL + SKINCOLOR_LIME,8, // 27 // SKINCOLOR_TANGERINE + SKINCOLOR_CYAN,8, // 28 // SKINCOLOR_GOLD + SKINCOLOR_ROBOHOOD,8, // 29 // SKINCOLOR_VOMIT + SKINCOLOR_CERULEAN,8, // 30 // SKINCOLOR_YELLOW + SKINCOLOR_KETCHUP,8, // 31 // SKINCOLOR_MUSTARD + SKINCOLOR_TEAL,8, // 32 // SKINCOLOR_OLIVE + SKINCOLOR_LAVENDER,8, // 33 // SKINCOLOR_GARDEN + SKINCOLOR_TANGERINE,8, // 34 // SKINCOLOR_LIME + SKINCOLOR_BYZANTIUM,6, // 35 // SKINCOLOR_DREAM SKINCOLOR_SALMON,8, // 36 // SKINCOLOR_TEA - SKINCOLOR_PINK,6, // 37 // SKINCOLOR_ARMY - SKINCOLOR_CYAN,8, // 38 // SKINCOLOR_PISTACHIO - SKINCOLOR_ROSE,8, // 39 // SKINCOLOR_MOSS - SKINCOLOR_RASPBERRY,6, // 40 // SKINCOLOR_MINT - SKINCOLOR_RED,8, // 41 // SKINCOLOR_GREEN - SKINCOLOR_VOMIT,8, // 42 // SKINCOLOR_ROBOHOOD - SKINCOLOR_CRIMSON,8, // 43 // SKINCOLOR_PINETREE - SKINCOLOR_RUBY,8, // 44 // SKINCOLOR_EMERALD - SKINCOLOR_SAPPHIRE,8, // 45 // SKINCOLOR_SWAMP - SKINCOLOR_GARDEN,10, // 46 // SKINCOLOR_AQUA - SKINCOLOR_CARAMEL,8, // 47 // SKINCOLOR_TEAL - SKINCOLOR_PISTACHIO,6, // 48 // SKINCOLOR_CYAN - SKINCOLOR_LILAC,8, // 49 // SKINCOLOR_CERULEAN + SKINCOLOR_PINK,8, // 37 // SKINCOLOR_PISTACHIO + SKINCOLOR_ROSE,8, // 38 // SKINCOLOR_MOSS + SKINCOLOR_RASPBERRY,6, // 39 // SKINCOLOR_MINT + SKINCOLOR_RED,8, // 40 // SKINCOLOR_GREEN + SKINCOLOR_VOMIT,8, // 41 // SKINCOLOR_ROBOHOOD + SKINCOLOR_CRIMSON,8, // 42 // SKINCOLOR_PINETREE + SKINCOLOR_PURPLE,8, // 43 // SKINCOLOR_EMERALD + SKINCOLOR_INDIGO,6, // 44 // SKINCOLOR_SWAMP + SKINCOLOR_BRONZE,7, // 45 // SKINCOLOR_AQUA + SKINCOLOR_OLIVE,10, // 46 // SKINCOLOR_TEAL + SKINCOLOR_GOLD,8, // 47 // SKINCOLOR_CYAN + SKINCOLOR_YELLOW,8, // 48 // SKINCOLOR_CERULEAN + SKINCOLOR_LILAC,6, // 49 // SKINCOLOR_JAWZ SKINCOLOR_PEACH,8, // 50 // SKINCOLOR_SLATE - SKINCOLOR_BRONZE,10, // 51 // SKINCOLOR_STEEL + SKINCOLOR_CARAMEL,8, // 51 // SKINCOLOR_STEEL SKINCOLOR_CREAMSICLE,8, // 52 // SKINCOLOR_PERIWINKLE SKINCOLOR_ORANGE,8, // 53 // SKINCOLOR_BLUE - SKINCOLOR_SWAMP,8, // 54 // SKINCOLOR_SAPPHIRE + SKINCOLOR_RUBY,8, // 54 // SKINCOLOR_SAPPHIRE SKINCOLOR_PUMPKIN,8, // 55 // SKINCOLOR_BLUEBERRY SKINCOLOR_ROSEWOOD,8, // 56 // SKINCOLOR_NAVY SKINCOLOR_BURGUNDY,6, // 57 // SKINCOLOR_JET SKINCOLOR_DAWN,8, // 58 // SKINCOLOR_DUSK - SKINCOLOR_CANARY,8, // 59 // SKINCOLOR_PURPLE - SKINCOLOR_GOLD,10, // 60 // SKINCOLOR_LAVENDER - SKINCOLOR_OLIVE,8, // 61 // SKINCOLOR_INDIGO - SKINCOLOR_YELLOW,8, // 62 // SKINCOLOR_BYZANTIUM - SKINCOLOR_CERULEAN,8 // 63 // SKINCOLOR_LILAC + SKINCOLOR_EMERALD,8, // 59 // SKINCOLOR_PURPLE + SKINCOLOR_GARDEN,8, // 60 // SKINCOLOR_LAVENDER + SKINCOLOR_SWAMP,6, // 61 // SKINCOLOR_INDIGO + SKINCOLOR_DREAM,8, // 62 // SKINCOLOR_BYZANTIUM + SKINCOLOR_JAWZ,6 // 63 // SKINCOLOR_LILAC }; UINT8 colortranslations[MAXSKINCOLORS][16] = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // SKINCOLOR_NONE - {120, 120, 120, 120, 0, 1, 3, 4, 6, 7, 10, 14, 18, 22, 25, 28}, // SKINCOLOR_IVORY - {120, 120, 0, 1, 3, 4, 6, 7, 9, 11, 13, 16, 19, 23, 26, 29}, // SKINCOLOR_WHITE + {120, 120, 120, 120, 0, 1, 3, 4, 6, 7, 10, 14, 18, 22, 25, 28}, // SKINCOLOR_WHITE { 0, 1, 3, 5, 6, 8, 10, 11, 13, 15, 16, 18, 20, 24, 27, 30}, // SKINCOLOR_SILVER { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31}, // SKINCOLOR_CLOUDY { 8, 9, 10, 12, 13, 15, 16, 19, 19, 20, 21, 23, 25, 27, 29, 31}, // SKINCOLOR_GREY - { 16, 16, 17, 18, 19, 20, 21, 23, 24, 25, 26, 27, 28, 29, 30, 31}, // SKINCOLOR_NICKEL { 16, 17, 19, 21, 22, 24, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31}, // SKINCOLOR_BLACK {120, 120, 120, 121, 121, 122, 122, 123, 124, 125, 126, 128, 129, 131, 133, 135}, // SKINCOLOR_SALMON - {121, 121, 121, 121, 121, 122, 144, 145, 146, 147, 148, 149, 150, 150, 150, 151}, // SKINCOLOR_PINK + {121, 121, 122, 144, 144, 145, 145, 146, 147, 148, 149, 150, 151, 134, 136, 138}, // SKINCOLOR_PINK {144, 145, 146, 147, 148, 149, 150, 151, 134, 135, 136, 137, 138, 139, 140, 141}, // SKINCOLOR_ROSE {120, 121, 122, 123, 124, 125, 126, 127, 128, 130, 131, 133, 134, 136, 137, 139}, // SKINCOLOR_RASPBERRY {125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140}, // SKINCOLOR_RED - {120, 121, 144, 146, 149, 132, 132, 133, 134, 135, 197, 197, 198, 198, 199, 255}, // SKINCOLOR_RUBY + {121, 122, 145, 146, 147, 149, 131, 132, 133, 134, 135, 197, 197, 198, 199, 255}, // SKINCOLOR_RUBY {130, 131, 132, 133, 134, 136, 137, 138, 139, 139, 140, 140, 141, 141, 142, 143}, // SKINCOLOR_CRIMSON + {104, 113, 113, 85, 86, 88, 128, 129, 131, 133, 134, 136, 138, 139, 141, 143}, // SKINCOLOR_KETCHUP {120, 121, 122, 123, 124, 147, 147, 148, 90, 91, 92, 93, 94, 95, 152, 154}, // SKINCOLOR_DAWN {120, 120, 80, 80, 81, 82, 83, 83, 84, 85, 86, 88, 89, 91, 93, 95}, // SKINCOLOR_CREAMSICLE { 80, 81, 82, 83, 84, 85, 86, 88, 89, 91, 94, 95, 154, 156, 158, 159}, // SKINCOLOR_ORANGE @@ -210,12 +209,12 @@ UINT8 colortranslations[MAXSKINCOLORS][16] = { {112, 112, 112, 113, 113, 114, 114, 115, 115, 116, 116, 117, 117, 118, 118, 119}, // SKINCOLOR_GOLD {121, 144, 145, 72, 73, 84, 114, 115, 107, 108, 109, 183, 223, 207, 30, 246}, // SKINCOLOR_VOMIT { 96, 97, 98, 100, 101, 102, 104, 113, 114, 115, 116, 117, 118, 119, 156, 159}, // SKINCOLOR_YELLOW - { 96, 97, 99, 100, 102, 104, 105, 105, 106, 107, 107, 108, 109, 109, 110, 111}, // SKINCOLOR_CANARY + { 96, 98, 99, 112, 113, 114, 114, 106, 106, 107, 107, 108, 108, 109, 110, 111}, // SKINCOLOR_MUSTARD {105, 105, 105, 106, 106, 107, 107, 108, 108, 109, 109, 110, 110, 111, 111, 31}, // SKINCOLOR_OLIVE { 98, 99, 112, 101, 113, 114, 106, 179, 180, 180, 181, 182, 183, 173, 174, 175}, // SKINCOLOR_GARDEN { 96, 97, 99, 100, 102, 104, 160, 162, 164, 166, 168, 171, 223, 223, 207, 31}, // SKINCOLOR_LIME + { 96, 98, 99, 112, 113, 178, 179, 165, 203, 203, 204, 204, 205, 205, 206, 207}, // SKINCOLOR_DREAM {120, 120, 176, 176, 176, 177, 177, 178, 178, 179, 180, 180, 181, 181, 182, 183}, // SKINCOLOR_TEA - {176, 176, 176, 177, 177, 178, 178, 179, 179, 180, 180, 181, 181, 182, 182, 183}, // SKINCOLOR_ARMY {120, 120, 176, 176, 177, 177, 178, 179, 165, 166, 167, 168, 169, 170, 171, 172}, // SKINCOLOR_PISTACHIO {178, 178, 178, 179, 179, 180, 181, 182, 183, 172, 172, 173, 173, 174, 174, 175}, // SKINCOLOR_MOSS {120, 176, 176, 176, 177, 163, 164, 165, 167, 221, 221, 222, 223, 207, 207, 31}, // SKINCOLOR_MINT @@ -228,6 +227,7 @@ UINT8 colortranslations[MAXSKINCOLORS][16] = { {210, 213, 220, 220, 220, 221, 221, 221, 221, 222, 222, 222, 223, 223, 191, 31}, // SKINCOLOR_TEAL {120, 208, 209, 210, 211, 212, 213, 215, 216, 216, 216, 217, 217, 218, 218, 219}, // SKINCOLOR_CYAN {208, 209, 211, 213, 215, 216, 216, 217, 217, 218, 218, 219, 205, 206, 207, 207}, // SKINCOLOR_CERULEAN + {120, 120, 208, 209, 210, 226, 215, 216, 217, 229, 229, 205, 205, 206, 207, 31}, // SKINCOLOR_JAWZ {120, 120, 200, 200, 200, 201, 201, 201, 202, 202, 202, 203, 204, 205, 206, 207}, // SKINCOLOR_SLATE {120, 200, 200, 201, 201, 202, 202, 203, 203, 204, 204, 205, 205, 206, 207, 31}, // SKINCOLOR_STEEL {120, 224, 225, 226, 226, 227, 228, 228, 229, 230, 231, 234, 235, 237, 239, 241}, // SKINCOLOR_PERIWINKLE @@ -243,9 +243,9 @@ UINT8 colortranslations[MAXSKINCOLORS][16] = { {192, 248, 249, 250, 251, 252, 253, 254, 255, 255, 29, 29, 30, 30, 31, 31}, // SKINCOLOR_BYZANTIUM {120, 120, 120, 121, 121, 122, 122, 123, 192, 248, 249, 250, 251, 252, 253, 254}, // SKINCOLOR_LILAC /* Removed Colours - {120, 121, 123, 124, 126, 127, 129, 130, 132, 133, 135, 136, 138, 139, 141, 143}, // SKINCOLOR_RUBY, removed for other colors + {120, 121, 123, 124, 126, 127, 129, 130, 132, 133, 135, 136, 138, 139, 141, 143}, // old SKINCOLOR_RUBY, removed for other colors { 80, 81, 83, 85, 86, 88, 90, 91, 93, 95, 152, 153, 154, 156, 157, 159}, // SKINCOLOR_AMBER, removed for other colors - {224, 225, 226, 228, 229, 231, 232, 234, 235, 237, 238, 240, 241, 243, 244, 246}, // SKINCOLOR_SAPPHIRE, removed for other colors + {224, 225, 226, 228, 229, 231, 232, 234, 235, 237, 238, 240, 241, 243, 244, 246}, // old SKINCOLOR_SAPPHIRE, removed for other colors {160, 160, 160, 184, 184, 184, 185, 185, 185, 186, 187, 187, 188, 188, 189, 190}, // SKINCOLOR_JADE, removed for other colors {224, 225, 226, 212, 213, 213, 214, 215, 220, 221, 172, 222, 173, 223, 174, 175}, // SKINCOLOR_FROST, merged into Aqua { 72, 73, 74, 75, 76, 77, 78, 79, 48, 49, 50, 51, 52, 53, 54, 55}, // SKINCOLOR_CARAMEL, new Caramel was previously Shiny Caramel @@ -2215,7 +2215,6 @@ static void K_SpawnDriftSparks(player_t *player) { fixed_t newx; fixed_t newy; - //fixed_t ground; mobj_t *spark; angle_t travelangle; INT32 i; @@ -2233,25 +2232,12 @@ static void K_SpawnDriftSparks(player_t *player) if (!player->kartstuff[k_drift] || player->kartstuff[k_driftcharge] < K_GetKartDriftSparkValue(player)) return; - /*if (player->mo->eflags & MFE_VERTICALFLIP) - ground = player->mo->ceilingz - FixedMul(mobjinfo[MT_DRIFTSPARK].height, player->mo->scale); - else - ground = player->mo->floorz;*/ - travelangle = player->mo->angle-(ANGLE_45/5)*player->kartstuff[k_drift]; for (i = 0; i < 2; i++) { newx = player->mo->x + P_ReturnThrustX(player->mo, travelangle + ((i&1) ? -1 : 1)*ANGLE_135, FixedMul(32*FRACUNIT, player->mo->scale)); newy = player->mo->y + P_ReturnThrustY(player->mo, travelangle + ((i&1) ? -1 : 1)*ANGLE_135, FixedMul(32*FRACUNIT, player->mo->scale)); -/*#ifdef ESLOPE - if (player->mo->standingslope) - { - ground = P_GetZAt(player->mo->standingslope, newx, newy); - if (player->mo->eflags & MFE_VERTICALFLIP) - ground -= FixedMul(mobjinfo[MT_DRIFTSPARK].height, player->mo->scale); - } -#endif*/ spark = P_SpawnMobj(newx, newy, player->mo->z, MT_DRIFTSPARK); P_SetTarget(&spark->target, player->mo); From 7532e58a8c019fa8c4a94dbb97e8171737dca329 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 13 Sep 2018 03:04:01 -0400 Subject: [PATCH 113/146] Tweak these blues Try to make all the blues using this range look a little different, you know? - Cyan is brighter, and has more contrast. - Teal has 1 more shade of blue for slightly better anti-aliasing. --- src/k_kart.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index ed4043c5e..a05880da8 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -224,8 +224,8 @@ UINT8 colortranslations[MAXSKINCOLORS][16] = { {160, 184, 184, 185, 185, 186, 186, 187, 187, 188, 188, 189, 189, 190, 191, 175}, // SKINCOLOR_EMERALD {186, 187, 188, 188, 188, 189, 189, 190, 190, 191, 175, 175, 30, 30, 31, 31}, // SKINCOLOR_SWAMP {120, 208, 208, 210, 212, 214, 220, 220, 220, 221, 221, 222, 222, 223, 223, 191}, // SKINCOLOR_AQUA - {210, 213, 220, 220, 220, 221, 221, 221, 221, 222, 222, 222, 223, 223, 191, 31}, // SKINCOLOR_TEAL - {120, 208, 209, 210, 211, 212, 213, 215, 216, 216, 216, 217, 217, 218, 218, 219}, // SKINCOLOR_CYAN + {210, 213, 220, 220, 220, 216, 216, 221, 221, 221, 222, 222, 223, 223, 191, 31}, // SKINCOLOR_TEAL + {120, 120, 208, 208, 209, 210, 211, 212, 213, 215, 216, 217, 218, 219, 222, 223}, // SKINCOLOR_CYAN {208, 209, 211, 213, 215, 216, 216, 217, 217, 218, 218, 219, 205, 206, 207, 207}, // SKINCOLOR_CERULEAN {120, 120, 208, 209, 210, 226, 215, 216, 217, 229, 229, 205, 205, 206, 207, 31}, // SKINCOLOR_JAWZ {120, 120, 200, 200, 200, 201, 201, 201, 202, 202, 202, 203, 204, 205, 206, 207}, // SKINCOLOR_SLATE From 14ced23300db4e9f04bf36774c7362446b3274cc Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 13 Sep 2018 20:26:43 -0400 Subject: [PATCH 114/146] Speed lines --- src/dehacked.c | 11 +++++++++++ src/info.c | 48 ++++++++++++++++++++++++++++++++++++++++++------ src/info.h | 12 ++++++++++++ src/k_kart.c | 13 +++++++++++++ 4 files changed, 78 insertions(+), 6 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 54d876189..3083b2050 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -6247,6 +6247,16 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_DRIFTDUST3", "S_DRIFTDUST4", + // Fast lines + "S_FASTLINE1", + "S_FASTLINE2", + "S_FASTLINE3", + "S_FASTLINE4", + "S_FASTLINE5", + "S_FASTLINE6", + "S_FASTLINE7", + "S_FASTLINE8", + // Thunder Shield Burst // Sneaker boost effect @@ -7219,6 +7229,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_RANDOMITEM", "MT_RANDOMITEMPOP", + "MT_FASTLINE", "MT_BOOSTFLAME", "MT_BOOSTSMOKE", "MT_SNEAKERTRAIL", diff --git a/src/info.c b/src/info.c index 47b9e2c76..00819753b 100644 --- a/src/info.c +++ b/src/info.c @@ -55,12 +55,12 @@ char sprnames[NUMSPRITES + 1][5] = "GWLR","SRBA","SRBB","SRBC","SRBD","SRBE","SRBF","SRBG","SRBH","SRBI", "SRBJ","SRBK","SRBL","SRBM","SRBN","SRBO", //SRB2kart Sprites - "SPRG","BSPR","RNDM","RPOP","BOST","BOSM","KFRE","KINV","KINF","WIPD", - "DRIF","DUST","FITM","BANA","ORBN","JAWZ","SSMN","KRBM","BHOG","BHBM", - "BLIG","LIGH","THNS","SINK","SITR","KBLN","DEZL","POKE","AUDI","DECO", - "DOOD","SNES","GBAS","SPRS","BUZB","CHOM","SACO","CRAB","SHAD","BRNG", - "BUMP","FLEN","CLAS","PSHW","ISTA","ISTB","ARRO","ITEM","ITMO","ITMI", - "ITMN","WANT","PBOM","RETI","VIEW" + "SPRG","BSPR","RNDM","RPOP","FAST","BOST","BOSM","KFRE","KINV","KINF", + "WIPD","DRIF","DUST","FITM","BANA","ORBN","JAWZ","SSMN","KRBM","BHOG", + "BHBM","BLIG","LIGH","THNS","SINK","SITR","KBLN","DEZL","POKE","AUDI", + "DECO","DOOD","SNES","GBAS","SPRS","BUZB","CHOM","SACO","CRAB","SHAD", + "BRNG","BUMP","FLEN","CLAS","PSHW","ISTA","ISTB","ARRO","ITEM","ITMO", + "ITMI","ITMN","WANT","PBOM","RETI","VIEW" }; // Doesn't work with g++, needs actionf_p1 (don't modify this comment) @@ -2580,6 +2580,15 @@ state_t states[NUMSTATES] = {SPR_DUST, FF_TRANS20|2, 3, {NULL}, 0, 0, S_DRIFTDUST4}, // S_DRIFTDUST3 {SPR_DUST, FF_TRANS20|3, 3, {NULL}, 0, 0, S_NULL}, // S_DRIFTDUST4 + {SPR_FAST, FF_PAPERSPRITE|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_FASTLINE2}, // S_FASTLINE1 + {SPR_FAST, FF_PAPERSPRITE|FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_FASTLINE3}, // S_FASTLINE2 + {SPR_FAST, FF_PAPERSPRITE|FF_FULLBRIGHT|2, 1, {NULL}, 0, 0, S_FASTLINE4}, // S_FASTLINE3 + {SPR_FAST, FF_PAPERSPRITE|FF_FULLBRIGHT|3, 1, {NULL}, 0, 0, S_FASTLINE5}, // S_FASTLINE4 + {SPR_FAST, FF_PAPERSPRITE|FF_FULLBRIGHT|4, 1, {NULL}, 0, 0, S_FASTLINE6}, // S_FASTLINE5 + {SPR_FAST, FF_PAPERSPRITE|FF_FULLBRIGHT|5, 1, {NULL}, 0, 0, S_FASTLINE7}, // S_FASTLINE6 + {SPR_FAST, FF_PAPERSPRITE|FF_FULLBRIGHT|6, 1, {NULL}, 0, 0, S_FASTLINE8}, // S_FASTLINE7 + {SPR_FAST, FF_PAPERSPRITE|FF_FULLBRIGHT|7, 1, {NULL}, 0, 0, S_NULL}, // S_FASTLINE8 + {SPR_BOST, FF_FULLBRIGHT|FF_ANIMATE, TICRATE, {NULL}, 6, 1, S_BOOSTSMOKESPAWNER}, // S_BOOSTFLAME {SPR_NULL, 0, TICRATE/2, {NULL}, 0, 0, S_NULL}, // S_BOOSTSMOKESPAWNER @@ -14402,6 +14411,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_FASTLINE + -1, // doomednum + S_FASTLINE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 8, // speed + 14*FRACUNIT, // radius + 14*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + { // MT_BOOSTFLAME -1, // doomednum S_BOOSTFLAME, // spawnstate diff --git a/src/info.h b/src/info.h index b359bef56..0fb0f9c16 100644 --- a/src/info.h +++ b/src/info.h @@ -582,6 +582,7 @@ typedef enum sprite SPR_RNDM, // Random Item Box SPR_RPOP, // Random Item Box Pop + SPR_FAST, // Speed boost trail SPR_BOST, // Sneaker booster flame SPR_BOSM, // Sneaker booster smoke SPR_KFRE, // Sneaker fire trail @@ -3094,6 +3095,16 @@ typedef enum state S_DRIFTDUST3, S_DRIFTDUST4, + // Fast lines + S_FASTLINE1, + S_FASTLINE2, + S_FASTLINE3, + S_FASTLINE4, + S_FASTLINE5, + S_FASTLINE6, + S_FASTLINE7, + S_FASTLINE8, + // Magnet Burst // Sneaker boost effect @@ -4083,6 +4094,7 @@ typedef enum mobj_type MT_RANDOMITEM, MT_RANDOMITEMPOP, + MT_FASTLINE, MT_BOOSTFLAME, MT_BOOSTSMOKE, MT_SNEAKERTRAIL, diff --git a/src/k_kart.c b/src/k_kart.c index a05880da8..373bba041 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3309,6 +3309,19 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) K_UpdateOffroad(player); K_GetKartBoostPower(player); + // Speed lines + if (player->kartstuff[k_speedboost] > FRACUNIT/8 && (leveltime & 1)) + { + mobj_t *fast = P_SpawnMobj(player->mo->x + (P_RandomRange(-32,32)<mo->y + (P_RandomRange(-32,32)<mo->z + (player->mo->height/2) + (P_RandomRange(-24,24)<angle = R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy); + fast->momx = player->mo->momx/2; + fast->momy = player->mo->momy/2; + fast->momz = player->mo->momz/2; + } + if (player->kartstuff[k_eggmanexplode]) // You're gonna diiiiie { const INT32 flashtime = 4<<(player->kartstuff[k_eggmanexplode]/TICRATE); From 1863fb953dbb78afb77fe1bd171c3a8d8a1e1d49 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 13 Sep 2018 23:29:14 -0400 Subject: [PATCH 115/146] Ketchup, faster drift sparks --- src/k_kart.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 373bba041..0aa6934f5 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2252,9 +2252,9 @@ static void K_SpawnDriftSparks(player_t *player) if (player->kartstuff[k_driftcharge] >= K_GetKartDriftSparkValue(player)*2) { if (player->kartstuff[k_driftcharge] <= (K_GetKartDriftSparkValue(player)*2)+(32*3)) - spark->color = SKINCOLOR_DUSK; // transition + spark->color = SKINCOLOR_RASPBERRY; // transition else - spark->color = SKINCOLOR_RUBY; + spark->color = SKINCOLOR_KETCHUP; } else spark->color = SKINCOLOR_SAPPHIRE; From 80177931c3d87bceb7fa78927793945ac8ee1881 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 13 Sep 2018 23:39:41 -0400 Subject: [PATCH 116/146] Rainbow sparks --- src/k_kart.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 0aa6934f5..910ee8c16 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2249,9 +2249,13 @@ static void K_SpawnDriftSparks(player_t *player) spark->momy = player->mo->momy/2; //spark->momz = player->mo->momz/2; - if (player->kartstuff[k_driftcharge] >= K_GetKartDriftSparkValue(player)*2) + if (player->kartstuff[k_driftcharge] >= K_GetKartDriftSparkValue(player)*4) { - if (player->kartstuff[k_driftcharge] <= (K_GetKartDriftSparkValue(player)*2)+(32*3)) + spark->color = (UINT8)(1 + (leveltime % (MAXSKINCOLORS-1))); + } + else if (player->kartstuff[k_driftcharge] >= K_GetKartDriftSparkValue(player)*2) + { + if (player->kartstuff[k_driftcharge] <= (K_GetKartDriftSparkValue(player)*2)+(24*3)) spark->color = SKINCOLOR_RASPBERRY; // transition else spark->color = SKINCOLOR_KETCHUP; @@ -3760,6 +3764,7 @@ static void K_KartDrift(player_t *player, boolean onground) { fixed_t dsone = K_GetKartDriftSparkValue(player); fixed_t dstwo = dsone*2; + fixed_t dsthree = dstwo*2; // Drifting is actually straffing + automatic turning. // Holding the Jump button will enable drifting. @@ -3783,13 +3788,22 @@ static void K_KartDrift(player_t *player, boolean onground) } else if ((player->kartstuff[k_drift] != -5 && player->kartstuff[k_drift] != 5) // || (player->kartstuff[k_drift] >= 1 && player->kartstuff[k_turndir] != 1) || (player->kartstuff[k_drift] <= -1 && player->kartstuff[k_turndir] != -1)) - && player->kartstuff[k_driftcharge] >= dstwo + && player->kartstuff[k_driftcharge] < dsthree && onground) { player->kartstuff[k_driftboost] = 50; S_StartSound(player->mo, sfx_s23c); player->kartstuff[k_driftcharge] = 0; } + else if ((player->kartstuff[k_drift] != -5 && player->kartstuff[k_drift] != 5) + // || (player->kartstuff[k_drift] >= 1 && player->kartstuff[k_turndir] != 1) || (player->kartstuff[k_drift] <= -1 && player->kartstuff[k_turndir] != -1)) + && player->kartstuff[k_driftcharge] >= dsthree + && onground) + { + player->kartstuff[k_driftboost] = 80; + S_StartSound(player->mo, sfx_s23c); + player->kartstuff[k_driftcharge] = 0; + } // Drifting: left or right? if ((player->cmd.driftturn > 0) && player->speed > FixedMul(10<<16, player->mo->scale) && player->kartstuff[k_jmp] == 1 @@ -6566,6 +6580,7 @@ static void K_drawKartFirstPerson(void) { fixed_t dsone = K_GetKartDriftSparkValue(stplyr); fixed_t dstwo = dsone*2; + fixed_t dsthree = dstwo*2; #ifndef DONTLIKETOASTERSFPTWEAKS { @@ -6604,8 +6619,10 @@ static void K_drawKartFirstPerson(void) } // drift sparks! - if ((leveltime & 1) && (stplyr->kartstuff[k_driftcharge] >= dstwo)) - colmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_TANGERINE, 0); + if ((leveltime & 1) && (stplyr->kartstuff[k_driftcharge] >= dsthree)) + colmap = R_GetTranslationColormap(TC_RAINBOW, (UINT8)(1 + (leveltime % (MAXSKINCOLORS-1))), 0); + else if ((leveltime & 1) && (stplyr->kartstuff[k_driftcharge] >= dstwo)) + colmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_KETCHUP, 0); else if ((leveltime & 1) && (stplyr->kartstuff[k_driftcharge] >= dsone)) colmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_SAPPHIRE, 0); else From 078fa2924790686bdfaf246ae12ea61fe1a1ba4e Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sat, 15 Sep 2018 01:24:29 -0400 Subject: [PATCH 117/146] Updated speed lines --- src/dehacked.c | 3 --- src/info.c | 5 +---- src/info.h | 3 --- src/k_kart.c | 14 +++++++------- 4 files changed, 8 insertions(+), 17 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 3083b2050..05be25837 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -6253,9 +6253,6 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_FASTLINE3", "S_FASTLINE4", "S_FASTLINE5", - "S_FASTLINE6", - "S_FASTLINE7", - "S_FASTLINE8", // Thunder Shield Burst diff --git a/src/info.c b/src/info.c index 00819753b..74a7a4d34 100644 --- a/src/info.c +++ b/src/info.c @@ -2584,10 +2584,7 @@ state_t states[NUMSTATES] = {SPR_FAST, FF_PAPERSPRITE|FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_FASTLINE3}, // S_FASTLINE2 {SPR_FAST, FF_PAPERSPRITE|FF_FULLBRIGHT|2, 1, {NULL}, 0, 0, S_FASTLINE4}, // S_FASTLINE3 {SPR_FAST, FF_PAPERSPRITE|FF_FULLBRIGHT|3, 1, {NULL}, 0, 0, S_FASTLINE5}, // S_FASTLINE4 - {SPR_FAST, FF_PAPERSPRITE|FF_FULLBRIGHT|4, 1, {NULL}, 0, 0, S_FASTLINE6}, // S_FASTLINE5 - {SPR_FAST, FF_PAPERSPRITE|FF_FULLBRIGHT|5, 1, {NULL}, 0, 0, S_FASTLINE7}, // S_FASTLINE6 - {SPR_FAST, FF_PAPERSPRITE|FF_FULLBRIGHT|6, 1, {NULL}, 0, 0, S_FASTLINE8}, // S_FASTLINE7 - {SPR_FAST, FF_PAPERSPRITE|FF_FULLBRIGHT|7, 1, {NULL}, 0, 0, S_NULL}, // S_FASTLINE8 + {SPR_FAST, FF_PAPERSPRITE|FF_FULLBRIGHT|4, 1, {NULL}, 0, 0, S_NULL}, // S_FASTLINE5 {SPR_BOST, FF_FULLBRIGHT|FF_ANIMATE, TICRATE, {NULL}, 6, 1, S_BOOSTSMOKESPAWNER}, // S_BOOSTFLAME {SPR_NULL, 0, TICRATE/2, {NULL}, 0, 0, S_NULL}, // S_BOOSTSMOKESPAWNER diff --git a/src/info.h b/src/info.h index 0fb0f9c16..8d27944f5 100644 --- a/src/info.h +++ b/src/info.h @@ -3101,9 +3101,6 @@ typedef enum state S_FASTLINE3, S_FASTLINE4, S_FASTLINE5, - S_FASTLINE6, - S_FASTLINE7, - S_FASTLINE8, // Magnet Burst diff --git a/src/k_kart.c b/src/k_kart.c index 910ee8c16..94cdc399f 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3314,16 +3314,16 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) K_GetKartBoostPower(player); // Speed lines - if (player->kartstuff[k_speedboost] > FRACUNIT/8 && (leveltime & 1)) + if ((player->kartstuff[k_sneakertimer] || player->kartstuff[k_driftboost] || player->kartstuff[k_startboost]) && player->speed > 0) { - mobj_t *fast = P_SpawnMobj(player->mo->x + (P_RandomRange(-32,32)<mo->y + (P_RandomRange(-32,32)<mo->z + (player->mo->height/2) + (P_RandomRange(-24,24)<mo->x + (P_RandomRange(-36,36)<mo->y + (P_RandomRange(-36,36)<mo->z + (player->mo->height/2) + (P_RandomRange(-20,20)<angle = R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy); - fast->momx = player->mo->momx/2; - fast->momy = player->mo->momy/2; - fast->momz = player->mo->momz/2; + fast->momx = 3*player->mo->momx/4; + fast->momy = 3*player->mo->momy/4; + fast->momz = 3*player->mo->momz/4; } if (player->kartstuff[k_eggmanexplode]) // You're gonna diiiiie From 17660379dea009e99cbdb255cbea6ebc7b74e182 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sat, 15 Sep 2018 01:29:38 -0400 Subject: [PATCH 118/146] Grow/Shrink fixed min speed --- src/p_map.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_map.c b/src/p_map.c index 88045a3e1..41d61cb05 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -188,7 +188,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) P_InstaThrustEvenIn2D(object, spring->angle, FixedMul(horizspeed,FixedSqrt(FixedMul(hscale, spring->scale)))); else { - fixed_t finalSpeed = horizspeed; + fixed_t finalSpeed = FixedDiv(horizspeed, hscale); fixed_t pSpeed = object->player->speed; if (pSpeed > finalSpeed) From 7f92aaba66f70f35eabcade489aa4b69d19658b3 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sat, 15 Sep 2018 19:59:39 -0400 Subject: [PATCH 119/146] Buff rainbow sparks --- src/k_kart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index 94cdc399f..78e3cbd59 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3800,7 +3800,7 @@ static void K_KartDrift(player_t *player, boolean onground) && player->kartstuff[k_driftcharge] >= dsthree && onground) { - player->kartstuff[k_driftboost] = 80; + player->kartstuff[k_driftboost] = 125; S_StartSound(player->mo, sfx_s23c); player->kartstuff[k_driftcharge] = 0; } From 30c37ee4401c693083f313e0ea7bb61d190bb0ee Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sat, 15 Sep 2018 20:13:29 -0400 Subject: [PATCH 120/146] Revert this now that we have ESC functionality (I mean. I still think this feels nicer than pressing the menu button, but...) --- src/m_menu.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index e697b9151..54f9e9399 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -2737,10 +2737,9 @@ boolean M_Responder(event_t *ev) } // Why _does_ backspace go back anyway? - // Sal: Because it supports gamepads better. And still makes sense for keyboard. - currentMenu->lastOn = itemOn; - if (currentMenu->prevMenu) - M_SetupNextMenu(currentMenu->prevMenu); + //currentMenu->lastOn = itemOn; + //if (currentMenu->prevMenu) + // M_SetupNextMenu(currentMenu->prevMenu); return false; default: From 05456a4a0fd51eae946b001d83c075f885b47653 Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Sun, 16 Sep 2018 11:01:00 +0200 Subject: [PATCH 121/146] Fixed crash when replacing first character. --- src/hu_stuff.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 293031571..794a89d76 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -856,6 +856,9 @@ static inline boolean HU_keyInChatString(char *s, char ch) { if (s[m]) s[m+1] = (s[m]); + + if (m < 1) + break; // fix the chat going ham if your replace the first character. (For whatever reason this didn't happen in vanilla????) } s[c_input] = ch; // and replace this. } From 05ad8937b341ec4385e5c761dad4121879b6954e Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sun, 16 Sep 2018 18:10:29 -0400 Subject: [PATCH 122/146] Alternate TC_RAINBOW Leaving behind a commented out define for now because I dunno if I like it yet --- src/k_kart.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 78e3cbd59..9966b5573 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -253,6 +253,8 @@ UINT8 colortranslations[MAXSKINCOLORS][16] = { */ }; +//#define SALLYALTRAINBOW // Sal's edited version of the below, which keeps a colors' lightness, and looks better with hue-shifted colors like Ruby & Dream. Not strictly *better*, just different... + /** \brief Generates the rainbow colourmaps that are used when a player has the invincibility power \param dest_colormap colormap to populate @@ -260,10 +262,12 @@ UINT8 colortranslations[MAXSKINCOLORS][16] = { */ void K_RainbowColormap(UINT8 *dest_colormap, UINT8 skincolor) { - INT32 i, j; + INT32 i; RGBA_t color; - UINT8 colorbrightnesses[16]; UINT8 brightness; +#ifndef SALLYALTRAINBOW + INT32 j; + UINT8 colorbrightnesses[16]; UINT16 brightdif; INT32 temp; @@ -273,6 +277,7 @@ void K_RainbowColormap(UINT8 *dest_colormap, UINT8 skincolor) color = V_GetColor(colortranslations[skincolor][i]); colorbrightnesses[i] = (UINT8)(((UINT16)color.s.red + (UINT16)color.s.green + (UINT16)color.s.blue)/3); } +#endif // next, for every colour in the palette, choose the transcolor that has the closest brightness for (i = 0; i < NUM_PALETTE_ENTRIES; i++) @@ -284,6 +289,10 @@ void K_RainbowColormap(UINT8 *dest_colormap, UINT8 skincolor) } color = V_GetColor(i); brightness = (UINT8)(((UINT16)color.s.red + (UINT16)color.s.green + (UINT16)color.s.blue)/3); +#ifdef SALLYALTRAINBOW + brightness = 15-(brightness/16); // Yes, 15. + dest_colormap[i] = colortranslations[skincolor][brightness]; +#else brightdif = 256; for (j = 0; j < 16; j++) { @@ -294,6 +303,7 @@ void K_RainbowColormap(UINT8 *dest_colormap, UINT8 skincolor) dest_colormap[i] = colortranslations[skincolor][j]; } } +#endif } } From 60c5eb372b7ff2c34e265845eb029a30baf0bf93 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sun, 16 Sep 2018 23:28:10 -0400 Subject: [PATCH 123/146] New color brightness formula Gets more accurate looking results --- src/hardware/hw_md2.c | 17 ++++++++++++++--- src/k_kart.c | 15 +++++++++++++-- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 2446b023b..f87f187ad 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -948,6 +948,15 @@ spritemd2found: fclose(f); } +// Define for getting accurate color brightness readings according to how the human eye sees them. +// https://en.wikipedia.org/wiki/Relative_luminance +// 0.2126 to red +// 0.7152 to green +// 0.0722 to blue +// (See this same define in k_kart.c!) +#define SETBRIGHTNESS(brightness,r,g,b) \ + brightness = (UINT8)(((1063*((UINT16)r)/5000) + (3576*((UINT16)g)/5000) + (361*((UINT16)b)/5000)) / 3) + static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, GLMipmap_t *grmip, INT32 skinnum, skincolors_t color) { UINT8 i; @@ -1028,11 +1037,11 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, { UINT32 tempcolor; UINT16 imagebright, blendbright, finalbright, colorbright; - imagebright = (image->s.red+image->s.green+image->s.blue)/3; - blendbright = (blendimage->s.red+blendimage->s.green+blendimage->s.blue)/3; + SETBRIGHTNESS(imagebright,image->s.red,image->s.green,image->s.blue); + SETBRIGHTNESS(blendbright,blendimage->s.red,blendimage->s.green,blendimage->s.blue); // slightly dumb average between the blend image color and base image colour, usually one or the other will be fully opaque anyway finalbright = (imagebright*(255-blendimage->s.alpha))/255 + (blendbright*blendimage->s.alpha)/255; - colorbright = (blendcolor.s.red+blendcolor.s.green+blendcolor.s.blue)/3; + SETBRIGHTNESS(colorbright,blendcolor.s.red,blendcolor.s.green,blendcolor.s.blue); tempcolor = (finalbright*blendcolor.s.red)/colorbright; tempcolor = min(255, tempcolor); @@ -1090,6 +1099,8 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, return; } +#undef SETBRIGHTNESS + static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, INT32 skinnum, const UINT8 *colormap, skincolors_t color) { // mostly copied from HWR_GetMappedPatch, hence the similarities and comment diff --git a/src/k_kart.c b/src/k_kart.c index 9966b5573..65f427890 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -255,6 +255,15 @@ UINT8 colortranslations[MAXSKINCOLORS][16] = { //#define SALLYALTRAINBOW // Sal's edited version of the below, which keeps a colors' lightness, and looks better with hue-shifted colors like Ruby & Dream. Not strictly *better*, just different... +// Define for getting accurate color brightness readings according to how the human eye sees them. +// https://en.wikipedia.org/wiki/Relative_luminance +// 0.2126 to red +// 0.7152 to green +// 0.0722 to blue +// (See this same define in hw_md2.c!) +#define SETBRIGHTNESS(brightness,r,g,b) \ + brightness = (UINT8)(((1063*((UINT16)r)/5000) + (3576*((UINT16)g)/5000) + (361*((UINT16)b)/5000)) / 3) + /** \brief Generates the rainbow colourmaps that are used when a player has the invincibility power \param dest_colormap colormap to populate @@ -275,7 +284,7 @@ void K_RainbowColormap(UINT8 *dest_colormap, UINT8 skincolor) for (i = 0; i < 16; i++) { color = V_GetColor(colortranslations[skincolor][i]); - colorbrightnesses[i] = (UINT8)(((UINT16)color.s.red + (UINT16)color.s.green + (UINT16)color.s.blue)/3); + SETBRIGHTNESS(colorbrightnesses[i], color.s.red, color.s.green, color.s.blue); } #endif @@ -288,7 +297,7 @@ void K_RainbowColormap(UINT8 *dest_colormap, UINT8 skincolor) continue; } color = V_GetColor(i); - brightness = (UINT8)(((UINT16)color.s.red + (UINT16)color.s.green + (UINT16)color.s.blue)/3); + SETBRIGHTNESS(brightness, color.s.red, color.s.green, color.s.blue); #ifdef SALLYALTRAINBOW brightness = 15-(brightness/16); // Yes, 15. dest_colormap[i] = colortranslations[skincolor][brightness]; @@ -307,6 +316,8 @@ void K_RainbowColormap(UINT8 *dest_colormap, UINT8 skincolor) } } +#undef SETBRIGHTNESS + /** \brief Generates a translation colormap for Kart, to replace R_GenerateTranslationColormap in r_draw.c \param dest_colormap colormap to populate From fc194b63e8613ccf4a2c2f5bd93361fc6f55eeec Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sun, 16 Sep 2018 23:39:18 -0400 Subject: [PATCH 124/146] Changed MD2 coloring again Squares the colors to get nicer looking results (https://www.youtube.com/watch?v=LKnqECcg6Gw), as well as only blending a small chunk of the skincolor to prevent desaturation from the brightest/darkest values. --- src/hardware/hw_md2.c | 44 +++++++++++++++---------------------------- 1 file changed, 15 insertions(+), 29 deletions(-) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index f87f187ad..145a01507 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -987,40 +987,26 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, // Average all of the translation's colors { - UINT16 r, g, b; - UINT8 div = 0; + const UINT8 div = 6; + const UINT8 start = 4; + UINT32 r, g, b; - blendcolor = V_GetColor(colortranslations[color][0]); - r = (UINT16)blendcolor.s.red; - g = (UINT16)blendcolor.s.green; - b = (UINT16)blendcolor.s.blue; + blendcolor = V_GetColor(colortranslations[color][start]); + r = (UINT32)(blendcolor.s.red*blendcolor.s.red); + g = (UINT32)(blendcolor.s.green*blendcolor.s.green); + b = (UINT32)(blendcolor.s.blue*blendcolor.s.blue); - for (i = 1; i < 16; i++) + for (i = 1; i < div; i++) { - RGBA_t nextcolor = V_GetColor(colortranslations[color][i]); - UINT8 mul = 1; - // Weight these shades more. Indices 1-9 weren't randomly picked, they are commonly used on sprites and are generally what the colors "look" like - if (i >= 1 && i <= 9) - mul++; - // The mid & dark tons on the minimap icons get weighted even harder - if (i == 4 || i == 6) - mul += 2; - // And the shade between them, why not - if (i == 5) - mul++; - r += (UINT16)(nextcolor.s.red)*mul; - g += (UINT16)(nextcolor.s.green)*mul; - b += (UINT16)(nextcolor.s.blue)*mul; - div += mul; + RGBA_t nextcolor = V_GetColor(colortranslations[color][start+i]); + r += (UINT32)(nextcolor.s.red*nextcolor.s.red); + g += (UINT32)(nextcolor.s.green*nextcolor.s.green); + b += (UINT32)(nextcolor.s.blue*nextcolor.s.blue); } - // This shouldn't happen. - if (div < 1) - div = 1; - - blendcolor.s.red = (UINT8)(r/div); - blendcolor.s.green = (UINT8)(g/div); - blendcolor.s.blue = (UINT8)(b/div); + blendcolor.s.red = (UINT8)(FixedSqrt((r/div)<>FRACBITS); + blendcolor.s.green = (UINT8)(FixedSqrt((g/div)<>FRACBITS); + blendcolor.s.blue = (UINT8)(FixedSqrt((b/div)<>FRACBITS); } // rainbow support, could theoretically support boss ones too From 0a4a8b1236a4ef97fdae9d6057839b62399e660f Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Mon, 17 Sep 2018 02:09:22 -0400 Subject: [PATCH 125/146] More color tweaks - Renamed Grey to Nickel, and Cloudy to Grey - Updated Silver and Nickel to look a teeensy bit more inbetween White/Grey and Grey/Black, previously they both leaned more toward Grey - Drastically changed Navy to be more distinct from Jet - Replaced Indigo with Pomegranate - Moved certain colors around to match (most notably, beiges and browns are in their own little sub-section after the greyscale colors, instead of being lumped in the middle of orange and yellow) - Updated color opposite table to match --- src/dehacked.c | 86 ++++++++--------- src/doomdef.h | 26 ++--- src/k_kart.c | 257 +++++++++++++++++++++++++------------------------ 3 files changed, 186 insertions(+), 183 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 05be25837..e78189d72 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -7554,66 +7554,66 @@ static const char *COLOR_ENUMS[] = { // Rejigged for Kart. "NONE", // 00 // SKINCOLOR_NONE "WHITE", // 01 // SKINCOLOR_WHITE "SILVER", // 02 // SKINCOLOR_SILVER - "CLOUDY", // 03 // SKINCOLOR_CLOUDY - "GREY", // 04 // SKINCOLOR_GREY + "GREY", // 03 // SKINCOLOR_GREY + "NICKEL", // 04 // SKINCOLOR_NICKEL "BLACK", // 05 // SKINCOLOR_BLACK - "SALMON", // 06 // SKINCOLOR_SALMON - "PINK", // 07 // SKINCOLOR_PINK - "ROSE", // 08 // SKINCOLOR_ROSE - "RASPBERRY", // 09 // SKINCOLOR_RASPBERRY - "RED", // 10 // SKINCOLOR_RED - "RUBY", // 11 // SKINCOLOR_RUBY - "CRIMSON", // 12 // SKINCOLOR_CRIMSON - "KETCHUP", // 13 // SKINCOLOR_KETCHUP - "DAWN", // 14 // SKINCOLOR_DAWN - "CREAMSICLE", // 15 // SKINCOLOR_CREAMSICLE - "ORANGE", // 16 // SKINCOLOR_ORANGE - "PUMPKIN", // 17 // SKINCOLOR_PUMPKIN - "ROSEWOOD", // 18 // SKINCOLOR_ROSEWOOD - "BURGUNDY", // 19 // SKINCOLOR_BURGUNDY - "BRONZE", // 20 // SKINCOLOR_BRONZE - "SEPIA", // 21 // SKINCOLOR_SEPIA - "BEIGE", // 22 // SKINCOLOR_BEIGE - "BROWN", // 23 // SKINCOLOR_BROWN - "LEATHER", // 24 // SKINCOLOR_LEATHER + "SEPIA", // 06 // SKINCOLOR_SEPIA + "BEIGE", // 07 // SKINCOLOR_BEIGE + "BROWN", // 08 // SKINCOLOR_BROWN + "LEATHER", // 09 // SKINCOLOR_LEATHER + "SALMON", // 10 // SKINCOLOR_SALMON + "PINK", // 11 // SKINCOLOR_PINK + "ROSE", // 12 // SKINCOLOR_ROSE + "RASPBERRY", // 13 // SKINCOLOR_RASPBERRY + "RED", // 14 // SKINCOLOR_RED + "RUBY", // 15 // SKINCOLOR_RUBY + "CRIMSON", // 16 // SKINCOLOR_CRIMSON + "KETCHUP", // 17 // SKINCOLOR_KETCHUP + "DAWN", // 18 // SKINCOLOR_DAWN + "CREAMSICLE", // 19 // SKINCOLOR_CREAMSICLE + "ORANGE", // 20 // SKINCOLOR_ORANGE + "PUMPKIN", // 21 // SKINCOLOR_PUMPKIN + "ROSEWOOD", // 22 // SKINCOLOR_ROSEWOOD + "BURGUNDY", // 23 // SKINCOLOR_BURGUNDY + "TANGERINE", // 24 // SKINCOLOR_TANGERINE "PEACH", // 25 // SKINCOLOR_PEACH "CARAMEL", // 26 // SKINCOLOR_CARAMEL - "TANGERINE", // 27 // SKINCOLOR_TANGERINE - "GOLD", // 28 // SKINCOLOR_GOLD - "VOMIT", // 29 // SKINCOLOR_VOMIT - "YELLOW", // 30 // SKINCOLOR_YELLOW - "MUSTARD", // 31 // SKINCOLOR_MUSTARD - "OLIVE", // 32 // SKINCOLOR_OLIVE + "GOLD", // 27 // SKINCOLOR_GOLD + "BRONZE", // 28 // SKINCOLOR_BRONZE + "YELLOW", // 29 // SKINCOLOR_YELLOW + "MUSTARD", // 30 // SKINCOLOR_MUSTARD + "OLIVE", // 31 // SKINCOLOR_OLIVE + "VOMIT", // 32 // SKINCOLOR_VOMIT "GARDEN", // 33 // SKINCOLOR_GARDEN "LIME", // 34 // SKINCOLOR_LIME "DREAM", // 35 // SKINCOLOR_DREAM "TEA", // 36 // SKINCOLOR_TEA "PISTACHIO", // 37 // SKINCOLOR_PISTACHIO - "MOSS", // 38 // SKINCOLOR_MOSS - "MINT", // 39 // SKINCOLOR_MINT - "GREEN", // 40 // SKINCOLOR_GREEN - "ROBOHOOD", // 41 // SKINCOLOR_ROBOHOOD + "ROBOHOOD", // 38 // SKINCOLOR_ROBOHOOD + "MOSS", // 39 // SKINCOLOR_MOSS + "MINT", // 40 // SKINCOLOR_MINT + "GREEN", // 41 // SKINCOLOR_GREEN "PINETREE", // 42 // SKINCOLOR_PINETREE "EMERALD", // 43 // SKINCOLOR_EMERALD "SWAMP", // 44 // SKINCOLOR_SWAMP "AQUA", // 45 // SKINCOLOR_AQUA "TEAL", // 46 // SKINCOLOR_TEAL "CYAN", // 47 // SKINCOLOR_CYAN - "CERULEAN", // 48 // SKINCOLOR_CERULEAN - "JAWZ", // 49 // SKINCOLOR_JAWZ - "SLATE", // 50 // SKINCOLOR_SLATE - "STEEL", // 51 // SKINCOLOR_STEEL - "PERIWINKLE", // 52 // SKINCOLOR_PERIWINKLE - "BLUE", // 53 // SKINCOLOR_BLUE - "SAPPHIRE", // 54 // SKINCOLOR_SAPPHIRE - "BLUEBERRY", // 55 // SKINCOLOR_BLUEBERRY - "NAVY", // 56 // SKINCOLOR_NAVY - "JET", // 57 // SKINCOLOR_JET + "JAWZ", // 48 // SKINCOLOR_JAWZ + "CERULEAN", // 49 // SKINCOLOR_CERULEAN + "NAVY", // 50 // SKINCOLOR_NAVY + "SLATE", // 51 // SKINCOLOR_SLATE + "STEEL", // 52 // SKINCOLOR_STEEL + "JET", // 53 // SKINCOLOR_JET + "PERIWINKLE", // 54 // SKINCOLOR_PERIWINKLE + "BLUE", // 55 // SKINCOLOR_BLUE + "SAPPHIRE", // 56 // SKINCOLOR_SAPPHIRE + "BLUEBERRY", // 57 // SKINCOLOR_BLUEBERRY "DUSK", // 58 // SKINCOLOR_DUSK "PURPLE", // 59 // SKINCOLOR_PURPLE "LAVENDER", // 60 // SKINCOLOR_LAVENDER - "INDIGO", // 61 // SKINCOLOR_INDIGO - "BYZANTIUM", // 62 // SKINCOLOR_BYZANTIUM + "BYZANTIUM", // 61 // SKINCOLOR_BYZANTIUM + "POMEGRANATE", // 62 // SKINCOLOR_POMEGRANATE "LILAC", // 63 // SKINCOLOR_LILAC // Super special awesome Super flashing colors! diff --git a/src/doomdef.h b/src/doomdef.h index 2e15cb7ec..b5519f6fd 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -234,9 +234,13 @@ typedef enum SKINCOLOR_NONE = 0, SKINCOLOR_WHITE, SKINCOLOR_SILVER, - SKINCOLOR_CLOUDY, SKINCOLOR_GREY, + SKINCOLOR_NICKEL, SKINCOLOR_BLACK, + SKINCOLOR_SEPIA, + SKINCOLOR_BEIGE, + SKINCOLOR_BROWN, + SKINCOLOR_LEATHER, SKINCOLOR_SALMON, SKINCOLOR_PINK, SKINCOLOR_ROSE, @@ -251,49 +255,45 @@ typedef enum SKINCOLOR_PUMPKIN, SKINCOLOR_ROSEWOOD, SKINCOLOR_BURGUNDY, - SKINCOLOR_BRONZE, - SKINCOLOR_SEPIA, - SKINCOLOR_BEIGE, - SKINCOLOR_BROWN, - SKINCOLOR_LEATHER, + SKINCOLOR_TANGERINE, SKINCOLOR_PEACH, SKINCOLOR_CARAMEL, - SKINCOLOR_TANGERINE, SKINCOLOR_GOLD, - SKINCOLOR_VOMIT, + SKINCOLOR_BRONZE, SKINCOLOR_YELLOW, SKINCOLOR_MUSTARD, SKINCOLOR_OLIVE, + SKINCOLOR_VOMIT, SKINCOLOR_GARDEN, SKINCOLOR_LIME, SKINCOLOR_DREAM, SKINCOLOR_TEA, SKINCOLOR_PISTACHIO, + SKINCOLOR_ROBOHOOD, SKINCOLOR_MOSS, SKINCOLOR_MINT, SKINCOLOR_GREEN, - SKINCOLOR_ROBOHOOD, SKINCOLOR_PINETREE, SKINCOLOR_EMERALD, SKINCOLOR_SWAMP, SKINCOLOR_AQUA, SKINCOLOR_TEAL, SKINCOLOR_CYAN, - SKINCOLOR_CERULEAN, SKINCOLOR_JAWZ, // Oni's torment + SKINCOLOR_CERULEAN, + SKINCOLOR_NAVY, SKINCOLOR_SLATE, SKINCOLOR_STEEL, + SKINCOLOR_JET, SKINCOLOR_PERIWINKLE, SKINCOLOR_BLUE, SKINCOLOR_SAPPHIRE, // sweet mother, i cannot weave – slender aphrodite has overcome me with longing for a girl SKINCOLOR_BLUEBERRY, - SKINCOLOR_NAVY, - SKINCOLOR_JET, SKINCOLOR_DUSK, SKINCOLOR_PURPLE, SKINCOLOR_LAVENDER, - SKINCOLOR_INDIGO, SKINCOLOR_BYZANTIUM, + SKINCOLOR_POMEGRANATE, SKINCOLOR_LILAC, // Careful! MAXSKINCOLORS cannot be greater than 0x40 -- Which it is now. diff --git a/src/k_kart.c b/src/k_kart.c index 65f427890..c01c9a984 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -45,147 +45,151 @@ const char *KartColor_Names[MAXSKINCOLORS] = "None", // 00 // SKINCOLOR_NONE "White", // 01 // SKINCOLOR_WHITE "Silver", // 02 // SKINCOLOR_SILVER - "Cloudy", // 03 // SKINCOLOR_CLOUDY - "Grey", // 04 // SKINCOLOR_GREY + "Grey", // 03 // SKINCOLOR_GREY + "Nickel", // 04 // SKINCOLOR_NICKEL "Black", // 05 // SKINCOLOR_BLACK - "Salmon", // 06 // SKINCOLOR_SALMON - "Pink", // 07 // SKINCOLOR_PINK - "Rose", // 08 // SKINCOLOR_ROSE - "Raspberry", // 09 // SKINCOLOR_RASPBERRY - "Red", // 10 // SKINCOLOR_RED - "Ruby", // 11 // SKINCOLOR_RUBY - "Crimson", // 12 // SKINCOLOR_CRIMSON - "Ketchup", // 13 // SKINCOLOR_KETCHUP - "Dawn", // 14 // SKINCOLOR_DAWN - "Creamsicle", // 15 // SKINCOLOR_CREAMSICLE - "Orange", // 16 // SKINCOLOR_ORANGE - "Pumpkin", // 17 // SKINCOLOR_PUMPKIN - "Rosewood", // 18 // SKINCOLOR_ROSEWOOD - "Burgundy", // 19 // SKINCOLOR_BURGUNDY - "Bronze", // 20 // SKINCOLOR_BRONZE - "Sepia", // 21 // SKINCOLOR_SEPIA - "Beige", // 22 // SKINCOLOR_BEIGE - "Brown", // 23 // SKINCOLOR_BROWN - "Leather", // 24 // SKINCOLOR_LEATHER + "Sepia", // 06 // SKINCOLOR_SEPIA + "Beige", // 07 // SKINCOLOR_BEIGE + "Brown", // 08 // SKINCOLOR_BROWN + "Leather", // 09 // SKINCOLOR_LEATHER + "Salmon", // 10 // SKINCOLOR_SALMON + "Pink", // 11 // SKINCOLOR_PINK + "Rose", // 12 // SKINCOLOR_ROSE + "Raspberry", // 13 // SKINCOLOR_RASPBERRY + "Red", // 14 // SKINCOLOR_RED + "Ruby", // 15 // SKINCOLOR_RUBY + "Crimson", // 16 // SKINCOLOR_CRIMSON + "Ketchup", // 17 // SKINCOLOR_KETCHUP + "Dawn", // 18 // SKINCOLOR_DAWN + "Creamsicle", // 19 // SKINCOLOR_CREAMSICLE + "Orange", // 20 // SKINCOLOR_ORANGE + "Pumpkin", // 21 // SKINCOLOR_PUMPKIN + "Rosewood", // 22 // SKINCOLOR_ROSEWOOD + "Burgundy", // 23 // SKINCOLOR_BURGUNDY + "Tangerine", // 24 // SKINCOLOR_TANGERINE "Peach", // 25 // SKINCOLOR_PEACH "Caramel", // 26 // SKINCOLOR_CARAMEL - "Tangerine", // 27 // SKINCOLOR_TANGERINE - "Gold", // 28 // SKINCOLOR_GOLD - "Vomit", // 29 // SKINCOLOR_VOMIT - "Yellow", // 30 // SKINCOLOR_YELLOW - "Mustard", // 31 // SKINCOLOR_MUSTARD - "Olive", // 32 // SKINCOLOR_OLIVE + "Gold", // 27 // SKINCOLOR_GOLD + "Bronze", // 28 // SKINCOLOR_BRONZE + "Yellow", // 29 // SKINCOLOR_YELLOW + "Mustard", // 30 // SKINCOLOR_MUSTARD + "Olive", // 31 // SKINCOLOR_OLIVE + "Vomit", // 32 // SKINCOLOR_VOMIT "Garden", // 33 // SKINCOLOR_GARDEN "Lime", // 34 // SKINCOLOR_LIME "Dream", // 35 // SKINCOLOR_DREAM "Tea", // 36 // SKINCOLOR_TEA "Pistachio", // 37 // SKINCOLOR_PISTACHIO - "Moss", // 38 // SKINCOLOR_MOSS - "Mint", // 39 // SKINCOLOR_MINT - "Green", // 40 // SKINCOLOR_GREEN - "Robo-Hood", // 41 // SKINCOLOR_ROBOHOOD + "Robo-Hood", // 38 // SKINCOLOR_ROBOHOOD + "Moss", // 39 // SKINCOLOR_MOSS + "Mint", // 40 // SKINCOLOR_MINT + "Green", // 41 // SKINCOLOR_GREEN "Pinetree", // 42 // SKINCOLOR_PINETREE "Emerald", // 43 // SKINCOLOR_EMERALD "Swamp", // 44 // SKINCOLOR_SWAMP "Aqua", // 45 // SKINCOLOR_AQUA "Teal", // 46 // SKINCOLOR_TEAL "Cyan", // 47 // SKINCOLOR_CYAN - "Cerulean", // 48 // SKINCOLOR_CERULEAN - "Jawz", // 49 // SKINCOLOR_JAWZ - "Slate", // 50 // SKINCOLOR_SLATE - "Steel", // 51 // SKINCOLOR_STEEL - "Periwinkle", // 52 // SKINCOLOR_PERIWINKLE - "Blue", // 53 // SKINCOLOR_BLUE - "Sapphire", // 54 // SKINCOLOR_SAPPHIRE - "Blueberry", // 55 // SKINCOLOR_BLUEBERRY - "Navy", // 56 // SKINCOLOR_NAVY - "Jet", // 57 // SKINCOLOR_JET + "Jawz", // 48 // SKINCOLOR_JAWZ + "Cerulean", // 49 // SKINCOLOR_CERULEAN + "Navy", // 50 // SKINCOLOR_NAVY + "Slate", // 51 // SKINCOLOR_SLATE + "Steel", // 52 // SKINCOLOR_STEEL + "Jet", // 53 // SKINCOLOR_JET + "Periwinkle", // 54 // SKINCOLOR_PERIWINKLE + "Blue", // 55 // SKINCOLOR_BLUE + "Sapphire", // 56 // SKINCOLOR_SAPPHIRE + "Blueberry", // 57 // SKINCOLOR_BLUEBERRY "Dusk", // 58 // SKINCOLOR_DUSK "Purple", // 59 // SKINCOLOR_PURPLE "Lavender", // 60 // SKINCOLOR_LAVENDER - "Indigo", // 61 // SKINCOLOR_INDIGO - "Byzantium", // 62 // SKINCOLOR_BYZANTIUM + "Byzantium", // 61 // SKINCOLOR_BYZANTIUM + "Pomegranate", // 62 // SKINCOLOR_POMEGRANATE "Lilac" // 63 // SKINCOLOR_LILAC }; // Color_Opposite replacement; frame setting has not been changed from 8 for most, should be done later const UINT8 KartColor_Opposite[MAXSKINCOLORS*2] = { - SKINCOLOR_NONE,8, // 00 // SKINCOLOR_NONE - SKINCOLOR_BLACK,8, // 01 // SKINCOLOR_WHITE - SKINCOLOR_GREY,8, // 02 // SKINCOLOR_SILVER - SKINCOLOR_CLOUDY,8, // 03 // SKINCOLOR_CLOUDY - SKINCOLOR_SILVER,8, // 04 // SKINCOLOR_GREY - SKINCOLOR_WHITE,8, // 05 // SKINCOLOR_BLACK - SKINCOLOR_TEA,8, // 06 // SKINCOLOR_SALMON - SKINCOLOR_PISTACHIO,8, // 07 // SKINCOLOR_PINK - SKINCOLOR_MOSS,8, // 08 // SKINCOLOR_ROSE - SKINCOLOR_MINT,10, // 09 // SKINCOLOR_RASPBERRY - SKINCOLOR_GREEN,8, // 10 // SKINCOLOR_RED - SKINCOLOR_SAPPHIRE,8, // 11 // SKINCOLOR_RUBY - SKINCOLOR_PINETREE,6, // 12 // SKINCOLOR_CRIMSON - SKINCOLOR_MUSTARD,6, // 13 // SKINCOLOR_KETCHUP - SKINCOLOR_DUSK,8, // 14 // SKINCOLOR_DAWN - SKINCOLOR_PERIWINKLE,8, // 15 // SKINCOLOR_CREAMSICLE - SKINCOLOR_BLUE,8, // 16 // SKINCOLOR_ORANGE - SKINCOLOR_BLUEBERRY,8, // 17 // SKINCOLOR_PUMPKIN - SKINCOLOR_NAVY,8, // 18 // SKINCOLOR_ROSEWOOD - SKINCOLOR_JET,8, // 19 // SKINCOLOR_BURGUNDY - SKINCOLOR_AQUA,8, // 20 // SKINCOLOR_BRONZE - SKINCOLOR_LEATHER,6, // 21 // SKINCOLOR_SEPIA - SKINCOLOR_BROWN,2, // 22 // SKINCOLOR_BEIGE - SKINCOLOR_BEIGE,8, // 23 // SKINCOLOR_BROWN - SKINCOLOR_SEPIA,8, // 24 // SKINCOLOR_LEATHER - SKINCOLOR_SLATE,8, // 25 // SKINCOLOR_PEACH - SKINCOLOR_STEEL,8, // 26 // SKINCOLOR_CARAMEL - SKINCOLOR_LIME,8, // 27 // SKINCOLOR_TANGERINE - SKINCOLOR_CYAN,8, // 28 // SKINCOLOR_GOLD - SKINCOLOR_ROBOHOOD,8, // 29 // SKINCOLOR_VOMIT - SKINCOLOR_CERULEAN,8, // 30 // SKINCOLOR_YELLOW - SKINCOLOR_KETCHUP,8, // 31 // SKINCOLOR_MUSTARD - SKINCOLOR_TEAL,8, // 32 // SKINCOLOR_OLIVE - SKINCOLOR_LAVENDER,8, // 33 // SKINCOLOR_GARDEN - SKINCOLOR_TANGERINE,8, // 34 // SKINCOLOR_LIME - SKINCOLOR_BYZANTIUM,6, // 35 // SKINCOLOR_DREAM - SKINCOLOR_SALMON,8, // 36 // SKINCOLOR_TEA - SKINCOLOR_PINK,8, // 37 // SKINCOLOR_PISTACHIO - SKINCOLOR_ROSE,8, // 38 // SKINCOLOR_MOSS - SKINCOLOR_RASPBERRY,6, // 39 // SKINCOLOR_MINT - SKINCOLOR_RED,8, // 40 // SKINCOLOR_GREEN - SKINCOLOR_VOMIT,8, // 41 // SKINCOLOR_ROBOHOOD - SKINCOLOR_CRIMSON,8, // 42 // SKINCOLOR_PINETREE - SKINCOLOR_PURPLE,8, // 43 // SKINCOLOR_EMERALD - SKINCOLOR_INDIGO,6, // 44 // SKINCOLOR_SWAMP - SKINCOLOR_BRONZE,7, // 45 // SKINCOLOR_AQUA - SKINCOLOR_OLIVE,10, // 46 // SKINCOLOR_TEAL - SKINCOLOR_GOLD,8, // 47 // SKINCOLOR_CYAN - SKINCOLOR_YELLOW,8, // 48 // SKINCOLOR_CERULEAN - SKINCOLOR_LILAC,6, // 49 // SKINCOLOR_JAWZ - SKINCOLOR_PEACH,8, // 50 // SKINCOLOR_SLATE - SKINCOLOR_CARAMEL,8, // 51 // SKINCOLOR_STEEL - SKINCOLOR_CREAMSICLE,8, // 52 // SKINCOLOR_PERIWINKLE - SKINCOLOR_ORANGE,8, // 53 // SKINCOLOR_BLUE - SKINCOLOR_RUBY,8, // 54 // SKINCOLOR_SAPPHIRE - SKINCOLOR_PUMPKIN,8, // 55 // SKINCOLOR_BLUEBERRY - SKINCOLOR_ROSEWOOD,8, // 56 // SKINCOLOR_NAVY - SKINCOLOR_BURGUNDY,6, // 57 // SKINCOLOR_JET - SKINCOLOR_DAWN,8, // 58 // SKINCOLOR_DUSK - SKINCOLOR_EMERALD,8, // 59 // SKINCOLOR_PURPLE - SKINCOLOR_GARDEN,8, // 60 // SKINCOLOR_LAVENDER - SKINCOLOR_SWAMP,6, // 61 // SKINCOLOR_INDIGO - SKINCOLOR_DREAM,8, // 62 // SKINCOLOR_BYZANTIUM - SKINCOLOR_JAWZ,6 // 63 // SKINCOLOR_LILAC + SKINCOLOR_NONE,8, // 00 // SKINCOLOR_NONE + SKINCOLOR_BLACK,8, // 01 // SKINCOLOR_WHITE + SKINCOLOR_NICKEL,8, // 02 // SKINCOLOR_SILVER + SKINCOLOR_GREY,8, // 03 // SKINCOLOR_GREY + SKINCOLOR_SILVER,8, // 04 // SKINCOLOR_NICKEL + SKINCOLOR_WHITE,8, // 05 // SKINCOLOR_BLACK + SKINCOLOR_LEATHER,6, // 06 // SKINCOLOR_SEPIA + SKINCOLOR_BROWN,2, // 07 // SKINCOLOR_BEIGE + SKINCOLOR_BEIGE,8, // 08 // SKINCOLOR_BROWN + SKINCOLOR_SEPIA,8, // 09 // SKINCOLOR_LEATHER + SKINCOLOR_TEA,8, // 10 // SKINCOLOR_SALMON + SKINCOLOR_PISTACHIO,8, // 11 // SKINCOLOR_PINK + SKINCOLOR_MOSS,8, // 12 // SKINCOLOR_ROSE + SKINCOLOR_MINT,10, // 13 // SKINCOLOR_RASPBERRY + SKINCOLOR_GREEN,8, // 14 // SKINCOLOR_RED + SKINCOLOR_SAPPHIRE,8, // 15 // SKINCOLOR_RUBY + SKINCOLOR_PINETREE,6, // 16 // SKINCOLOR_CRIMSON + SKINCOLOR_MUSTARD,6, // 17 // SKINCOLOR_KETCHUP + SKINCOLOR_DUSK,8, // 18 // SKINCOLOR_DAWN + SKINCOLOR_PERIWINKLE,8, // 19 // SKINCOLOR_CREAMSICLE + SKINCOLOR_BLUE,8, // 20 // SKINCOLOR_ORANGE + SKINCOLOR_BLUEBERRY,8, // 21 // SKINCOLOR_PUMPKIN + SKINCOLOR_NAVY,8, // 22 // SKINCOLOR_ROSEWOOD + SKINCOLOR_JET,6, // 23 // SKINCOLOR_BURGUNDY + SKINCOLOR_LIME,8, // 24 // SKINCOLOR_TANGERINE + SKINCOLOR_CYAN,8, // 25 // SKINCOLOR_PEACH + SKINCOLOR_CERULEAN,8, // 26 // SKINCOLOR_CARAMEL + SKINCOLOR_SLATE,8, // 27 // SKINCOLOR_GOLD + SKINCOLOR_STEEL,8, // 28 // SKINCOLOR_BRONZE + SKINCOLOR_AQUA,8, // 29 // SKINCOLOR_YELLOW + SKINCOLOR_KETCHUP,8, // 30 // SKINCOLOR_MUSTARD + SKINCOLOR_TEAL,8, // 31 // SKINCOLOR_OLIVE + SKINCOLOR_ROBOHOOD,8, // 32 // SKINCOLOR_VOMIT + SKINCOLOR_LAVENDER,8, // 33 // SKINCOLOR_GARDEN + SKINCOLOR_TANGERINE,8, // 34 // SKINCOLOR_LIME + SKINCOLOR_POMEGRANATE,8, // 35 // SKINCOLOR_DREAM + SKINCOLOR_SALMON,8, // 36 // SKINCOLOR_TEA + SKINCOLOR_PINK,8, // 37 // SKINCOLOR_PISTACHIO + SKINCOLOR_VOMIT,8, // 38 // SKINCOLOR_ROBOHOOD + SKINCOLOR_ROSE,8, // 39 // SKINCOLOR_MOSS + SKINCOLOR_RASPBERRY,6, // 40 // SKINCOLOR_MINT + SKINCOLOR_RED,8, // 41 // SKINCOLOR_GREEN + SKINCOLOR_CRIMSON,8, // 42 // SKINCOLOR_PINETREE + SKINCOLOR_PURPLE,8, // 43 // SKINCOLOR_EMERALD + SKINCOLOR_BYZANTIUM,6, // 44 // SKINCOLOR_SWAMP + SKINCOLOR_YELLOW,8, // 45 // SKINCOLOR_AQUA + SKINCOLOR_OLIVE,8, // 46 // SKINCOLOR_TEAL + SKINCOLOR_PEACH,8, // 47 // SKINCOLOR_CYAN + SKINCOLOR_LILAC,6, // 48 // SKINCOLOR_JAWZ + SKINCOLOR_CARAMEL,8, // 49 // SKINCOLOR_CERULEAN + SKINCOLOR_ROSEWOOD,8, // 50 // SKINCOLOR_NAVY + SKINCOLOR_GOLD,8, // 51 // SKINCOLOR_SLATE + SKINCOLOR_BRONZE,8, // 52 // SKINCOLOR_STEEL + SKINCOLOR_BURGUNDY,6, // 53 // SKINCOLOR_JET + SKINCOLOR_CREAMSICLE,8, // 54 // SKINCOLOR_PERIWINKLE + SKINCOLOR_ORANGE,8, // 55 // SKINCOLOR_BLUE + SKINCOLOR_RUBY,8, // 56 // SKINCOLOR_SAPPHIRE + SKINCOLOR_PUMPKIN,8, // 57 // SKINCOLOR_BLUEBERRY + SKINCOLOR_DAWN,8, // 58 // SKINCOLOR_DUSK + SKINCOLOR_EMERALD,8, // 59 // SKINCOLOR_PURPLE + SKINCOLOR_GARDEN,8, // 60 // SKINCOLOR_LAVENDER + SKINCOLOR_SWAMP,8, // 61 // SKINCOLOR_BYZANTIUM + SKINCOLOR_DREAM,6, // 62 // SKINCOLOR_POMEGRANATE + SKINCOLOR_JAWZ,6 // 63 // SKINCOLOR_LILAC }; UINT8 colortranslations[MAXSKINCOLORS][16] = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // SKINCOLOR_NONE {120, 120, 120, 120, 0, 1, 3, 4, 6, 7, 10, 14, 18, 22, 25, 28}, // SKINCOLOR_WHITE - { 0, 1, 3, 5, 6, 8, 10, 11, 13, 15, 16, 18, 20, 24, 27, 30}, // SKINCOLOR_SILVER - { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31}, // SKINCOLOR_CLOUDY - { 8, 9, 10, 12, 13, 15, 16, 19, 19, 20, 21, 23, 25, 27, 29, 31}, // SKINCOLOR_GREY + { 0, 1, 2, 4, 5, 7, 8, 10, 13, 15, 18, 20, 23, 25, 28, 30}, // SKINCOLOR_SILVER + { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31}, // SKINCOLOR_GREY + { 12, 14, 16, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}, // SKINCOLOR_NICKEL { 16, 17, 19, 21, 22, 24, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31}, // SKINCOLOR_BLACK + { 0, 1, 3, 5, 7, 9, 34, 36, 38, 40, 42, 44, 60, 61, 62, 63}, // SKINCOLOR_SEPIA + { 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47}, // SKINCOLOR_BEIGE + { 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63}, // SKINCOLOR_BROWN + { 51, 52, 53, 55, 56, 57, 58, 60, 61, 63, 28, 28, 29, 29, 30, 31}, // SKINCOLOR_LEATHER {120, 120, 120, 121, 121, 122, 122, 123, 124, 125, 126, 128, 129, 131, 133, 135}, // SKINCOLOR_SALMON - {121, 121, 122, 144, 144, 145, 145, 146, 147, 148, 149, 150, 151, 134, 136, 138}, // SKINCOLOR_PINK + {121, 121, 144, 144, 145, 145, 146, 146, 147, 148, 149, 150, 151, 134, 136, 138}, // SKINCOLOR_PINK {144, 145, 146, 147, 148, 149, 150, 151, 134, 135, 136, 137, 138, 139, 140, 141}, // SKINCOLOR_ROSE {120, 121, 122, 123, 124, 125, 126, 127, 128, 130, 131, 133, 134, 136, 137, 139}, // SKINCOLOR_RASPBERRY {125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140}, // SKINCOLOR_RED @@ -198,57 +202,56 @@ UINT8 colortranslations[MAXSKINCOLORS][16] = { { 84, 85, 86, 87, 88, 90, 92, 93, 94, 95, 152, 153, 154, 156, 157, 159}, // SKINCOLOR_PUMPKIN { 90, 91, 92, 93, 94, 152, 153, 154, 155, 156, 157, 158, 159, 139, 141, 143}, // SKINCOLOR_ROSEWOOD { 94, 95, 152, 153, 154, 156, 157, 159, 141, 141, 141, 142, 142, 143, 143, 31}, // SKINCOLOR_BURGUNDY - {112, 113, 114, 115, 116, 117, 118, 119, 156, 157, 158, 159, 141, 141, 142, 143}, // SKINCOLOR_BRONZE - { 0, 1, 3, 5, 7, 9, 34, 36, 38, 40, 42, 44, 60, 61, 62, 63}, // SKINCOLOR_SEPIA - { 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47}, // SKINCOLOR_BEIGE - { 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63}, // SKINCOLOR_BROWN - { 51, 52, 53, 55, 56, 57, 58, 60, 61, 63, 28, 28, 29, 29, 30, 31}, // SKINCOLOR_LEATHER + { 98, 98, 112, 112, 113, 113, 84, 85, 87, 89, 91, 93, 95, 153, 156, 159}, // SKINCOLOR_TANGERINE { 64, 65, 67, 68, 70, 71, 73, 74, 76, 77, 79, 48, 50, 53, 56, 59}, // SKINCOLOR_PEACH { 64, 66, 68, 70, 72, 74, 76, 78, 48, 50, 52, 54, 56, 58, 60, 62}, // SKINCOLOR_CARAMEL - { 98, 98, 112, 112, 113, 113, 84, 85, 87, 89, 91, 93, 95, 153, 156, 159}, // SKINCOLOR_TANGERINE {112, 112, 112, 113, 113, 114, 114, 115, 115, 116, 116, 117, 117, 118, 118, 119}, // SKINCOLOR_GOLD - {121, 144, 145, 72, 73, 84, 114, 115, 107, 108, 109, 183, 223, 207, 30, 246}, // SKINCOLOR_VOMIT + {112, 113, 114, 115, 116, 117, 118, 119, 156, 157, 158, 159, 141, 141, 142, 143}, // SKINCOLOR_BRONZE { 96, 97, 98, 100, 101, 102, 104, 113, 114, 115, 116, 117, 118, 119, 156, 159}, // SKINCOLOR_YELLOW { 96, 98, 99, 112, 113, 114, 114, 106, 106, 107, 107, 108, 108, 109, 110, 111}, // SKINCOLOR_MUSTARD {105, 105, 105, 106, 106, 107, 107, 108, 108, 109, 109, 110, 110, 111, 111, 31}, // SKINCOLOR_OLIVE + {121, 144, 145, 72, 73, 84, 114, 115, 107, 108, 109, 183, 223, 207, 30, 246}, // SKINCOLOR_VOMIT { 98, 99, 112, 101, 113, 114, 106, 179, 180, 180, 181, 182, 183, 173, 174, 175}, // SKINCOLOR_GARDEN { 96, 97, 99, 100, 102, 104, 160, 162, 164, 166, 168, 171, 223, 223, 207, 31}, // SKINCOLOR_LIME { 96, 98, 99, 112, 113, 178, 179, 165, 203, 203, 204, 204, 205, 205, 206, 207}, // SKINCOLOR_DREAM - {120, 120, 176, 176, 176, 177, 177, 178, 178, 179, 180, 180, 181, 181, 182, 183}, // SKINCOLOR_TEA + {120, 120, 176, 176, 176, 177, 177, 178, 178, 179, 179, 180, 180, 181, 182, 183}, // SKINCOLOR_TEA {120, 120, 176, 176, 177, 177, 178, 179, 165, 166, 167, 168, 169, 170, 171, 172}, // SKINCOLOR_PISTACHIO + {176, 176, 177, 178, 165, 166, 167, 167, 168, 169, 182, 182, 182, 183, 183, 183}, // SKINCOLOR_ROBOHOOD {178, 178, 178, 179, 179, 180, 181, 182, 183, 172, 172, 173, 173, 174, 174, 175}, // SKINCOLOR_MOSS {120, 176, 176, 176, 177, 163, 164, 165, 167, 221, 221, 222, 223, 207, 207, 31}, // SKINCOLOR_MINT {160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175}, // SKINCOLOR_GREEN - {176, 176, 177, 178, 165, 166, 167, 167, 168, 169, 182, 182, 182, 183, 183, 183}, // SKINCOLOR_ROBOHOOD {160, 161, 162, 164, 165, 167, 169, 170, 171, 171, 172, 173, 174, 175, 30, 31}, // SKINCOLOR_PINETREE {160, 184, 184, 185, 185, 186, 186, 187, 187, 188, 188, 189, 189, 190, 191, 175}, // SKINCOLOR_EMERALD {186, 187, 188, 188, 188, 189, 189, 190, 190, 191, 175, 175, 30, 30, 31, 31}, // SKINCOLOR_SWAMP {120, 208, 208, 210, 212, 214, 220, 220, 220, 221, 221, 222, 222, 223, 223, 191}, // SKINCOLOR_AQUA {210, 213, 220, 220, 220, 216, 216, 221, 221, 221, 222, 222, 223, 223, 191, 31}, // SKINCOLOR_TEAL {120, 120, 208, 208, 209, 210, 211, 212, 213, 215, 216, 217, 218, 219, 222, 223}, // SKINCOLOR_CYAN - {208, 209, 211, 213, 215, 216, 216, 217, 217, 218, 218, 219, 205, 206, 207, 207}, // SKINCOLOR_CERULEAN {120, 120, 208, 209, 210, 226, 215, 216, 217, 229, 229, 205, 205, 206, 207, 31}, // SKINCOLOR_JAWZ + {208, 209, 211, 213, 215, 216, 216, 217, 217, 218, 218, 219, 205, 206, 207, 207}, // SKINCOLOR_CERULEAN + {215, 215, 215, 216, 216, 217, 218, 204, 204, 205, 205, 206, 207, 29, 30, 31}, // SKINCOLOR_NAVY {120, 120, 200, 200, 200, 201, 201, 201, 202, 202, 202, 203, 204, 205, 206, 207}, // SKINCOLOR_SLATE {120, 200, 200, 201, 201, 202, 202, 203, 203, 204, 204, 205, 205, 206, 207, 31}, // SKINCOLOR_STEEL + {200, 201, 202, 203, 204, 205, 206, 207, 28, 28, 29, 29, 30, 30, 31, 31}, // SKINCOLOR_JET {120, 224, 225, 226, 226, 227, 228, 228, 229, 230, 231, 234, 235, 237, 239, 241}, // SKINCOLOR_PERIWINKLE {224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239}, // SKINCOLOR_BLUE {208, 209, 211, 213, 215, 217, 229, 230, 232, 234, 236, 238, 240, 242, 244, 246}, // SKINCOLOR_SAPPHIRE {228, 229, 230, 231, 232, 233, 234, 235, 237, 238, 239, 240, 242, 243, 244, 245}, // SKINCOLOR_BLUEBERRY - {215, 216, 217, 218, 204, 205, 206, 237, 238, 239, 240, 241, 242, 243, 244, 245}, // SKINCOLOR_NAVY - {200, 201, 202, 203, 204, 205, 206, 207, 28, 28, 29, 29, 30, 30, 31, 31}, // SKINCOLOR_JET {192, 192, 248, 249, 250, 251, 204, 204, 205, 205, 206, 206, 207, 29, 30, 31}, // SKINCOLOR_DUSK {192, 192, 192, 193, 193, 194, 194, 195, 195, 196, 196, 197, 197, 198, 198, 199}, // SKINCOLOR_PURPLE {248, 248, 248, 249, 249, 250, 250, 251, 251, 252, 252, 253, 253, 254, 254, 255}, // SKINCOLOR_LAVENDER - {192, 193, 194, 195, 196, 197, 198, 199, 255, 255, 29, 29, 30, 30, 31, 31}, // SKINCOLOR_INDIGO {192, 248, 249, 250, 251, 252, 253, 254, 255, 255, 29, 29, 30, 30, 31, 31}, // SKINCOLOR_BYZANTIUM + {144, 145, 146, 147, 148, 149, 150, 251, 251, 252, 252, 253, 254, 255, 29, 30}, // SKINCOLOR_POMEGRANATE {120, 120, 120, 121, 121, 122, 122, 123, 192, 248, 249, 250, 251, 252, 253, 254}, // SKINCOLOR_LILAC /* Removed Colours {120, 121, 123, 124, 126, 127, 129, 130, 132, 133, 135, 136, 138, 139, 141, 143}, // old SKINCOLOR_RUBY, removed for other colors - { 80, 81, 83, 85, 86, 88, 90, 91, 93, 95, 152, 153, 154, 156, 157, 159}, // SKINCOLOR_AMBER, removed for other colors {224, 225, 226, 228, 229, 231, 232, 234, 235, 237, 238, 240, 241, 243, 244, 246}, // old SKINCOLOR_SAPPHIRE, removed for other colors + { 72, 73, 74, 75, 76, 77, 78, 79, 48, 49, 50, 51, 52, 53, 54, 55}, // old SKINCOLOR_CARAMEL, new Caramel was previously Shiny Caramel + {215, 216, 217, 218, 204, 205, 206, 237, 238, 239, 240, 241, 242, 243, 244, 245}, // old SKINCOLOR_NAVY, too similar to Jet + { 80, 81, 83, 85, 86, 88, 90, 91, 93, 95, 152, 153, 154, 156, 157, 159}, // SKINCOLOR_AMBER, removed for other colors {160, 160, 160, 184, 184, 184, 185, 185, 185, 186, 187, 187, 188, 188, 189, 190}, // SKINCOLOR_JADE, removed for other colors {224, 225, 226, 212, 213, 213, 214, 215, 220, 221, 172, 222, 173, 223, 174, 175}, // SKINCOLOR_FROST, merged into Aqua - { 72, 73, 74, 75, 76, 77, 78, 79, 48, 49, 50, 51, 52, 53, 54, 55}, // SKINCOLOR_CARAMEL, new Caramel was previously Shiny Caramel + { 96, 97, 99, 100, 102, 104, 105, 105, 106, 107, 107, 108, 109, 109, 110, 111}, // SKINCOLOR_CANARY, replaced with Mustard + {192, 193, 194, 195, 196, 197, 198, 199, 255, 255, 29, 29, 30, 30, 31, 31}, // SKINCOLOR_INDIGO, too similar to Byzantium { 1, 145, 125, 73, 83, 114, 106, 180, 187, 168, 219, 205, 236, 206, 199, 255}, // SKINCOLOR_RAINBOW, is Vomit 2.0 */ }; @@ -2215,7 +2218,7 @@ static mobj_t *K_SpawnKartMissile(mobj_t *source, mobjtype_t type, angle_t angle if (source && source->player) th->color = source->player->skincolor; else - th->color = SKINCOLOR_CLOUDY; + th->color = SKINCOLOR_GREY; } else if (type == MT_JAWZ || type == MT_JAWZ_DUD) { From f319046d82eb4e6acbb144087bd8b19d237d3e3a Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Mon, 17 Sep 2018 02:48:10 -0400 Subject: [PATCH 126/146] Updated Dream --- src/k_kart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index c01c9a984..5341e58c8 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -213,7 +213,7 @@ UINT8 colortranslations[MAXSKINCOLORS][16] = { {121, 144, 145, 72, 73, 84, 114, 115, 107, 108, 109, 183, 223, 207, 30, 246}, // SKINCOLOR_VOMIT { 98, 99, 112, 101, 113, 114, 106, 179, 180, 180, 181, 182, 183, 173, 174, 175}, // SKINCOLOR_GARDEN { 96, 97, 99, 100, 102, 104, 160, 162, 164, 166, 168, 171, 223, 223, 207, 31}, // SKINCOLOR_LIME - { 96, 98, 99, 112, 113, 178, 179, 165, 203, 203, 204, 204, 205, 205, 206, 207}, // SKINCOLOR_DREAM + {120, 120, 80, 80, 81, 177, 162, 164, 228, 228, 204, 204, 205, 205, 206, 207}, // SKINCOLOR_DREAM {120, 120, 176, 176, 176, 177, 177, 178, 178, 179, 179, 180, 180, 181, 182, 183}, // SKINCOLOR_TEA {120, 120, 176, 176, 177, 177, 178, 179, 165, 166, 167, 168, 169, 170, 171, 172}, // SKINCOLOR_PISTACHIO {176, 176, 177, 178, 165, 166, 167, 167, 168, 169, 182, 182, 182, 183, 183, 183}, // SKINCOLOR_ROBOHOOD From b87feaecebf06c71b3c120f8a9aa9426e83e404b Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 17 Sep 2018 11:21:25 +0100 Subject: [PATCH 127/146] Animated sky backport --- src/hardware/hw_main.c | 6 +++--- src/r_plane.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 9dbf37dcc..f1c5e555f 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5581,7 +5581,7 @@ static void HWR_DrawSkyBackground(player_t *player) // 0--1 (void)player; - HWR_GetTexture(skytexture); + HWR_GetTexture(texturetranslation[skytexture]); //Hurdler: the sky is the only texture who need 4.0f instead of 1.0 // because it's called just after clearing the screen @@ -5601,7 +5601,7 @@ static void HWR_DrawSkyBackground(player_t *player) // The only time this will probably be an issue is when a sky wider than 1024 is used as a sky AND a regular wall texture angle = (dup_viewangle + gr_xtoviewangle[0]); - dimensionmultiply = ((float)textures[skytexture]->width/256.0f); + dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->width/256.0f); if (atransform.mirror) { @@ -5616,7 +5616,7 @@ static void HWR_DrawSkyBackground(player_t *player) angle = aimingangle; aspectratio = (float)vid.width/(float)vid.height; - dimensionmultiply = ((float)textures[skytexture]->height/(128.0f*aspectratio)); + dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->height/(128.0f*aspectratio)); angleturn = (((float)ANGLE_45-1.0f)*aspectratio)*dimensionmultiply; // Middle of the sky should always be at angle 0 diff --git a/src/r_plane.c b/src/r_plane.c index 68be24b28..cf973ebc9 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -720,7 +720,7 @@ void R_DrawPlanes(void) dc_iscale = FixedMul(skyscale, FINECOSINE(xtoviewangle[x]>>ANGLETOFINESHIFT)); dc_x = x; dc_source = - R_GetColumn(skytexture, + R_GetColumn(texturetranslation[skytexture], angle); wallcolfunc(); } From a14829207ac46c5b6de0485b05e3b28f7c200480 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 17 Sep 2018 11:36:22 +0100 Subject: [PATCH 128/146] correct oversight in merge --- src/k_kart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index 88c4c60c4..aec4287ba 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2219,7 +2219,7 @@ static mobj_t *K_SpawnKartMissile(mobj_t *source, mobjtype_t type, angle_t angle if (source && source->player) th->color = source->player->skincolor; else - th->color = SKINCOLOR_CLOUDY; + th->color = SKINCOLOR_GREY; break; case MT_JAWZ: if (source && source->player) From 1a80dd13ee8a3ef4dcf116e2703702ec0850942a Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Mon, 17 Sep 2018 20:24:03 -0400 Subject: [PATCH 129/146] Booster+wipeout fix --- src/k_kart.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/k_kart.c b/src/k_kart.c index 5341e58c8..fad2da43a 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3459,7 +3459,11 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->kartstuff[k_thunderanim]--;*/ if (player->kartstuff[k_sneakertimer]) + { player->kartstuff[k_sneakertimer]--; + if (player->kartstuff[k_wipeoutslow] > 0 && player->kartstuff[k_wipeoutslow] < wipeoutslowtime+1) + player->kartstuff[k_wipeoutslow] = wipeoutslowtime+1; + } if (player->kartstuff[k_floorboost]) player->kartstuff[k_floorboost]--; From 15bf75d5604b7a88c450569b8f993e0a71b22582 Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 18 Sep 2018 19:37:03 +0100 Subject: [PATCH 130/146] Update a bunch of icons - `SDL_icon.xpm` and other targets' `.ico`s. --- src/sdl/SDL_icon.xpm | 499 +++++++++++++++++++++++----------------- src/sdl/Srb2SDL.ico | Bin 372798 -> 82992 bytes src/sdl12/Srb2SDL.ico | Bin 372798 -> 82992 bytes src/win32ce/Srb2win.ico | Bin 372798 -> 82992 bytes 4 files changed, 289 insertions(+), 210 deletions(-) diff --git a/src/sdl/SDL_icon.xpm b/src/sdl/SDL_icon.xpm index 30259d55e..17eb78dd9 100644 --- a/src/sdl/SDL_icon.xpm +++ b/src/sdl/SDL_icon.xpm @@ -1,213 +1,292 @@ /* XPM */ static const char *SDL_icon_xpm[] = { /* columns rows colors chars-per-pixel */ -"32 32 175 2 ", -" c None", -". c #2E2E2E", -"X c #3C3C3C", -"o c #493939", -"O c #4E473F", -"+ c #161658", -"@ c #131369", -"# c #06067B", -"$ c #111173", -"% c #16167F", -"& c #252567", -"* c #372B7C", -"= c #3D3679", -"- c #41414A", -"; c #575655", -": c #6A5841", -"> c #5B4B72", -", c #616160", -"< c #7B7B7B", -"1 c #906E49", -"2 c #89685D", -"3 c #A67B4A", -"4 c #AA7F50", -"5 c #9B7560", -"6 c #856C78", -"7 c #997B7D", -"8 c #B48552", -"9 c #BA8A55", -"0 c #A48665", -"q c #B98F67", -"w c #B9946A", -"e c #B7937A", -"r c #C8955C", -"t c #CA9966", -"y c #DAA469", -"u c #C9A37B", -"i c #D7AB7B", -"p c #DFB07D", -"a c #EBAE6A", -"s c #E5B27A", -"d c #F1B779", -"f c #0A0A83", -"g c #05058B", -"h c #060687", -"j c #101089", -"k c #131382", -"l c #040494", -"z c #02029D", -"x c #0C0B9C", -"c c #120F9E", -"v c #19199B", -"b c #382D84", -"n c #39398D", -"m c #222296", -"M c #0101A6", -"N c #0A0AA2", -"B c #0202AC", -"V c #1919A2", -"C c #1616AD", -"Z c #0000B5", -"A c #0202BC", -"S c #0C0CB6", -"D c #1313B3", -"F c #1011BD", -"G c #1B1BBE", -"H c #2B2BAC", -"J c #3737A1", -"K c #2A26BE", -"L c #2A29B4", -"P c #3B3BB8", -"I c #48478B", -"U c #57578A", -"Y c #4A499A", -"T c #524F95", -"R c #565399", -"E c #4C4CA8", -"W c #524DA7", -"Q c #5353A4", -"! c #5555A9", -"~ c #5555B4", -"^ c #5656B7", -"/ c #6464A6", -"( c #6F67B5", -") c #0404C3", -"_ c #0707CA", -"` c #1414CB", -"' c #1A1AC6", -"] c #0A0AD3", -"[ c #0D0DDC", -"{ c #1A1AD4", -"} c #1010DF", -"| c #1E1EDE", -" . c #1817DE", -".. c #221FCA", -"X. c #2B2BCC", -"o. c #2727C9", -"O. c #3434C3", -"+. c #3434D4", -"@. c #0F0FE2", -"#. c #1313E5", -"$. c #1515ED", -"%. c #1B1BEA", -"&. c #1C1CE4", -"*. c #1515F4", -"=. c #1818F3", -"-. c #1717FD", -";. c #1818FF", -":. c #2B2BE9", -">. c #2424FF", -",. c #2A2AFF", -"<. c #2222F1", -"1. c #3737FF", -"2. c #5D5DC3", -"3. c #5F5FC9", -"4. c #5655C2", -"5. c #4747D1", -"6. c #5B5BD4", -"7. c #6565C8", -"8. c #6363DA", -"9. c #4545FF", -"0. c #4D4DFC", -"q. c #5454FF", -"w. c #5959FF", -"e. c #6969E5", -"r. c #6B6CEA", -"t. c #6666E7", -"y. c #6B6BFE", -"u. c #6767F8", -"i. c #7070F6", -"p. c #7373FF", -"a. c #7C7CFF", -"s. c #91918F", -"d. c #8F9090", -"f. c #979797", -"g. c #9C9C9C", -"h. c #8585A1", -"j. c #9C9CA7", -"k. c #9292B6", -"l. c #A4A4A4", -"z. c #BDB2A4", -"x. c #A4A4B1", -"c. c #BFBFBD", -"v. c #BABAB7", -"b. c #C8AA87", -"n. c #DAAE82", -"m. c #DBB081", -"M. c #EBBA85", -"N. c #F3BF84", -"B. c #F2BE88", -"V. c #C2B3A3", -"C. c #FBC386", -"Z. c #FCC68C", -"A. c #FFC88F", -"S. c #F4C387", -"D. c #FFC990", -"F. c #C3C1BF", -"G. c #8F8FCB", -"H. c #BDBDC2", -"J. c #BDBDD1", -"K. c #8888F9", -"L. c #A4A4FB", -"P. c #CDCDCC", -"I. c #CECAC6", -"U. c #D3CFCA", -"Y. c #D3D0CC", -"T. c #C0C0D5", -"R. c #D6D5D4", -"E. c #D7D7DD", -"W. c #E1E1DF", -"Q. c #DEDEE1", -"!. c #E4E4E4", -"~. c #E8E8E8", -"^. c #F0F0EE", -"/. c #F5F5F2", -"(. c #FFFFFF", -/* pixels */ -" ", -" ", -" ", -" I Q T = ", -" Q 7.e.r.i.8.E E 3.r.6.J ", -" H ~ n 4.r.p.p.p.p.8.R > 5.^ w.,.-.{ v ", -" { 9.^ & P t.p.p.p.p.p.8.I 5 q K L <.;.;.;.-.' ", -" { %.H +.y.p.p.p.p.p.e.Y 2 a n.K F $.*.$.@.} ] N ", -" x D :.y.p.p.p.p.p.p.r.R 8 C.u ..F A ) A Z M h $ ", -" f =.q.p.p.p.p.p.p.p.p.i.( e 6 $.` l B M g ", -" ` ;.q.p.p.p.p.p.a.K.a.p.p.4.L -.` l N % ", -" V =.-.>.q.y.p.p.p.L.L.K.i.w.,.-.;.$.<.q.u.2. ", -" D { =.-.;.>.1.1.9.( h.h.Q &.-.-.-.;.9.p.p.p.r.! ", -" U j.o.-.;.-.;.-.P x.Q.^.R.~ *.-.;.;.>.1.q.y.p.i.2. ", -" H./.! *.;.;.;.o.x./.(.(.(.J.| -.-.;.-.-.;.,.9.u.p.7. ", -" !.(.k.#.;.-.=./ !.(.(.(.(.Q.X.-.;.;.;.;.-.-.;.;.1.w.6. ", -" ~.(.H.G ;.-.D j.(.(.(.(.(.!.O.-.-.;.;.;.-.;.-.;.-.;.,.O. ", -" ~.(.v.@ *.$.+ d.(.(.(.(.(.E.o.-.-.;.;.-.;.;.;.*.=.=.*.$.v ", -" ~.(.l.- Y T ; < (.(.(.(.(.J.&.-.;.;.$.@.[ ] _ ) ) Z B B f ", -" P.(.F.X c.I.X f.(.(.(.(.(.G.=.-.=.] A Z Z Z Z z f $ ", -" l.!.R.s.F.I.g.W.(.(.(.(.R.E .[ A Z Z Z B g $ ", -" . , ; - 0 M.b.V.U.R.Y.z.u n.7 c Z Z B g # + ", -" : w p Z.D.A.S.p u i M.A.A.S.* Z B h z ] C ", -" s D.D.A.A.A.A.A.A.A.i B.B.b A Z Z @.-.` ", -" 1 y C.D.A.A.A.A.A.M.u Z.e c A Z Z [ ;.&. ", -" 8 y d C.A.A.A.C.B.t * B Z Z Z A #.=.m ", -" 3 9 r t r 9 8 o @ $ # f j l B #.V ", -" j k ", -" ", -" ", -" ", -" " -}; +"256 256 32 1", +" c None", +". c #E7E7E7", +"+ c #DFDFDF", +"@ c #AFAFAF", +"# c #979797", +"$ c #8F8F8F", +"% c #B7B7B7", +"& c #F7F7F7", +"* c #D7D7D7", +"= c #4F4F4F", +"- c #0F0F0F", +"; c #070707", +"> c #575757", +", c #C7C7C7", +"' c #676767", +") c #7F7F7F", +"! c #5F5F5F", +"~ c #777777", +"{ c #474747", +"] c #878787", +"^ c #6F6F6F", +"/ c #BFBFBF", +"( c #373737", +"_ c #1F1F1F", +": c #272727", +"< c #2F2F2F", +"[ c #3F3F3F", +"} c #EFEFEF", +"| c #A7A7A7", +"1 c #9F9F9F", +"2 c #171717", +"3 c #CFCFCF", +" ", +" ", +" ", +" ", +" ................................................................................ ", +" ................................................................................ ", +" ................................................................................ ", +" ................................................................................ ", +" ............++++@@@@########$$$$$$$$$$$$$$$$############@@@@%%%%&&&&............................ ", +" ............++++@@@@########$$$$$$$$$$$$$$$$############@@@@%%%%&&&&............................ ", +" ............++++@@@@########$$$$$$$$$$$$$$$$############@@@@%%%%&&&&............................ ", +" ............++++@@@@########$$$$$$$$$$$$$$$$############@@@@%%%%&&&&............................ ", +" ........****====----;;;;;;;;;;;;----;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@@@@................................ ", +" ........****====----;;;;;;;;;;;;----;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@@@@................................ ", +" ........****====----;;;;;;;;;;;;----;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@@@@................................ ", +" ........****====----;;;;;;;;;;;;----;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@@@@................................ ", +" ........++++----;;;;;;;;;;;;;;;;--------;;;;;;;;;;;;;;;;;;;;;;;;;;;;>>>>........................................ ", +" ........++++----;;;;;;;;;;;;;;;;--------;;;;;;;;;;;;;;;;;;;;;;;;;;;;>>>>........................................ ", +" ........++++----;;;;;;;;;;;;;;;;--------;;;;;;;;;;;;;;;;;;;;;;;;;;;;>>>>........................................ ", +" ........++++----;;;;;;;;;;;;;;;;--------;;;;;;;;;;;;;;;;;;;;;;;;;;;;>>>>........................................ ", +" ............,,,,''''))))!!!!!!!!''''~~~~>>>>{{{{!!!!))))$$$$))))>>>>''''................****]]]]>>>>^^^^%%%%&&&&........ ", +" ............,,,,''''))))!!!!!!!!''''~~~~>>>>{{{{!!!!))))$$$$))))>>>>''''................****]]]]>>>>^^^^%%%%&&&&........ ", +" ............,,,,''''))))!!!!!!!!''''~~~~>>>>{{{{!!!!))))$$$$))))>>>>''''................****]]]]>>>>^^^^%%%%&&&&........ ", +" ............,,,,''''))))!!!!!!!!''''~~~~>>>>{{{{!!!!))))$$$$))))>>>>''''................****]]]]>>>>^^^^%%%%&&&&........ ", +" ........////((((________((((>>>>::::{{{{<<<<))))$$$$!!!![[[[[[[[[[[[%%%%&&&&............^^^^!!!!!!!!!!!!!!!!!!!!~~~~****.... ", +" ........////((((________((((>>>>::::{{{{<<<<))))$$$$!!!![[[[[[[[[[[[%%%%&&&&............^^^^!!!!!!!!!!!!!!!!!!!!~~~~****.... ", +" ........////((((________((((>>>>::::{{{{<<<<))))$$$$!!!![[[[[[[[[[[[%%%%&&&&............^^^^!!!!!!!!!!!!!!!!!!!!~~~~****.... ", +" ........////((((________((((>>>>::::{{{{<<<<))))$$$$!!!![[[[[[[[[[[[%%%%&&&&............^^^^!!!!!!!!!!!!!!!!!!!!~~~~****.... ", +" ........@@@@;;;;;;;;;;;;;;;;;;;;(((({{{{====]]]]::::;;;;;;;;;;;;;;;;;;;;~~~~........****____;;;;;;;;;;;;;;;;;;;;;;;;;;;;____........ ", +" ........@@@@;;;;;;;;;;;;;;;;;;;;(((({{{{====]]]]::::;;;;;;;;;;;;;;;;;;;;~~~~........****____;;;;;;;;;;;;;;;;;;;;;;;;;;;;____........ ", +" ........@@@@;;;;;;;;;;;;;;;;;;;;(((({{{{====]]]]::::;;;;;;;;;;;;;;;;;;;;~~~~........****____;;;;;;;;;;;;;;;;;;;;;;;;;;;;____........ ", +" ........@@@@;;;;;;;;;;;;;;;;;;;;(((({{{{====]]]]::::;;;;;;;;;;;;;;;;;;;;~~~~........****____;;;;;;;;;;;;;;;;;;;;;;;;;;;;____........ ", +" ....}}}}>>>>;;;;;;;;;;;;;;;;;;;;^^^^####====;;;;;;;;;;;;;;;;;;;;;;;;>>>>............<<<<;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;||||........ ", +" ....}}}}>>>>;;;;;;;;;;;;;;;;;;;;^^^^####====;;;;;;;;;;;;;;;;;;;;;;;;>>>>............<<<<;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;||||........ ", +" ....}}}}>>>>;;;;;;;;;;;;;;;;;;;;^^^^####====;;;;;;;;;;;;;;;;;;;;;;;;>>>>............<<<<;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;||||........ ", +" ....}}}}>>>>;;;;;;;;;;;;;;;;;;;;^^^^####====;;;;;;;;;;;;;;;;;;;;;;;;>>>>............<<<<;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;||||........ ", +" ........****1111))))))))))))))))))))%%%%]]]]))))))))))))))))))))))))%%%%&&&&........1111]]]]))))))))))))))))))))))))))))))))))))####}}}}.... ", +" ........****1111))))))))))))))))))))%%%%]]]]))))))))))))))))))))))))%%%%&&&&........1111]]]]))))))))))))))))))))))))))))))))))))####}}}}.... ", +" ........****1111))))))))))))))))))))%%%%]]]]))))))))))))))))))))))))%%%%&&&&........1111]]]]))))))))))))))))))))))))))))))))))))####}}}}.... ", +" ........****1111))))))))))))))))))))%%%%]]]]))))))))))))))))))))))))%%%%&&&&........1111]]]]))))))))))))))))))))))))))))))))))))####}}}}.... ", +" ........%%%%[[[[;;;;;;;;;;;;;;;;;;;;[[[[2222;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::........####;;;;;;;;;;;;2222[[[[[[[[----;;;;;;;;;;;;;;;;;;;;====........ ", +" ........%%%%[[[[;;;;;;;;;;;;;;;;;;;;[[[[2222;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::........####;;;;;;;;;;;;2222[[[[[[[[----;;;;;;;;;;;;;;;;;;;;====........ ", +" ........%%%%[[[[;;;;;;;;;;;;;;;;;;;;[[[[2222;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::........####;;;;;;;;;;;;2222[[[[[[[[----;;;;;;;;;;;;;;;;;;;;====........ ", +" ........%%%%[[[[;;;;;;;;;;;;;;;;;;;;[[[[2222;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::........####;;;;;;;;;;;;2222[[[[[[[[----;;;;;;;;;;;;;;;;;;;;====........ ", +" ....&&&&::::;;;;[[[[{{{{;;;;;;;;;;;;{{{{;;;;;;;;;;;;~~~~===={{{{::::;;;;^^^^........____;;;;;;;;''''}}}}............>>>>;;;;;;;;;;;;;;;;;;;;,,,,.... ", +" ....&&&&::::;;;;[[[[{{{{;;;;;;;;;;;;{{{{;;;;;;;;;;;;~~~~===={{{{::::;;;;^^^^........____;;;;;;;;''''}}}}............>>>>;;;;;;;;;;;;;;;;;;;;,,,,.... ", +" ....&&&&::::;;;;[[[[{{{{;;;;;;;;;;;;{{{{;;;;;;;;;;;;~~~~===={{{{::::;;;;^^^^........____;;;;;;;;''''}}}}............>>>>;;;;;;;;;;;;;;;;;;;;,,,,.... ", +" ....&&&&::::;;;;[[[[{{{{;;;;;;;;;;;;{{{{;;;;;;;;;;;;~~~~===={{{{::::;;;;^^^^........____;;;;;;;;''''}}}}............>>>>;;;;;;;;;;;;;;;;;;;;,,,,.... ", +" ....}}}}<<<<;;;;;;;;::::{{{{;;;;____::::2222!!!!''''----;;;;;;;;;;;;]]]]****....&&&&((((____]]]]....||||{{{{====@@@@....~~~~____________[[[[////........ ", +" ....}}}}<<<<;;;;;;;;::::{{{{;;;;____::::2222!!!!''''----;;;;;;;;;;;;]]]]****....&&&&((((____]]]]....||||{{{{====@@@@....~~~~____________[[[[////........ ", +" ....}}}}<<<<;;;;;;;;::::{{{{;;;;____::::2222!!!!''''----;;;;;;;;;;;;]]]]****....&&&&((((____]]]]....||||{{{{====@@@@....~~~~____________[[[[////........ ", +" ....}}}}<<<<;;;;;;;;::::{{{{;;;;____::::2222!!!!''''----;;;;;;;;;;;;]]]]****....&&&&((((____]]]]....||||{{{{====@@@@....~~~~____________[[[[////........ ", +" ........****$$$$))))))))]]]]@@@@%%%%////////,,,,111111111111111111111111}}}}........||||1111****....@@@@1111111111111111@@@@....3333111111111111||||&&&&.... ", +" ........****$$$$))))))))]]]]@@@@%%%%////////,,,,111111111111111111111111}}}}........||||1111****....@@@@1111111111111111@@@@....3333111111111111||||&&&&.... ", +" ........****$$$$))))))))]]]]@@@@%%%%////////,,,,111111111111111111111111}}}}........||||1111****....@@@@1111111111111111@@@@....3333111111111111||||&&&&.... ", +" ........****$$$$))))))))]]]]@@@@%%%%////////,,,,111111111111111111111111}}}}........||||1111****....@@@@1111111111111111@@@@....3333111111111111||||&&&&.... ", +" ....,,,,::::;;;;;;;;;;;;;;;;;;;;''''####^^^^;;;;;;;;;;;;;;;;;;;;;;;;;;;;]]]]....////;;;;;;;;++++))));;;;;;;;;;;;;;;;;;;;;;;;$$$$****;;;;;;;;;;;;;;;;........ ", +" ....,,,,::::;;;;;;;;;;;;;;;;;;;;''''####^^^^;;;;;;;;;;;;;;;;;;;;;;;;;;;;]]]]....////;;;;;;;;++++))));;;;;;;;;;;;;;;;;;;;;;;;$$$$****;;;;;;;;;;;;;;;;........ ", +" ....,,,,::::;;;;;;;;;;;;;;;;;;;;''''####^^^^;;;;;;;;;;;;;;;;;;;;;;;;;;;;]]]]....////;;;;;;;;++++))));;;;;;;;;;;;;;;;;;;;;;;;$$$$****;;;;;;;;;;;;;;;;........ ", +" ....,,,,::::;;;;;;;;;;;;;;;;;;;;''''####^^^^;;;;;;;;;;;;;;;;;;;;;;;;;;;;]]]]....////;;;;;;;;++++))));;;;;;;;;;;;;;;;;;;;;;;;$$$$****;;;;;;;;;;;;;;;;........ ", +" ....^^^^;;;;;;;;;;;;;;;;;;;;;;;;))))))));;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;$$$$....~~~~;;;;$$$$****;;;;;;;;;;;;;;;;;;;;;;;;;;;;----++++^^^^;;;;;;;;;;;;####.... ", +" ....^^^^;;;;;;;;;;;;;;;;;;;;;;;;))))))));;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;$$$$....~~~~;;;;$$$$****;;;;;;;;;;;;;;;;;;;;;;;;;;;;----++++^^^^;;;;;;;;;;;;####.... ", +" ....^^^^;;;;;;;;;;;;;;;;;;;;;;;;))))))));;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;$$$$....~~~~;;;;$$$$****;;;;;;;;;;;;;;;;;;;;;;;;;;;;----++++^^^^;;;;;;;;;;;;####.... ", +" ....^^^^;;;;;;;;;;;;;;;;;;;;;;;;))))))));;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;$$$$....~~~~;;;;$$$$****;;;;;;;;;;;;;;;;;;;;;;;;;;;;----++++^^^^;;;;;;;;;;;;####.... ", +" ........$$$$;;;;;;;;;;;;;;;;;;;;;;;;>>>>;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;>>>>}}}}....^^^^----....!!!!;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;))))****::::;;;;;;;;||||.... ", +" ........$$$$;;;;;;;;;;;;;;;;;;;;;;;;>>>>;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;>>>>}}}}....^^^^----....!!!!;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;))))****::::;;;;;;;;||||.... ", +" ........$$$$;;;;;;;;;;;;;;;;;;;;;;;;>>>>;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;>>>>}}}}....^^^^----....!!!!;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;))))****::::;;;;;;;;||||.... ", +" ........$$$$;;;;;;;;;;;;;;;;;;;;;;;;>>>>;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;>>>>}}}}....^^^^----....!!!!;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;))))****::::;;;;;;;;||||.... ", +" ....&&&&@@@@$$$$||||####))))))))))))||||))))))))))))1111||||||||####]]]]++++........$$$$////}}}}]]]]))))))))))))))))))))))))))))))))$$$$....3333))))))))####........ ", +" ....&&&&@@@@$$$$||||####))))))))))))||||))))))))))))1111||||||||####]]]]++++........$$$$////}}}}]]]]))))))))))))))))))))))))))))))))$$$$....3333))))))))####........ ", +" ....&&&&@@@@$$$$||||####))))))))))))||||))))))))))))1111||||||||####]]]]++++........$$$$////}}}}]]]]))))))))))))))))))))))))))))))))$$$$....3333))))))))####........ ", +" ....&&&&@@@@$$$$||||####))))))))))))||||))))))))))))1111||||||||####]]]]++++........$$$$////}}}}]]]]))))))))))))))))))))))))))))))))$$$$....3333))))))))####........ ", +" ....####;;;;;;;;;;;;[[[[{{{{;;;;---->>>>;;;;----^^^^[[[[;;;;;;;;;;;;;;;;]]]]....~~~~;;;;@@@@]]]];;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1111####;;;;;;;;----}}}}.... ", +" ....####;;;;;;;;;;;;[[[[{{{{;;;;---->>>>;;;;----^^^^[[[[;;;;;;;;;;;;;;;;]]]]....~~~~;;;;@@@@]]]];;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1111####;;;;;;;;----}}}}.... ", +" ....####;;;;;;;;;;;;[[[[{{{{;;;;---->>>>;;;;----^^^^[[[[;;;;;;;;;;;;;;;;]]]]....~~~~;;;;@@@@]]]];;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1111####;;;;;;;;----}}}}.... ", +" ....####;;;;;;;;;;;;[[[[{{{{;;;;---->>>>;;;;----^^^^[[[[;;;;;;;;;;;;;;;;]]]]....~~~~;;;;@@@@]]]];;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1111####;;;;;;;;----}}}}.... ", +" ....{{{{;;;;;;;;;;;;;;;;{{{{<<<<[[[[::::((((~~~~----;;;;;;;;;;;;;;;;;;;;$$$$....((((----....<<<<;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;{{{{}}}};;;;;;;;;;;;3333.... ", +" ....{{{{;;;;;;;;;;;;;;;;{{{{<<<<[[[[::::((((~~~~----;;;;;;;;;;;;;;;;;;;;$$$$....((((----....<<<<;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;{{{{}}}};;;;;;;;;;;;3333.... ", +" ....{{{{;;;;;;;;;;;;;;;;{{{{<<<<[[[[::::((((~~~~----;;;;;;;;;;;;;;;;;;;;$$$$....((((----....<<<<;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;{{{{}}}};;;;;;;;;;;;3333.... ", +" ....{{{{;;;;;;;;;;;;;;;;{{{{<<<<[[[[::::((((~~~~----;;;;;;;;;;;;;;;;;;;;$$$$....((((----....<<<<;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;{{{{}}}};;;;;;;;;;;;3333.... ", +" ........))));;;;;;;;;;;;;;;;;;;;~~~~~~~~[[[[!!!!;;;;;;;;;;;;;;;;;;;;;;;;----////....>>>>====....>>>>;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2222}}}}^^^^;;;;::::3333.... ", +" ........))));;;;;;;;;;;;;;;;;;;;~~~~~~~~[[[[!!!!;;;;;;;;;;;;;;;;;;;;;;;;----////....>>>>====....>>>>;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2222}}}}^^^^;;;;::::3333.... ", +" ........))));;;;;;;;;;;;;;;;;;;;~~~~~~~~[[[[!!!!;;;;;;;;;;;;;;;;;;;;;;;;----////....>>>>====....>>>>;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2222}}}}^^^^;;;;::::3333.... ", +" ........))));;;;;;;;;;;;;;;;;;;;~~~~~~~~[[[[!!!!;;;;;;;;;;;;;;;;;;;;;;;;----////....>>>>====....>>>>;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2222}}}}^^^^;;;;::::3333.... ", +" ....&&&&####))))))))))))))))))))$$$$}}}}@@@@))))))))))))))))))))))))))))@@@@....}}}}]]]]3333....****))))))))))))))))))))))))))))))))))))))))))))....,,,,))))))))........ ", +" ....&&&&####))))))))))))))))))))$$$$}}}}@@@@))))))))))))))))))))))))))))@@@@....}}}}]]]]3333....****))))))))))))))))))))))))))))))))))))))))))))....,,,,))))))))........ ", +" ....&&&&####))))))))))))))))))))$$$$}}}}@@@@))))))))))))))))))))))))))))@@@@....}}}}]]]]3333....****))))))))))))))))))))))))))))))))))))))))))))....,,,,))))))))........ ", +" ....&&&&####))))))))))))))))))))$$$$}}}}@@@@))))))))))))))))))))))))))))@@@@....}}}}]]]]3333....****))))))))))))))))))))))))))))))))))))))))))))....,,,,))))))))........ ", +" ....3333;;;;;;;;;;;;;;;;;;;;;;;;;;;;))));;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2222++++||||;;;;%%%%....'''';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;]]]]1111;;;;;;;;1111.... ", +" ....3333;;;;;;;;;;;;;;;;;;;;;;;;;;;;))));;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2222++++||||;;;;%%%%....'''';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;]]]]1111;;;;;;;;1111.... ", +" ....3333;;;;;;;;;;;;;;;;;;;;;;;;;;;;))));;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2222++++||||;;;;%%%%....'''';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;]]]]1111;;;;;;;;1111.... ", +" ....3333;;;;;;;;;;;;;;;;;;;;;;;;;;;;))));;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2222++++||||;;;;%%%%....'''';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;]]]]1111;;;;;;;;1111.... ", +" ....1111____((((::::;;;;;;;;;;;;;;;;{{{{;;;;;;;;;;;;[[[[====[[[[::::;;;;;;;;....]]]];;;;}}}}....))));;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;====,,,,;;;;;;;;]]]].... ", +" ....1111____((((::::;;;;;;;;;;;;;;;;{{{{;;;;;;;;;;;;[[[[====[[[[::::;;;;;;;;....]]]];;;;}}}}....))));;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;====,,,,;;;;;;;;]]]].... ", +" ....1111____((((::::;;;;;;;;;;;;;;;;{{{{;;;;;;;;;;;;[[[[====[[[[::::;;;;;;;;....]]]];;;;}}}}....))));;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;====,,,,;;;;;;;;]]]].... ", +" ....1111____((((::::;;;;;;;;;;;;;;;;{{{{;;;;;;;;;;;;[[[[====[[[[::::;;;;;;;;....]]]];;;;}}}}....))));;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;====,,,,;;;;;;;;]]]].... ", +" ....%%%%2222----((((!!!!2222;;;;2222{{{{;;;;____''''::::;;;;;;;;;;;;;;;;))))....1111;;;;........++++::::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;____....;;;;;;;;1111.... ", +" ....%%%%2222----((((!!!!2222;;;;2222{{{{;;;;____''''::::;;;;;;;;;;;;;;;;))))....1111;;;;........++++::::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;____....;;;;;;;;1111.... ", +" ....%%%%2222----((((!!!!2222;;;;2222{{{{;;;;____''''::::;;;;;;;;;;;;;;;;))))....1111;;;;........++++::::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;____....;;;;;;;;1111.... ", +" ....%%%%2222----((((!!!!2222;;;;2222{{{{;;;;____''''::::;;;;;;;;;;;;;;;;))))....1111;;;;........++++::::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;____....;;;;;;;;1111.... ", +" ....++++))))))))))))))))@@@@1111$$$$1111####@@@@))))))))))))))))))))))))3333....,,,,@@@@............1111))))))))))))))))))))))))))))))))))))))))]]]]....1111####3333.... ", +" ....++++))))))))))))))))@@@@1111$$$$1111####@@@@))))))))))))))))))))))))3333....,,,,@@@@............1111))))))))))))))))))))))))))))))))))))))))]]]]....1111####3333.... ", +" ....++++))))))))))))))))@@@@1111$$$$1111####@@@@))))))))))))))))))))))))3333....,,,,@@@@............1111))))))))))))))))))))))))))))))))))))))))]]]]....1111####3333.... ", +" ....++++))))))))))))))))@@@@1111$$$$1111####@@@@))))))))))))))))))))))))3333....,,,,@@@@............1111))))))))))))))))))))))))))))))))))))))))]]]]....1111####3333.... ", +" ....{{{{;;;;;;;;;;;;;;;;;;;;^^^^<<<<>>>>))));;;;;;;;;;;;;;;;;;;;;;;;;;;;----....[[[[)))).... ....----;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3333{{{{;;;;####.... ", +" ....{{{{;;;;;;;;;;;;;;;;;;;;^^^^<<<<>>>>))));;;;;;;;;;;;;;;;;;;;;;;;;;;;----....[[[[)))).... ....----;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3333{{{{;;;;####.... ", +" ....{{{{;;;;;;;;;;;;;;;;;;;;^^^^<<<<>>>>))));;;;;;;;;;;;;;;;;;;;;;;;;;;;----....[[[[)))).... ....----;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3333{{{{;;;;####.... ", +" ....{{{{;;;;;;;;;;;;;;;;;;;;^^^^<<<<>>>>))));;;;;;;;;;;;;;;;;;;;;;;;;;;;----....[[[[)))).... ....----;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3333{{{{;;;;####.... ", +" ....____;;;;;;;;;;;;;;;;;;;;----~~~~]]]];;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;}}}};;;;####.... ....____;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;////^^^^;;;;####.... ", +" ....____;;;;;;;;;;;;;;;;;;;;----~~~~]]]];;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;}}}};;;;####.... ....____;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;////^^^^;;;;####.... ", +" ....____;;;;;;;;;;;;;;;;;;;;----~~~~]]]];;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;}}}};;;;####.... ....____;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;////^^^^;;;;####.... ", +" ....____;;;;;;;;;;;;;;;;;;;;----~~~~]]]];;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;}}}};;;;####.... ....____;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;////^^^^;;;;####.... ", +" ....$$$$''''!!!!!!!!!!!!!!!!!!!!1111]]]]!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!%%%%}}}}[[[[,,,,.... ....''''[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[,,,,||||>>>>}}}}.... ", +" ....$$$$''''!!!!!!!!!!!!!!!!!!!!1111]]]]!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!%%%%}}}}[[[[,,,,.... ....''''[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[,,,,||||>>>>}}}}.... ", +" ....$$$$''''!!!!!!!!!!!!!!!!!!!!1111]]]]!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!%%%%}}}}[[[[,,,,.... ....''''[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[,,,,||||>>>>}}}}.... ", +" ....$$$$''''!!!!!!!!!!!!!!!!!!!!1111]]]]!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!%%%%}}}}[[[[,,,,.... ....''''[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[,,,,||||>>>>}}}}.... ", +" ........''''{{{{::::::::____________!!!!{{{{____________::::((((>>>>____________::::[[[[@@@@............~~~~[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[1111####{{{{,,,,.... ", +" ........''''{{{{::::::::____________!!!!{{{{____________::::((((>>>>____________::::[[[[@@@@............~~~~[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[1111####{{{{,,,,.... ", +" ........''''{{{{::::::::____________!!!!{{{{____________::::((((>>>>____________::::[[[[@@@@............~~~~[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[1111####{{{{,,,,.... ", +" ........''''{{{{::::::::____________!!!!{{{{____________::::((((>>>>____________::::[[[[@@@@............~~~~[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[1111####{{{{,,,,.... ", +" ....++++;;;;----<<<<====((((;;;;;;;;[[[[::::;;;;;;;;((((====----;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;)))).... ", +" ....++++;;;;----<<<<====((((;;;;;;;;[[[[::::;;;;;;;;((((====----;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;)))).... ", +" ....++++;;;;----<<<<====((((;;;;;;;;[[[[::::;;;;;;;;((((====----;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;)))).... ", +" ....++++;;;;----<<<<====((((;;;;;;;;[[[[::::;;;;;;;;((((====----;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;)))).... ", +" ....****;;;;;;;;;;;;;;;;[[[[====;;;;[[[[____;;;;{{{{((((;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;----####.... ", +" ....****;;;;;;;;;;;;;;;;[[[[====;;;;[[[[____;;;;{{{{((((;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;----####.... ", +" ....****;;;;;;;;;;;;;;;;[[[[====;;;;[[[[____;;;;{{{{((((;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;----####.... ", +" ....****;;;;;;;;;;;;;;;;[[[[====;;;;[[[[____;;;;{{{{((((;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;----####.... ", +" ....&&&&))))!!!!!!!!!!!!!!!!))))$$$$]]]]~~~~))))$$$$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!^^^^++++.... ", +" ....&&&&))))!!!!!!!!!!!!!!!!))))$$$$]]]]~~~~))))$$$$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!^^^^++++.... ", +" ....&&&&))))!!!!!!!!!!!!!!!!))))$$$$]]]]~~~~))))$$$$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!^^^^++++.... ", +" ....&&&&))))!!!!!!!!!!!!!!!!))))$$$$]]]]~~~~))))$$$$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!^^^^++++.... ", +" ....&&&&((((____________________!!!!$$$$))))!!!!________________________________________________________________________________________________________________<<<<3333.... ", +" ....&&&&((((____________________!!!!$$$$))))!!!!________________________________________________________________________________________________________________<<<<3333.... ", +" ....&&&&((((____________________!!!!$$$$))))!!!!________________________________________________________________________________________________________________<<<<3333.... ", +" ....&&&&((((____________________!!!!$$$$))))!!!!________________________________________________________________________________________________________________<<<<3333.... ", +" ....%%%%;;;;;;;;;;;;;;;;;;;;;;;;;;;;@@@@||||;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;========))))))))))))))))))))))))))))))))))))))))))))))))))))))))]]]]****&&&&.... ", +" ....%%%%;;;;;;;;;;;;;;;;;;;;;;;;;;;;@@@@||||;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;========))))))))))))))))))))))))))))))))))))))))))))))))))))))))]]]]****&&&&.... ", +" ....%%%%;;;;;;;;;;;;;;;;;;;;;;;;;;;;@@@@||||;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;========))))))))))))))))))))))))))))))))))))))))))))))))))))))))]]]]****&&&&.... ", +" ....%%%%;;;;;;;;;;;;;;;;;;;;;;;;;;;;@@@@||||;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;========))))))))))))))))))))))))))))))))))))))))))))))))))))))))]]]]****&&&&.... ", +" ....****22222222;;;;;;;;;;;;;;;;;;;;(((({{{{;;;;;;;;;;;;;;;;;;;;____----;;;;;;;;;;;;;;;;%%%%....&&&&........................................................................ ", +" ....****22222222;;;;;;;;;;;;;;;;;;;;(((({{{{;;;;;;;;;;;;;;;;;;;;____----;;;;;;;;;;;;;;;;%%%%....&&&&........................................................................ ", +" ....****22222222;;;;;;;;;;;;;;;;;;;;(((({{{{;;;;;;;;;;;;;;;;;;;;____----;;;;;;;;;;;;;;;;%%%%....&&&&........................................................................ ", +" ....****22222222;;;;;;;;;;;;;;;;;;;;(((({{{{;;;;;;;;;;;;;;;;;;;;____----;;;;;;;;;;;;;;;;%%%%....&&&&........................................................................ ", +" ....&&&&++++~~~~####]]]]!!!!!!!!!!!!~~~~]]]]!!!!====[[[[!!!!^^^^>>>>[[[[[[[[[[[[[[[[{{{{}}}}............ ", +" ....&&&&++++~~~~####]]]]!!!!!!!!!!!!~~~~]]]]!!!!====[[[[!!!!^^^^>>>>[[[[[[[[[[[[[[[[{{{{}}}}............ ", +" ....&&&&++++~~~~####]]]]!!!!!!!!!!!!~~~~]]]]!!!!====[[[[!!!!^^^^>>>>[[[[[[[[[[[[[[[[{{{{}}}}............ ", +" ....&&&&++++~~~~####]]]]!!!!!!!!!!!!~~~~]]]]!!!!====[[[[!!!!^^^^>>>>[[[[[[[[[[[[[[[[{{{{}}}}............ ", +" ........////________::::^^^^^^^^::::((((!!!!____[[[[$$$$>>>>[[[[[[[[[[[[[[[[[[[[[[[[{{{{++++.... ", +" ........////________::::^^^^^^^^::::((((!!!!____[[[[$$$$>>>>[[[[[[[[[[[[[[[[[[[[[[[[{{{{++++.... ", +" ........////________::::^^^^^^^^::::((((!!!!____[[[[$$$$>>>>[[[[[[[[[[[[[[[[[[[[[[[[{{{{++++.... ", +" ........////________::::^^^^^^^^::::((((!!!!____[[[[$$$$>>>>[[[[[[[[[[[[[[[[[[[[[[[[{{{{++++.... ", +" ....<<<<;;;;;;;;;;;;;;;;<<<<^^^^2222{{{{;;;;''''2222;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;]]]].... ", +" ....<<<<;;;;;;;;;;;;;;;;<<<<^^^^2222{{{{;;;;''''2222;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;]]]].... ", +" ....<<<<;;;;;;;;;;;;;;;;<<<<^^^^2222{{{{;;;;''''2222;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;]]]].... ", +" ....<<<<;;;;;;;;;;;;;;;;<<<<^^^^2222{{{{;;;;''''2222;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;]]]].... ", +" ....;;;;;;;;;;;;;;;;;;;;;;;;::::~~~~====>>>>::::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;]]]].... ", +" ....;;;;;;;;;;;;;;;;;;;;;;;;::::~~~~====>>>>::::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;]]]].... ", +" ....;;;;;;;;;;;;;;;;;;;;;;;;::::~~~~====>>>>::::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;]]]].... ", +" ....;;;;;;;;;;;;;;;;;;;;;;;;::::~~~~====>>>>::::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;]]]].... ", +" ....@@@@!!!!!!!!!!!!!!!!!!!!!!!!]]]]3333||||!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!****.... ", +" ....@@@@!!!!!!!!!!!!!!!!!!!!!!!!]]]]3333||||!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!****.... ", +" ....@@@@!!!!!!!!!!!!!!!!!!!!!!!!]]]]3333||||!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!****.... ", +" ....@@@@!!!!!!!!!!!!!!!!!!!!!!!!]]]]3333||||!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!****.... ", +" ....####____________________________####____________________::::<<<<________________~~~~........ ", +" ....####____________________________####____________________::::<<<<________________~~~~........ ", +" ....####____________________________####____________________::::<<<<________________~~~~........ ", +" ....####____________________________####____________________::::<<<<________________~~~~........ ", +" ....^^^^____{{{{[[[[____;;;;;;;;;;;;====2222;;;;;;;;;;;;<<<<<<<<----;;;;;;;;;;;;;;;;;;;;,,,,........................................................................ ", +" ....^^^^____{{{{[[[[____;;;;;;;;;;;;====2222;;;;;;;;;;;;<<<<<<<<----;;;;;;;;;;;;;;;;;;;;,,,,........................................................................ ", +" ....^^^^____{{{{[[[[____;;;;;;;;;;;;====2222;;;;;;;;;;;;<<<<<<<<----;;;;;;;;;;;;;;;;;;;;,,,,........................................................................ ", +" ....^^^^____{{{{[[[[____;;;;;;;;;;;;====2222;;;;;;;;;;;;<<<<<<<<----;;;;;;;;;;;;;;;;;;;;,,,,........................................................................ ", +" ....@@@@<<<<;;;;;;;;{{{{~~~~2222;;;;____>>>>;;;;;;;;((((((((;;;;;;;;;;;;;;;;;;;;;;;;;;;;3333,,,,--------------------------------------------||||....$$$$----!!!!.... ", +" ....@@@@<<<<;;;;;;;;{{{{~~~~2222;;;;____>>>>;;;;;;;;((((((((;;;;;;;;;;;;;;;;;;;;;;;;;;;;3333,,,,--------------------------------------------||||....$$$$----!!!!.... ", +" ....@@@@<<<<;;;;;;;;{{{{~~~~2222;;;;____>>>>;;;;;;;;((((((((;;;;;;;;;;;;;;;;;;;;;;;;;;;;3333,,,,--------------------------------------------||||....$$$$----!!!!.... ", +" ....@@@@<<<<;;;;;;;;{{{{~~~~2222;;;;____>>>>;;;;;;;;((((((((;;;;;;;;;;;;;;;;;;;;;;;;;;;;3333,,,,--------------------------------------------||||....$$$$----!!!!.... ", +" ........@@@@))))))))))))))))||||@@@@))))||||))))$$$$||||))))))))))))))))))))))))))))####}}}}&&&&////))))))))))))))))))))))))))))))))))))))))}}}}....////))))////.... ", +" ........@@@@))))))))))))))))||||@@@@))))||||))))$$$$||||))))))))))))))))))))))))))))####}}}}&&&&////))))))))))))))))))))))))))))))))))))))))}}}}....////))))////.... ", +" ........@@@@))))))))))))))))||||@@@@))))||||))))$$$$||||))))))))))))))))))))))))))))####}}}}&&&&////))))))))))))))))))))))))))))))))))))))))}}}}....////))))////.... ", +" ........@@@@))))))))))))))))||||@@@@))))||||))))$$$$||||))))))))))))))))))))))))))))####}}}}&&&&////))))))))))))))))))))))))))))))))))))))))}}}}....////))))////.... ", +" ....&&&&::::;;;;;;;;;;;;;;;;;;;;====>>>>>>>>;;;;^^^^;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;____....[[[[;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;^^^^....{{{{;;;;||||.... ", +" ....&&&&::::;;;;;;;;;;;;;;;;;;;;====>>>>>>>>;;;;^^^^;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;____....[[[[;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;^^^^....{{{{;;;;||||.... ", +" ....&&&&::::;;;;;;;;;;;;;;;;;;;;====>>>>>>>>;;;;^^^^;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;____....[[[[;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;^^^^....{{{{;;;;||||.... ", +" ....&&&&::::;;;;;;;;;;;;;;;;;;;;====>>>>>>>>;;;;^^^^;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;____....[[[[;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;^^^^....{{{{;;;;||||.... ", +" ........2222;;;;;;;;;;;;;;;;;;;;;;;;{{{{####<<<<[[[[;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++++'''';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;~~~~****;;;;;;;;........ ", +" ........2222;;;;;;;;;;;;;;;;;;;;;;;;{{{{####<<<<[[[[;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++++'''';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;~~~~****;;;;;;;;........ ", +" ........2222;;;;;;;;;;;;;;;;;;;;;;;;{{{{####<<<<[[[[;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++++'''';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;~~~~****;;;;;;;;........ ", +" ........2222;;;;;;;;;;;;;;;;;;;;;;;;{{{{####<<<<[[[[;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++++'''';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;~~~~****;;;;;;;;........ ", +" ....^^^^;;;;;;;;;;;;;;;;;;;;;;;;;;;;''''%%%%;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;{{{{&&&&}}}}####;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;[[[[++++||||;;;;----........ ", +" ....^^^^;;;;;;;;;;;;;;;;;;;;;;;;;;;;''''%%%%;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;{{{{&&&&}}}}####;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;[[[[++++||||;;;;----........ ", +" ....^^^^;;;;;;;;;;;;;;;;;;;;;;;;;;;;''''%%%%;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;{{{{&&&&}}}}####;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;[[[[++++||||;;;;----........ ", +" ....^^^^;;;;;;;;;;;;;;;;;;;;;;;;;;;;''''%%%%;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;{{{{&&&&}}}}####;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;[[[[++++||||;;;;----........ ", +" ....&&&&3333$$$$1111$$$$))))))))))))))))%%%%))))))))))))))))1111]]]]))))))))))))))))]]]]++++&&&&}}}}$$$$))))))))))))))))))))))))@@@@&&&&....////))))@@@@.... ", +" ....&&&&3333$$$$1111$$$$))))))))))))))))%%%%))))))))))))))))1111]]]]))))))))))))))))]]]]++++&&&&}}}}$$$$))))))))))))))))))))))))@@@@&&&&....////))))@@@@.... ", +" ....&&&&3333$$$$1111$$$$))))))))))))))))%%%%))))))))))))))))1111]]]]))))))))))))))))]]]]++++&&&&}}}}$$$$))))))))))))))))))))))))@@@@&&&&....////))))@@@@.... ", +" ....&&&&3333$$$$1111$$$$))))))))))))))))%%%%))))))))))))))))1111]]]]))))))))))))))))]]]]++++&&&&}}}}$$$$))))))))))))))))))))))))@@@@&&&&....////))))@@@@.... ", +" ........((((;;;;____<<<<''''{{{{;;;;;;;;((((----;;;;;;;;[[[[2222;;;;;;;;;;;;;;;;;;;;;;;;----@@@@3333;;;;;;;;;;;;;;;;;;;;;;;;;;;;____}}}}}}}};;;;;;;;~~~~.... ", +" ........((((;;;;____<<<<''''{{{{;;;;;;;;((((----;;;;;;;;[[[[2222;;;;;;;;;;;;;;;;;;;;;;;;----@@@@3333;;;;;;;;;;;;;;;;;;;;;;;;;;;;____}}}}}}}};;;;;;;;~~~~.... ", +" ........((((;;;;____<<<<''''{{{{;;;;;;;;((((----;;;;;;;;[[[[2222;;;;;;;;;;;;;;;;;;;;;;;;----@@@@3333;;;;;;;;;;;;;;;;;;;;;;;;;;;;____}}}}}}}};;;;;;;;~~~~.... ", +" ........((((;;;;____<<<<''''{{{{;;;;;;;;((((----;;;;;;;;[[[[2222;;;;;;;;;;;;;;;;;;;;;;;;----@@@@3333;;;;;;;;;;;;;;;;;;;;;;;;;;;;____}}}}}}}};;;;;;;;~~~~.... ", +" ....====;;;;;;;;;;;;;;;;::::~~~~<<<<----((((;;;;----[[[[;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::....====;;;;;;;;;;;;;;;;;;;;;;;;>>>>....!!!!;;;;;;;;,,,,.... ", +" ....====;;;;;;;;;;;;;;;;::::~~~~<<<<----((((;;;;----[[[[;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::....====;;;;;;;;;;;;;;;;;;;;;;;;>>>>....!!!!;;;;;;;;,,,,.... ", +" ....====;;;;;;;;;;;;;;;;::::~~~~<<<<----((((;;;;----[[[[;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::....====;;;;;;;;;;;;;;;;;;;;;;;;>>>>....!!!!;;;;;;;;,,,,.... ", +" ....====;;;;;;;;;;;;;;;;::::~~~~<<<<----((((;;;;----[[[[;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::....====;;;;;;;;;;;;;;;;;;;;;;;;>>>>....!!!!;;;;;;;;,,,,.... ", +" ....////::::;;;;;;;;;;;;;;;;;;;;!!!!!!!!!!!!;;;;====----;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;>>>>....++++$$$$;;;;;;;;;;;;;;;;[[[[....&&&&____;;;;====........ ", +" ....////::::;;;;;;;;;;;;;;;;;;;;!!!!!!!!!!!!;;;;====----;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;>>>>....++++$$$$;;;;;;;;;;;;;;;;[[[[....&&&&____;;;;====........ ", +" ....////::::;;;;;;;;;;;;;;;;;;;;!!!!!!!!!!!!;;;;====----;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;>>>>....++++$$$$;;;;;;;;;;;;;;;;[[[[....&&&&____;;;;====........ ", +" ....////::::;;;;;;;;;;;;;;;;;;;;!!!!!!!!!!!!;;;;====----;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;>>>>....++++$$$$;;;;;;;;;;;;;;;;[[[[....&&&&____;;;;====........ ", +" ........&&&&||||))))))))))))))))))))$$$$,,,,||||%%%%))))))))))))))))))))))))))))))))))))]]]]1111&&&&....||||]]]]]]]]@@@@&&&&....||||]]]]]]]]}}}}.... ", +" ........&&&&||||))))))))))))))))))))$$$$,,,,||||%%%%))))))))))))))))))))))))))))))))))))]]]]1111&&&&....||||]]]]]]]]@@@@&&&&....||||]]]]]]]]}}}}.... ", +" ........&&&&||||))))))))))))))))))))$$$$,,,,||||%%%%))))))))))))))))))))))))))))))))))))]]]]1111&&&&....||||]]]]]]]]@@@@&&&&....||||]]]]]]]]}}}}.... ", +" ........&&&&||||))))))))))))))))))))$$$$,,,,||||%%%%))))))))))))))))))))))))))))))))))))]]]]1111&&&&....||||]]]]]]]]@@@@&&&&....||||]]]]]]]]}}}}.... ", +" ....&&&&;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::@@@@====;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;----////................3333::::;;;;;;;;;;;;}}}}.... ", +" ....&&&&;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::@@@@====;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;----////................3333::::;;;;;;;;;;;;}}}}.... ", +" ....&&&&;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::@@@@====;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;----////................3333::::;;;;;;;;;;;;}}}}.... ", +" ....&&&&;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::@@@@====;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;----////................3333::::;;;;;;;;;;;;}}}}.... ", +" ........!!!!;;;;;;;;;;;;;;;;;;;;;;;;;;;;(((([[[[;;;;;;;;;;;;;;;;____2222;;;;;;;;;;;;;;;;;;;;;;;;;;;;>>>>)))))))){{{{;;;;;;;;;;;;;;;;^^^^........ ", +" ........!!!!;;;;;;;;;;;;;;;;;;;;;;;;;;;;(((([[[[;;;;;;;;;;;;;;;;____2222;;;;;;;;;;;;;;;;;;;;;;;;;;;;>>>>)))))))){{{{;;;;;;;;;;;;;;;;^^^^........ ", +" ........!!!!;;;;;;;;;;;;;;;;;;;;;;;;;;;;(((([[[[;;;;;;;;;;;;;;;;____2222;;;;;;;;;;;;;;;;;;;;;;;;;;;;>>>>)))))))){{{{;;;;;;;;;;;;;;;;^^^^........ ", +" ........!!!!;;;;;;;;;;;;;;;;;;;;;;;;;;;;(((([[[[;;;;;;;;;;;;;;;;____2222;;;;;;;;;;;;;;;;;;;;;;;;;;;;>>>>)))))))){{{{;;;;;;;;;;;;;;;;^^^^........ ", +" ........====2222____::::----;;;;;;;;;;;;((((;;;;;;;;;;;;2222<<<<;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;----))))........ ", +" ........====2222____::::----;;;;;;;;;;;;((((;;;;;;;;;;;;2222<<<<;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;----))))........ ", +" ........====2222____::::----;;;;;;;;;;;;((((;;;;;;;;;;;;2222<<<<;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;----))))........ ", +" ........====2222____::::----;;;;;;;;;;;;((((;;;;;;;;;;;;2222<<<<;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;----))))........ ", +" ............%%%%$$$$####@@@@%%%%####))))####))))))))||||))))))))))))))))))))))))))))))))))))))))))))))))))))))))||||}}}}&&&&.... ", +" ............%%%%$$$$####@@@@%%%%####))))####))))))))||||))))))))))))))))))))))))))))))))))))))))))))))))))))))))||||}}}}&&&&.... ", +" ............%%%%$$$$####@@@@%%%%####))))####))))))))||||))))))))))))))))))))))))))))))))))))))))))))))))))))))))||||}}}}&&&&.... ", +" ............%%%%$$$$####@@@@%%%%####))))####))))))))||||))))))))))))))))))))))))))))))))))))))))))))))))))))))))||||}}}}&&&&.... ", +" ........!!!!;;;;;;;;;;;;2222!!!!]]]]{{{{____----[[[[;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;&&&&........ ", +" ........!!!!;;;;;;;;;;;;2222!!!!]]]]{{{{____----[[[[;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;&&&&........ ", +" ........!!!!;;;;;;;;;;;;2222!!!!]]]]{{{{____----[[[[;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;&&&&........ ", +" ........!!!!;;;;;;;;;;;;2222!!!!]]]]{{{{____----[[[[;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;&&&&........ ", +" ........^^^^----;;;;;;;;;;;;;;;;^^^^))))((((::::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;''''........ ", +" ........^^^^----;;;;;;;;;;;;;;;;^^^^))))((((::::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;''''........ ", +" ........^^^^----;;;;;;;;;;;;;;;;^^^^))))((((::::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;''''........ ", +" ........^^^^----;;;;;;;;;;;;;;;;^^^^))))((((::::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;''''........ ", +" ........****''''----;;;;;;;;;;;;::::]]]]----;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;----$$$$........ ", +" ........****''''----;;;;;;;;;;;;::::]]]]----;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;----$$$$........ ", +" ........****''''----;;;;;;;;;;;;::::]]]]----;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;----$$$$........ ", +" ........****''''----;;;;;;;;;;;;::::]]]]----;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;----$$$$........ ", +" ................}}}}....////1111))))))))))))))))))))))))))))))))))))))))))))))))]]]]////............ ", +" ................}}}}....////1111))))))))))))))))))))))))))))))))))))))))))))))))]]]]////............ ", +" ................}}}}....////1111))))))))))))))))))))))))))))))))))))))))))))))))]]]]////............ ", +" ................}}}}....////1111))))))))))))))))))))))))))))))))))))))))))))))))]]]]////............ ", +" ................................}}}}3333||||||||1111####$$$$$$$$$$$$]]]]1111............ ", +" ................................}}}}3333||||||||1111####$$$$$$$$$$$$]]]]1111............ ", +" ................................}}}}3333||||||||1111####$$$$$$$$$$$$]]]]1111............ ", +" ................................}}}}3333||||||||1111####$$$$$$$$$$$$]]]]1111............ ", +" ............................................................................ ", +" ............................................................................ ", +" ............................................................................ ", +" ............................................................................ ", +" ", +" ", +" ", +" "}; diff --git a/src/sdl/Srb2SDL.ico b/src/sdl/Srb2SDL.ico index 700276fd4b9ac2810a6981eb054921f3708c702b..6e667b61c84414bc9758ea57721bb07d85a62083 100644 GIT binary patch literal 82992 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 G1OE?SzcGja diff --git a/src/sdl12/Srb2SDL.ico b/src/sdl12/Srb2SDL.ico index 700276fd4b9ac2810a6981eb054921f3708c702b..6e667b61c84414bc9758ea57721bb07d85a62083 100644 GIT binary patch literal 82992 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 G1OE?SzcGja diff --git a/src/win32ce/Srb2win.ico b/src/win32ce/Srb2win.ico index 700276fd4b9ac2810a6981eb054921f3708c702b..6e667b61c84414bc9758ea57721bb07d85a62083 100644 GIT binary patch literal 82992 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 G1OE?SzcGja From c043c79fd2cf7aab6bad0603aa71d16af27e6b38 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 18 Sep 2018 15:51:27 -0400 Subject: [PATCH 131/146] Spark fix (please don't spread these fixes out across different branches :boi:) --- src/k_kart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index fad2da43a..e6ba37111 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2308,7 +2308,7 @@ static void K_SpawnDriftSparks(player_t *player) P_SetMobjState(spark, S_DRIFTSPARK_A1); } - spark->flags2 = (spark->flags2 & ~MF2_DONTDRAW)|(player->mo->eflags & MF2_DONTDRAW); + spark->flags2 = (spark->flags2 & ~MF2_DONTDRAW)|(player->mo->flags2 & MF2_DONTDRAW); spark->eflags = (spark->eflags & ~MFE_VERTICALFLIP)|(player->mo->eflags & MFE_VERTICALFLIP); spark->eflags = (spark->eflags & ~MFE_DRAWONLYFORP1)|(player->mo->eflags & MFE_DRAWONLYFORP1); spark->eflags = (spark->eflags & ~MFE_DRAWONLYFORP2)|(player->mo->eflags & MFE_DRAWONLYFORP2); From a9d3789c37ccc276ec73b1c66ebee3cc5bb1f372 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 18 Sep 2018 23:56:26 -0400 Subject: [PATCH 132/146] Enable noclip cam again. It's just... TOO good, despite the couple of issues with it --- src/doomdef.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doomdef.h b/src/doomdef.h index b5519f6fd..31eb1877f 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -546,6 +546,6 @@ extern const char *compdate, *comptime, *comprevision, *compbranch; /// SRB2Kart: Camera always has noclip. /// \note Kind of problematic. If we decide to keep this on, we'll need serious map changes. -//#define NOCLIPCAM +#define NOCLIPCAM #endif // __DOOMDEF__ From a3089a546f7a65b0f8bec318d26976b9b9db7769 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Wed, 19 Sep 2018 20:13:48 -0400 Subject: [PATCH 133/146] Spindash boost dust, pogo spring sfx --- src/dehacked.c | 10 +++++++ src/info.c | 47 +++++++++++++++++++++++++++----- src/info.h | 11 ++++++++ src/k_kart.c | 72 +++++++++++++++++++++++++++++++++++++++++++++----- src/sounds.c | 1 + src/sounds.h | 1 + 6 files changed, 129 insertions(+), 13 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index e78189d72..1c18e0033 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -6254,6 +6254,15 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_FASTLINE4", "S_FASTLINE5", + // Fast dust release + "S_FASTDUST1", + "S_FASTDUST2", + "S_FASTDUST3", + "S_FASTDUST4", + "S_FASTDUST5", + "S_FASTDUST6", + "S_FASTDUST7", + // Thunder Shield Burst // Sneaker boost effect @@ -7227,6 +7236,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_RANDOMITEMPOP", "MT_FASTLINE", + "MT_FASTDUST", "MT_BOOSTFLAME", "MT_BOOSTSMOKE", "MT_SNEAKERTRAIL", diff --git a/src/info.c b/src/info.c index 74a7a4d34..cc8c3b944 100644 --- a/src/info.c +++ b/src/info.c @@ -55,12 +55,12 @@ char sprnames[NUMSPRITES + 1][5] = "GWLR","SRBA","SRBB","SRBC","SRBD","SRBE","SRBF","SRBG","SRBH","SRBI", "SRBJ","SRBK","SRBL","SRBM","SRBN","SRBO", //SRB2kart Sprites - "SPRG","BSPR","RNDM","RPOP","FAST","BOST","BOSM","KFRE","KINV","KINF", - "WIPD","DRIF","DUST","FITM","BANA","ORBN","JAWZ","SSMN","KRBM","BHOG", - "BHBM","BLIG","LIGH","THNS","SINK","SITR","KBLN","DEZL","POKE","AUDI", - "DECO","DOOD","SNES","GBAS","SPRS","BUZB","CHOM","SACO","CRAB","SHAD", - "BRNG","BUMP","FLEN","CLAS","PSHW","ISTA","ISTB","ARRO","ITEM","ITMO", - "ITMI","ITMN","WANT","PBOM","RETI","VIEW" + "SPRG","BSPR","RNDM","RPOP","FAST","DSHR","BOST","BOSM","KFRE","KINV", + "KINF","WIPD","DRIF","DUST","FITM","BANA","ORBN","JAWZ","SSMN","KRBM", + "BHOG","BHBM","BLIG","LIGH","THNS","SINK","SITR","KBLN","DEZL","POKE", + "AUDI","DECO","DOOD","SNES","GBAS","SPRS","BUZB","CHOM","SACO","CRAB", + "SHAD","BRNG","BUMP","FLEN","CLAS","PSHW","ISTA","ISTB","ARRO","ITEM", + "ITMO","ITMI","ITMN","WANT","PBOM","RETI","VIEW" }; // Doesn't work with g++, needs actionf_p1 (don't modify this comment) @@ -2586,6 +2586,14 @@ state_t states[NUMSTATES] = {SPR_FAST, FF_PAPERSPRITE|FF_FULLBRIGHT|3, 1, {NULL}, 0, 0, S_FASTLINE5}, // S_FASTLINE4 {SPR_FAST, FF_PAPERSPRITE|FF_FULLBRIGHT|4, 1, {NULL}, 0, 0, S_NULL}, // S_FASTLINE5 + {SPR_DSHR, FF_PAPERSPRITE, 1, {NULL}, 0, 0, S_FASTDUST2}, // S_FASTDUST1 + {SPR_DSHR, FF_PAPERSPRITE|1, 1, {NULL}, 0, 0, S_FASTDUST3}, // S_FASTDUST2 + {SPR_DSHR, FF_PAPERSPRITE|2, 1, {NULL}, 0, 0, S_FASTDUST4}, // S_FASTDUST3 + {SPR_DSHR, FF_PAPERSPRITE|3, 1, {NULL}, 0, 0, S_FASTDUST5}, // S_FASTDUST4 + {SPR_DSHR, FF_PAPERSPRITE|4, 1, {NULL}, 0, 0, S_FASTDUST6}, // S_FASTDUST5 + {SPR_DSHR, FF_PAPERSPRITE|5, 1, {NULL}, 0, 0, S_FASTDUST7}, // S_FASTDUST6 + {SPR_DSHR, FF_PAPERSPRITE|6, 1, {NULL}, 0, 0, S_NULL}, // S_FASTDUST7 + {SPR_BOST, FF_FULLBRIGHT|FF_ANIMATE, TICRATE, {NULL}, 6, 1, S_BOOSTSMOKESPAWNER}, // S_BOOSTFLAME {SPR_NULL, 0, TICRATE/2, {NULL}, 0, 0, S_NULL}, // S_BOOSTSMOKESPAWNER @@ -14435,6 +14443,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_FASTDUST + -1, // doomednum + S_FASTDUST1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 8, // speed + 14*FRACUNIT, // radius + 14*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + { // MT_BOOSTFLAME -1, // doomednum S_BOOSTFLAME, // spawnstate diff --git a/src/info.h b/src/info.h index 8d27944f5..8a242c43b 100644 --- a/src/info.h +++ b/src/info.h @@ -583,6 +583,7 @@ typedef enum sprite SPR_RNDM, // Random Item Box SPR_RPOP, // Random Item Box Pop SPR_FAST, // Speed boost trail + SPR_DSHR, // Speed boost dust release SPR_BOST, // Sneaker booster flame SPR_BOSM, // Sneaker booster smoke SPR_KFRE, // Sneaker fire trail @@ -3102,6 +3103,15 @@ typedef enum state S_FASTLINE4, S_FASTLINE5, + // Fast dust release + S_FASTDUST1, + S_FASTDUST2, + S_FASTDUST3, + S_FASTDUST4, + S_FASTDUST5, + S_FASTDUST6, + S_FASTDUST7, + // Magnet Burst // Sneaker boost effect @@ -4092,6 +4102,7 @@ typedef enum mobj_type MT_RANDOMITEMPOP, MT_FASTLINE, + MT_FASTDUST, MT_BOOSTFLAME, MT_BOOSTSMOKE, MT_SNEAKERTRAIL, diff --git a/src/k_kart.c b/src/k_kart.c index 23b161b62..0ed5947c9 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1247,6 +1247,55 @@ static void K_UpdateOffroad(player_t *player) player->kartstuff[k_offroad] = 0; } + +// This has to go earlier than its sisters because of K_RespawnChecker... +static void K_SpawnDashDustRelease(player_t *player) +{ + fixed_t newx; + fixed_t newy; + mobj_t *dust; + angle_t travelangle; + INT32 i; + + I_Assert(player != NULL); + I_Assert(player->mo != NULL); + I_Assert(!P_MobjWasRemoved(player->mo)); + + if (!P_IsObjectOnGround(player->mo)) + return; + + if (player->speed == 0) + return; + + travelangle = player->mo->angle; + + if (player->kartstuff[k_drift] || player->kartstuff[k_driftend]) + travelangle -= (ANGLE_45/5)*player->kartstuff[k_drift]; + + for (i = 0; i < 2; i++) + { + newx = player->mo->x + P_ReturnThrustX(player->mo, travelangle + ((i&1) ? -1 : 1)*ANGLE_90, FixedMul(48*FRACUNIT, player->mo->scale)); + newy = player->mo->y + P_ReturnThrustY(player->mo, travelangle + ((i&1) ? -1 : 1)*ANGLE_90, FixedMul(48*FRACUNIT, player->mo->scale)); + dust = P_SpawnMobj(newx, newy, player->mo->z, MT_FASTDUST); + + P_SetTarget(&dust->target, player->mo); + dust->angle = travelangle - ((i&1) ? -1 : 1)*ANGLE_45; + dust->destscale = player->mo->scale; + P_SetScale(dust, player->mo->scale); + + dust->momx = 3*player->mo->momx/5; + dust->momy = 3*player->mo->momy/5; + //dust->momz = 3*player->mo->momz/5; + + dust->flags2 = (dust->flags2 & ~MF2_DONTDRAW)|(player->mo->flags2 & MF2_DONTDRAW); + dust->eflags = (dust->eflags & ~MFE_VERTICALFLIP)|(player->mo->eflags & MFE_VERTICALFLIP); + dust->eflags = (dust->eflags & ~MFE_DRAWONLYFORP1)|(player->mo->eflags & MFE_DRAWONLYFORP1); + dust->eflags = (dust->eflags & ~MFE_DRAWONLYFORP2)|(player->mo->eflags & MFE_DRAWONLYFORP2); + dust->eflags = (dust->eflags & ~MFE_DRAWONLYFORP3)|(player->mo->eflags & MFE_DRAWONLYFORP3); + dust->eflags = (dust->eflags & ~MFE_DRAWONLYFORP4)|(player->mo->eflags & MFE_DRAWONLYFORP4); + } +} + /** \brief Calculates the respawn timer and drop-boosting \param player player object passed from K_KartPlayerThink @@ -1327,6 +1376,7 @@ void K_RespawnChecker(player_t *player) { S_StartSound(player->mo, sfx_s23c); player->kartstuff[k_startboost] = 50; + K_SpawnDashDustRelease(player); } player->mo->colorized = false; player->kartstuff[k_dropdash] = 0; @@ -2836,6 +2886,7 @@ void K_DoSneaker(player_t *player, boolean doPFlag) } player->kartstuff[k_sneakertimer] = sneakertime; + K_SpawnDashDustRelease(player); if (doPFlag) { @@ -2936,7 +2987,7 @@ void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, boolean mute) mo->momz = FixedMul(vertispeed, vscale); if (!mute) - S_StartSound(mo, sfx_kc2f); + S_StartSound(mo, sfx_kpogos); } void K_KillBananaChain(mobj_t *banana, mobj_t *inflictor, mobj_t *source) @@ -3821,6 +3872,7 @@ static void K_KartDrift(player_t *player, boolean onground) { player->kartstuff[k_driftboost] = 20; S_StartSound(player->mo, sfx_s23c); + //K_SpawnDashDustRelease(player); player->kartstuff[k_driftcharge] = 0; } else if ((player->kartstuff[k_drift] != -5 && player->kartstuff[k_drift] != 5) @@ -3830,6 +3882,7 @@ static void K_KartDrift(player_t *player, boolean onground) { player->kartstuff[k_driftboost] = 50; S_StartSound(player->mo, sfx_s23c); + //K_SpawnDashDustRelease(player); player->kartstuff[k_driftcharge] = 0; } else if ((player->kartstuff[k_drift] != -5 && player->kartstuff[k_drift] != 5) @@ -3839,6 +3892,7 @@ static void K_KartDrift(player_t *player, boolean onground) { player->kartstuff[k_driftboost] = 125; S_StartSound(player->mo, sfx_s23c); + //K_SpawnDashDustRelease(player); player->kartstuff[k_driftcharge] = 0; } @@ -4681,13 +4735,17 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (!player->kartstuff[k_floorboost] || player->kartstuff[k_floorboost] == 3) // Let everyone hear this one S_StartSound(player->mo, sfx_s25f); } - else if ((!player->kartstuff[k_floorboost] || player->kartstuff[k_floorboost] == 3) && P_IsLocalPlayer(player)) + else { - if (player->kartstuff[k_boostcharge] <= 40) - S_StartSound(player->mo, sfx_cdfm01); // You were almost there! - else - S_StartSound(player->mo, sfx_s23c); // Nope, better luck next time. - } + K_SpawnDashDustRelease(player); // already handled for perfect boosts by K_DoSneaker + if ((!player->kartstuff[k_floorboost] || player->kartstuff[k_floorboost] == 3) && P_IsLocalPlayer(player)) + { + if (player->kartstuff[k_boostcharge] <= 40) + S_StartSound(player->mo, sfx_cdfm01); // You were almost there! + else + S_StartSound(player->mo, sfx_s23c); // Nope, better luck next time. + } + } } // You overcharged your engine? Those things are expensive!!! else if (player->kartstuff[k_boostcharge] > 50) diff --git a/src/sounds.c b/src/sounds.c index ec88786cf..921450d6c 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -811,6 +811,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"noooo1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"noooo2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"hogbom", false, 110, 8, -1, NULL, 0, -1, -1, LUMPERROR}, + {"kpogos", false, 110, 8, -1, NULL, 0, -1, -1, LUMPERROR}, {"ddash", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"dbgsal", false, 110, 8, -1, NULL, 0, -1, -1, LUMPERROR}, diff --git a/src/sounds.h b/src/sounds.h index 980c097e0..8e065e69b 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -883,6 +883,7 @@ typedef enum sfx_noooo1, sfx_noooo2, sfx_hogbom, + sfx_kpogos, sfx_ddash, sfx_dbgsal, From d16021febdefe407d13d1e0945d59674b7bfc998 Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 20 Sep 2018 17:45:09 +0100 Subject: [PATCH 134/146] :shitsfree: --- src/m_menu.c | 25 ++++++++++++++++++++++++- src/sounds.c | 1 + src/sounds.h | 1 + 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index da45ea8af..847e126d9 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -8516,6 +8516,8 @@ static consvar_t *kartitemcvs[NUMKARTRESULTS-1] = { &cv_dualjawz }; +static tic_t shitsfree = 0; + static void M_DrawMonitorToggles(void) { const INT32 edges = 4; @@ -8632,7 +8634,18 @@ static void M_DrawMonitorToggles(void) { #ifdef ITEMTOGGLEBOTTOMRIGHT if (currentMenu->menuitems[itemOn].alphaKey == 255) + { V_DrawScaledPatch(onx-1, ony-2, V_TRANSLUCENT, W_CachePatchName("K_ITBG", PU_CACHE)); + if (shitsfree) + { + INT32 trans = V_TRANSLUCENT; + if (shitsfree-1 > TICRATE-5) + trans = ((10-TICRATE)+shitsfree-1)<menuitems[itemOn].alphaKey == 0) @@ -8679,6 +8692,9 @@ static void M_DrawMonitorToggles(void) } } + if (shitsfree) + shitsfree--; + V_DrawCenteredString(BASEVIDWIDTH/2, currentMenu->y, highlightflags, va("* %s *", currentMenu->menuitems[itemOn].text)); } @@ -8739,7 +8755,14 @@ static void M_HandleMonitorToggles(INT32 choice) case KEY_ENTER: #ifdef ITEMTOGGLEBOTTOMRIGHT if (currentMenu->menuitems[itemOn].alphaKey == 255) - S_StartSound(NULL, sfx_lose); + { + //S_StartSound(NULL, sfx_lose); + if (!shitsfree) + { + shitsfree = TICRATE; + S_StartSound(NULL, sfx_itfree); + } + } else #endif if (currentMenu->menuitems[itemOn].alphaKey == 0) diff --git a/src/sounds.c b/src/sounds.c index 921450d6c..e717574a5 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -813,6 +813,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"hogbom", false, 110, 8, -1, NULL, 0, -1, -1, LUMPERROR}, {"kpogos", false, 110, 8, -1, NULL, 0, -1, -1, LUMPERROR}, {"ddash", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"itfree", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"dbgsal", false, 110, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // SRB2kart - Skin sounds diff --git a/src/sounds.h b/src/sounds.h index 8e065e69b..173b13b42 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -885,6 +885,7 @@ typedef enum sfx_hogbom, sfx_kpogos, sfx_ddash, + sfx_itfree, sfx_dbgsal, sfx_kwin, From c3c39182fb8cd88fd8db5c62f40690cdf5d471f4 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 20 Sep 2018 17:11:11 -0400 Subject: [PATCH 135/146] Address review (for anything code I did, anyway) --- src/command.c | 3 --- src/command.h | 1 - src/d_netcmd.c | 1 - src/d_netcmd.h | 1 - src/k_kart.c | 38 ++++++++++++++++++-------------------- src/p_enemy.c | 7 +++---- 6 files changed, 21 insertions(+), 30 deletions(-) diff --git a/src/command.c b/src/command.c index a159ebcd7..3ac1abb1a 100644 --- a/src/command.c +++ b/src/command.c @@ -63,9 +63,6 @@ CV_PossibleValue_t CV_Unsigned[] = {{0, "MIN"}, {999999999, "MAX"}, {0, NULL}}; CV_PossibleValue_t CV_Natural[] = {{1, "MIN"}, {999999999, "MAX"}, {0, NULL}}; //SRB2kart -/*CV_PossibleValue_t karthud_cons_t[] = { - {0, "Off"}, {1, "Default"}, {2, "SMK"}, {3, "MK64"}, - {0, NULL}};*/ CV_PossibleValue_t kartspeed_cons_t[] = { {0, "Easy"}, {1, "Normal"}, {2, "Hard"}, {0, NULL}}; diff --git a/src/command.h b/src/command.h index 0c2ef9120..dbac8bd8b 100644 --- a/src/command.h +++ b/src/command.h @@ -127,7 +127,6 @@ extern CV_PossibleValue_t CV_Unsigned[]; extern CV_PossibleValue_t CV_Natural[]; // SRB2kart -//extern CV_PossibleValue_t karthud_cons_t[]; extern CV_PossibleValue_t kartspeed_cons_t[]; // register a variable for use at the console diff --git a/src/d_netcmd.c b/src/d_netcmd.c index fa2d00324..e79224c48 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -344,7 +344,6 @@ consvar_t cv_tripleorbinaut = {"tripleorbinaut", "On", CV_NETVAR|CV_CHEAT, C consvar_t cv_quadorbinaut = {"quadorbinaut", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_dualjawz = {"dualjawz", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -//consvar_t cv_karthud = {"karthud", "Default", CV_SAVE|CV_CALL, karthud_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; static CV_PossibleValue_t kartminimap_cons_t[] = {{0, "MIN"}, {10, "MAX"}, {0, NULL}}; consvar_t cv_kartminimap = {"kartminimap", "4", CV_SAVE, kartminimap_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_kartcheck = {"kartcheck", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; diff --git a/src/d_netcmd.h b/src/d_netcmd.h index 66c712c56..0a1cc3b7f 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -117,7 +117,6 @@ extern consvar_t cv_thundershield, cv_hyudoro, cv_pogospring, cv_kitchensink; extern consvar_t cv_triplesneaker, cv_triplebanana, cv_decabanana; extern consvar_t cv_tripleorbinaut, cv_quadorbinaut, cv_dualjawz; -//extern consvar_t cv_karthud; extern consvar_t cv_kartminimap; extern consvar_t cv_kartcheck; extern consvar_t cv_kartinvinsfx; diff --git a/src/k_kart.c b/src/k_kart.c index 0ed5947c9..d923c5c9e 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1247,8 +1247,19 @@ static void K_UpdateOffroad(player_t *player) player->kartstuff[k_offroad] = 0; } +// These have to go earlier than its sisters because of K_RespawnChecker... +static void K_MatchGenericExtraFlags(mobj_t *mo, mobj_t *master) +{ + // flipping + mo->eflags = (mo->eflags & ~MFE_VERTICALFLIP)|(master->eflags & MFE_VERTICALFLIP); + // visibility (usually for hyudoro) + mo->flags2 = (mo->flags2 & ~MF2_DONTDRAW)|(master->flags2 & MF2_DONTDRAW); + mo->eflags = (mo->eflags & ~MFE_DRAWONLYFORP1)|(master->eflags & MFE_DRAWONLYFORP1); + mo->eflags = (mo->eflags & ~MFE_DRAWONLYFORP2)|(master->eflags & MFE_DRAWONLYFORP2); + mo->eflags = (mo->eflags & ~MFE_DRAWONLYFORP3)|(master->eflags & MFE_DRAWONLYFORP3); + mo->eflags = (mo->eflags & ~MFE_DRAWONLYFORP4)|(master->eflags & MFE_DRAWONLYFORP4); +} -// This has to go earlier than its sisters because of K_RespawnChecker... static void K_SpawnDashDustRelease(player_t *player) { fixed_t newx; @@ -1287,12 +1298,7 @@ static void K_SpawnDashDustRelease(player_t *player) dust->momy = 3*player->mo->momy/5; //dust->momz = 3*player->mo->momz/5; - dust->flags2 = (dust->flags2 & ~MF2_DONTDRAW)|(player->mo->flags2 & MF2_DONTDRAW); - dust->eflags = (dust->eflags & ~MFE_VERTICALFLIP)|(player->mo->eflags & MFE_VERTICALFLIP); - dust->eflags = (dust->eflags & ~MFE_DRAWONLYFORP1)|(player->mo->eflags & MFE_DRAWONLYFORP1); - dust->eflags = (dust->eflags & ~MFE_DRAWONLYFORP2)|(player->mo->eflags & MFE_DRAWONLYFORP2); - dust->eflags = (dust->eflags & ~MFE_DRAWONLYFORP3)|(player->mo->eflags & MFE_DRAWONLYFORP3); - dust->eflags = (dust->eflags & ~MFE_DRAWONLYFORP4)|(player->mo->eflags & MFE_DRAWONLYFORP4); + K_MatchGenericExtraFlags(dust, player->mo); } } @@ -1543,7 +1549,7 @@ void K_MomentumToFacing(player_t *player) player->mo->momy = FixedMul(player->mo->momy - player->cmomy, player->mo->friction) + player->cmomy; } -// if speed is true it gets the speed boost power, otherwise it gets the acceleration +// sets k_boostpower, k_speedboost, and k_accelboost to whatever we need it to be static void K_GetKartBoostPower(player_t *player) { fixed_t boostpower = FRACUNIT; @@ -2367,12 +2373,7 @@ static void K_SpawnDriftSparks(player_t *player) P_SetMobjState(spark, S_DRIFTSPARK_A1); } - spark->flags2 = (spark->flags2 & ~MF2_DONTDRAW)|(player->mo->flags2 & MF2_DONTDRAW); - spark->eflags = (spark->eflags & ~MFE_VERTICALFLIP)|(player->mo->eflags & MFE_VERTICALFLIP); - spark->eflags = (spark->eflags & ~MFE_DRAWONLYFORP1)|(player->mo->eflags & MFE_DRAWONLYFORP1); - spark->eflags = (spark->eflags & ~MFE_DRAWONLYFORP2)|(player->mo->eflags & MFE_DRAWONLYFORP2); - spark->eflags = (spark->eflags & ~MFE_DRAWONLYFORP3)|(player->mo->eflags & MFE_DRAWONLYFORP3); - spark->eflags = (spark->eflags & ~MFE_DRAWONLYFORP4)|(player->mo->eflags & MFE_DRAWONLYFORP4); + K_MatchGenericExtraFlags(spark, player->mo); } } @@ -2423,7 +2424,7 @@ void K_SpawnBoostTrail(player_t *player) flame->fuse = TICRATE*2; flame->destscale = player->mo->scale; P_SetScale(flame, player->mo->scale); - flame->eflags = (flame->eflags & ~MFE_VERTICALFLIP)|(player->mo->eflags & MFE_VERTICALFLIP); + flame->eflags = (flame->eflags & ~MFE_VERTICALFLIP)|(player->mo->eflags & MFE_VERTICALFLIP); // not K_MatchGenericExtraFlags so that a stolen sneaker can be seen flame->momx = 8; P_XYMovement(flame); @@ -2463,7 +2464,7 @@ void K_SpawnSparkleTrail(mobj_t *mo) P_SetTarget(&sparkle->target, mo); sparkle->destscale = mo->destscale; P_SetScale(sparkle, mo->scale); - sparkle->eflags = (sparkle->eflags & ~MFE_VERTICALFLIP)|(mo->eflags & MFE_VERTICALFLIP); + sparkle->eflags = (sparkle->eflags & ~MFE_VERTICALFLIP)|(mo->eflags & MFE_VERTICALFLIP); // not K_MatchGenericExtraFlags so that a stolen invincibility can be seen sparkle->color = mo->color; //sparkle->colorized = mo->colorized; } @@ -2484,7 +2485,7 @@ void K_SpawnWipeoutTrail(mobj_t *mo, boolean translucent) dust->angle = R_PointToAngle2(0,0,mo->momx,mo->momy); dust->destscale = mo->scale; P_SetScale(dust, mo->scale); - dust->eflags = (dust->eflags & ~MFE_VERTICALFLIP)|(mo->eflags & MFE_VERTICALFLIP); + dust->eflags = (dust->eflags & ~MFE_VERTICALFLIP)|(mo->eflags & MFE_VERTICALFLIP); // not K_MatchGenericExtraFlags because hyudoro shouldn't be able to wipeout if (translucent) dust->flags2 |= MF2_SHADOW; @@ -4624,9 +4625,6 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } } - /*if (player->kartstuff[k_growshrinktimer] > 1) - player->powers[pw_flashing] = 2;*/ - // Friction if (player->speed > 0 && cmd->forwardmove == 0 && player->mo->friction == 59392) player->mo->friction += 4608; diff --git a/src/p_enemy.c b/src/p_enemy.c index a6c124db2..ded0a20f5 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -8172,10 +8172,7 @@ void A_JawzChase(mobj_t *actor) if (actor->tracer) { - if (!actor->tracer->health) - P_SetTarget(&actor->tracer, NULL); - - if (actor->tracer && actor->tracer->health) + if (actor->tracer->health) { mobj_t *ret; @@ -8187,6 +8184,8 @@ void A_JawzChase(mobj_t *actor) P_Thrust(actor, R_PointToAngle2(actor->x, actor->y, actor->tracer->x, actor->tracer->y), actor->info->speed); return; } + else + P_SetTarget(&actor->tracer, NULL); } if (actor->extravalue1) // Disable looking by setting this From 1dc0c8ad0d453a4851511a85188f6a22db9bb5d3 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 20 Sep 2018 17:11:59 -0400 Subject: [PATCH 136/146] Reeling back on this again Kinda want to save it for another branch --- src/doomdef.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doomdef.h b/src/doomdef.h index 31eb1877f..b5519f6fd 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -546,6 +546,6 @@ extern const char *compdate, *comptime, *comprevision, *compbranch; /// SRB2Kart: Camera always has noclip. /// \note Kind of problematic. If we decide to keep this on, we'll need serious map changes. -#define NOCLIPCAM +//#define NOCLIPCAM #endif // __DOOMDEF__ From a901e2de7e5f4c7194d10cacea3f51182d54eec8 Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 20 Sep 2018 22:36:01 +0100 Subject: [PATCH 137/146] Smaller XPM with no redundant pixels --- src/sdl/SDL_icon.xpm | 322 +++++++++---------------------------------- 1 file changed, 65 insertions(+), 257 deletions(-) diff --git a/src/sdl/SDL_icon.xpm b/src/sdl/SDL_icon.xpm index 17eb78dd9..0acac88ec 100644 --- a/src/sdl/SDL_icon.xpm +++ b/src/sdl/SDL_icon.xpm @@ -1,7 +1,7 @@ /* XPM */ static const char *SDL_icon_xpm[] = { /* columns rows colors chars-per-pixel */ -"256 256 32 1", +"64 64 32 1", " c None", ". c #E7E7E7", "+ c #DFDFDF", @@ -34,259 +34,67 @@ static const char *SDL_icon_xpm[] = { "1 c #9F9F9F", "2 c #171717", "3 c #CFCFCF", -" ", -" ", -" ", -" ", -" ................................................................................ ", -" ................................................................................ ", -" ................................................................................ ", -" ................................................................................ ", -" ............++++@@@@########$$$$$$$$$$$$$$$$############@@@@%%%%&&&&............................ ", -" ............++++@@@@########$$$$$$$$$$$$$$$$############@@@@%%%%&&&&............................ ", -" ............++++@@@@########$$$$$$$$$$$$$$$$############@@@@%%%%&&&&............................ ", -" ............++++@@@@########$$$$$$$$$$$$$$$$############@@@@%%%%&&&&............................ ", -" ........****====----;;;;;;;;;;;;----;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@@@@................................ ", -" ........****====----;;;;;;;;;;;;----;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@@@@................................ ", -" ........****====----;;;;;;;;;;;;----;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@@@@................................ ", -" ........****====----;;;;;;;;;;;;----;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@@@@................................ ", -" ........++++----;;;;;;;;;;;;;;;;--------;;;;;;;;;;;;;;;;;;;;;;;;;;;;>>>>........................................ ", -" ........++++----;;;;;;;;;;;;;;;;--------;;;;;;;;;;;;;;;;;;;;;;;;;;;;>>>>........................................ ", -" ........++++----;;;;;;;;;;;;;;;;--------;;;;;;;;;;;;;;;;;;;;;;;;;;;;>>>>........................................ ", -" ........++++----;;;;;;;;;;;;;;;;--------;;;;;;;;;;;;;;;;;;;;;;;;;;;;>>>>........................................ ", -" ............,,,,''''))))!!!!!!!!''''~~~~>>>>{{{{!!!!))))$$$$))))>>>>''''................****]]]]>>>>^^^^%%%%&&&&........ ", -" ............,,,,''''))))!!!!!!!!''''~~~~>>>>{{{{!!!!))))$$$$))))>>>>''''................****]]]]>>>>^^^^%%%%&&&&........ ", -" ............,,,,''''))))!!!!!!!!''''~~~~>>>>{{{{!!!!))))$$$$))))>>>>''''................****]]]]>>>>^^^^%%%%&&&&........ ", -" ............,,,,''''))))!!!!!!!!''''~~~~>>>>{{{{!!!!))))$$$$))))>>>>''''................****]]]]>>>>^^^^%%%%&&&&........ ", -" ........////((((________((((>>>>::::{{{{<<<<))))$$$$!!!![[[[[[[[[[[[%%%%&&&&............^^^^!!!!!!!!!!!!!!!!!!!!~~~~****.... ", -" ........////((((________((((>>>>::::{{{{<<<<))))$$$$!!!![[[[[[[[[[[[%%%%&&&&............^^^^!!!!!!!!!!!!!!!!!!!!~~~~****.... ", -" ........////((((________((((>>>>::::{{{{<<<<))))$$$$!!!![[[[[[[[[[[[%%%%&&&&............^^^^!!!!!!!!!!!!!!!!!!!!~~~~****.... ", -" ........////((((________((((>>>>::::{{{{<<<<))))$$$$!!!![[[[[[[[[[[[%%%%&&&&............^^^^!!!!!!!!!!!!!!!!!!!!~~~~****.... ", -" ........@@@@;;;;;;;;;;;;;;;;;;;;(((({{{{====]]]]::::;;;;;;;;;;;;;;;;;;;;~~~~........****____;;;;;;;;;;;;;;;;;;;;;;;;;;;;____........ ", -" ........@@@@;;;;;;;;;;;;;;;;;;;;(((({{{{====]]]]::::;;;;;;;;;;;;;;;;;;;;~~~~........****____;;;;;;;;;;;;;;;;;;;;;;;;;;;;____........ ", -" ........@@@@;;;;;;;;;;;;;;;;;;;;(((({{{{====]]]]::::;;;;;;;;;;;;;;;;;;;;~~~~........****____;;;;;;;;;;;;;;;;;;;;;;;;;;;;____........ ", -" ........@@@@;;;;;;;;;;;;;;;;;;;;(((({{{{====]]]]::::;;;;;;;;;;;;;;;;;;;;~~~~........****____;;;;;;;;;;;;;;;;;;;;;;;;;;;;____........ ", -" ....}}}}>>>>;;;;;;;;;;;;;;;;;;;;^^^^####====;;;;;;;;;;;;;;;;;;;;;;;;>>>>............<<<<;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;||||........ ", -" ....}}}}>>>>;;;;;;;;;;;;;;;;;;;;^^^^####====;;;;;;;;;;;;;;;;;;;;;;;;>>>>............<<<<;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;||||........ ", -" ....}}}}>>>>;;;;;;;;;;;;;;;;;;;;^^^^####====;;;;;;;;;;;;;;;;;;;;;;;;>>>>............<<<<;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;||||........ ", -" ....}}}}>>>>;;;;;;;;;;;;;;;;;;;;^^^^####====;;;;;;;;;;;;;;;;;;;;;;;;>>>>............<<<<;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;||||........ ", -" ........****1111))))))))))))))))))))%%%%]]]]))))))))))))))))))))))))%%%%&&&&........1111]]]]))))))))))))))))))))))))))))))))))))####}}}}.... ", -" ........****1111))))))))))))))))))))%%%%]]]]))))))))))))))))))))))))%%%%&&&&........1111]]]]))))))))))))))))))))))))))))))))))))####}}}}.... ", -" ........****1111))))))))))))))))))))%%%%]]]]))))))))))))))))))))))))%%%%&&&&........1111]]]]))))))))))))))))))))))))))))))))))))####}}}}.... ", -" ........****1111))))))))))))))))))))%%%%]]]]))))))))))))))))))))))))%%%%&&&&........1111]]]]))))))))))))))))))))))))))))))))))))####}}}}.... ", -" ........%%%%[[[[;;;;;;;;;;;;;;;;;;;;[[[[2222;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::........####;;;;;;;;;;;;2222[[[[[[[[----;;;;;;;;;;;;;;;;;;;;====........ ", -" ........%%%%[[[[;;;;;;;;;;;;;;;;;;;;[[[[2222;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::........####;;;;;;;;;;;;2222[[[[[[[[----;;;;;;;;;;;;;;;;;;;;====........ ", -" ........%%%%[[[[;;;;;;;;;;;;;;;;;;;;[[[[2222;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::........####;;;;;;;;;;;;2222[[[[[[[[----;;;;;;;;;;;;;;;;;;;;====........ ", -" ........%%%%[[[[;;;;;;;;;;;;;;;;;;;;[[[[2222;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::........####;;;;;;;;;;;;2222[[[[[[[[----;;;;;;;;;;;;;;;;;;;;====........ ", -" ....&&&&::::;;;;[[[[{{{{;;;;;;;;;;;;{{{{;;;;;;;;;;;;~~~~===={{{{::::;;;;^^^^........____;;;;;;;;''''}}}}............>>>>;;;;;;;;;;;;;;;;;;;;,,,,.... ", -" ....&&&&::::;;;;[[[[{{{{;;;;;;;;;;;;{{{{;;;;;;;;;;;;~~~~===={{{{::::;;;;^^^^........____;;;;;;;;''''}}}}............>>>>;;;;;;;;;;;;;;;;;;;;,,,,.... ", -" ....&&&&::::;;;;[[[[{{{{;;;;;;;;;;;;{{{{;;;;;;;;;;;;~~~~===={{{{::::;;;;^^^^........____;;;;;;;;''''}}}}............>>>>;;;;;;;;;;;;;;;;;;;;,,,,.... ", -" ....&&&&::::;;;;[[[[{{{{;;;;;;;;;;;;{{{{;;;;;;;;;;;;~~~~===={{{{::::;;;;^^^^........____;;;;;;;;''''}}}}............>>>>;;;;;;;;;;;;;;;;;;;;,,,,.... ", -" ....}}}}<<<<;;;;;;;;::::{{{{;;;;____::::2222!!!!''''----;;;;;;;;;;;;]]]]****....&&&&((((____]]]]....||||{{{{====@@@@....~~~~____________[[[[////........ ", -" ....}}}}<<<<;;;;;;;;::::{{{{;;;;____::::2222!!!!''''----;;;;;;;;;;;;]]]]****....&&&&((((____]]]]....||||{{{{====@@@@....~~~~____________[[[[////........ ", -" ....}}}}<<<<;;;;;;;;::::{{{{;;;;____::::2222!!!!''''----;;;;;;;;;;;;]]]]****....&&&&((((____]]]]....||||{{{{====@@@@....~~~~____________[[[[////........ ", -" ....}}}}<<<<;;;;;;;;::::{{{{;;;;____::::2222!!!!''''----;;;;;;;;;;;;]]]]****....&&&&((((____]]]]....||||{{{{====@@@@....~~~~____________[[[[////........ ", -" ........****$$$$))))))))]]]]@@@@%%%%////////,,,,111111111111111111111111}}}}........||||1111****....@@@@1111111111111111@@@@....3333111111111111||||&&&&.... ", -" ........****$$$$))))))))]]]]@@@@%%%%////////,,,,111111111111111111111111}}}}........||||1111****....@@@@1111111111111111@@@@....3333111111111111||||&&&&.... ", -" ........****$$$$))))))))]]]]@@@@%%%%////////,,,,111111111111111111111111}}}}........||||1111****....@@@@1111111111111111@@@@....3333111111111111||||&&&&.... ", -" ........****$$$$))))))))]]]]@@@@%%%%////////,,,,111111111111111111111111}}}}........||||1111****....@@@@1111111111111111@@@@....3333111111111111||||&&&&.... ", -" ....,,,,::::;;;;;;;;;;;;;;;;;;;;''''####^^^^;;;;;;;;;;;;;;;;;;;;;;;;;;;;]]]]....////;;;;;;;;++++))));;;;;;;;;;;;;;;;;;;;;;;;$$$$****;;;;;;;;;;;;;;;;........ ", -" ....,,,,::::;;;;;;;;;;;;;;;;;;;;''''####^^^^;;;;;;;;;;;;;;;;;;;;;;;;;;;;]]]]....////;;;;;;;;++++))));;;;;;;;;;;;;;;;;;;;;;;;$$$$****;;;;;;;;;;;;;;;;........ ", -" ....,,,,::::;;;;;;;;;;;;;;;;;;;;''''####^^^^;;;;;;;;;;;;;;;;;;;;;;;;;;;;]]]]....////;;;;;;;;++++))));;;;;;;;;;;;;;;;;;;;;;;;$$$$****;;;;;;;;;;;;;;;;........ ", -" ....,,,,::::;;;;;;;;;;;;;;;;;;;;''''####^^^^;;;;;;;;;;;;;;;;;;;;;;;;;;;;]]]]....////;;;;;;;;++++))));;;;;;;;;;;;;;;;;;;;;;;;$$$$****;;;;;;;;;;;;;;;;........ ", -" ....^^^^;;;;;;;;;;;;;;;;;;;;;;;;))))))));;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;$$$$....~~~~;;;;$$$$****;;;;;;;;;;;;;;;;;;;;;;;;;;;;----++++^^^^;;;;;;;;;;;;####.... ", -" ....^^^^;;;;;;;;;;;;;;;;;;;;;;;;))))))));;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;$$$$....~~~~;;;;$$$$****;;;;;;;;;;;;;;;;;;;;;;;;;;;;----++++^^^^;;;;;;;;;;;;####.... ", -" ....^^^^;;;;;;;;;;;;;;;;;;;;;;;;))))))));;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;$$$$....~~~~;;;;$$$$****;;;;;;;;;;;;;;;;;;;;;;;;;;;;----++++^^^^;;;;;;;;;;;;####.... ", -" ....^^^^;;;;;;;;;;;;;;;;;;;;;;;;))))))));;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;$$$$....~~~~;;;;$$$$****;;;;;;;;;;;;;;;;;;;;;;;;;;;;----++++^^^^;;;;;;;;;;;;####.... ", -" ........$$$$;;;;;;;;;;;;;;;;;;;;;;;;>>>>;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;>>>>}}}}....^^^^----....!!!!;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;))))****::::;;;;;;;;||||.... ", -" ........$$$$;;;;;;;;;;;;;;;;;;;;;;;;>>>>;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;>>>>}}}}....^^^^----....!!!!;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;))))****::::;;;;;;;;||||.... ", -" ........$$$$;;;;;;;;;;;;;;;;;;;;;;;;>>>>;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;>>>>}}}}....^^^^----....!!!!;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;))))****::::;;;;;;;;||||.... ", -" ........$$$$;;;;;;;;;;;;;;;;;;;;;;;;>>>>;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;>>>>}}}}....^^^^----....!!!!;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;))))****::::;;;;;;;;||||.... ", -" ....&&&&@@@@$$$$||||####))))))))))))||||))))))))))))1111||||||||####]]]]++++........$$$$////}}}}]]]]))))))))))))))))))))))))))))))))$$$$....3333))))))))####........ ", -" ....&&&&@@@@$$$$||||####))))))))))))||||))))))))))))1111||||||||####]]]]++++........$$$$////}}}}]]]]))))))))))))))))))))))))))))))))$$$$....3333))))))))####........ ", -" ....&&&&@@@@$$$$||||####))))))))))))||||))))))))))))1111||||||||####]]]]++++........$$$$////}}}}]]]]))))))))))))))))))))))))))))))))$$$$....3333))))))))####........ ", -" ....&&&&@@@@$$$$||||####))))))))))))||||))))))))))))1111||||||||####]]]]++++........$$$$////}}}}]]]]))))))))))))))))))))))))))))))))$$$$....3333))))))))####........ ", -" ....####;;;;;;;;;;;;[[[[{{{{;;;;---->>>>;;;;----^^^^[[[[;;;;;;;;;;;;;;;;]]]]....~~~~;;;;@@@@]]]];;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1111####;;;;;;;;----}}}}.... ", -" ....####;;;;;;;;;;;;[[[[{{{{;;;;---->>>>;;;;----^^^^[[[[;;;;;;;;;;;;;;;;]]]]....~~~~;;;;@@@@]]]];;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1111####;;;;;;;;----}}}}.... ", -" ....####;;;;;;;;;;;;[[[[{{{{;;;;---->>>>;;;;----^^^^[[[[;;;;;;;;;;;;;;;;]]]]....~~~~;;;;@@@@]]]];;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1111####;;;;;;;;----}}}}.... ", -" ....####;;;;;;;;;;;;[[[[{{{{;;;;---->>>>;;;;----^^^^[[[[;;;;;;;;;;;;;;;;]]]]....~~~~;;;;@@@@]]]];;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1111####;;;;;;;;----}}}}.... ", -" ....{{{{;;;;;;;;;;;;;;;;{{{{<<<<[[[[::::((((~~~~----;;;;;;;;;;;;;;;;;;;;$$$$....((((----....<<<<;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;{{{{}}}};;;;;;;;;;;;3333.... ", -" ....{{{{;;;;;;;;;;;;;;;;{{{{<<<<[[[[::::((((~~~~----;;;;;;;;;;;;;;;;;;;;$$$$....((((----....<<<<;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;{{{{}}}};;;;;;;;;;;;3333.... ", -" ....{{{{;;;;;;;;;;;;;;;;{{{{<<<<[[[[::::((((~~~~----;;;;;;;;;;;;;;;;;;;;$$$$....((((----....<<<<;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;{{{{}}}};;;;;;;;;;;;3333.... ", -" ....{{{{;;;;;;;;;;;;;;;;{{{{<<<<[[[[::::((((~~~~----;;;;;;;;;;;;;;;;;;;;$$$$....((((----....<<<<;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;{{{{}}}};;;;;;;;;;;;3333.... ", -" ........))));;;;;;;;;;;;;;;;;;;;~~~~~~~~[[[[!!!!;;;;;;;;;;;;;;;;;;;;;;;;----////....>>>>====....>>>>;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2222}}}}^^^^;;;;::::3333.... ", -" ........))));;;;;;;;;;;;;;;;;;;;~~~~~~~~[[[[!!!!;;;;;;;;;;;;;;;;;;;;;;;;----////....>>>>====....>>>>;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2222}}}}^^^^;;;;::::3333.... ", -" ........))));;;;;;;;;;;;;;;;;;;;~~~~~~~~[[[[!!!!;;;;;;;;;;;;;;;;;;;;;;;;----////....>>>>====....>>>>;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2222}}}}^^^^;;;;::::3333.... ", -" ........))));;;;;;;;;;;;;;;;;;;;~~~~~~~~[[[[!!!!;;;;;;;;;;;;;;;;;;;;;;;;----////....>>>>====....>>>>;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2222}}}}^^^^;;;;::::3333.... ", -" ....&&&&####))))))))))))))))))))$$$$}}}}@@@@))))))))))))))))))))))))))))@@@@....}}}}]]]]3333....****))))))))))))))))))))))))))))))))))))))))))))....,,,,))))))))........ ", -" ....&&&&####))))))))))))))))))))$$$$}}}}@@@@))))))))))))))))))))))))))))@@@@....}}}}]]]]3333....****))))))))))))))))))))))))))))))))))))))))))))....,,,,))))))))........ ", -" ....&&&&####))))))))))))))))))))$$$$}}}}@@@@))))))))))))))))))))))))))))@@@@....}}}}]]]]3333....****))))))))))))))))))))))))))))))))))))))))))))....,,,,))))))))........ ", -" ....&&&&####))))))))))))))))))))$$$$}}}}@@@@))))))))))))))))))))))))))))@@@@....}}}}]]]]3333....****))))))))))))))))))))))))))))))))))))))))))))....,,,,))))))))........ ", -" ....3333;;;;;;;;;;;;;;;;;;;;;;;;;;;;))));;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2222++++||||;;;;%%%%....'''';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;]]]]1111;;;;;;;;1111.... ", -" ....3333;;;;;;;;;;;;;;;;;;;;;;;;;;;;))));;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2222++++||||;;;;%%%%....'''';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;]]]]1111;;;;;;;;1111.... ", -" ....3333;;;;;;;;;;;;;;;;;;;;;;;;;;;;))));;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2222++++||||;;;;%%%%....'''';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;]]]]1111;;;;;;;;1111.... ", -" ....3333;;;;;;;;;;;;;;;;;;;;;;;;;;;;))));;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2222++++||||;;;;%%%%....'''';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;]]]]1111;;;;;;;;1111.... ", -" ....1111____((((::::;;;;;;;;;;;;;;;;{{{{;;;;;;;;;;;;[[[[====[[[[::::;;;;;;;;....]]]];;;;}}}}....))));;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;====,,,,;;;;;;;;]]]].... ", -" ....1111____((((::::;;;;;;;;;;;;;;;;{{{{;;;;;;;;;;;;[[[[====[[[[::::;;;;;;;;....]]]];;;;}}}}....))));;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;====,,,,;;;;;;;;]]]].... ", -" ....1111____((((::::;;;;;;;;;;;;;;;;{{{{;;;;;;;;;;;;[[[[====[[[[::::;;;;;;;;....]]]];;;;}}}}....))));;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;====,,,,;;;;;;;;]]]].... ", -" ....1111____((((::::;;;;;;;;;;;;;;;;{{{{;;;;;;;;;;;;[[[[====[[[[::::;;;;;;;;....]]]];;;;}}}}....))));;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;====,,,,;;;;;;;;]]]].... ", -" ....%%%%2222----((((!!!!2222;;;;2222{{{{;;;;____''''::::;;;;;;;;;;;;;;;;))))....1111;;;;........++++::::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;____....;;;;;;;;1111.... ", -" ....%%%%2222----((((!!!!2222;;;;2222{{{{;;;;____''''::::;;;;;;;;;;;;;;;;))))....1111;;;;........++++::::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;____....;;;;;;;;1111.... ", -" ....%%%%2222----((((!!!!2222;;;;2222{{{{;;;;____''''::::;;;;;;;;;;;;;;;;))))....1111;;;;........++++::::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;____....;;;;;;;;1111.... ", -" ....%%%%2222----((((!!!!2222;;;;2222{{{{;;;;____''''::::;;;;;;;;;;;;;;;;))))....1111;;;;........++++::::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;____....;;;;;;;;1111.... ", -" ....++++))))))))))))))))@@@@1111$$$$1111####@@@@))))))))))))))))))))))))3333....,,,,@@@@............1111))))))))))))))))))))))))))))))))))))))))]]]]....1111####3333.... ", -" ....++++))))))))))))))))@@@@1111$$$$1111####@@@@))))))))))))))))))))))))3333....,,,,@@@@............1111))))))))))))))))))))))))))))))))))))))))]]]]....1111####3333.... ", -" ....++++))))))))))))))))@@@@1111$$$$1111####@@@@))))))))))))))))))))))))3333....,,,,@@@@............1111))))))))))))))))))))))))))))))))))))))))]]]]....1111####3333.... ", -" ....++++))))))))))))))))@@@@1111$$$$1111####@@@@))))))))))))))))))))))))3333....,,,,@@@@............1111))))))))))))))))))))))))))))))))))))))))]]]]....1111####3333.... ", -" ....{{{{;;;;;;;;;;;;;;;;;;;;^^^^<<<<>>>>))));;;;;;;;;;;;;;;;;;;;;;;;;;;;----....[[[[)))).... ....----;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3333{{{{;;;;####.... ", -" ....{{{{;;;;;;;;;;;;;;;;;;;;^^^^<<<<>>>>))));;;;;;;;;;;;;;;;;;;;;;;;;;;;----....[[[[)))).... ....----;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3333{{{{;;;;####.... ", -" ....{{{{;;;;;;;;;;;;;;;;;;;;^^^^<<<<>>>>))));;;;;;;;;;;;;;;;;;;;;;;;;;;;----....[[[[)))).... ....----;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3333{{{{;;;;####.... ", -" ....{{{{;;;;;;;;;;;;;;;;;;;;^^^^<<<<>>>>))));;;;;;;;;;;;;;;;;;;;;;;;;;;;----....[[[[)))).... ....----;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3333{{{{;;;;####.... ", -" ....____;;;;;;;;;;;;;;;;;;;;----~~~~]]]];;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;}}}};;;;####.... ....____;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;////^^^^;;;;####.... ", -" ....____;;;;;;;;;;;;;;;;;;;;----~~~~]]]];;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;}}}};;;;####.... ....____;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;////^^^^;;;;####.... ", -" ....____;;;;;;;;;;;;;;;;;;;;----~~~~]]]];;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;}}}};;;;####.... ....____;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;////^^^^;;;;####.... ", -" ....____;;;;;;;;;;;;;;;;;;;;----~~~~]]]];;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;}}}};;;;####.... ....____;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;////^^^^;;;;####.... ", -" ....$$$$''''!!!!!!!!!!!!!!!!!!!!1111]]]]!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!%%%%}}}}[[[[,,,,.... ....''''[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[,,,,||||>>>>}}}}.... ", -" ....$$$$''''!!!!!!!!!!!!!!!!!!!!1111]]]]!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!%%%%}}}}[[[[,,,,.... ....''''[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[,,,,||||>>>>}}}}.... ", -" ....$$$$''''!!!!!!!!!!!!!!!!!!!!1111]]]]!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!%%%%}}}}[[[[,,,,.... ....''''[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[,,,,||||>>>>}}}}.... ", -" ....$$$$''''!!!!!!!!!!!!!!!!!!!!1111]]]]!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!%%%%}}}}[[[[,,,,.... ....''''[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[,,,,||||>>>>}}}}.... ", -" ........''''{{{{::::::::____________!!!!{{{{____________::::((((>>>>____________::::[[[[@@@@............~~~~[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[1111####{{{{,,,,.... ", -" ........''''{{{{::::::::____________!!!!{{{{____________::::((((>>>>____________::::[[[[@@@@............~~~~[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[1111####{{{{,,,,.... ", -" ........''''{{{{::::::::____________!!!!{{{{____________::::((((>>>>____________::::[[[[@@@@............~~~~[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[1111####{{{{,,,,.... ", -" ........''''{{{{::::::::____________!!!!{{{{____________::::((((>>>>____________::::[[[[@@@@............~~~~[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[1111####{{{{,,,,.... ", -" ....++++;;;;----<<<<====((((;;;;;;;;[[[[::::;;;;;;;;((((====----;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;)))).... ", -" ....++++;;;;----<<<<====((((;;;;;;;;[[[[::::;;;;;;;;((((====----;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;)))).... ", -" ....++++;;;;----<<<<====((((;;;;;;;;[[[[::::;;;;;;;;((((====----;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;)))).... ", -" ....++++;;;;----<<<<====((((;;;;;;;;[[[[::::;;;;;;;;((((====----;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;)))).... ", -" ....****;;;;;;;;;;;;;;;;[[[[====;;;;[[[[____;;;;{{{{((((;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;----####.... ", -" ....****;;;;;;;;;;;;;;;;[[[[====;;;;[[[[____;;;;{{{{((((;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;----####.... ", -" ....****;;;;;;;;;;;;;;;;[[[[====;;;;[[[[____;;;;{{{{((((;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;----####.... ", -" ....****;;;;;;;;;;;;;;;;[[[[====;;;;[[[[____;;;;{{{{((((;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;----####.... ", -" ....&&&&))))!!!!!!!!!!!!!!!!))))$$$$]]]]~~~~))))$$$$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!^^^^++++.... ", -" ....&&&&))))!!!!!!!!!!!!!!!!))))$$$$]]]]~~~~))))$$$$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!^^^^++++.... ", -" ....&&&&))))!!!!!!!!!!!!!!!!))))$$$$]]]]~~~~))))$$$$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!^^^^++++.... ", -" ....&&&&))))!!!!!!!!!!!!!!!!))))$$$$]]]]~~~~))))$$$$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!^^^^++++.... ", -" ....&&&&((((____________________!!!!$$$$))))!!!!________________________________________________________________________________________________________________<<<<3333.... ", -" ....&&&&((((____________________!!!!$$$$))))!!!!________________________________________________________________________________________________________________<<<<3333.... ", -" ....&&&&((((____________________!!!!$$$$))))!!!!________________________________________________________________________________________________________________<<<<3333.... ", -" ....&&&&((((____________________!!!!$$$$))))!!!!________________________________________________________________________________________________________________<<<<3333.... ", -" ....%%%%;;;;;;;;;;;;;;;;;;;;;;;;;;;;@@@@||||;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;========))))))))))))))))))))))))))))))))))))))))))))))))))))))))]]]]****&&&&.... ", -" ....%%%%;;;;;;;;;;;;;;;;;;;;;;;;;;;;@@@@||||;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;========))))))))))))))))))))))))))))))))))))))))))))))))))))))))]]]]****&&&&.... ", -" ....%%%%;;;;;;;;;;;;;;;;;;;;;;;;;;;;@@@@||||;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;========))))))))))))))))))))))))))))))))))))))))))))))))))))))))]]]]****&&&&.... ", -" ....%%%%;;;;;;;;;;;;;;;;;;;;;;;;;;;;@@@@||||;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;========))))))))))))))))))))))))))))))))))))))))))))))))))))))))]]]]****&&&&.... ", -" ....****22222222;;;;;;;;;;;;;;;;;;;;(((({{{{;;;;;;;;;;;;;;;;;;;;____----;;;;;;;;;;;;;;;;%%%%....&&&&........................................................................ ", -" ....****22222222;;;;;;;;;;;;;;;;;;;;(((({{{{;;;;;;;;;;;;;;;;;;;;____----;;;;;;;;;;;;;;;;%%%%....&&&&........................................................................ ", -" ....****22222222;;;;;;;;;;;;;;;;;;;;(((({{{{;;;;;;;;;;;;;;;;;;;;____----;;;;;;;;;;;;;;;;%%%%....&&&&........................................................................ ", -" ....****22222222;;;;;;;;;;;;;;;;;;;;(((({{{{;;;;;;;;;;;;;;;;;;;;____----;;;;;;;;;;;;;;;;%%%%....&&&&........................................................................ ", -" ....&&&&++++~~~~####]]]]!!!!!!!!!!!!~~~~]]]]!!!!====[[[[!!!!^^^^>>>>[[[[[[[[[[[[[[[[{{{{}}}}............ ", -" ....&&&&++++~~~~####]]]]!!!!!!!!!!!!~~~~]]]]!!!!====[[[[!!!!^^^^>>>>[[[[[[[[[[[[[[[[{{{{}}}}............ ", -" ....&&&&++++~~~~####]]]]!!!!!!!!!!!!~~~~]]]]!!!!====[[[[!!!!^^^^>>>>[[[[[[[[[[[[[[[[{{{{}}}}............ ", -" ....&&&&++++~~~~####]]]]!!!!!!!!!!!!~~~~]]]]!!!!====[[[[!!!!^^^^>>>>[[[[[[[[[[[[[[[[{{{{}}}}............ ", -" ........////________::::^^^^^^^^::::((((!!!!____[[[[$$$$>>>>[[[[[[[[[[[[[[[[[[[[[[[[{{{{++++.... ", -" ........////________::::^^^^^^^^::::((((!!!!____[[[[$$$$>>>>[[[[[[[[[[[[[[[[[[[[[[[[{{{{++++.... ", -" ........////________::::^^^^^^^^::::((((!!!!____[[[[$$$$>>>>[[[[[[[[[[[[[[[[[[[[[[[[{{{{++++.... ", -" ........////________::::^^^^^^^^::::((((!!!!____[[[[$$$$>>>>[[[[[[[[[[[[[[[[[[[[[[[[{{{{++++.... ", -" ....<<<<;;;;;;;;;;;;;;;;<<<<^^^^2222{{{{;;;;''''2222;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;]]]].... ", -" ....<<<<;;;;;;;;;;;;;;;;<<<<^^^^2222{{{{;;;;''''2222;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;]]]].... ", -" ....<<<<;;;;;;;;;;;;;;;;<<<<^^^^2222{{{{;;;;''''2222;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;]]]].... ", -" ....<<<<;;;;;;;;;;;;;;;;<<<<^^^^2222{{{{;;;;''''2222;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;]]]].... ", -" ....;;;;;;;;;;;;;;;;;;;;;;;;::::~~~~====>>>>::::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;]]]].... ", -" ....;;;;;;;;;;;;;;;;;;;;;;;;::::~~~~====>>>>::::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;]]]].... ", -" ....;;;;;;;;;;;;;;;;;;;;;;;;::::~~~~====>>>>::::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;]]]].... ", -" ....;;;;;;;;;;;;;;;;;;;;;;;;::::~~~~====>>>>::::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;]]]].... ", -" ....@@@@!!!!!!!!!!!!!!!!!!!!!!!!]]]]3333||||!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!****.... ", -" ....@@@@!!!!!!!!!!!!!!!!!!!!!!!!]]]]3333||||!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!****.... ", -" ....@@@@!!!!!!!!!!!!!!!!!!!!!!!!]]]]3333||||!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!****.... ", -" ....@@@@!!!!!!!!!!!!!!!!!!!!!!!!]]]]3333||||!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!****.... ", -" ....####____________________________####____________________::::<<<<________________~~~~........ ", -" ....####____________________________####____________________::::<<<<________________~~~~........ ", -" ....####____________________________####____________________::::<<<<________________~~~~........ ", -" ....####____________________________####____________________::::<<<<________________~~~~........ ", -" ....^^^^____{{{{[[[[____;;;;;;;;;;;;====2222;;;;;;;;;;;;<<<<<<<<----;;;;;;;;;;;;;;;;;;;;,,,,........................................................................ ", -" ....^^^^____{{{{[[[[____;;;;;;;;;;;;====2222;;;;;;;;;;;;<<<<<<<<----;;;;;;;;;;;;;;;;;;;;,,,,........................................................................ ", -" ....^^^^____{{{{[[[[____;;;;;;;;;;;;====2222;;;;;;;;;;;;<<<<<<<<----;;;;;;;;;;;;;;;;;;;;,,,,........................................................................ ", -" ....^^^^____{{{{[[[[____;;;;;;;;;;;;====2222;;;;;;;;;;;;<<<<<<<<----;;;;;;;;;;;;;;;;;;;;,,,,........................................................................ ", -" ....@@@@<<<<;;;;;;;;{{{{~~~~2222;;;;____>>>>;;;;;;;;((((((((;;;;;;;;;;;;;;;;;;;;;;;;;;;;3333,,,,--------------------------------------------||||....$$$$----!!!!.... ", -" ....@@@@<<<<;;;;;;;;{{{{~~~~2222;;;;____>>>>;;;;;;;;((((((((;;;;;;;;;;;;;;;;;;;;;;;;;;;;3333,,,,--------------------------------------------||||....$$$$----!!!!.... ", -" ....@@@@<<<<;;;;;;;;{{{{~~~~2222;;;;____>>>>;;;;;;;;((((((((;;;;;;;;;;;;;;;;;;;;;;;;;;;;3333,,,,--------------------------------------------||||....$$$$----!!!!.... ", -" ....@@@@<<<<;;;;;;;;{{{{~~~~2222;;;;____>>>>;;;;;;;;((((((((;;;;;;;;;;;;;;;;;;;;;;;;;;;;3333,,,,--------------------------------------------||||....$$$$----!!!!.... ", -" ........@@@@))))))))))))))))||||@@@@))))||||))))$$$$||||))))))))))))))))))))))))))))####}}}}&&&&////))))))))))))))))))))))))))))))))))))))))}}}}....////))))////.... ", -" ........@@@@))))))))))))))))||||@@@@))))||||))))$$$$||||))))))))))))))))))))))))))))####}}}}&&&&////))))))))))))))))))))))))))))))))))))))))}}}}....////))))////.... ", -" ........@@@@))))))))))))))))||||@@@@))))||||))))$$$$||||))))))))))))))))))))))))))))####}}}}&&&&////))))))))))))))))))))))))))))))))))))))))}}}}....////))))////.... ", -" ........@@@@))))))))))))))))||||@@@@))))||||))))$$$$||||))))))))))))))))))))))))))))####}}}}&&&&////))))))))))))))))))))))))))))))))))))))))}}}}....////))))////.... ", -" ....&&&&::::;;;;;;;;;;;;;;;;;;;;====>>>>>>>>;;;;^^^^;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;____....[[[[;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;^^^^....{{{{;;;;||||.... ", -" ....&&&&::::;;;;;;;;;;;;;;;;;;;;====>>>>>>>>;;;;^^^^;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;____....[[[[;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;^^^^....{{{{;;;;||||.... ", -" ....&&&&::::;;;;;;;;;;;;;;;;;;;;====>>>>>>>>;;;;^^^^;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;____....[[[[;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;^^^^....{{{{;;;;||||.... ", -" ....&&&&::::;;;;;;;;;;;;;;;;;;;;====>>>>>>>>;;;;^^^^;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;____....[[[[;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;^^^^....{{{{;;;;||||.... ", -" ........2222;;;;;;;;;;;;;;;;;;;;;;;;{{{{####<<<<[[[[;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++++'''';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;~~~~****;;;;;;;;........ ", -" ........2222;;;;;;;;;;;;;;;;;;;;;;;;{{{{####<<<<[[[[;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++++'''';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;~~~~****;;;;;;;;........ ", -" ........2222;;;;;;;;;;;;;;;;;;;;;;;;{{{{####<<<<[[[[;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++++'''';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;~~~~****;;;;;;;;........ ", -" ........2222;;;;;;;;;;;;;;;;;;;;;;;;{{{{####<<<<[[[[;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++++'''';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;~~~~****;;;;;;;;........ ", -" ....^^^^;;;;;;;;;;;;;;;;;;;;;;;;;;;;''''%%%%;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;{{{{&&&&}}}}####;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;[[[[++++||||;;;;----........ ", -" ....^^^^;;;;;;;;;;;;;;;;;;;;;;;;;;;;''''%%%%;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;{{{{&&&&}}}}####;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;[[[[++++||||;;;;----........ ", -" ....^^^^;;;;;;;;;;;;;;;;;;;;;;;;;;;;''''%%%%;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;{{{{&&&&}}}}####;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;[[[[++++||||;;;;----........ ", -" ....^^^^;;;;;;;;;;;;;;;;;;;;;;;;;;;;''''%%%%;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;{{{{&&&&}}}}####;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;[[[[++++||||;;;;----........ ", -" ....&&&&3333$$$$1111$$$$))))))))))))))))%%%%))))))))))))))))1111]]]]))))))))))))))))]]]]++++&&&&}}}}$$$$))))))))))))))))))))))))@@@@&&&&....////))))@@@@.... ", -" ....&&&&3333$$$$1111$$$$))))))))))))))))%%%%))))))))))))))))1111]]]]))))))))))))))))]]]]++++&&&&}}}}$$$$))))))))))))))))))))))))@@@@&&&&....////))))@@@@.... ", -" ....&&&&3333$$$$1111$$$$))))))))))))))))%%%%))))))))))))))))1111]]]]))))))))))))))))]]]]++++&&&&}}}}$$$$))))))))))))))))))))))))@@@@&&&&....////))))@@@@.... ", -" ....&&&&3333$$$$1111$$$$))))))))))))))))%%%%))))))))))))))))1111]]]]))))))))))))))))]]]]++++&&&&}}}}$$$$))))))))))))))))))))))))@@@@&&&&....////))))@@@@.... ", -" ........((((;;;;____<<<<''''{{{{;;;;;;;;((((----;;;;;;;;[[[[2222;;;;;;;;;;;;;;;;;;;;;;;;----@@@@3333;;;;;;;;;;;;;;;;;;;;;;;;;;;;____}}}}}}}};;;;;;;;~~~~.... ", -" ........((((;;;;____<<<<''''{{{{;;;;;;;;((((----;;;;;;;;[[[[2222;;;;;;;;;;;;;;;;;;;;;;;;----@@@@3333;;;;;;;;;;;;;;;;;;;;;;;;;;;;____}}}}}}}};;;;;;;;~~~~.... ", -" ........((((;;;;____<<<<''''{{{{;;;;;;;;((((----;;;;;;;;[[[[2222;;;;;;;;;;;;;;;;;;;;;;;;----@@@@3333;;;;;;;;;;;;;;;;;;;;;;;;;;;;____}}}}}}}};;;;;;;;~~~~.... ", -" ........((((;;;;____<<<<''''{{{{;;;;;;;;((((----;;;;;;;;[[[[2222;;;;;;;;;;;;;;;;;;;;;;;;----@@@@3333;;;;;;;;;;;;;;;;;;;;;;;;;;;;____}}}}}}}};;;;;;;;~~~~.... ", -" ....====;;;;;;;;;;;;;;;;::::~~~~<<<<----((((;;;;----[[[[;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::....====;;;;;;;;;;;;;;;;;;;;;;;;>>>>....!!!!;;;;;;;;,,,,.... ", -" ....====;;;;;;;;;;;;;;;;::::~~~~<<<<----((((;;;;----[[[[;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::....====;;;;;;;;;;;;;;;;;;;;;;;;>>>>....!!!!;;;;;;;;,,,,.... ", -" ....====;;;;;;;;;;;;;;;;::::~~~~<<<<----((((;;;;----[[[[;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::....====;;;;;;;;;;;;;;;;;;;;;;;;>>>>....!!!!;;;;;;;;,,,,.... ", -" ....====;;;;;;;;;;;;;;;;::::~~~~<<<<----((((;;;;----[[[[;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::....====;;;;;;;;;;;;;;;;;;;;;;;;>>>>....!!!!;;;;;;;;,,,,.... ", -" ....////::::;;;;;;;;;;;;;;;;;;;;!!!!!!!!!!!!;;;;====----;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;>>>>....++++$$$$;;;;;;;;;;;;;;;;[[[[....&&&&____;;;;====........ ", -" ....////::::;;;;;;;;;;;;;;;;;;;;!!!!!!!!!!!!;;;;====----;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;>>>>....++++$$$$;;;;;;;;;;;;;;;;[[[[....&&&&____;;;;====........ ", -" ....////::::;;;;;;;;;;;;;;;;;;;;!!!!!!!!!!!!;;;;====----;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;>>>>....++++$$$$;;;;;;;;;;;;;;;;[[[[....&&&&____;;;;====........ ", -" ....////::::;;;;;;;;;;;;;;;;;;;;!!!!!!!!!!!!;;;;====----;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;>>>>....++++$$$$;;;;;;;;;;;;;;;;[[[[....&&&&____;;;;====........ ", -" ........&&&&||||))))))))))))))))))))$$$$,,,,||||%%%%))))))))))))))))))))))))))))))))))))]]]]1111&&&&....||||]]]]]]]]@@@@&&&&....||||]]]]]]]]}}}}.... ", -" ........&&&&||||))))))))))))))))))))$$$$,,,,||||%%%%))))))))))))))))))))))))))))))))))))]]]]1111&&&&....||||]]]]]]]]@@@@&&&&....||||]]]]]]]]}}}}.... ", -" ........&&&&||||))))))))))))))))))))$$$$,,,,||||%%%%))))))))))))))))))))))))))))))))))))]]]]1111&&&&....||||]]]]]]]]@@@@&&&&....||||]]]]]]]]}}}}.... ", -" ........&&&&||||))))))))))))))))))))$$$$,,,,||||%%%%))))))))))))))))))))))))))))))))))))]]]]1111&&&&....||||]]]]]]]]@@@@&&&&....||||]]]]]]]]}}}}.... ", -" ....&&&&;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::@@@@====;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;----////................3333::::;;;;;;;;;;;;}}}}.... ", -" ....&&&&;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::@@@@====;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;----////................3333::::;;;;;;;;;;;;}}}}.... ", -" ....&&&&;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::@@@@====;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;----////................3333::::;;;;;;;;;;;;}}}}.... ", -" ....&&&&;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::@@@@====;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;----////................3333::::;;;;;;;;;;;;}}}}.... ", -" ........!!!!;;;;;;;;;;;;;;;;;;;;;;;;;;;;(((([[[[;;;;;;;;;;;;;;;;____2222;;;;;;;;;;;;;;;;;;;;;;;;;;;;>>>>)))))))){{{{;;;;;;;;;;;;;;;;^^^^........ ", -" ........!!!!;;;;;;;;;;;;;;;;;;;;;;;;;;;;(((([[[[;;;;;;;;;;;;;;;;____2222;;;;;;;;;;;;;;;;;;;;;;;;;;;;>>>>)))))))){{{{;;;;;;;;;;;;;;;;^^^^........ ", -" ........!!!!;;;;;;;;;;;;;;;;;;;;;;;;;;;;(((([[[[;;;;;;;;;;;;;;;;____2222;;;;;;;;;;;;;;;;;;;;;;;;;;;;>>>>)))))))){{{{;;;;;;;;;;;;;;;;^^^^........ ", -" ........!!!!;;;;;;;;;;;;;;;;;;;;;;;;;;;;(((([[[[;;;;;;;;;;;;;;;;____2222;;;;;;;;;;;;;;;;;;;;;;;;;;;;>>>>)))))))){{{{;;;;;;;;;;;;;;;;^^^^........ ", -" ........====2222____::::----;;;;;;;;;;;;((((;;;;;;;;;;;;2222<<<<;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;----))))........ ", -" ........====2222____::::----;;;;;;;;;;;;((((;;;;;;;;;;;;2222<<<<;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;----))))........ ", -" ........====2222____::::----;;;;;;;;;;;;((((;;;;;;;;;;;;2222<<<<;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;----))))........ ", -" ........====2222____::::----;;;;;;;;;;;;((((;;;;;;;;;;;;2222<<<<;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;----))))........ ", -" ............%%%%$$$$####@@@@%%%%####))))####))))))))||||))))))))))))))))))))))))))))))))))))))))))))))))))))))))||||}}}}&&&&.... ", -" ............%%%%$$$$####@@@@%%%%####))))####))))))))||||))))))))))))))))))))))))))))))))))))))))))))))))))))))))||||}}}}&&&&.... ", -" ............%%%%$$$$####@@@@%%%%####))))####))))))))||||))))))))))))))))))))))))))))))))))))))))))))))))))))))))||||}}}}&&&&.... ", -" ............%%%%$$$$####@@@@%%%%####))))####))))))))||||))))))))))))))))))))))))))))))))))))))))))))))))))))))))||||}}}}&&&&.... ", -" ........!!!!;;;;;;;;;;;;2222!!!!]]]]{{{{____----[[[[;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;&&&&........ ", -" ........!!!!;;;;;;;;;;;;2222!!!!]]]]{{{{____----[[[[;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;&&&&........ ", -" ........!!!!;;;;;;;;;;;;2222!!!!]]]]{{{{____----[[[[;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;&&&&........ ", -" ........!!!!;;;;;;;;;;;;2222!!!!]]]]{{{{____----[[[[;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;&&&&........ ", -" ........^^^^----;;;;;;;;;;;;;;;;^^^^))))((((::::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;''''........ ", -" ........^^^^----;;;;;;;;;;;;;;;;^^^^))))((((::::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;''''........ ", -" ........^^^^----;;;;;;;;;;;;;;;;^^^^))))((((::::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;''''........ ", -" ........^^^^----;;;;;;;;;;;;;;;;^^^^))))((((::::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;''''........ ", -" ........****''''----;;;;;;;;;;;;::::]]]]----;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;----$$$$........ ", -" ........****''''----;;;;;;;;;;;;::::]]]]----;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;----$$$$........ ", -" ........****''''----;;;;;;;;;;;;::::]]]]----;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;----$$$$........ ", -" ........****''''----;;;;;;;;;;;;::::]]]]----;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;----$$$$........ ", -" ................}}}}....////1111))))))))))))))))))))))))))))))))))))))))))))))))]]]]////............ ", -" ................}}}}....////1111))))))))))))))))))))))))))))))))))))))))))))))))]]]]////............ ", -" ................}}}}....////1111))))))))))))))))))))))))))))))))))))))))))))))))]]]]////............ ", -" ................}}}}....////1111))))))))))))))))))))))))))))))))))))))))))))))))]]]]////............ ", -" ................................}}}}3333||||||||1111####$$$$$$$$$$$$]]]]1111............ ", -" ................................}}}}3333||||||||1111####$$$$$$$$$$$$]]]]1111............ ", -" ................................}}}}3333||||||||1111####$$$$$$$$$$$$]]]]1111............ ", -" ................................}}}}3333||||||||1111####$$$$$$$$$$$$]]]]1111............ ", -" ............................................................................ ", -" ............................................................................ ", -" ............................................................................ ", -" ............................................................................ ", -" ", -" ", -" ", -" "}; +" ", +" .................... ", +" ...+@##$$$$###@%&....... ", +" ..*=-;;;-;;;;;;;;@........ ", +" ..+-;;;;--;;;;;;;>.......... ", +" ...,')!!'~>{!)$)>'....*]>^%&.. ", +" ../(__(>:{<)$![[[%&...^!!!!!~*. ", +" ..@;;;;;({=]:;;;;;~..*_;;;;;;;_.. ", +" .}>;;;;;^#=;;;;;;>...<;;;;;;;;;|.. ", +" ..*1)))))%]))))))%&..1])))))))))#}. ", +" ..%[;;;;;[2;;;;;;;:..#;;;2[[-;;;;;=.. ", +" .&:;[{;;;{;;;~={:;^.._;;'}...>;;;;;,. ", +" .}<;;:{;_:2!'-;;;]*.&(_].|{=@.~___[/.. ", +" ..*$))]@%//,111111}..|1*.@1111@.3111|&. ", +" .,:;;;;;'#^;;;;;;;]./;;+);;;;;;$*;;;;.. ", +" .^;;;;;;));;;;;;;;$.~;$*;;;;;;;-+^;;;#. ", +" ..$;;;;;;>;;;;;;;;>}.^-.!;;;;;;;;)*:;;|. ", +" .&@$|#)))|)))1||#]+..$/}]))))))))$.3))#.. ", +" .#;;;[{;->;-^[;;;;].~;@];;;;;;;;;;1#;;-}. ", +" .{;;;;{<[:(~-;;;;;$.(-.<;;;;;;;;;;{};;;3. ", +" ..);;;;;~~[!;;;;;;-/.>=.>;;;;;;;;;;2}^;:3. ", +" .&#)))))$}@)))))))@.}]3.*))))))))))).,)).. ", +" .3;;;;;;;);;;;;;;;2+|;%.';;;;;;;;;;;]1;;1. ", +" .1_(:;;;;{;;;[=[:;;.];}.);;;;;;;;;;;=,;;]. ", +" .%2-(!2;2{;_':;;;;).1;..+:;;;;;;;;;;_.;;1. ", +" .+))))@1$1#@))))))3.,@...1))))))))))].1#3. ", +" .{;;;;;^<>);;;;;;;-.[). .-;;;;;;;;;;;3{;#. ", +" ._;;;;;-~];;;;;;;;;};#. ._;;;;;;;;;;;/^;#. ", +" .$'!!!!!1]!!!!!!!!%}[,. .'[[[[[[[[[[[,|>}. ", +" ..'{::___!{___:(>___:[@...~[[[[[[[[[[[1#{,. ", +" .+;-<=(;;[:;;(=-;;;;;;;;;;;;;;;;;;;;;;;;;). ", +" .*;;;;[=;[_;{(;;;;;;;;;;;;;;;;;;;;;;;;;;-#. ", +" .&)!!!!)$]~)$!!!!!!!!!!!!!!!!!!!!!!!!!!!^+. ", +" .&(_____!$)!____________________________<3. ", +" .%;;;;;;;@|;;;;;;;;;;;;==))))))))))))))]*&. ", +" .*22;;;;;({;;;;;_-;;;;%.&.................. ", +" .&+~#]!!!~]!=[!^>[[[[{}... ", +" ../__:^^:(!_[$>[[[[[[{+. ", +" .<;;;;<^2{;'2;;;;;;;;]. ", +" .;;;;;;:~=>:;;;;;;;;;]. ", +" .@!!!!!!]3|!!!!!!!!!!*. ", +" .#_______#_____:<____~.. ", +" .^_{[_;;;=2;;;<<-;;;;;,.................. ", +" .@<;;{~2;_>;;((;;;;;;;3,-----------|.$-!. ", +" ..@))))|@)|)$|)))))))#}&/))))))))))}./)/. ", +" .&:;;;;;=>>;^;;;;;;;;;_.[;;;;;;;;;;^.{;|. ", +" ..2;;;;;;{#<[;;;;;;;;;;+';;;;;;;;;;~*;;.. ", +" .^;;;;;;;'%;;;;;;;;;;{&}#;;;;;;;;[+|;-.. ", +" .&3$1$))))%))))1]))))]+&}$))))))@&./)@. ", +" ..(;_<'{;;(-;;[2;;;;;;-@3;;;;;;;_}};;~. ", +" .=;;;;:~<-(;-[;;;;;;;;:.=;;;;;;>.!;;,. ", +" ./:;;;;;!!!;=-;;;;;;;;>.+$;;;;[.&_;=.. ", +" ..&|)))))$,|%)))))))))]1&.|]]@&.|]]}. ", +" .&;;;;;;;:@=;;;;;;;;;;;-/....3:;;;}. ", +" ..!;;;;;;;([;;;;_2;;;;;;;>)){;;;;^.. ", +" ..=2_:-;;;(;;;2<;;;;;;;;;;;;;;-).. ", +" ...%$#@%#)#))|))))))))))))))|}&. ", +" ..!;;;2!]{_-[;;;;;;;;;;;;;;;&.. ", +" ..^-;;;;^)(:;;;;;;;;;;;;;;'.. ", +" ..*'-;;;:]-;;;;;;;;;;;;-$.. ", +" ....}./1))))))))))))]/... ", +" ........}3||1#$$$]1... ", +" ................... ", +" "}; From 748028e8d5fcefdfe5d8f7bfdb23e9a4c90d15a0 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 20 Sep 2018 22:16:04 -0400 Subject: [PATCH 138/146] Condense this re: wolfs --- src/m_menu.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index da45ea8af..0d878d888 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -8592,8 +8592,6 @@ static void M_DrawMonitorToggles(void) break; case KRITEM_TRIPLESNEAKER: case KRITEM_TRIPLEBANANA: - drawnum = 3; - break; case KRITEM_TRIPLEORBINAUT: drawnum = 3; break; From ed3b69ff7f0feafaa74dcd63dfb0d0c381c71940 Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Fri, 21 Sep 2018 12:23:00 +0200 Subject: [PATCH 139/146] Fix visual error related to moving the cursor on multi-line messages. --- src/hu_stuff.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 794a89d76..cab5937c5 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -1565,7 +1565,7 @@ static void HU_DrawChat(void) if (hu_tick < 4) V_DrawChatCharacter(cursorx, cursory+1, '_' |V_SNAPTOBOTTOM|V_SNAPTOLEFT|t, !cv_allcaps.value, NULL); - if (cursorx == chatx+1) // a weirdo hack + if (cursorx == chatx+1 && strlen(w_chat) == i) // a weirdo hack { typelines += 1; skippedline = true; From 1e57004fada5bf84a59ea756bfdc2cf3ce7ef2cc Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 21 Sep 2018 12:12:17 +0100 Subject: [PATCH 140/146] Partially address Sal's review last night by switching to a more sensible default. I'm still unconvinced on the need to make encore mode a seperate knob on the grounds of overcomplexity and "you can't turn map hell off", but hopefully this'll be a shippable state we can come back to later. Also, thank you for reminding me, Sryder - disable my very, very limited progress on encore mode in openGL so that stages aren't an unintended hodgepodge of different colourschemes for the objects versus the level environment. --- src/d_netcmd.c | 2 +- src/hardware/hw_main.c | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index cb2ed49d0..5f5e7e30d 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -354,7 +354,7 @@ consvar_t cv_kartfrantic = {"kartfrantic", "Off", CV_NETVAR|CV_CHEAT|CV_CALL|CV_ consvar_t cv_kartcomeback = {"kartcomeback", "On", CV_NETVAR|CV_CHEAT|CV_CALL|CV_NOINIT, CV_OnOff, KartComeback_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_kartencore = {"kartencore", "Off", CV_NETVAR|CV_CALL|CV_NOINIT, CV_OnOff, KartEncore_OnChange, 0, NULL, NULL, 0, 0, NULL}; static CV_PossibleValue_t kartvoterulechanges_cons_t[] = {{0, "Never"}, {1, "Sometimes"}, {2, "Frequent"}, {3, "Always"}, {0, NULL}}; -consvar_t cv_kartvoterulechanges = {"kartvoterulechanges", "Frequent", CV_NETVAR, kartvoterulechanges_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_kartvoterulechanges = {"kartvoterulechanges", "Sometimes", CV_NETVAR, kartvoterulechanges_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; static CV_PossibleValue_t kartspeedometer_cons_t[] = {{0, "Off"}, {1, "Kilometers"}, {2, "Miles"}, {3, "Fracunits"}, {0, NULL}}; consvar_t cv_kartspeedometer = {"kartdisplayspeed", "Off", CV_SAVE, kartspeedometer_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; // use tics in display static CV_PossibleValue_t kartvoices_cons_t[] = {{0, "Never"}, {1, "Tasteful"}, {2, "Meme"}, {0, NULL}}; diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 87de473ef..4c2063375 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5452,8 +5452,10 @@ static void HWR_ProjectSprite(mobj_t *thing) else { vis->colormap = colormaps; +#ifdef GLENCORE if (encoremap && (thing->flags & (MF_SCENERY|MF_NOTHINK))) vis->colormap += (256*32); +#endif } // set top/bottom coords @@ -5558,8 +5560,10 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) vis->mobj = (mobj_t *)thing; vis->colormap = colormaps; +#ifdef GLENCORE if (encoremap) vis->colormap += (256*32); +#endif // set top/bottom coords vis->ty = FIXED_TO_FLOAT(thing->z + spritecachedinfo[lumpoff].topoffset); From 44e6bb8df35f00f1a92f7ecb2258c5b11aa457b6 Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Fri, 21 Sep 2018 17:03:09 +0200 Subject: [PATCH 141/146] Moved strlen(w_chat) out of the loop. --- src/hu_stuff.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index cab5937c5..77b873286 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -1523,6 +1523,7 @@ static void HU_DrawChat(void) INT32 charwidth = 4, charheight = 6; INT32 t = 0, c = 0, y = chaty - (typelines*charheight) - (cv_kartspeedometer.value ? 16 : 0); UINT32 i = 0; + INT32 saylen = strlen(w_chat); // You learn new things everyday! const char *ntalk = "Say: ", *ttalk = "Team: "; const char *talk = ntalk; @@ -1538,7 +1539,7 @@ static void HU_DrawChat(void) } V_DrawFillConsoleMap(chatx, y-1, cv_chatwidth.value, (typelines*charheight), 239 | V_SNAPTOBOTTOM | V_SNAPTOLEFT); - + while (talk[i]) { if (talk[i] < HU_FONTSTART) @@ -1565,7 +1566,7 @@ static void HU_DrawChat(void) if (hu_tick < 4) V_DrawChatCharacter(cursorx, cursory+1, '_' |V_SNAPTOBOTTOM|V_SNAPTOLEFT|t, !cv_allcaps.value, NULL); - if (cursorx == chatx+1 && strlen(w_chat) == i) // a weirdo hack + if (cursorx == chatx+1 && saylen == i) // a weirdo hack { typelines += 1; skippedline = true; From fd247b82521fcb2f612c01c523f963df94340a65 Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 22 Sep 2018 11:59:07 +0100 Subject: [PATCH 142/146] Sign compare fix via boolean cast --- src/g_game.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index 79fb89f12..73d20bfd0 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3175,7 +3175,7 @@ INT16 G_SometimesGetDifferentGametype(void) encorepossible = M_RandomChance(FRACUNIT>>3); break; } - if (encorepossible != cv_kartencore.value) + if (encorepossible != (boolean)cv_kartencore.value) return (gametype|0x80); } return gametype; From 3e23576060cc86e3b90b6842a04454250fc57749 Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 22 Sep 2018 12:43:54 +0100 Subject: [PATCH 143/146] One last thing - make the OpenGL level loading bar screen have the correct background colour. --- src/hardware/hw_bsp.c | 2 +- src/p_setup.c | 7 +++++-- src/p_setup.h | 1 + 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/hardware/hw_bsp.c b/src/hardware/hw_bsp.c index 17eb8761c..38a6026fa 100644 --- a/src/hardware/hw_bsp.c +++ b/src/hardware/hw_bsp.c @@ -646,7 +646,7 @@ static void WalkBSPNode(INT32 bspnum, poly_t *poly, UINT16 *leafnode, fixed_t *b sprintf(s, "%d%%", (++ls_percent)<<1); x = BASEVIDWIDTH/2; y = BASEVIDHEIGHT/2; - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); // Black background to match fade in effect + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, levelfadecol); // White background to match fade in effect //V_DrawPatchFill(W_CachePatchName("SRB2BACK",PU_CACHE)); // SRB2 background, ehhh too bright. M_DrawTextBox(x-58, y-8, 13, 1); V_DrawString(x-50, y, V_YELLOWMAP, "Loading..."); diff --git a/src/p_setup.c b/src/p_setup.c index a416f991f..501c80d9c 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -101,6 +101,7 @@ side_t *sides; mapthing_t *mapthings; INT32 numstarposts; boolean levelloading; +UINT8 levelfadecol; // BLOCKMAP // Created from axis aligned bounding box @@ -2691,12 +2692,14 @@ boolean P_SetupLevel(boolean skipprecip) if (leveltime < (starttime + (TICRATE/2))) S_ChangeMusicInternal((encoremode ? "estart" : "kstart"), false); //S_StopMusic(); + levelfadecol = (encoremode && !ranspecialwipe ? 122 : 120); + // Let's fade to white here // But only if we didn't do the encore startup wipe if (rendermode != render_none && !ranspecialwipe) { F_WipeStartScreen(); - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (encoremode ? 122 : 120)); + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, levelfadecol); F_WipeEndScreen(); F_RunWipe(wipedefs[(encoremode ? wipe_level_final : wipe_level_toblack)], false); @@ -3040,7 +3043,7 @@ boolean P_SetupLevel(boolean skipprecip) // Remove the loading shit from the screen if (rendermode != render_none) - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (encoremode && !ranspecialwipe ? 122 : 120)); + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, levelfadecol); if (precache || dedicated) R_PrecacheLevel(); diff --git a/src/p_setup.h b/src/p_setup.h index 3bca11047..c3c206a5c 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -27,6 +27,7 @@ extern mapthing_t *deathmatchstarts[MAX_DM_STARTS]; extern INT32 numdmstarts, numcoopstarts, numredctfstarts, numbluectfstarts; extern boolean levelloading; +extern UINT8 levelfadecol; extern lumpnum_t lastloadedmaplumpnum; // for comparative savegame // From 6884e4aa9aa06d77fccd5c41bfcb50dfb499b4cf Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 22 Sep 2018 18:22:04 +0100 Subject: [PATCH 144/146] * Seven new text colours! Gold, Lavender, Tea-green, Steel, Pink, Teal, and Peach, all added to the menu highlights cvar. * Revamp the saycmd colour list to take advantage of them. Peach and Purple are used the least... * In all of the string drawers, replace colormap only when charflags changes. * Add V_SKYMAP to dehacked.c alongside the above (oversight from when I added it yonks ago...) --- src/console.c | 68 +++++++++++++++++++++++++------------- src/console.h | 3 +- src/dehacked.c | 8 +++++ src/hu_stuff.c | 89 +++++++++++++++++++++----------------------------- src/v_video.c | 60 ++++++++++++++++++++++++---------- src/v_video.h | 11 +++++-- 6 files changed, 143 insertions(+), 96 deletions(-) diff --git a/src/console.c b/src/console.c index 212e6c8d9..bd19cdf3b 100644 --- a/src/console.c +++ b/src/console.c @@ -150,6 +150,13 @@ static CV_PossibleValue_t menuhighlight_cons_t[] = {V_GRAYMAP, "Always gray"}, {V_ORANGEMAP, "Always orange"}, {V_SKYMAP, "Always sky-blue"}, + {V_GOLDMAP, "Always gold"}, + {V_LAVENDERMAP, "Always lavender"}, + {V_TEAMAP, "Always tea-green"}, + {V_STEELMAP, "Always steel"}, + {V_PINKMAP, "Always pink"}, + {V_TEALMAP, "Always teal"}, + {V_PEACHMAP, "Always peach"}, {0, NULL} }; consvar_t cons_menuhighlight = {"menuhighlight", "Game type", CV_SAVE, menuhighlight_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -239,11 +246,6 @@ static void CONS_Bind_f(void) // CONSOLE SETUP //====================================================================== -// Font colormap colors -// TODO: This could probably be improved somehow... -// These colormaps are 99% identical, with just a few changed bytes -UINT8 *yellowmap, *purplemap, *greenmap, *bluemap, *graymap, *redmap, *orangemap, *skymap; - // Console BG color UINT8 *consolebgmap = NULL; @@ -284,37 +286,57 @@ static void CONS_backcolor_Change(void) CON_SetupBackColormap(); } +// Font colormap colors +// TODO: This could probably be improved somehow... +// These colormaps are 99% identical, with just a few changed bytes +UINT8 *yellowmap, *purplemap, *greenmap, *bluemap, *graymap, *redmap, *orangemap,\ + *skymap, *goldmap, *lavendermap, *teamap, *steelmap, *pinkmap, *tealmap, *peachmap; + static void CON_SetupColormaps(void) { INT32 i; - UINT8 *memorysrc = (UINT8 *)Z_Malloc((256*8), PU_STATIC, NULL); + UINT8 *memorysrc = (UINT8 *)Z_Malloc((256*15), PU_STATIC, NULL); - purplemap = memorysrc; - yellowmap = (purplemap+256); - greenmap = (yellowmap+256); - bluemap = (greenmap+256); - redmap = (bluemap+256); - graymap = (redmap+256); - orangemap = (graymap+256); - skymap = (orangemap+256); + purplemap = memorysrc; + yellowmap = (purplemap+256); + greenmap = (yellowmap+256); + bluemap = (greenmap+256); + redmap = (bluemap+256); + graymap = (redmap+256); + orangemap = (graymap+256); + skymap = (orangemap+256); + lavendermap = (skymap+256); + goldmap = (lavendermap+256); + teamap = (goldmap+256); + steelmap = (teamap+256); + pinkmap = (steelmap+256); + tealmap = (pinkmap+256); + peachmap = (tealmap+256); // setup the other colormaps, for console text // these don't need to be aligned, unless you convert the // V_DrawMappedPatch() into optimised asm. - for (i = 0; i < (256*8); i++, ++memorysrc) + for (i = 0; i < (256*15); i++, ++memorysrc) *memorysrc = (UINT8)(i & 0xFF); // remap each color to itself... // SRB2Kart: Different console font, new colors - purplemap[120] = (UINT8)194; - yellowmap[120] = (UINT8)103; - greenmap[120] = (UINT8)162; - bluemap[120] = (UINT8)228; - graymap[120] = (UINT8)10; - redmap[120] = (UINT8)126; // battle - orangemap[120] = (UINT8)85; // record attack - skymap[120] = (UINT8)214; // race + purplemap[120] = (UINT8)194; + yellowmap[120] = (UINT8)103; + greenmap[120] = (UINT8)162; + bluemap[120] = (UINT8)228; + redmap[120] = (UINT8)126; // battle + graymap[120] = (UINT8)10; + orangemap[120] = (UINT8)85; // record attack + skymap[120] = (UINT8)214; // race + lavendermap[120] = (UINT8)248; + goldmap[120] = (UINT8)114; + teamap[120] = (UINT8)177; + steelmap[120] = (UINT8)201; + pinkmap[120] = (UINT8)124; + tealmap[120] = (UINT8)220; + peachmap[120] = (UINT8)69; // nice // Init back colormap CON_SetupBackColormap(); diff --git a/src/console.h b/src/console.h index 896214c99..b15ccb6f1 100644 --- a/src/console.h +++ b/src/console.h @@ -38,7 +38,8 @@ extern UINT32 con_scalefactor; // console text scale factor extern consvar_t cons_backcolor, cons_menuhighlight; -extern UINT8 *yellowmap, *purplemap, *greenmap, *bluemap, *graymap, *redmap, *orangemap, *skymap; +extern UINT8 *yellowmap, *purplemap, *greenmap, *bluemap, *graymap, *redmap, *orangemap,\ + *skymap, *goldmap, *lavendermap, *teamap, *steelmap, *pinkmap, *tealmap, *peachmap; // Console bg color (auto updated to match) extern UINT8 *consolebgmap; diff --git a/src/dehacked.c b/src/dehacked.c index 1c18e0033..8c11cb8fd 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8206,6 +8206,14 @@ struct { {"V_REDMAP",V_REDMAP}, {"V_GRAYMAP",V_GRAYMAP}, {"V_ORANGEMAP",V_ORANGEMAP}, + {"V_SKYMAP",V_SKYMAP}, + {"V_LAVENDERMAP",V_LAVENDERMAP}, + {"V_GOLDMAP",V_GOLDMAP}, + {"V_TEAMAP",V_TEAMAP}, + {"V_STEELMAP",V_STEELMAP}, + {"V_PINKMAP",V_PINKMAP}, + {"V_TEALMAP",V_TEALMAP}, + {"V_PEACHMAP",V_PEACHMAP}, {"V_TRANSLUCENT",V_TRANSLUCENT}, {"V_10TRANS",V_10TRANS}, {"V_20TRANS",V_20TRANS}, diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 8ff23e4db..33d4f2aaf 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -726,25 +726,39 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) { const UINT8 color = players[playernum].skincolor; if (color <= SKINCOLOR_SILVER) - cstart = "\x80"; - else if (color <= SKINCOLOR_BLACK || color == SKINCOLOR_JET) // jet is more black than blue so it goes here. - cstart = "\x86"; + cstart = "\x80"; // white + else if (color <= SKINCOLOR_BEIGE || color == SKINCOLOR_JET) + cstart = "\x86"; // V_GRAYMAP + else if (color <= SKINCOLOR_LEATHER) + cstart = "\x8A"; // V_GOLDMAP + else if (color <= SKINCOLOR_ROSE || color == SKINCOLOR_RUBY || color == SKINCOLOR_DAWN || color == SKINCOLOR_LILAC) + cstart = "\x8d"; // V_PINKMAP else if (color <= SKINCOLOR_KETCHUP) - cstart = "\x85"; + cstart = "\x85"; // V_REDMAP + else if (color <= SKINCOLOR_TANGERINE) + cstart = "\x87"; // V_ORANGEMAP else if (color <= SKINCOLOR_CARAMEL) - cstart = "\x87"; - else if (color <= SKINCOLOR_MUSTARD) - cstart = "\x82"; - else if (SKINCOLOR_SWAMP) - cstart = "\x83"; - else if (color <= SKINCOLOR_STEEL || color == SKINCOLOR_SAPPHIRE) // toaster wanted that specific one too shrug - cstart = "\x88"; - else if (color <= SKINCOLOR_NAVY) - cstart = "\x84"; - else if (color <= SKINCOLOR_LILAC) - cstart = "\x81"; - else - cstart = "\x83"; + cstart = "\x8f"; // V_PEACHMAP + else if (color <= SKINCOLOR_BRONZE) + cstart = "\x8A"; // V_GOLDMAP + else if (color <= SKINCOLOR_MUSTARD || color == SKINCOLOR_LIME) + cstart = "\x82"; // V_YELLOWMAP + else if (color <= SKINCOLOR_PISTACHIO) + cstart = "\x8b"; // V_TEAMAP + else if (color <= SKINCOLOR_SWAMP) + cstart = "\x83"; // V_GREENMAP + else if (color <= SKINCOLOR_TEAL) + cstart = "\x8e"; // V_TEALMAP + else if (color <= SKINCOLOR_NAVY || color == SKINCOLOR_SAPPHIRE) + cstart = "\x88"; // V_SKYMAP + else if (color <= SKINCOLOR_STEEL) + cstart = "\x8c"; // V_STEELMAP + else if (color <= SKINCOLOR_BLUEBERRY) + cstart = "\x84"; // V_BLUEMAP + else if (color == SKINCOLOR_PURPLE) + cstart = "\x81"; // V_PURPLEMAP + else //if (color <= SKINCOLOR_POMEGRANATE) + cstart = "\x89"; // V_LAVENDERMAP } prefix = cstart; @@ -1171,33 +1185,6 @@ boolean HU_Responder(event_t *ev) // HEADS UP DRAWING //====================================================================== -// Gets string colormap, used for 0x80 color codes -// -static UINT8 *CHAT_GetStringColormap(INT32 colorflags) // pasted from video.c, sorry for the mess. -{ - switch ((colorflags & V_CHARCOLORMASK) >> V_CHARCOLORSHIFT) - { - case 1: // 0x81, purple - return purplemap; - case 2: // 0x82, yellow - return yellowmap; - case 3: // 0x83, lgreen - return greenmap; - case 4: // 0x84, blue - return bluemap; - case 5: // 0x85, red - return redmap; - case 6: // 0x86, gray - return graymap; - case 7: // 0x87, orange - return orangemap; - case 8: // 0x88, sky - return skymap; - default: // reset - return NULL; - } -} - // Precompile a wordwrapped string to any given width. // This is a muuuch better method than V_WORDWRAP. // again stolen and modified a bit from video.c, don't mind me, will need to rearrange this one day. @@ -1216,7 +1203,7 @@ static char *CHAT_WordWrap(INT32 x, INT32 w, INT32 option, const char *string) for (i = 0; i < slen; ++i) { c = newstring[i]; - if ((UINT8)c >= 0x80 && (UINT8)c <= 0x89) //color parsing! -Inuyasha 2.16.09 + if ((UINT8)c >= 0x80 && (UINT8)c <= 0x8F) //color parsing! -Inuyasha 2.16.09 continue; if (c == '\n') @@ -1333,6 +1320,7 @@ static void HU_drawMiniChat(void) INT32 transflag = (timer >= 0 && timer <= 9) ? (timer*V_10TRANS) : 0; // you can make bad jokes out of this one. size_t j = 0; const char *msg = CHAT_WordWrap(x+2, cv_chatwidth.value-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i]); // get the current message, and word wrap it. + UINT8 *colormap = NULL; while(msg[j]) // iterate through msg { @@ -1352,6 +1340,7 @@ static void HU_drawMiniChat(void) else if (msg[j] & 0x80) // stolen from video.c, nice. { clrflag = ((msg[j] & 0x7f) << V_CHARCOLORSHIFT) & V_CHARCOLORMASK; + colormap = V_GetStringColormap(clrflag); ++j; continue; } @@ -1360,8 +1349,6 @@ static void HU_drawMiniChat(void) } else { - UINT8 *colormap = CHAT_GetStringColormap(clrflag); - if (cv_chatbacktint.value) // on request of wolfy V_DrawFillConsoleMap(x + dx + 2, y+dy, charwidth, charheight, 239|V_SNAPTOBOTTOM|V_SNAPTOLEFT); @@ -1411,6 +1398,7 @@ static void HU_drawChatLog(INT32 offset) INT32 clrflag = 0; INT32 j = 0; const char *msg = CHAT_WordWrap(x+2, cv_chatwidth.value-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_log[i]); // get the current message, and word wrap it. + UINT8 *colormap = NULL; while(msg[j]) // iterate through msg { if (msg[j] < HU_FONTSTART) // don't draw @@ -1425,6 +1413,7 @@ static void HU_drawChatLog(INT32 offset) else if (msg[j] & 0x80) // stolen from video.c, nice. { clrflag = ((msg[j] & 0x7f) << V_CHARCOLORSHIFT) & V_CHARCOLORMASK; + colormap = V_GetStringColormap(clrflag); ++j; continue; } @@ -1434,10 +1423,7 @@ static void HU_drawChatLog(INT32 offset) else { if ((y+dy+2 >= chat_topy) && (y+dy < (chat_bottomy))) - { - UINT8 *colormap = CHAT_GetStringColormap(clrflag); V_DrawChatCharacter(x + dx + 2, y+dy+2, msg[j++] |V_SNAPTOBOTTOM|V_SNAPTOLEFT, !cv_allcaps.value, colormap); - } else j++; // don't forget to increment this or we'll get stuck in the limbo. } @@ -1498,8 +1484,7 @@ static void HU_DrawChat(void) { INT32 charwidth = 4, charheight = 6; INT32 t = 0, c = 0, y = chaty - (typelines*charheight) - (cv_kartspeedometer.value ? 16 : 0); - UINT32 i = 0; - INT32 saylen = strlen(w_chat); // You learn new things everyday! + UINT32 i = 0, saylen = strlen(w_chat); // You learn new things everyday! const char *ntalk = "Say: ", *ttalk = "Team: "; const char *talk = ntalk; diff --git a/src/v_video.c b/src/v_video.c index 58115e020..a56a5cfc2 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -1248,26 +1248,40 @@ void V_DrawFadeConsBack(INT32 plines) // Gets string colormap, used for 0x80 color codes // -const UINT8 *V_GetStringColormap(INT32 colorflags) +UINT8 *V_GetStringColormap(INT32 colorflags) { switch ((colorflags & V_CHARCOLORMASK) >> V_CHARCOLORSHIFT) { - case 1: // 0x81, purple + case 1: // 0x81, purple return purplemap; - case 2: // 0x82, yellow + case 2: // 0x82, yellow return yellowmap; - case 3: // 0x83, lgreen + case 3: // 0x83, green return greenmap; - case 4: // 0x84, blue + case 4: // 0x84, blue return bluemap; - case 5: // 0x85, red + case 5: // 0x85, red return redmap; - case 6: // 0x86, gray + case 6: // 0x86, gray return graymap; - case 7: // 0x87, orange + case 7: // 0x87, orange return orangemap; - case 8: // 0x88, sky + case 8: // 0x88, sky return skymap; + case 9: // 0x89, lavender + return lavendermap; + case 10: // 0x8A, gold + return goldmap; + case 11: // 0x8B, tea-green + return teamap; + case 12: // 0x8C, steel + return steelmap; + case 13: // 0x8D, pink + return pinkmap; + case 14: // 0x8E, teal + return tealmap; + case 15: // 0x8F, peach + return peachmap; default: // reset return NULL; } @@ -1359,7 +1373,7 @@ char *V_WordWrap(INT32 x, INT32 w, INT32 option, const char *string) for (i = 0; i < slen; ++i) { c = newstring[i]; - if ((UINT8)c >= 0x80 && (UINT8)c <= 0x89) //color parsing! -Inuyasha 2.16.09 + if ((UINT8)c >= 0x80 && (UINT8)c <= 0x8F) //color parsing! -Inuyasha 2.16.09 continue; if (c == '\n') @@ -1424,6 +1438,7 @@ void V_DrawString(INT32 x, INT32 y, INT32 option, const char *string) } charflags = (option & V_CHARCOLORMASK); + colormap = V_GetStringColormap(charflags); switch (option & V_SPACINGMASK) { @@ -1447,7 +1462,10 @@ void V_DrawString(INT32 x, INT32 y, INT32 option, const char *string) { // manually set flags override color codes if (!(option & V_CHARCOLORMASK)) + { charflags = ((*ch & 0x7f) << V_CHARCOLORSHIFT) & V_CHARCOLORMASK; + colormap = V_GetStringColormap(charflags); + } continue; } if (*ch == '\n') @@ -1490,7 +1508,6 @@ void V_DrawString(INT32 x, INT32 y, INT32 option, const char *string) continue; } - colormap = V_GetStringColormap(charflags); V_DrawFixedPatch((cx + center)<= 0x80 && (UINT8)c <= 0x89) //color parsing! -Inuyasha 2.16.09 + if ((UINT8)c >= 0x80 && (UINT8)c <= 0x8F) //color parsing! -Inuyasha 2.16.09 continue; c = toupper(c) - HU_FONTSTART; @@ -2192,7 +2218,7 @@ INT32 V_SmallStringWidth(const char *string, INT32 option) for (i = 0; i < strlen(string); i++) { c = string[i]; - if ((UINT8)c >= 0x80 && (UINT8)c <= 0x89) //color parsing! -Inuyasha 2.16.09 + if ((UINT8)c >= 0x80 && (UINT8)c <= 0x8F) //color parsing! -Inuyasha 2.16.09 continue; c = toupper(c) - HU_FONTSTART; @@ -2232,7 +2258,7 @@ INT32 V_ThinStringWidth(const char *string, INT32 option) for (i = 0; i < strlen(string); i++) { c = string[i]; - if ((UINT8)c >= 0x80 && (UINT8)c <= 0x89) //color parsing! -Inuyasha 2.16.09 + if ((UINT8)c >= 0x80 && (UINT8)c <= 0x8F) //color parsing! -Inuyasha 2.16.09 continue; c = toupper(c) - HU_FONTSTART; diff --git a/src/v_video.h b/src/v_video.h index e118d5cfb..f6826cf7b 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -66,8 +66,6 @@ extern UINT8 hudtrans; #define V_MONOSPACE 0x00000C00 // Don't do width checks on characters, all characters 8 width // use bits 13-16 for colors -// though we only have 7 colors now, perhaps we can introduce -// more as needed later #define V_CHARCOLORSHIFT 12 #define V_CHARCOLORMASK 0x0000F000 // for simplicity's sake, shortcuts to specific colors @@ -79,6 +77,13 @@ extern UINT8 hudtrans; #define V_GRAYMAP 0x00006000 #define V_ORANGEMAP 0x00007000 #define V_SKYMAP 0x00008000 +#define V_LAVENDERMAP 0x00009000 +#define V_GOLDMAP 0x0000A000 +#define V_TEAMAP 0x0000B000 +#define V_STEELMAP 0x0000C000 +#define V_PINKMAP 0x0000D000 +#define V_TEALMAP 0x0000E000 +#define V_PEACHMAP 0x0000F000 // use bits 17-20 for alpha transparency #define V_ALPHASHIFT 16 @@ -157,7 +162,7 @@ void V_DrawFadeConsBack(INT32 plines); void V_DrawCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed); // draw a single character, but for the chat void V_DrawChatCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed, UINT8 *colormap); -const UINT8 *V_GetStringColormap(INT32 colorflags); +UINT8 *V_GetStringColormap(INT32 colorflags); void V_DrawLevelTitle(INT32 x, INT32 y, INT32 option, const char *string); From bbed50b73f10f1f528ba7fe72dca8ee0101415ed Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 22 Sep 2018 20:56:44 +0100 Subject: [PATCH 145/146] List update as requested by Sal --- src/hu_stuff.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 33d4f2aaf..ab427b486 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -725,13 +725,13 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) else { const UINT8 color = players[playernum].skincolor; - if (color <= SKINCOLOR_SILVER) + if (color <= SKINCOLOR_SILVER || color == SKINCOLOR_SLATE) cstart = "\x80"; // white else if (color <= SKINCOLOR_BEIGE || color == SKINCOLOR_JET) cstart = "\x86"; // V_GRAYMAP else if (color <= SKINCOLOR_LEATHER) cstart = "\x8A"; // V_GOLDMAP - else if (color <= SKINCOLOR_ROSE || color == SKINCOLOR_RUBY || color == SKINCOLOR_DAWN || color == SKINCOLOR_LILAC) + else if (color <= SKINCOLOR_ROSE || color == SKINCOLOR_LILAC) cstart = "\x8d"; // V_PINKMAP else if (color <= SKINCOLOR_KETCHUP) cstart = "\x85"; // V_REDMAP @@ -741,11 +741,11 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) cstart = "\x8f"; // V_PEACHMAP else if (color <= SKINCOLOR_BRONZE) cstart = "\x8A"; // V_GOLDMAP - else if (color <= SKINCOLOR_MUSTARD || color == SKINCOLOR_LIME) + else if (color <= SKINCOLOR_MUSTARD) cstart = "\x82"; // V_YELLOWMAP else if (color <= SKINCOLOR_PISTACHIO) cstart = "\x8b"; // V_TEAMAP - else if (color <= SKINCOLOR_SWAMP) + else if (color <= SKINCOLOR_SWAMP || color == SKINCOLOR_LIME) cstart = "\x83"; // V_GREENMAP else if (color <= SKINCOLOR_TEAL) cstart = "\x8e"; // V_TEALMAP From a5f8b8ac655431a24d07208e471dbaa6772bf87f Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 22 Sep 2018 21:05:20 +0100 Subject: [PATCH 146/146] Turns out I actually forgot to push this when I did the GL fade colour thing earlier, woops. --- src/hardware/hw_bsp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hardware/hw_bsp.c b/src/hardware/hw_bsp.c index 38a6026fa..e0e4abb4e 100644 --- a/src/hardware/hw_bsp.c +++ b/src/hardware/hw_bsp.c @@ -29,6 +29,7 @@ #include "../m_argv.h" #include "../i_video.h" #include "../w_wad.h" +#include "../p_setup.h" // levelfadecol // -------------------------------------------------------------------------- // This is global data for planes rendering