diff --git a/src/d_main.c b/src/d_main.c index 045d558ed..3936559d5 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -233,7 +233,10 @@ void D_ProcessEvents(void) #endif if (eaten) + { + hu_keystrokes = true; continue; // ate the event + } G_Responder(ev); } diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 8bc1bc905..233252536 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -939,6 +939,7 @@ void D_RegisterClientCommands(void) // g_input.c for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) { + CV_RegisterVar(&cv_kickstartaccel[i]); CV_RegisterVar(&cv_turnaxis[i]); CV_RegisterVar(&cv_moveaxis[i]); CV_RegisterVar(&cv_brakeaxis[i]); @@ -1627,6 +1628,8 @@ void SendWeaponPref(UINT8 n) buf[0] = 0; // Player option cvars that need to be synched go HERE + if (cv_kickstartaccel[n].value) + buf[0] |= 1; SendNetXCmdForPlayer(n, XD_WEAPONPREF, buf, 1); } @@ -1635,11 +1638,13 @@ static void Got_WeaponPref(UINT8 **cp,INT32 playernum) { UINT8 prefs = READUINT8(*cp); - (void)prefs; - (void)playernum; - - //players[playernum].pflags &= ~(PF_FLIPCAM); // Player option cvars that need to be synched go HERE + players[playernum].pflags &= ~(PF_KICKSTARTACCEL); + if (prefs & 1) + players[playernum].pflags |= PF_KICKSTARTACCEL; + + // SEE ALSO g_demo.c + demo_extradata[playernum] |= DXD_WEAPONPREF; } static void Got_PowerLevel(UINT8 **cp,INT32 playernum) @@ -3374,9 +3379,11 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) { if (players[playernum].mo) { - P_DamageMobj(players[playernum].mo, NULL, NULL, 1, DMG_INSTAKILL); + P_DamageMobj(players[playernum].mo, NULL, NULL, 1, + (NetPacket.packet.newteam ? DMG_INSTAKILL : DMG_SPECTATOR)); } - else + //else + if (!NetPacket.packet.newteam) { players[playernum].playerstate = PST_REBORN; } diff --git a/src/d_player.h b/src/d_player.h index 95fd8adea..b055f6d9f 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -67,48 +67,45 @@ typedef enum // True if button down last tic. PF_ATTACKDOWN = 1<<7, - PF_SPINDOWN = 1<<8, - PF_JUMPDOWN = 1<<9, - PF_WPNDOWN = 1<<10, + PF_ACCELDOWN = 1<<8, + PF_BRAKEDOWN = 1<<9, + PF_WPNDOWN = 1<<10, // unused // Unmoving states PF_STASIS = 1<<11, // Player is not allowed to move - PF_JUMPSTASIS = 1<<12, // and that includes jumping. - PF_FULLSTASIS = PF_STASIS|PF_JUMPSTASIS, + PF_JUMPSTASIS = 1<<12, // unused // SRB2Kart: Spectator that wants to join PF_WANTSTOJOIN = 1<<13, // Character action status - PF_STARTJUMP = 1<<14, - PF_JUMPED = 1<<15, - PF_NOJUMPDAMAGE = 1<<16, - - PF_SPINNING = 1<<17, - PF_STARTDASH = 1<<18, - - PF_THOKKED = 1<<19, - PF_SHIELDABILITY = 1<<20, - PF_GLIDING = 1<<21, - PF_BOUNCING = 1<<22, + PF_STARTJUMP = 1<<14, // unused + PF_JUMPED = 1<<15, // unused + PF_NOJUMPDAMAGE = 1<<16, // unused + PF_SPINNING = 1<<17, // unused + PF_STARTDASH = 1<<18, // unused + PF_THOKKED = 1<<19, // unused + PF_SHIELDABILITY = 1<<20, // unused + PF_GLIDING = 1<<21, // unused + PF_BOUNCING = 1<<22, // unused // Sliding (usually in water) like Labyrinth/Oil Ocean PF_SLIDING = 1<<23, // NiGHTS stuff - PF_TRANSFERTOCLOSEST = 1<<24, - PF_DRILLING = 1<<25, + PF_TRANSFERTOCLOSEST = 1<<24, // unused + PF_DRILLING = 1<<25, // unused // Gametype-specific stuff - PF_GAMETYPEOVER = 1<<26, // Race time over, or H&S out-of-game - PF_TAGIT = 1<<27, // The player is it! For Tag Mode + PF_GAMETYPEOVER = 1<<26, // Race time over + PF_TAGIT = 1<<27, // unused /*** misc ***/ - PF_FORCESTRAFE = 1<<28, // Turning inputs are translated into strafing inputs - PF_CANCARRY = 1<<29, // Can carry another player? + PF_KICKSTARTACCEL = 1<<28, // Accessibility feature - is accelerate in kickstart mode? + PF_CANCARRY = 1<<29, // unused PF_HITFINISHLINE = 1<<30, // Already hit the finish line this tic - // up to 1<<31 is free + // up to 1<<31 is free, but try to hit unused stuff first } pflags_t; typedef enum @@ -450,6 +447,9 @@ typedef enum //} +// for kickstartaccel +#define ACCEL_KICKSTART 35 + // player_t struct for all respawn variables typedef struct respawnvars_s { @@ -697,6 +697,11 @@ typedef struct player_s tic_t jointime; // Timer when player joins game to change skin/color tic_t quittime; // Time elapsed since user disconnected, zero if connected + UINT8 typing_timer; // Counts down while keystrokes are not emitted + UINT8 typing_duration; // How long since resumed timer + + UINT8 kickstartaccel; + #ifdef HWRENDER fixed_t fovadd; // adjust FOV for hw rendering #endif diff --git a/src/d_ticcmd.h b/src/d_ticcmd.h index ed72659e5..226c8f4d8 100644 --- a/src/d_ticcmd.h +++ b/src/d_ticcmd.h @@ -26,17 +26,17 @@ // Button/action code definitions. typedef enum { - BT_ACCELERATE = 1, // Accelerate - BT_DRIFT = 1<<2, // Drift (direction is cmd->turning) - BT_BRAKE = 1<<3, // Brake - BT_ATTACK = 1<<4, // Use Item - BT_FORWARD = 1<<5, // Aim Item Forward - BT_BACKWARD = 1<<6, // Aim Item Backward - BT_LOOKBACK = 1<<7, // Look Backward + BT_ACCELERATE = 1, // Accelerate + BT_DRIFT = 1<<2, // Drift (direction is cmd->turning) + BT_BRAKE = 1<<3, // Brake + BT_ATTACK = 1<<4, // Use Item + BT_FORWARD = 1<<5, // Aim Item Forward + BT_BACKWARD = 1<<6, // Aim Item Backward + BT_LOOKBACK = 1<<7, // Look Backward BT_EBRAKEMASK = (BT_ACCELERATE|BT_BRAKE), - // free: 1<<8 to 1<<12 + // free: 1<<9 to 1<<12 // Lua garbage BT_CUSTOM1 = 1<<13, @@ -54,6 +54,8 @@ typedef enum // ticcmd flags #define TICCMD_RECEIVED 1 +#define TICCMD_TYPING 2/* chat window or console open */ +#define TICCMD_KEYSTROKE 4/* chat character input */ #if defined(_MSC_VER) #pragma pack(1) diff --git a/src/dehacked.c b/src/dehacked.c index 5d77e61dc..fb3608849 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -10645,17 +10645,13 @@ static const char *const PLAYERFLAG_LIST[] = { // True if button down last tic. "ATTACKDOWN", - "SPINDOWN", - "JUMPDOWN", + "ACCELDOWN", + "BRAKEDOWN", "WPNDOWN", // Unmoving states "STASIS", // Player is not allowed to move "JUMPSTASIS", // and that includes jumping. - // (we don't include FULLSTASIS here I guess because it's just those two together...?) - - // Did you get a time-over? - "TIMEOVER", // SRB2Kart: spectator that wants to join "WANTSTOJOIN", @@ -10664,10 +10660,8 @@ static const char *const PLAYERFLAG_LIST[] = { "STARTJUMP", "JUMPED", "NOJUMPDAMAGE", - "SPINNING", "STARTDASH", - "THOKKED", "SHIELDABILITY", "GLIDING", @@ -10681,13 +10675,13 @@ static const char *const PLAYERFLAG_LIST[] = { "DRILLING", // Gametype-specific stuff - "GAMETYPEOVER", // Race time over, or H&S out-of-game - "TAGIT", // The player is it! For Tag Mode + "GAMETYPEOVER", // Race time over + "TAGIT", /*** misc ***/ - "FORCESTRAFE", // Translate turn inputs into strafe inputs + "FORCESTRAFE", // Accessibility feature - is accelerate in kickstart mode? + "CANCARRY", "HITFINISHLINE", // Already hit the finish line this tic - "FINISHED", NULL // stop loop here. }; @@ -12183,8 +12177,6 @@ static fixed_t find_const(const char **rword) free(word); return (1<p += 32; // ok (32 because there's both the skin and the colour) if (ziptic & DXD_PLAYSTATE && READUINT8(g->p) != DXD_PST_PLAYING) I_Error("Ghost is not a record attack ghost PLAYSTATE"); //@TODO lmao don't blow up like this + if (ziptic & DXD_WEAPONPREF) + g->p++; // ditto } else if (ziptic == DW_RNG) g->p += 4; // RNG seed @@ -1983,7 +1999,12 @@ void G_BeginRecording(void) if (playeringame[p]) { player = &players[p]; - WRITEUINT8(demo_p, p | (player->spectator ? DEMO_SPECTATOR : 0)); + i = p; + if (player->pflags & PF_KICKSTARTACCEL) + i |= DEMO_KICKSTART; + if (player->spectator) + i |= DEMO_SPECTATOR; + WRITEUINT8(demo_p, i); // Name memset(name, 0, 16); @@ -2903,6 +2924,12 @@ void G_DoPlayDemo(char *defdemoname) while (p != 0xFF) { + players[p].pflags &= ~PF_KICKSTARTACCEL; + if (p & DEMO_KICKSTART) + { + players[p].pflags |= PF_KICKSTARTACCEL; + p &= ~DEMO_KICKSTART; + } spectator = false; if (p & DEMO_SPECTATOR) { @@ -3194,7 +3221,7 @@ void G_AddGhost(char *defdemoname) return; } - if (READUINT8(p) != 0) + if ((READUINT8(p) & ~DEMO_KICKSTART) != 0) { CONS_Alert(CONS_NOTICE, M_GetText("Failed to add ghost %s: Invalid player slot.\n"), pdemoname); Z_Free(pdemoname); diff --git a/src/g_demo.h b/src/g_demo.h index b4039434e..03d75cf4b 100644 --- a/src/g_demo.h +++ b/src/g_demo.h @@ -110,16 +110,17 @@ typedef enum extern UINT8 demo_extradata[MAXPLAYERS]; extern UINT8 demo_writerng; -#define DXD_RESPAWN 0x01 // "respawn" command in console -#define DXD_SKIN 0x02 // skin changed -#define DXD_NAME 0x04 // name changed -#define DXD_COLOR 0x08 // color changed -#define DXD_PLAYSTATE 0x10 // state changed between playing, spectating, or not in-game -#define DXD_FOLLOWER 0x20 // follower was changed +#define DXD_RESPAWN 0x01 // "respawn" command in console +#define DXD_SKIN 0x02 // skin changed +#define DXD_NAME 0x04 // name changed +#define DXD_COLOR 0x08 // color changed +#define DXD_PLAYSTATE 0x10 // state changed between playing, spectating, or not in-game +#define DXD_FOLLOWER 0x20 // follower was changed +#define DXD_WEAPONPREF 0x40 // netsynced playsim settings were changed -#define DXD_PST_PLAYING 0x01 +#define DXD_PST_PLAYING 0x01 #define DXD_PST_SPECTATING 0x02 -#define DXD_PST_LEFT 0x03 +#define DXD_PST_LEFT 0x03 // Record/playback tics void G_ReadDemoExtraData(void); diff --git a/src/g_game.c b/src/g_game.c index 6cc1f9aa2..9a766dc42 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -246,11 +246,11 @@ INT32 gameovertics = 15*TICRATE; UINT8 ammoremovaltics = 2*TICRATE; // SRB2kart -tic_t introtime = 0; -tic_t starttime = 0; +tic_t introtime = 3; +tic_t starttime = 3; const tic_t bulbtime = TICRATE/2; -UINT8 numbulbs = 0; +UINT8 numbulbs = 1; tic_t raceexittime = 5*TICRATE + (2*TICRATE/3); tic_t battleexittime = 8*TICRATE; @@ -342,10 +342,11 @@ INT16 prevmap, nextmap; static UINT8 *savebuffer; -void SendWeaponPref(void); -void SendWeaponPref2(void); -void SendWeaponPref3(void); -void SendWeaponPref4(void); +static void kickstartaccel_OnChange(void); +static void kickstartaccel2_OnChange(void); +static void kickstartaccel3_OnChange(void); +static void kickstartaccel4_OnChange(void); +void SendWeaponPref(UINT8 n); static CV_PossibleValue_t joyaxis_cons_t[] = {{0, "None"}, {1, "X-Axis"}, {2, "Y-Axis"}, {-1, "X-Axis-"}, {-2, "Y-Axis-"}, @@ -405,6 +406,13 @@ consvar_t cv_resetspecialmusic = CVAR_INIT ("resetspecialmusic", "Yes", CV_SAVE, consvar_t cv_resume = CVAR_INIT ("resume", "Yes", CV_SAVE, CV_YesNo, NULL); +consvar_t cv_kickstartaccel[MAXSPLITSCREENPLAYERS] = { + CVAR_INIT ("kickstartaccel", "Off", CV_SAVE|CV_CALL, CV_OnOff, kickstartaccel_OnChange), + CVAR_INIT ("kickstartaccel2", "Off", CV_SAVE|CV_CALL, CV_OnOff, kickstartaccel2_OnChange), + CVAR_INIT ("kickstartaccel3", "Off", CV_SAVE|CV_CALL, CV_OnOff, kickstartaccel3_OnChange), + CVAR_INIT ("kickstartaccel4", "Off", CV_SAVE|CV_CALL, CV_OnOff, kickstartaccel4_OnChange) +}; + consvar_t cv_turnaxis[MAXSPLITSCREENPLAYERS] = { CVAR_INIT ("joyaxis_turn", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL), CVAR_INIT ("joyaxis2_turn", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL), @@ -1003,7 +1011,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) { // forward with key or button // SRB2kart - we use an accel/brake instead of forward/backward. axis = PlayerJoyAxis(ssplayer, AXISMOVE); - if (PlayerInputDown(ssplayer, gc_accelerate) || (gamepadjoystickmove && axis > 0) || player->kartstuff[k_sneakertimer]) + if (PlayerInputDown(ssplayer, gc_accelerate) || (gamepadjoystickmove && axis > 0)) { cmd->buttons |= BT_ACCELERATE; forward = MAXPLMOVE; // 50 @@ -1120,6 +1128,16 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) cmd->latency = modeattacking ? 0 : (leveltime & 0xFF); // Send leveltime when this tic was generated to the server for control lag calculations cmd->flags = 0; + if (chat_on || CON_Ready()) + { + cmd->flags |= TICCMD_TYPING; + + if (hu_keystrokes) + { + cmd->flags |= TICCMD_KEYSTROKE; + } + } + /* Lua: Allow this hook to overwrite ticcmd. We check if we're actually in a level because for some reason this Hook would run in menus and on the titlescreen otherwise. Be aware that within this hook, nothing but this player's cmd can be edited (otherwise we'd run in some pretty bad synching problems since this is clientsided, or something) @@ -1174,6 +1192,26 @@ ticcmd_t *G_MoveTiccmd(ticcmd_t* dest, const ticcmd_t* src, const size_t n) return dest; } +static void kickstartaccel_OnChange(void) +{ + SendWeaponPref(0); +} + +static void kickstartaccel2_OnChange(void) +{ + SendWeaponPref(1); +} + +static void kickstartaccel3_OnChange(void) +{ + SendWeaponPref(2); +} + +static void kickstartaccel4_OnChange(void) +{ + SendWeaponPref(3); +} + // // G_DoLoadLevel // @@ -1357,7 +1395,10 @@ boolean G_Responder(event_t *ev) if (gamestate == GS_LEVEL) { if (HU_Responder(ev)) + { + hu_keystrokes = true; return true; // chat ate the event + } if (AM_Responder(ev)) return true; // automap ate it // map the event (key/mouse/joy) to a gamecontrol @@ -1374,7 +1415,10 @@ boolean G_Responder(event_t *ev) else if (gamestate == GS_CUTSCENE) { if (HU_Responder(ev)) + { + hu_keystrokes = true; return true; // chat ate the event + } if (F_CutsceneResponder(ev)) { @@ -1385,7 +1429,10 @@ boolean G_Responder(event_t *ev) else if (gamestate == GS_CREDITS || gamestate == GS_ENDING) // todo: keep ending here? { if (HU_Responder(ev)) + { + hu_keystrokes = true; return true; // chat ate the event + } if (F_CreditResponder(ev)) { @@ -1408,7 +1455,10 @@ boolean G_Responder(event_t *ev) } else if (gamestate == GS_INTERMISSION || gamestate == GS_VOTING || gamestate == GS_EVALUATION) if (HU_Responder(ev)) + { + hu_keystrokes = true; return true; // chat ate the event + } // allow spy mode changes even during the demo if (gamestate == GS_LEVEL && ev->type == ev_keydown @@ -2084,6 +2134,9 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) INT32 wanted; boolean songcredit = false; boolean eliminated; + UINT16 nocontrol; + INT32 khudfault; + INT32 kickstartaccel; score = players[player].score; marescore = players[player].marescore; @@ -2099,7 +2152,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) splitscreenindex = players[player].splitscreenindex; spectator = players[player].spectator; - pflags = (players[player].pflags & (PF_WANTSTOJOIN|PF_GAMETYPEOVER|PF_FAULT)); + pflags = (players[player].pflags & (PF_WANTSTOJOIN|PF_GAMETYPEOVER|PF_FAULT|PF_KICKSTARTACCEL)); playerangleturn = players[player].angleturn; // As long as we're not in multiplayer, carry over cheatcodes from map to map @@ -2153,6 +2206,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) spheres = 0; eliminated = false; wanted = 0; + kickstartaccel = 0; } else { @@ -2181,8 +2235,17 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) spheres = players[player].spheres; eliminated = players[player].eliminated; wanted = players[player].kartstuff[k_wanted]; + kickstartaccel = players[player].kickstartaccel; } + if (!betweenmaps) + { + khudfault = players[player].karthud[khud_fault]; + nocontrol = players[player].powers[pw_nocontrol]; + } + else + khudfault = nocontrol = 0; + // Obliterate follower from existence P_SetTarget(&players[player].follower, NULL); @@ -2244,6 +2307,9 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) p->kartstuff[k_wanted] = wanted; p->kartstuff[k_eggmanblame] = -1; p->kartstuff[k_lastdraft] = -1; + p->karthud[khud_fault] = khudfault; + p->powers[pw_nocontrol] = nocontrol; + p->kickstartaccel = kickstartaccel; memcpy(&p->respawn, &respawn, sizeof (p->respawn)); @@ -2258,9 +2324,9 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) // Don't do anything immediately - p->pflags |= PF_SPINDOWN; + p->pflags |= PF_BRAKEDOWN; p->pflags |= PF_ATTACKDOWN; - p->pflags |= PF_JUMPDOWN; + p->pflags |= PF_ACCELDOWN; p->playerstate = PST_LIVE; p->panim = PA_STILL; // standing animation @@ -2297,6 +2363,9 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) if (betweenmaps) return; + if (leveltime < starttime) + return; + if (p-players == consoleplayer) { if (mapmusflags & MUSIC_RELOADRESET) @@ -2319,11 +2388,6 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) if (songcredit) S_ShowMusicCredit(); - - if (leveltime > (starttime + (TICRATE/2)) && !p->spectator) - { - K_DoIngameRespawn(p); - } } // @@ -2385,10 +2449,17 @@ void G_SpawnPlayer(INT32 playernum) void G_MovePlayerToSpawnOrStarpost(INT32 playernum) { +#if 0 + if (leveltime <= introtime && !players[playernum].spectator) + P_MovePlayerToSpawn(playernum, G_FindMapStart(playernum)); + else + P_MovePlayerToStarpost(playernum); +#else if (leveltime > starttime) P_MovePlayerToStarpost(playernum); else P_MovePlayerToSpawn(playernum, G_FindMapStart(playernum)); +#endif } mapthing_t *G_FindTeamStart(INT32 playernum) @@ -4407,7 +4478,7 @@ void G_InitNew(UINT8 pencoremode, const char *mapname, boolean resetplayer, bool memset(&players[i].respawn, 0, sizeof (players[i].respawn)); // The latter two should clear by themselves, but just in case - players[i].pflags &= ~(PF_GAMETYPEOVER|PF_FULLSTASIS|PF_FAULT); + players[i].pflags &= ~(PF_GAMETYPEOVER|PF_STASIS|PF_FAULT); // Clear cheatcodes too, just in case. players[i].pflags &= ~(PF_GODMODE|PF_NOCLIP|PF_INVIS); diff --git a/src/g_game.h b/src/g_game.h index 89156b82f..28321adc5 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -57,6 +57,7 @@ extern consvar_t cv_pauseifunfocused; extern consvar_t cv_invertmouse; +extern consvar_t cv_kickstartaccel[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_turnaxis[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_moveaxis[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_brakeaxis[MAXSPLITSCREENPLAYERS]; diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index 73ba81c58..aa7338ad2 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -478,7 +478,7 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex) #ifdef GLENCORE if (encoremap) - grtex->mipmap.colormap += (256*32); + grtex->mipmap.colormap += COLORMAP_REMAPOFFSET; #endif blockwidth = texture->width; @@ -833,7 +833,7 @@ void HWR_LiterallyGetFlat(lumpnum_t flatlumpnum, boolean noencoremap) #ifdef GLENCORE if (!noencoremap && encoremap) - grmip->colormap += (256*32); + grmip->colormap += COLORMAP_REMAPOFFSET; #endif grmip = HWR_GetCachedGLPatch(flatlumpnum)->mipmap; diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index 9cb48620e..3752cbf05 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -219,7 +219,8 @@ enum EPolyFlags PF_Substractive = 0x00000010, // for splat PF_NoAlphaTest = 0x00000020, // hiden param PF_Fog = 0x00000040, // Fog blocks - PF_Blending = (PF_Environment|PF_Additive|PF_Translucent|PF_Masked|PF_Substractive|PF_Fog)&~PF_NoAlphaTest, + PF_Invert = 0x00000080, // Polygon inverts the colours of what it's in front of + PF_Blending = (PF_Environment|PF_Additive|PF_Translucent|PF_Masked|PF_Substractive|PF_Fog|PF_Invert)&~PF_NoAlphaTest, // other flag bits diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index 69f37a29b..d3812983e 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -697,6 +697,27 @@ void HWR_DrawConsoleBack(UINT32 color, INT32 height) HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); } +void HWR_EncoreInvertScreen(void) +{ + FOutVector v[4]; + FSurfaceInfo Surf; + + v[0].x = v[3].x = -1.0f; + v[2].x = v[1].x = 1.0f; + v[0].y = v[1].y = -1.0f; + v[2].y = v[3].y = 1.0f; + v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; + + v[0].s = v[3].s = 0.0f; + v[2].s = v[1].s = 1.0f; + v[0].t = v[1].t = 1.0f; + v[2].t = v[3].t = 0.0f; + + Surf.PolyColor.rgba = 0xFFFFFFFF; + + HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Invert|PF_NoDepthTest); +} + // Very similar to HWR_DrawConsoleBack, except we draw from the middle(-ish) of the screen to the bottom. void HWR_DrawTutorialBack(UINT32 color, INT32 boxheight) { diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index c299d9c87..4c06c8604 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5224,7 +5224,7 @@ static void HWR_ProjectSprite(mobj_t *thing) vis->colormap = colormaps; #ifdef GLENCORE if (encoremap && (thing->flags & (MF_SCENERY|MF_NOTHINK)) && !(thing->flags & MF_DONTENCOREMAP)) - vis->colormap += (256*32); + vis->colormap += COLORMAP_REMAPOFFSET; #endif } @@ -5331,7 +5331,7 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) #ifdef GLENCORE if (encoremap && !(thing->flags & MF_DONTENCOREMAP)) - vis->colormap += (256*32); + vis->colormap += COLORMAP_REMAPOFFSET; #endif // set top/bottom coords @@ -5526,6 +5526,11 @@ static void HWR_DrawSkyBackground(player_t *player) else dometransform.flip = false; + if (*type == postimg_mirror) + dometransform.mirror = true; + else + dometransform.mirror = false; + dometransform.scalex = 1; dometransform.scaley = (float)vid.width/vid.height; dometransform.scalez = 1; @@ -5802,6 +5807,11 @@ void HWR_RenderSkyboxView(player_t *player) else atransform.flip = false; + if (*type == postimg_mirror) + atransform.mirror = true; + else + atransform.mirror = false; + atransform.x = gl_viewx; // FIXED_TO_FLOAT(viewx) atransform.y = gl_viewy; // FIXED_TO_FLOAT(viewy) atransform.z = gl_viewz; // FIXED_TO_FLOAT(viewz) @@ -6005,6 +6015,11 @@ void HWR_RenderPlayerView(void) else atransform.flip = false; + if (*type == postimg_mirror) + atransform.mirror = true; + else + atransform.mirror = false; + atransform.x = gl_viewx; // FIXED_TO_FLOAT(viewx) atransform.y = gl_viewy; // FIXED_TO_FLOAT(viewy) atransform.z = gl_viewz; // FIXED_TO_FLOAT(viewz) diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index 3efeca45b..dfefc2a2f 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -28,6 +28,7 @@ void HWR_Shutdown(void); void HWR_drawAMline(const fline_t *fl, INT32 color); void HWR_FadeScreenMenuBack(UINT16 color, UINT8 strength); void HWR_DrawConsoleBack(UINT32 color, INT32 height); +void HWR_EncoreInvertScreen(void); void HWR_DrawTutorialBack(UINT32 color, INT32 boxheight); void HWR_RenderSkyboxView(player_t *player); void HWR_RenderPlayerView(void); diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 9e9bbee81..ceea6558d 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -1599,6 +1599,10 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags) pglBlendFunc(GL_SRC_ALPHA, GL_SRC_COLOR); pglAlphaFunc(GL_ALWAYS, 0.0f); // Don't discard zero alpha fragments break; + case PF_Invert & PF_Invert: + pglBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO); + pglAlphaFunc(GL_GREATER, 0.5f); + break; default : // must be 0, otherwise it's an error // No blending pglBlendFunc(GL_ONE, GL_ZERO); // the same as no blending diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 35f977bd6..2e6ff3600 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -78,6 +78,7 @@ patch_t *frameslash; // framerate stuff. Used in screen.c static player_t *plr; boolean chat_on; // entering a chat message? +boolean hu_keystrokes; // :) static char w_chat[HU_MAXMSGLEN]; static size_t c_input = 0; // let's try to make the chat input less shitty. static boolean headsupactive = false; @@ -879,6 +880,8 @@ void HU_Ticker(void) hu_showscores = !chat_on; else hu_showscores = false; + + hu_keystrokes = false; } #ifndef NONET diff --git a/src/hu_stuff.h b/src/hu_stuff.h index afbbe7b73..6a425926b 100644 --- a/src/hu_stuff.h +++ b/src/hu_stuff.h @@ -94,6 +94,9 @@ void HU_AddChatText(const char *text, boolean playsound); // set true when entering a chat message extern boolean chat_on; +// keystrokes in the console or chat window +extern boolean hu_keystrokes; + extern patch_t *pinggfx[5]; extern patch_t *framecounter; extern patch_t *frameslash; diff --git a/src/k_bot.c b/src/k_bot.c index 331309f9a..1abe44913 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -237,6 +237,8 @@ void K_UpdateMatchRaceBots(void) while (numbots > wantedbots && i > 0) { + i--; + if (playeringame[i] && players[i].bot) { buf[0] = i; @@ -245,8 +247,6 @@ void K_UpdateMatchRaceBots(void) numbots--; } - - i--; } } diff --git a/src/k_hud.c b/src/k_hud.c index 87cda81cc..b40c16ae0 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -133,6 +133,9 @@ static patch_t *kp_check[6]; static patch_t *kp_rival[2]; static patch_t *kp_localtag[4][2]; +static patch_t *kp_talk; +static patch_t *kp_typdot; + static patch_t *kp_eggnum[4]; static patch_t *kp_flameshieldmeter[104][2]; @@ -503,6 +506,10 @@ void K_LoadKartHUDGraphics(void) } } + // Typing indicator + kp_talk = W_CachePatchName("K_TALK", PU_HUDGFX); + kp_typdot = W_CachePatchName("K_TYPDOT", PU_HUDGFX); + // Eggman warning numbers sprintf(buffer, "K_EGGNx"); for (i = 0; i < 4; i++) @@ -816,7 +823,7 @@ void K_ObjectTracking(trackingResult_t *result, vector3_t *point, UINT8 cameraNu return; } - if (cam->chase == true) + if (cam->chase == true && !player->spectator) { // Use the camera's properties. viewpointX = cam->x; @@ -2193,6 +2200,63 @@ static void K_drawKartLapsAndRings(void) #undef RINGANIM_FLIPFRAME +static void K_drawKartAccessibilityIcons(INT32 fx) +{ + INT32 fy = LAPS_Y-25; + UINT8 col = 0, i, wid, fil; + INT32 splitflags = V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_SPLITSCREEN; + //INT32 step = 1; -- if there's ever more than one accessibility icon + + fx += LAPS_X; + + if (r_splitscreen < 2) // adjust to speedometer height + { + if (gametype == GT_BATTLE) + fy -= 4; + } + else + { + fy += 4; + if (!(stplyr == &players[displayplayers[0]] || stplyr == &players[displayplayers[2]])) // If we are not P1 or P3... + { + splitflags ^= (V_SNAPTOLEFT|V_SNAPTORIGHT); + fx = (BASEVIDWIDTH/2) - (fx + 10); + //step = -step; + } + } + + if (stplyr->pflags & PF_KICKSTARTACCEL) // just KICKSTARTACCEL right now, maybe more later + { + fil = 7-(stplyr->kickstartaccel*7)/ACCEL_KICKSTART; + i = 7; + + V_DrawFill(fx+4, fy-1, 2, 1, 31|V_SLIDEIN|splitflags); + V_DrawFill(fx, (fy-1)+8, 10, 1, 31|V_SLIDEIN|splitflags); + + while (i--) + { + wid = (i/2)+1; + V_DrawFill(fx+4-wid, fy+i, 2+(wid*2), 1, 31|V_SLIDEIN|splitflags); + if (fil) + { + if (i < fil) + col = 23; + else if (i == fil) + col = 3; + else + col = 5 + (i-fil)*2; + } + else if ((leveltime % 7) == i) + col = 0; + else + col = 3; + V_DrawFill(fx+5-wid, fy+i, (wid*2), 1, col|V_SLIDEIN|splitflags); + } + + //fx += step*12; + } +} + static void K_drawKartSpeedometer(void) { static fixed_t convSpeed; @@ -2242,6 +2306,8 @@ static void K_drawKartSpeedometer(void) V_DrawScaledPatch(LAPS_X+13, LAPS_Y-25 + battleoffset, V_HUDTRANS|V_SLIDEIN|splitflags, kp_facenum[numbers[1]]); V_DrawScaledPatch(LAPS_X+19, LAPS_Y-25 + battleoffset, V_HUDTRANS|V_SLIDEIN|splitflags, kp_facenum[numbers[2]]); V_DrawScaledPatch(LAPS_X+29, LAPS_Y-25 + battleoffset, V_HUDTRANS|V_SLIDEIN|splitflags, kp_speedometerlabel[labeln]); + + K_drawKartAccessibilityIcons(56); } static void K_drawBlueSphereMeter(void) @@ -2598,6 +2664,27 @@ static void K_DrawRivalTagForPlayer(fixed_t x, fixed_t y) V_DrawFixedPatch(x, y, FRACUNIT, V_HUDTRANS|V_SPLITSCREEN, kp_rival[blink], NULL); } +static void K_DrawTypingDot(fixed_t x, fixed_t y, UINT8 duration, player_t *p) +{ + if (p->typing_duration > duration) + { + V_DrawFixedPatch(x, y, FRACUNIT, V_HUDTRANS|V_SPLITSCREEN, kp_typdot, NULL); + } +} + +static void K_DrawTypingNotifier(fixed_t x, fixed_t y, player_t *p) +{ + if (p->cmd.flags & TICCMD_TYPING) + { + V_DrawFixedPatch(x, y, FRACUNIT, V_HUDTRANS|V_SPLITSCREEN, kp_talk, NULL); + + /* spacing closer with the last two looks a better most of the time */ + K_DrawTypingDot(x + 3*FRACUNIT, y, 15, p); + K_DrawTypingDot(x + 6*FRACUNIT - FRACUNIT/3, y, 31, p); + K_DrawTypingDot(x + 9*FRACUNIT - FRACUNIT/3, y, 47, p); + } +} + static void K_DrawNameTagForPlayer(fixed_t x, fixed_t y, player_t *p, UINT8 cnum) { const INT32 clr = skincolors[p->skincolor].chatcolor; @@ -2840,6 +2927,7 @@ static void K_drawKartNameTags(void) if (K_ShowPlayerNametag(ntplayer) == true) { K_DrawNameTagForPlayer(result.x, result.y, ntplayer, cnum); + K_DrawTypingNotifier(result.x, result.y, ntplayer); } } } @@ -3632,7 +3720,27 @@ static void K_drawKartFirstPerson(void) const angle_t ang = R_PointToAngle2(0, 0, stplyr->rmomx, stplyr->rmomy) - stplyr->drawangle; // yes, the following is correct. no, you do not need to swap the x and y. fixed_t xoffs = -P_ReturnThrustY(stplyr->mo, ang, (BASEVIDWIDTH<<(FRACBITS-2))/2); - fixed_t yoffs = -(P_ReturnThrustX(stplyr->mo, ang, 4*FRACUNIT) - 4*FRACUNIT); + fixed_t yoffs = -P_ReturnThrustX(stplyr->mo, ang, 4*FRACUNIT); + + // hitlag vibrating + if (stplyr->mo->hitlag > 0) + { + fixed_t mul = stplyr->mo->hitlag * (FRACUNIT / 10); + if (r_splitscreen && mul > FRACUNIT) + mul = FRACUNIT; + + if (leveltime & 1) + { + mul = -mul; + } + + xoffs = FixedMul(xoffs, mul); + yoffs = FixedMul(yoffs, mul); + + } + + if ((yoffs += 4*FRACUNIT) < 0) + yoffs = 0; if (r_splitscreen) xoffs = FixedMul(xoffs, scale); @@ -4125,13 +4233,6 @@ void K_drawKartHUD(void) if (!stplyr->spectator && !demo.freecam) // Bottom of the screen elements, don't need in spectate mode { - // Draw the speedometer - if (cv_kartspeedometer.value && !r_splitscreen) - { - if (LUA_HudEnabled(hud_speedometer)) - K_drawKartSpeedometer(); - } - if (demo.title) // Draw title logo instead in demo.titles { INT32 x = BASEVIDWIDTH - 32, y = 128, offs; @@ -4182,6 +4283,16 @@ void K_drawKartHUD(void) K_drawKartBumpersOrKarma(); } + // Draw the speedometer and/or accessibility icons + if (cv_kartspeedometer.value && !r_splitscreen && (LUA_HudEnabled(hud_speedometer))) + { + K_drawKartSpeedometer(); + } + else + { + K_drawKartAccessibilityIcons((r_splitscreen > 1) ? 0 : 8); + } + if (gametyperules & GTR_SPHERES) { K_drawBlueSphereMeter(); diff --git a/src/k_kart.c b/src/k_kart.c index 4d5e1770e..6621042d8 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -43,6 +43,63 @@ // indirectitemcooldown is timer before anyone's allowed another Shrink/SPB // mapreset is set when enough players fill an empty server +void K_TimerReset(void) +{ + starttime = introtime = 3; + numbulbs = 1; +} + +void K_TimerInit(void) +{ + UINT8 i; + UINT8 numPlayers = 0; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + { + continue; + } + + if (players[i].spectator == true) + { + continue; + } + + numPlayers++; + } + + if (numPlayers >= 2) + { + rainbowstartavailable = true; + } + else + { + rainbowstartavailable = false; + } + + if (numPlayers <= 2) + { + introtime = 0; // No intro in Record Attack / 1v1 + } + else + { + introtime = (108) + 5; // 108 for rotation, + 5 for white fade + } + + numbulbs = 5; + + if (numPlayers > 2) + { + numbulbs += (numPlayers-2); + } + + starttime = (introtime + (3*TICRATE)) + ((2*TICRATE) + (numbulbs * bulbtime)); // Start countdown time, + buffer time + + // NOW you can try to spawn in the Battle capsules, if there's not enough players for a match + K_SpawnBattleCapsules(); +} + UINT16 K_GetPlayerDontDrawFlag(player_t *player) { UINT16 flag = 0; @@ -1845,19 +1902,19 @@ void K_KartMoveAnimation(player_t *player) const boolean onground = P_IsObjectOnGround(player->mo); - ticcmd_t *cmd = &player->cmd; - const boolean spinningwheels = (((cmd->buttons & BT_ACCELERATE) == BT_ACCELERATE) || (onground && player->speed > 0)); - const boolean lookback = ((cmd->buttons & BT_LOOKBACK) == BT_LOOKBACK); + UINT16 buttons = K_GetKartButtons(player); + const boolean spinningwheels = (((buttons & BT_ACCELERATE) == BT_ACCELERATE) || (onground && player->speed > 0)); + const boolean lookback = ((buttons & BT_LOOKBACK) == BT_LOOKBACK); SINT8 turndir = 0; SINT8 destGlanceDir = 0; SINT8 drift = player->kartstuff[k_drift]; - if (cmd->turning < -minturn) + if (player->cmd.turning < -minturn) { turndir = -1; } - else if (cmd->turning > minturn) + else if (player->cmd.turning > minturn) { turndir = 1; } @@ -2526,6 +2583,19 @@ UINT16 K_GetKartFlashing(player_t *player) return tics; } +boolean K_KartKickstart(player_t *player) +{ + return ((player->pflags & PF_KICKSTARTACCEL) + && (!K_PlayerUsesBotMovement(player)) + && (player->kickstartaccel >= ACCEL_KICKSTART)); +} + +UINT16 K_GetKartButtons(player_t *player) +{ + return (player->cmd.buttons | + (K_KartKickstart(player) ? BT_ACCELERATE : 0)); +} + SINT8 K_GetForwardMove(player_t *player) { SINT8 forwardmove = player->cmd.forwardmove; @@ -2545,6 +2615,13 @@ SINT8 K_GetForwardMove(player_t *player) return 0; } + if (K_KartKickstart(player)) // unlike the brute forward of sneakers, allow for backwards easing here + { + forwardmove += MAXPLMOVE; + if (forwardmove > MAXPLMOVE) + forwardmove = MAXPLMOVE; + } + return forwardmove; } @@ -5575,7 +5652,7 @@ player_t *K_FindJawzTarget(mobj_t *actor, player_t *source) } // Engine Sounds. -static void K_UpdateEngineSounds(player_t *player, ticcmd_t *cmd) +static void K_UpdateEngineSounds(player_t *player) { const INT32 numsnds = 13; @@ -5584,6 +5661,8 @@ static void K_UpdateEngineSounds(player_t *player, ticcmd_t *cmd) const UINT8 dampenval = 48; // 255 * 48 = close enough to FRACUNIT/6 + const UINT16 buttons = K_GetKartButtons(player); + INT32 class, s, w; // engine class number UINT8 volume = 255; @@ -5624,17 +5703,17 @@ static void K_UpdateEngineSounds(player_t *player, ticcmd_t *cmd) if (player->respawn.state == RESPAWNST_DROP) // Dropdashing { // Dropdashing - targetsnd = ((cmd->buttons & BT_ACCELERATE) ? 12 : 0); + targetsnd = ((buttons & BT_ACCELERATE) ? 12 : 0); } else if (K_PlayerEBrake(player) == true) { // Spindashing - targetsnd = ((cmd->buttons & BT_DRIFT) ? 12 : 0); + targetsnd = ((buttons & BT_DRIFT) ? 12 : 0); } else { // Average out the value of forwardmove and the speed that you're moving at. - targetsnd = (((6 * cmd->forwardmove) / 25) + ((player->speed / mapobjectscale) / 5)) / 2; + targetsnd = (((6 * K_GetForwardMove(player)) / 25) + ((player->speed / mapobjectscale) / 5)) / 2; } if (targetsnd < 0) { targetsnd = 0; } @@ -5932,7 +6011,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) { K_UpdateOffroad(player); K_UpdateDraft(player); - K_UpdateEngineSounds(player, cmd); // Thanks, VAda! + K_UpdateEngineSounds(player); // Thanks, VAda! // update boost angle if not spun out if (!player->kartstuff[k_spinouttimer] && !player->kartstuff[k_wipeoutslow]) @@ -6156,15 +6235,13 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->karthud[khud_timeovercam] = 0; - // Specific hack because it insists on setting flashing tics during this anyway... - if (( player->kartstuff[k_spinouttype] & KSPIN_IFRAMES ) == 0) - { - player->powers[pw_flashing] = 0; - } // Make ABSOLUTELY SURE that your flashing tics don't get set WHILE you're still in hit animations. - else if (player->kartstuff[k_spinouttimer] != 0 || player->kartstuff[k_wipeoutslow] != 0) + if (player->kartstuff[k_spinouttimer] != 0 || player->kartstuff[k_wipeoutslow] != 0) { - player->powers[pw_flashing] = K_GetKartFlashing(player); + if (( player->kartstuff[k_spinouttype] & KSPIN_IFRAMES ) == 0) + player->powers[pw_flashing] = 0; + else + player->powers[pw_flashing] = K_GetKartFlashing(player); } if (player->kartstuff[k_spinouttimer]) @@ -6414,7 +6491,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (cmd->buttons & BT_DRIFT) { // Only allow drifting while NOT trying to do an spindash input. - if ((cmd->buttons & BT_EBRAKEMASK) != BT_EBRAKEMASK) + if ((K_GetKartButtons(player) & BT_EBRAKEMASK) != BT_EBRAKEMASK) { player->driftInput = true; } @@ -6553,8 +6630,12 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player) if (bestwaypoint == K_GetFinishLineWaypoint()) { + waypoint_t *nextwaypoint = waypoint->nextwaypoints[0]; + angle_t angletonextwaypoint = + R_PointToAngle2(waypoint->mobj->x, waypoint->mobj->y, nextwaypoint->mobj->x, nextwaypoint->mobj->y); + // facing towards the finishline - if (angledelta <= ANGLE_90) + if (abs(AngleDifference(angletonextwaypoint, angletowaypoint)) <= ANGLE_90) { finishlinehack = true; } @@ -6698,6 +6779,7 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player) return bestwaypoint; } +#if 0 static boolean K_PlayerCloserToNextWaypoints(waypoint_t *const waypoint, player_t *const player) { boolean nextiscloser = true; @@ -6758,6 +6840,7 @@ static boolean K_PlayerCloserToNextWaypoints(waypoint_t *const waypoint, player_ return nextiscloser; } +#endif /*-------------------------------------------------- void K_UpdateDistanceFromFinishLine(player_t *const player) @@ -6837,6 +6920,7 @@ void K_UpdateDistanceFromFinishLine(player_t *const player) player->distancetofinish += numfulllapsleft * K_GetCircuitLength(); +#if 0 // An additional HACK, to fix looking backwards towards the finish line // If the player's next waypoint is the finishline and the angle distance from player to // connectin waypoints implies they're closer to a next waypoint, add a full track distance @@ -6847,6 +6931,7 @@ void K_UpdateDistanceFromFinishLine(player_t *const player) player->distancetofinish += K_GetCircuitLength(); } } +#endif } } } @@ -6951,10 +7036,15 @@ INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue) return 0; } + if (player->respawn.state == RESPAWNST_MOVE) + { + return 0; + } + currentSpeed = R_PointToDist2(0, 0, player->mo->momx, player->mo->momy); if ((currentSpeed <= 0) // Not moving - && ((player->cmd.buttons & BT_EBRAKEMASK) != BT_EBRAKEMASK) // not e-braking + && ((K_GetKartButtons(player) & BT_EBRAKEMASK) != BT_EBRAKEMASK) // not e-braking && (player->respawn.state == RESPAWNST_NONE)) // Not respawning { return 0; @@ -7058,6 +7148,8 @@ static void K_KartDrift(player_t *player, boolean onground) const INT32 dstwo = dsone*2; const INT32 dsthree = dstwo*2; + const UINT16 buttons = K_GetKartButtons(player); + // Drifting is actually straffing + automatic turning. // Holding the Jump button will enable drifting. // (This comment is extremely funny) @@ -7264,8 +7356,8 @@ static void K_KartDrift(player_t *player, boolean onground) K_SpawnAIZDust(player); if (player->kartstuff[k_drift] - && ((player->cmd.buttons & BT_BRAKE) - || !(player->cmd.buttons & BT_ACCELERATE)) + && ((buttons & BT_BRAKE) + || !(buttons & BT_ACCELERATE)) && P_IsObjectOnGround(player->mo)) { if (!player->kartstuff[k_brakedrift]) @@ -7439,7 +7531,7 @@ static INT32 K_FlameShieldMax(player_t *player) boolean K_PlayerEBrake(player_t *player) { - return (player->cmd.buttons & BT_EBRAKEMASK) == BT_EBRAKEMASK + return (K_GetKartButtons(player) & BT_EBRAKEMASK) == BT_EBRAKEMASK && P_IsObjectOnGround(player->mo) == true && player->kartstuff[k_drift] == 0 && player->kartstuff[k_spinouttimer] == 0 @@ -7622,8 +7714,6 @@ static void K_AirFailsafe(player_t *player) const fixed_t maxSpeed = 6*player->mo->scale; const fixed_t thrustSpeed = 6*player->mo->scale; // 10*player->mo->scale - ticcmd_t *cmd = &player->cmd; - if (player->speed > maxSpeed // Above the max speed that you're allowed to use this technique. || player->respawn.state != RESPAWNST_NONE) // Respawning, you don't need this AND drop dash :V { @@ -7631,7 +7721,7 @@ static void K_AirFailsafe(player_t *player) return; } - if ((cmd->buttons & BT_ACCELERATE) || K_GetForwardMove(player) != 0) + if ((K_GetKartButtons(player) & BT_ACCELERATE) || K_GetForwardMove(player) != 0) { // Queue up later player->airFailsafe = true; @@ -7673,7 +7763,7 @@ void K_AdjustPlayerFriction(player_t *player) { player->mo->friction -= 1024; } - else if (player->speed > 0 && cmd->forwardmove < 0) + else if (player->speed > 0 && K_GetForwardMove(player) < 0) { player->mo->friction -= 512; } diff --git a/src/k_kart.h b/src/k_kart.h index 9b92fff7c..c91bba806 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -17,6 +17,8 @@ angle_t K_ReflectAngle(angle_t angle, angle_t against, fixed_t maxspeed, fixed_t void K_RegisterKartStuff(void); +void K_TimerReset(void); +void K_TimerInit(void); UINT16 K_GetPlayerDontDrawFlag(player_t *player); boolean K_IsPlayerLosing(player_t *player); fixed_t K_GetKartGameSpeedScalar(SINT8 value); @@ -89,6 +91,8 @@ fixed_t K_GetKartSpeedFromStat(UINT8 kartspeed); fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower); fixed_t K_GetKartAccel(player_t *player); UINT16 K_GetKartFlashing(player_t *player); +boolean K_KartKickstart(player_t *player); +UINT16 K_GetKartButtons(player_t *player); SINT8 K_GetForwardMove(player_t *player); fixed_t K_3dKartMovement(player_t *player); boolean K_PlayerEBrake(player_t *player); diff --git a/src/k_respawn.c b/src/k_respawn.c index 7052fe466..6018c2e54 100644 --- a/src/k_respawn.c +++ b/src/k_respawn.c @@ -54,6 +54,21 @@ fixed_t K_RespawnOffset(player_t *player, boolean flip) return z; } +/*-------------------------------------------------- + static void K_FudgeRespawn(player_t *player, const waypoint_t *const waypoint) + + Fudges respawn coordinates to slightly before the waypoint if it would + be exactly on a line. See K_GetWaypointIsOnLine. +--------------------------------------------------*/ +static void K_FudgeRespawn(player_t *player, const waypoint_t *const waypoint) +{ + const angle_t from = R_PointToAngle2(waypoint->mobj->x, waypoint->mobj->y, + player->mo->x, player->mo->y) >> ANGLETOFINESHIFT; + + player->respawn.pointx += FixedMul(16, FINECOSINE(from)); + player->respawn.pointy += FixedMul(16, FINESINE(from)); +} + /*-------------------------------------------------- static void K_RespawnAtWaypoint(player_t *player, waypoint_t *waypoint) @@ -83,6 +98,28 @@ static void K_RespawnAtWaypoint(player_t *player, waypoint_t *waypoint) player->respawn.pointz = waypoint->mobj->z; player->respawn.flip = (waypoint->mobj->flags2 & MF2_OBJECTFLIP) ? true : false; // K_RespawnOffset wants a boolean! player->respawn.pointz += K_RespawnOffset(player, player->respawn.flip); + + if (waypoint->onaline) + { + K_FudgeRespawn(player, waypoint); + } +} + +/*-------------------------------------------------- + void K_DoFault(player_t *player) + + See header file for description. +--------------------------------------------------*/ + +void K_DoFault(player_t *player) +{ + player->powers[pw_nocontrol] = (starttime - leveltime) + 50; + if (!(player->pflags & PF_FAULT)) + { + S_StartSound(player->mo, sfx_s3k83); + player->karthud[khud_fault] = 1; + player->pflags |= PF_FAULT; + } } /*-------------------------------------------------- @@ -103,18 +140,14 @@ void K_DoIngameRespawn(player_t *player) return; } - if (leveltime < introtime) + if (leveltime <= introtime) { return; } - if (leveltime < starttime) // FAULT - { - player->powers[pw_nocontrol] = (starttime - leveltime) + 50; - player->pflags |= PF_FAULT; - S_StartSound(player->mo, sfx_s3k83); - player->karthud[khud_fault] = 1; - } + // FAULT + if (leveltime < starttime) + K_DoFault(player); player->kartstuff[k_ringboost] = 0; player->kartstuff[k_driftboost] = 0; @@ -338,6 +371,12 @@ static void K_MovePlayerToRespawnPoint(player_t *player) } // Set angle, regardless of if we're done or not + P_SetPlayerAngle(player, R_PointToAngle2( + player->respawn.wp->mobj->x, + player->respawn.wp->mobj->y, + player->respawn.wp->nextwaypoints[nwp]->mobj->x, + player->respawn.wp->nextwaypoints[nwp]->mobj->y + )); player->drawangle = R_PointToAngle2( player->mo->x, player->mo->y, dest.x, dest.y @@ -615,7 +654,7 @@ static void K_DropDashWait(player_t *player) --------------------------------------------------*/ static void K_HandleDropDash(player_t *player) { - ticcmd_t *cmd = &player->cmd; + const UINT16 buttons = K_GetKartButtons(player); if (player->kartstuff[k_growshrinktimer] < 0) { @@ -640,7 +679,7 @@ static void K_HandleDropDash(player_t *player) // The old behavior was 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->kartstuff[k_spinouttimer]) // Since we're letting players spin out on respawn, don't let them charge a dropdash in this state. (It wouldn't work anyway) + if ((buttons & BT_ACCELERATE) && !player->kartstuff[k_spinouttimer]) // Since we're letting players spin out on respawn, don't let them charge a dropdash in this state. (It wouldn't work anyway) { player->respawn.dropdash++; } @@ -665,7 +704,7 @@ static void K_HandleDropDash(player_t *player) } else { - if ((cmd->buttons & BT_ACCELERATE) && (player->respawn.dropdash >= TICRATE/4)) + if ((buttons & BT_ACCELERATE) && (player->respawn.dropdash >= TICRATE/4)) { S_StartSound(player->mo, sfx_s23c); player->kartstuff[k_startboost] = 50; diff --git a/src/k_respawn.h b/src/k_respawn.h index d5a946560..5dd78ff1f 100644 --- a/src/k_respawn.h +++ b/src/k_respawn.h @@ -38,6 +38,21 @@ fixed_t K_RespawnOffset(player_t *player, boolean flip); +/*-------------------------------------------------- + void K_DoFault(player_t *player); + + Faults the specified player. + + Input Arguments:- + player - Player to preform this for. + + Return:- + None +--------------------------------------------------*/ + +void K_DoFault(player_t *player); + + /*-------------------------------------------------- void K_DoIngameRespawn(player_t *player); diff --git a/src/k_waypoint.c b/src/k_waypoint.c index 39e9efa5e..ae6841a34 100644 --- a/src/k_waypoint.c +++ b/src/k_waypoint.c @@ -153,6 +153,38 @@ boolean K_GetWaypointIsSpawnpoint(waypoint_t *waypoint) return waypointisspawnpoint; } +/*-------------------------------------------------- + static boolean K_GetWaypointIsOnLine(waypoint_t *const waypoint) + + Checks if a waypoint is exactly on a line. Moving to an exact point + on a line won't count as crossing it. Moving off of that point does. + Respawning to a waypoint which is exactly on a line is the easiest + way to for this to occur. + + Return:- + Whether the waypoint is exactly on a line. +--------------------------------------------------*/ +static boolean K_GetWaypointIsOnLine(waypoint_t *const waypoint) +{ + const fixed_t x = waypoint->mobj->x; + const fixed_t y = waypoint->mobj->y; + + line_t *line = P_FindNearestLine(x, y, + waypoint->mobj->subsector->sector, -1); + + vertex_t point; + + if (line != NULL) + { + P_ClosestPointOnLine(x, y, line, &point); + + if (x == point.x && y == point.y) + return true; + } + + return false; +} + /*-------------------------------------------------- INT32 K_GetWaypointNextID(waypoint_t *waypoint) @@ -253,6 +285,40 @@ waypoint_t *K_GetClosestWaypointToMobj(mobj_t *const mobj) return closestwaypoint; } +/*-------------------------------------------------- + static void K_CompareOverlappingWaypoint + ( waypoint_t *const checkwaypoint, + waypoint_t **const bestwaypoint, + fixed_t *const bestfindist) + + Solves touching overlapping waypoint radiuses by sorting by distance to + finish line. +--------------------------------------------------*/ +static void K_CompareOverlappingWaypoint +( waypoint_t *const checkwaypoint, + waypoint_t **const bestwaypoint, + fixed_t *const bestfindist) +{ + const boolean useshortcuts = false; + const boolean huntbackwards = false; + boolean pathfindsuccess = false; + path_t pathtofinish = {}; + + pathfindsuccess = + K_PathfindToWaypoint(checkwaypoint, finishline, &pathtofinish, useshortcuts, huntbackwards); + + if (pathfindsuccess == true) + { + if ((INT32)(pathtofinish.totaldist) < *bestfindist) + { + *bestwaypoint = checkwaypoint; + *bestfindist = pathtofinish.totaldist; + } + + Z_Free(pathtofinish.array); + } +} + /*-------------------------------------------------- waypoint_t *K_GetBestWaypointForMobj(mobj_t *const mobj) @@ -292,30 +358,18 @@ waypoint_t *K_GetBestWaypointForMobj(mobj_t *const mobj) rad = (checkwaypoint->mobj->radius / FRACUNIT); - if (closestdist < rad && checkdist < rad && finishline != NULL) + // remember: huge radius + if (closestdist <= rad && checkdist <= rad && finishline != NULL) { - const boolean useshortcuts = false; - const boolean huntbackwards = false; - boolean pathfindsuccess = false; - path_t pathtofinish = {}; - // If the mobj is touching multiple waypoints at once, // then solve ties by taking the one closest to the finish line. // Prevents position from flickering wildly when taking turns. - pathfindsuccess = - K_PathfindToWaypoint(checkwaypoint, finishline, &pathtofinish, useshortcuts, huntbackwards); + // For the first couple overlapping, check the previous best too. + if (bestfindist == INT32_MAX) + K_CompareOverlappingWaypoint(bestwaypoint, &bestwaypoint, &bestfindist); - if (pathfindsuccess == true) - { - if ((INT32)(pathtofinish.totaldist) < bestfindist) - { - bestwaypoint = checkwaypoint; - bestfindist = pathtofinish.totaldist; - } - - Z_Free(pathtofinish.array); - } + K_CompareOverlappingWaypoint(checkwaypoint, &bestwaypoint, &bestfindist); } else if (checkdist < closestdist && bestfindist == INT32_MAX) { @@ -1678,6 +1732,12 @@ static waypoint_t *K_SetupWaypoint(mobj_t *const mobj) finishline = thiswaypoint; } + /* only relevant for respawning */ + if (K_GetWaypointIsSpawnpoint(thiswaypoint)) + { + thiswaypoint->onaline = K_GetWaypointIsOnLine(thiswaypoint); + } + if (thiswaypoint->numnextwaypoints > 0) { waypoint_t *nextwaypoint = NULL; diff --git a/src/k_waypoint.h b/src/k_waypoint.h index 41230b49b..f49e162e8 100644 --- a/src/k_waypoint.h +++ b/src/k_waypoint.h @@ -23,6 +23,7 @@ typedef struct waypoint_s { mobj_t *mobj; + boolean onaline; struct waypoint_s **nextwaypoints; struct waypoint_s **prevwaypoints; UINT32 *nextwaypointdistances; diff --git a/src/lua_baselib.c b/src/lua_baselib.c index b33db8728..035d930de 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -1195,8 +1195,8 @@ static int lib_pGivePlayerRings(lua_State *L) INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); - P_GivePlayerRings(player, num_rings); - return 0; + lua_pushinteger(L, P_GivePlayerRings(player, num_rings)); + return 1; } static int lib_pGivePlayerLives(lua_State *L) @@ -1491,17 +1491,6 @@ static int lib_pDoSpring(lua_State *L) // P_INTER //////////// -static int lib_pRemoveShield(lua_State *L) -{ - player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); - NOHUD - INLEVEL - if (!player) - return LUA_ErrInvalid(L, "player_t"); - P_RemoveShield(player); - return 0; -} - static int lib_pDamageMobj(lua_State *L) { mobj_t *target = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)), *inflictor = NULL, *source = NULL; @@ -3803,7 +3792,6 @@ static luaL_Reg lib[] = { {"P_DoSpring",lib_pDoSpring}, // p_inter - {"P_RemoveShield",lib_pRemoveShield}, {"P_DamageMobj",lib_pDamageMobj}, {"P_KillMobj",lib_pKillMobj}, {"P_PlayerRingBurst",lib_pPlayerRingBurst}, diff --git a/src/p_enemy.c b/src/p_enemy.c index a2c719609..c96bf979f 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -4186,10 +4186,8 @@ void A_AttractChase(mobj_t *actor) { if (actor->extravalue1 >= 16) { - if (actor->target->player->rings >= 20) + if (!P_GivePlayerRings(actor->target->player, 1)) // returns 0 if addition failed actor->target->player->kartstuff[k_ringboost] += K_GetKartRingPower(actor->target->player)+3; - else - P_GivePlayerRings(actor->target->player, 1); if (actor->cvmem) // caching S_StartSound(actor->target, sfx_s1c5); diff --git a/src/p_inter.c b/src/p_inter.c index 4371752c8..541d1a890 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1370,6 +1370,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget break; case MT_PLAYER: + if (damagetype != DMG_SPECTATOR) { angle_t flingAngle; mobj_t *kart; @@ -1750,8 +1751,15 @@ static boolean P_KillPlayer(player_t *player, mobj_t *inflictor, mobj_t *source, // Respawn kill types K_DoIngameRespawn(player); return false; + case DMG_SPECTATOR: + // disappearifies, but still gotta put items back in play + break; default: // Everything else REALLY kills + if (leveltime < starttime) + { + K_DoFault(player); + } break; } @@ -1795,35 +1803,6 @@ static boolean P_KillPlayer(player_t *player, mobj_t *inflictor, mobj_t *source, return true; } -void P_RemoveShield(player_t *player) -{ - if (player->powers[pw_shield] & SH_FORCE) - { // Multi-hit - if (player->powers[pw_shield] & SH_FORCEHP) - player->powers[pw_shield]--; - else - player->powers[pw_shield] &= SH_STACK; - } - else if (player->powers[pw_shield] & SH_NOSTACK) - { // First layer shields - if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ARMAGEDDON) // Give them what's coming to them! - { - player->pflags |= PF_JUMPDOWN; - } - else - player->powers[pw_shield] &= SH_STACK; - } - else - { // Second layer shields - if (((player->powers[pw_shield] & SH_STACK) == SH_FIREFLOWER) && !player->powers[pw_super]) - { - player->mo->color = player->skincolor; - G_GhostAddColor((INT32) (player - players), GHC_NORMAL); - } - player->powers[pw_shield] = SH_NONE; - } -} - /** Damages an object, which may or may not be a player. * For melee attacks, source and inflictor are the same. * @@ -2138,7 +2117,6 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da static void P_FlingBurst ( player_t *player, angle_t fa, - fixed_t z, mobjtype_t objType, tic_t objFuse, fixed_t objScale, @@ -2149,18 +2127,17 @@ static void P_FlingBurst fixed_t momxy = 5<> 1; - z = player->mo->z; - if (player->mo->eflags & MFE_VERTICALFLIP) - z += player->mo->height - mobjinfo[objType].height; - - mo = P_SpawnMobj(player->mo->x, player->mo->y, z, objType); + mo = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, objType); mo->threshold = 10; // not useful for spikes mo->fuse = objFuse; P_SetTarget(&mo->target, player->mo); - mo->destscale = objScale; - P_SetScale(mo, objScale); + if (objScale != FRACUNIT) + { + P_SetScale(mo, FixedMul(objScale, mo->scale)); + mo->destscale = mo->scale; + } /* 0: 0 @@ -2197,7 +2174,6 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings) INT32 num_fling_rings; INT32 i; angle_t fa; - fixed_t z; // Rings shouldn't be in Battle! if (gametyperules & GTR_SPHERES) @@ -2211,32 +2187,25 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings) if (K_GetShieldFromItem(player->kartstuff[k_itemtype]) != KSHIELD_NONE) return; - // 20 is the ring cap in kart + // 20 is the maximum number of rings that can be taken from you at once - half the span of your counter if (num_rings > 20) num_rings = 20; else if (num_rings <= 0) return; - num_fling_rings = min(num_rings, player->rings); - - P_GivePlayerRings(player, -num_rings); + num_rings = -P_GivePlayerRings(player, -num_rings); + num_fling_rings = num_rings+min(0, player->rings); // determine first angle fa = player->mo->angle + ((P_RandomByte() & 1) ? -ANGLE_90 : ANGLE_90); - z = player->mo->z; - if (player->mo->eflags & MFE_VERTICALFLIP) - z += player->mo->height - mobjinfo[MT_RING].height; - for (i = 0; i < num_fling_rings; i++) { - P_FlingBurst(player, fa, z, - MT_FLINGRING, 60*TICRATE, player->mo->scale, i); + P_FlingBurst(player, fa, MT_FLINGRING, 60*TICRATE, FRACUNIT, i); } while (i < num_rings) { - P_FlingBurst(player, fa, z, - MT_DEBTSPIKE, 0, 3 * player->mo->scale / 2, i++); + P_FlingBurst(player, fa, MT_DEBTSPIKE, 0, 3 * FRACUNIT / 2, i++); } } diff --git a/src/p_local.h b/src/p_local.h index c5eac863e..4182d0658 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -158,6 +158,7 @@ boolean P_IsObjectInGoop(mobj_t *mo); boolean P_IsObjectOnGround(mobj_t *mo); boolean P_IsObjectOnGroundIn(mobj_t *mo, sector_t *sec); boolean P_IsObjectOnRealGround(mobj_t *mo, sector_t *sec); // SRB2Kart +#define P_IsObjectFlipped(o) ((o)->eflags & MFE_VERTICALFLIP) boolean P_InQuicksand(mobj_t *mo); boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff); @@ -167,7 +168,7 @@ boolean P_EndingMusic(player_t *player); void P_SpawnShieldOrb(player_t *player); void P_SwitchShield(player_t *player, UINT16 shieldtype); mobj_t *P_SpawnGhostMobj(mobj_t *mobj); -void P_GivePlayerRings(player_t *player, INT32 num_rings); +INT32 P_GivePlayerRings(player_t *player, INT32 num_rings); void P_GivePlayerSpheres(player_t *player, INT32 num_spheres); void P_GivePlayerLives(player_t *player, INT32 numlives); UINT8 P_GetNextEmerald(void); @@ -485,7 +486,6 @@ typedef struct BasicFF_s void P_ForceFeed(const player_t *player, INT32 attack, INT32 fade, tic_t duration, INT32 period); void P_ForceConstant(const BasicFF_t *FFInfo); void P_RampConstant(const BasicFF_t *FFInfo, INT32 Start, INT32 End); -void P_RemoveShield(player_t *player); void P_SpecialStageDamage(player_t *player, mobj_t *inflictor, mobj_t *source); boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype); void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damagetype); @@ -521,5 +521,9 @@ void P_Thrust(mobj_t *mo, angle_t angle, fixed_t move); void P_ExplodeMissile(mobj_t *mo); void P_CheckGravity(mobj_t *mo, boolean affect); void P_SetPitchRollFromSlope(mobj_t *mo, pslope_t *slope); +fixed_t P_ScaleFromMap(fixed_t n, fixed_t scale); +fixed_t P_GetMobjHead(const mobj_t *); +fixed_t P_GetMobjFeet(const mobj_t *); +fixed_t P_GetMobjGround(const mobj_t *); #endif // __P_LOCAL__ diff --git a/src/p_maputl.c b/src/p_maputl.c index 9131c24bb..5cf2e81fe 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -259,6 +259,76 @@ fixed_t P_InterceptVector(divline_t *v2, divline_t *v1) return frac; } +static fixed_t dist2line(const line_t *ld, const fixed_t x, const fixed_t y) +{ + return FixedHypot + ( + ld->v1->x + (ld->dx / 2) - x, + ld->v1->y + (ld->dy / 2) - y + ); +} + +static void checknearline +( line_t * line, + fixed_t * nearest, + line_t ** near_line, + const fixed_t x, + const fixed_t y) +{ + const fixed_t d = dist2line(line, x, y); + + if (d < *nearest) + { + *nearest = d; + *near_line = line; + } +} + +// +// P_FindNearestLine +// Returns the nearest line to a point which +// is in a sector and/or a specific type. +// +line_t * P_FindNearestLine +( const fixed_t x, + const fixed_t y, + const sector_t * sector, + const INT32 special) +{ + fixed_t nearest = INT32_MAX; + line_t *near_line = NULL; + size_t i; + INT32 line = -1; + + if (special == -1) + { + if (sector == NULL) + sector = R_PointInSubsector(x, y)->sector; + + for (i = 0; i < sector->linecount; ++i) + { + checknearline(sector->lines[i], &nearest, &near_line, x, y); + } + } + else if (sector != NULL) + { + for (i = 0; i < sector->linecount; ++i) + { + if (sector->lines[i]->special == special) + checknearline(sector->lines[i], &nearest, &near_line, x, y); + } + } + else + { + while ((line = P_FindSpecialLineFromTag(special, -1, line)) != -1) + { + checknearline(&lines[line], &nearest, &near_line, x, y); + } + } + + return near_line; +} + // // P_LineOpening // Sets opentop and openbottom to the window through a two sided line. diff --git a/src/p_maputl.h b/src/p_maputl.h index ce4509ca9..6f0c1f8ad 100644 --- a/src/p_maputl.h +++ b/src/p_maputl.h @@ -49,6 +49,7 @@ void P_MakeDivline(line_t *li, divline_t *dl); void P_CameraLineOpening(line_t *plinedef); fixed_t P_InterceptVector(divline_t *v2, divline_t *v1); INT32 P_BoxOnLineSide(fixed_t *tmbox, line_t *ld); +line_t * P_FindNearestLine(const fixed_t x, const fixed_t y, const sector_t *, const INT32 special); void P_UnsetPrecipThingPosition(precipmobj_t *thing); void P_SetPrecipitationThingPosition(precipmobj_t *thing); void P_CreatePrecipSecNodeList(precipmobj_t *thing, fixed_t x,fixed_t y); diff --git a/src/p_mobj.c b/src/p_mobj.c index 2bc6c620f..6a58fc907 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -2296,11 +2296,6 @@ boolean P_ZMovement(mobj_t *mo) { mom.x = mom.y = 0; mom.z = -mom.z/2; - - if (mo->fuse == 0) - { - mo->fuse = 90; - } } else if (mo->flags & MF_MISSILE) { @@ -6267,6 +6262,12 @@ static boolean P_MobjRegularThink(mobj_t *mobj) else A_AttractChase(mobj); break; + case MT_DEBTSPIKE: + if (mobj->fuse == 0 && P_GetMobjFeet(mobj) == P_GetMobjGround(mobj)) + { + mobj->fuse = 90; + } + break; case MT_EMBLEM: if (mobj->flags2 & MF2_NIGHTSPULL) P_NightsItemChase(mobj); @@ -6838,7 +6839,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) if ((!mobj->target || !mobj->target->health || !mobj->target->player || !P_IsObjectOnGround(mobj->target)) || !mobj->target->player->kartstuff[k_drift] || !mobj->target->player->kartstuff[k_brakedrift] || !((mobj->target->player->cmd.buttons & BT_BRAKE) - || !(mobj->target->player->cmd.buttons & BT_ACCELERATE))) // Letting go of accel functions about the same as brake-drifting + || (K_GetKartButtons(mobj->target->player) & BT_ACCELERATE))) // Letting go of accel functions about the same as brake-drifting { P_RemoveMobj(mobj); return false; @@ -10591,7 +10592,7 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing) { fixed_t offset = mthing->z << FRACBITS; - if (p->respawn.state != RESPAWNST_NONE) + if (p->respawn.state != RESPAWNST_NONE || p->spectator) offset += K_RespawnOffset(p, (mthing->options & MTF_OBJECTFLIP)); // Flagging a player's ambush will make them start on the ceiling @@ -10637,6 +10638,12 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing) mobj->angle = angle; + // FAULT + if (leveltime > introtime && !p->spectator) + { + K_DoIngameRespawn(p); + } + P_AfterPlayerSpawn(playernum); } @@ -10690,6 +10697,8 @@ void P_MovePlayerToStarpost(INT32 playernum) ); } } + else + p->drawangle = mobj->angle; // default to the camera angle P_AfterPlayerSpawn(playernum); } @@ -11325,6 +11334,18 @@ static boolean P_SetupBooster(mapthing_t* mthing, mobj_t* mobj, boolean strong) return true; } +static void P_SnapToFinishLine(mobj_t *mobj) +{ + line_t *finishline = P_FindNearestLine(mobj->x, mobj->y, + mobj->subsector->sector, 2001); // case 2001: Finish Line + if (finishline != NULL) + { + P_UnsetThingPosition(mobj); + P_ClosestPointOnLine(mobj->x, mobj->y, finishline, (vertex_t *)&mobj->x); + P_SetThingPosition(mobj); + } +} + static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean *doangle) { boolean override = LUAh_MapThingSpawn(mobj, mthing); @@ -11708,7 +11729,10 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean } if (mthing->args[2] == 1) { - mobj->extravalue2 = 1; // args[1] of 1 means the waypoint is at the finish line + mobj->extravalue2 = 1; // args[2] of 1 means the waypoint is at the finish line + mobj->reactiontime = 0; // Also don't respawn at finish lines + + P_SnapToFinishLine(mobj); } else { @@ -12748,6 +12772,15 @@ void P_FlashPal(player_t *pl, UINT16 type, UINT16 duration) pl->flashpal = type; } +// +// P_ScaleFromMap +// Scales a number relative to the mapobjectscale. +// +fixed_t P_ScaleFromMap(fixed_t n, fixed_t scale) +{ + return FixedMul(n, FixedDiv(scale, mapobjectscale)); +} + // // P_SpawnMobjFromMobj // Spawns an object with offsets relative to the position of another object. @@ -12765,16 +12798,40 @@ mobj_t *P_SpawnMobjFromMobj(mobj_t *mobj, fixed_t xofs, fixed_t yofs, fixed_t zo if (!newmobj) return NULL; + newmobj->destscale = P_ScaleFromMap(mobj->destscale, newmobj->destscale); + P_SetScale(newmobj, P_ScaleFromMap(mobj->scale, newmobj->scale)); + if (mobj->eflags & MFE_VERTICALFLIP) { - fixed_t elementheight = FixedMul(newmobj->info->height, mobj->scale); - newmobj->eflags |= MFE_VERTICALFLIP; newmobj->flags2 |= MF2_OBJECTFLIP; - newmobj->z = mobj->z + mobj->height - zofs - elementheight; + newmobj->z = mobj->z + mobj->height - zofs - newmobj->height; } - newmobj->destscale = mobj->destscale; - P_SetScale(newmobj, mobj->scale); return newmobj; } + +// +// P_GetMobjHead & P_GetMobjFeet +// Returns the top and bottom of an object, follows appearance, not physics, +// in reverse gravity. +// + +fixed_t P_GetMobjHead(const mobj_t *mobj) +{ + return P_IsObjectFlipped(mobj) ? mobj->z : mobj->z + mobj->height; +} + +fixed_t P_GetMobjFeet(const mobj_t *mobj) +{ + return P_IsObjectFlipped(mobj) ? mobj->z + mobj->height : mobj->z; +} + +// +// P_GetMobjGround +// Returns the object's floor, or ceiling in reverse gravity. +// +fixed_t P_GetMobjGround(const mobj_t *mobj) +{ + return P_IsObjectFlipped(mobj) ? mobj->ceilingz : mobj->floorz; +} diff --git a/src/p_saveg.c b/src/p_saveg.c index e24e3d2f7..8f5a1c709 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -277,6 +277,11 @@ static void P_NetArchivePlayers(void) WRITESINT8(save_p, players[i].glanceDir); + WRITEUINT8(save_p, players[i].typing_timer); + WRITEUINT8(save_p, players[i].typing_duration); + + WRITEUINT8(save_p, players[i].kickstartaccel); + // respawnvars_t WRITEUINT8(save_p, players[i].respawn.state); WRITEUINT32(save_p, K_GetWaypointHeapIndex(players[i].respawn.wp)); @@ -483,6 +488,11 @@ static void P_NetUnArchivePlayers(void) players[i].glanceDir = READSINT8(save_p); + players[i].typing_timer = READUINT8(save_p); + players[i].typing_duration = READUINT8(save_p); + + players[i].kickstartaccel = READUINT8(save_p); + // respawnvars_t players[i].respawn.state = READUINT8(save_p); players[i].respawn.wp = (waypoint_t *)(size_t)READUINT32(save_p); @@ -4180,6 +4190,7 @@ static void P_NetArchiveMisc(void) WRITEUINT32(save_p, introtime); WRITEUINT32(save_p, starttime); + WRITEUINT8(save_p, numbulbs); // Is it paused? if (paused) @@ -4314,6 +4325,7 @@ static inline boolean P_NetUnArchiveMisc(void) introtime = READUINT32(save_p); starttime = READUINT32(save_p); + numbulbs = READUINT8(save_p); // Is it paused? if (READUINT8(save_p) == 0x2f) diff --git a/src/p_setup.c b/src/p_setup.c index 6cd4ffd72..2f8b746eb 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1261,6 +1261,24 @@ static void P_LoadSidedefs(UINT8 *data) break; } + case 423: // Change Sky + { + char process[8*3+1]; + memset(process,0,8*3+1); + sd->toptexture = sd->midtexture = sd->bottomtexture = 0; + if (msd->toptexture[0] != '-' || msd->toptexture[1] != '\0') + M_Memcpy(process,msd->toptexture,8); + if (msd->midtexture[0] != '-' || msd->midtexture[1] != '\0') + M_Memcpy(process+strlen(process), msd->midtexture, 8); + if (msd->bottomtexture[0] != '-' || msd->bottomtexture[1] != '\0') + M_Memcpy(process+strlen(process), msd->bottomtexture, 8); + if (!strlen(process)) + break; + sd->text = Z_Malloc(strlen(process)+1, PU_LEVEL, NULL); + M_Memcpy(sd->text, process, strlen(process)+1); + break; + } + case 9: // Mace parameters case 14: // Bustable block parameters case 15: // Fan particle spawner parameters @@ -3305,6 +3323,9 @@ static boolean P_LoadMapFromFile(void) void P_SetupLevelSky(const char *skytexname, boolean global) { char tex[9]; + if (!skytexname || !skytexname[0]) + return; + strncpy(tex, skytexname, 9); tex[8] = 0; @@ -3427,29 +3448,6 @@ static void P_InitLevelSettings(void) players[i].follower = NULL; } - rainbowstartavailable = false; - - if (p >= 2) - rainbowstartavailable = true; - - if (p <= 2) - { - introtime = 0; // No intro in Record Attack / 1v1 - } - else - { - introtime = (108) + 5; // 108 for rotation, + 5 for white fade - } - - numbulbs = 5; - - if (p > 2) - { - numbulbs += (p-2); - } - - starttime = (introtime + (3*TICRATE)) + ((2*TICRATE) + (numbulbs * bulbtime)); // Start countdown time, + buffer time - // SRB2Kart: map load variables if (grandprixinfo.gp == true) { @@ -4013,7 +4011,7 @@ boolean P_LoadLevel(boolean fromnetsave) I_Error("Map %s not found.\n", maplumpname); R_ReInitColormaps(mapheaderinfo[gamemap-1]->palette, - (encoremode ? W_CheckNumForName(va("%sE", maplumpname)) : LUMPERROR)); + W_CheckNumForName(va("%s%c", maplumpname, (encoremode ? 'E' : 'T')))); CON_SetupBackColormap(); // SRB2 determines the sky texture to be used depending on the map header. @@ -4149,21 +4147,6 @@ boolean P_LoadLevel(boolean fromnetsave) lastmaploaded = gamemap; // HAS to be set after saving!! } - if (!fromnetsave) // uglier hack - { // to make a newly loaded level start on the second frame. - INT32 buf = gametic % TICQUEUE; - for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i]) - G_CopyTiccmd(&players[i].cmd, &netcmds[buf][i], 1); - } - P_PreTicker(2); - LUAh_MapLoad(); - } - - // NOW you can try to spawn in the Battle capsules, if there's not enough players for a match - K_SpawnBattleCapsules(); - if (grandprixinfo.gp == true) { if (grandprixinfo.initalize == true) @@ -4183,6 +4166,20 @@ boolean P_LoadLevel(boolean fromnetsave) K_UpdateMatchRaceBots(); } + if (!fromnetsave) // uglier hack + { // to make a newly loaded level start on the second frame. + INT32 buf = gametic % TICQUEUE; + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i]) + G_CopyTiccmd(&players[i].cmd, &netcmds[buf][i], 1); + } + P_PreTicker(2); + LUAh_MapLoad(); + } + + K_TimerReset(); + // No render mode, stop here. if (rendermode == render_none) return true; diff --git a/src/p_spec.c b/src/p_spec.c index d0a8f085c..98ae6faf9 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -8763,12 +8763,8 @@ void T_Pusher(pusher_t *p) { if (p->slider && thing->player) { - pflags_t jumped = (thing->player->pflags & (PF_JUMPED|PF_NOJUMPDAMAGE)); P_ResetPlayer (thing->player); - if (jumped) - thing->player->pflags |= jumped; - thing->player->pflags |= PF_SLIDING; thing->angle = R_PointToAngle2 (0, 0, xspeed<<(FRACBITS-PUSH_FACTOR), yspeed<<(FRACBITS-PUSH_FACTOR)); diff --git a/src/p_tick.c b/src/p_tick.c index 71ded772c..85ee844dd 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -705,6 +705,13 @@ void P_Ticker(boolean run) if (demo.playback) G_StoreRewindInfo(); + if (leveltime == 2) + { + // The values needed to set this properly are not correct at map load, + // so we have to do it at the second tick instead... + K_TimerInit(); + } + // Z_CheckMemCleanup(); } diff --git a/src/p_user.c b/src/p_user.c index e4785b249..7b79d5627 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -206,7 +206,7 @@ void P_CalcHeight(player_t *player) player->bob = FixedMul(cv_movebob.value, bobmul); - if (!P_IsObjectOnGround(mo)) + if (!P_IsObjectOnGround(mo) || player->spectator) { if (mo->eflags & MFE_VERTICALFLIP) { @@ -461,7 +461,7 @@ UINT8 P_FindHighestLap(void) // boolean P_PlayerInPain(player_t *player) { - if (player->kartstuff[k_spinouttimer] || player->tumbleBounces > 0) + if (player->kartstuff[k_spinouttimer] || (player->tumbleBounces > 0) || (player->pflags & PF_FAULT)) return true; return false; @@ -487,23 +487,29 @@ void P_ResetPlayer(player_t *player) // // Gives rings to the player, and does any special things required. // Call this function when you want to increment the player's health. +// Returns the number of rings successfully given (or taken). // -void P_GivePlayerRings(player_t *player, INT32 num_rings) +INT32 P_GivePlayerRings(player_t *player, INT32 num_rings) { + INT32 test; + if (!player->mo) - return; + return 0; if ((gametyperules & GTR_BUMPERS)) // No rings in Battle Mode - return; + return 0; + + test = player->rings + num_rings; + if (test > 20) // Caps at 20 rings, sorry! + num_rings -= (test-20); + else if (test < -20) // Chaotix ring debt! + num_rings -= (test+20); player->rings += num_rings; - //player->totalring += num_rings; // Used for GP lives later + //player->totalring += num_rings; // Used for GP lives later -- maybe you might want to move this earlier to discourage ring debt... - if (player->rings > 20) - player->rings = 20; // Caps at 20 rings, sorry! - else if (player->rings < -20) - player->rings = -20; // Chaotix ring debt! + return num_rings; } // @@ -2117,11 +2123,7 @@ void P_MovePlayer(player_t *player) // Control relinquishing stuff! if (player->powers[pw_nocontrol]) - { player->pflags |= PF_STASIS; - if (!(player->powers[pw_nocontrol] & (1<<15))) - player->pflags |= PF_JUMPSTASIS; - } // note: don't unset stasis here @@ -2177,9 +2179,13 @@ void P_MovePlayer(player_t *player) player->drawangle -= ANGLE_22h; player->mo->rollangle = 0; } - else if (player->kartstuff[k_spinouttimer] > 0) + else if ((player->pflags & PF_FAULT) || (player->kartstuff[k_spinouttimer] > 0)) { - UINT8 speed = max(1, min(8, player->kartstuff[k_spinouttimer]/8)); + UINT16 speed = ((player->pflags & PF_FAULT) ? player->powers[pw_nocontrol] : player->kartstuff[k_spinouttimer])/8; + if (speed > 8) + speed = 8; + else if (speed < 1) + speed = 1; P_SetPlayerMobjState(player->mo, S_KART_SPINOUT); @@ -2190,7 +2196,7 @@ void P_MovePlayer(player_t *player) player->mo->rollangle = 0; } - else if (player->pflags & PF_FAULT) + /*else if (player->pflags & PF_FAULT) -- v1 fault { P_SetPlayerMobjState(player->mo, S_KART_SPINOUT); @@ -2200,7 +2206,7 @@ void P_MovePlayer(player_t *player) player->drawangle -= ANGLE_11hh; player->mo->rollangle = 0; - } + }*/ else { K_KartMoveAnimation(player); @@ -2991,7 +2997,7 @@ void P_ResetCamera(player_t *player, camera_t *thiscam) if (thiscam->chase && player->mo->health <= 0) return; - thiscam->chase = true; + thiscam->chase = !player->spectator; x = player->mo->x - P_ReturnThrustX(player->mo, thiscam->angle, player->mo->radius); y = player->mo->y - P_ReturnThrustY(player->mo, thiscam->angle, player->mo->radius); if (player->mo->eflags & MFE_VERTICALFLIP) @@ -3074,6 +3080,10 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall { // Do not move the camera while in hitlag! // The camera zooming out after you got hit makes it hard to focus on the vibration. + // of course, if you're in chase, don't forget the postimage - otherwise encore will flip back + if (thiscam->chase) + P_CalcChasePostImg(player, thiscam); + return true; } @@ -4314,6 +4324,19 @@ void P_PlayerThink(player_t *player) player->kartstuff[k_throwdir] = 0; } + // Accessibility - kickstart your acceleration + if (!(player->pflags & PF_KICKSTARTACCEL)) + player->kickstartaccel = 0; + else if (cmd->buttons & BT_ACCELERATE) + { + if (!player->exiting && !(player->pflags & PF_ACCELDOWN)) + player->kickstartaccel = 0; + else if (player->kickstartaccel < ACCEL_KICKSTART) + player->kickstartaccel++; + } + else if (player->kickstartaccel < ACCEL_KICKSTART) + player->kickstartaccel = 0; + #ifdef PARANOIA if (player->playerstate == PST_REBORN) I_Error("player %s is in PST_REBORN\n", sizeu1(playeri)); @@ -4470,11 +4493,6 @@ void P_PlayerThink(player_t *player) // Allows some turning P_MovePlayer(player); } - else if (player->respawn.state == RESPAWNST_MOVE) - { - angle_t angleChange = player->cmd.turning << TICCMD_REDUCE; - P_SetPlayerAngle(player, player->angleturn + angleChange); - } } else if (player->mo->reactiontime) { @@ -4496,10 +4514,10 @@ void P_PlayerThink(player_t *player) player->mo->movefactor = FRACUNIT; // We're not going to do any more with this, so let's change it back for the next frame. - // Unset statis flags after moving. + // Unset statis flag after moving. // In other words, if you manually set stasis via code, // it lasts for one tic. - player->pflags &= ~PF_FULLSTASIS; + player->pflags &= ~PF_STASIS; if (player->onconveyor == 1) player->onconveyor = 3; @@ -4545,11 +4563,16 @@ void P_PlayerThink(player_t *player) } #endif - // check for use - if (cmd->buttons & BT_BRAKE) - player->pflags |= PF_SPINDOWN; + // check for buttons + if (cmd->buttons & BT_ACCELERATE) + player->pflags |= PF_ACCELDOWN; else - player->pflags &= ~PF_SPINDOWN; + player->pflags &= ~PF_ACCELDOWN; + + if (cmd->buttons & BT_BRAKE) + player->pflags |= PF_BRAKEDOWN; + else + player->pflags &= ~PF_BRAKEDOWN; // Counters, time dependent power ups. // Time Bonus & Ring Bonus count settings @@ -4561,7 +4584,7 @@ void P_PlayerThink(player_t *player) player->powers[pw_flashing]--; } - if (player->powers[pw_nocontrol] & ((1<<15)-1) && player->powers[pw_nocontrol] < UINT16_MAX) + if (player->powers[pw_nocontrol] && player->powers[pw_nocontrol] < UINT16_MAX) { if (!(--player->powers[pw_nocontrol])) player->pflags &= ~PF_FAULT; @@ -4588,6 +4611,64 @@ void P_PlayerThink(player_t *player) player->mo->drawflags &= ~MFD_DONTDRAW; } + if (cmd->flags & TICCMD_TYPING) + { + /* + typing_duration is slow to start and slow to stop. + + typing_timer counts down a grace period before the player is not + actually considered typing anymore. + */ + if (cmd->flags & TICCMD_KEYSTROKE) + { + /* speed up if we are typing quickly! */ + if (player->typing_duration > 0 && player->typing_timer > 12) + { + if (player->typing_duration < 16) + { + player->typing_duration = 24; + } + else + { + /* slows down a tiny bit as it approaches the next dot */ + const UINT8 step = (((player->typing_duration + 15) & ~15) - + player->typing_duration) / 2; + player->typing_duration += max(step, 4); + } + } + + player->typing_timer = 15; + } + else if (player->typing_timer > 0) + { + player->typing_timer--; + } + + /* if we are in the grace period (including currently typing) */ + if (player->typing_timer + player->typing_duration > 0) + { + /* always end the cycle on two dots */ + if (player->typing_timer == 0 && + (player->typing_duration < 16 || player->typing_duration == 40)) + { + player->typing_duration = 0; + } + else if (player->typing_duration < 63) + { + player->typing_duration++; + } + else + { + player->typing_duration = 16; + } + } + } + else + { + player->typing_timer = 0; + player->typing_duration = 0; + } + player->pflags &= ~PF_SLIDING; K_KartPlayerThink(player, cmd); // SRB2kart diff --git a/src/r_data.c b/src/r_data.c index 39c41d8bf..7c5fb6ce5 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -287,7 +287,9 @@ static void R_InitColormaps(void) // Load in the light tables lump = W_GetNumForName("COLORMAP"); len = W_LumpLength(lump); - colormaps = Z_MallocAlign(len * 2, PU_STATIC, NULL, 8); // * 2 for encore + if (len < COLORMAP_SIZE*2) // accomodate encore mode later + len = COLORMAP_SIZE*2; + colormaps = Z_MallocAlign(len, PU_STATIC, NULL, 8); W_ReadLump(lump, colormaps); // no need to init encoremap at this stage @@ -330,9 +332,9 @@ void R_ReInitColormaps(UINT16 num, lumpnum_t newencoremap) encoremap = Z_MallocAlign(256 + 10, PU_LEVEL, NULL, 8); W_ReadLump(newencoremap, encoremap); colormap_p = colormap_p2 = colormaps; - colormap_p += (256 * 32); + colormap_p += COLORMAP_REMAPOFFSET; - for (p = 0; p < 32; p++) + for (p = 0; p < LIGHTLEVELS; p++) { for (i = 0; i < 256; i++) { @@ -731,12 +733,12 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) // Now allocate memory for the actual colormap array itself! // aligned on 8 bit for asm code - colormap_p = Z_MallocAlign((256 * 34) + 10, PU_LEVEL, NULL, 8); + colormap_p = Z_MallocAlign((COLORMAP_SIZE * (encoremap ? 2 : 1)) + 10, PU_LEVEL, NULL, 8); lighttable = (UINT8 *)colormap_p; // Calculate the palette index for each palette index, for each light level // (as well as the two unused colormap lines we inherited from Doom) - for (p = 0; p < 32; p++) + for (p = 0; p < LIGHTLEVELS; p++) { for (i = 0; i < 256; i++) { @@ -776,7 +778,7 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) { lighttable_t *colormap_p2 = lighttable; - for (p = 0; p < 32; p++) + for (p = 0; p < LIGHTLEVELS; p++) { for (i = 0; i < 256; i++) { diff --git a/src/r_draw8.c b/src/r_draw8.c index 2f7bb64b8..41c74ba3c 100644 --- a/src/r_draw8.c +++ b/src/r_draw8.c @@ -1698,7 +1698,7 @@ void R_DrawColumnShadowed_8(void) { dc_colormap = dc_lightlist[i].rcolormap; if (encoremap) - dc_colormap += (256*32); + dc_colormap += COLORMAP_REMAPOFFSET; if (solid && dc_yl < bheight) dc_yl = bheight; continue; @@ -1716,7 +1716,7 @@ void R_DrawColumnShadowed_8(void) dc_colormap = dc_lightlist[i].rcolormap; if (encoremap) - dc_colormap += (256*32); + dc_colormap += COLORMAP_REMAPOFFSET; } dc_yh = realyh; if (dc_yl <= realyh) diff --git a/src/r_main.c b/src/r_main.c index 835ed26f7..93fadd134 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1191,9 +1191,7 @@ void R_SetupFrame(player_t *player) if (i > r_splitscreen) return; // shouldn't be possible, but just in case - if (player->playerstate == PST_DEAD || gamestate == GS_TITLESCREEN || tutorialmode) - chasecam = true; // force chasecam on - else if (player->spectator) // no spectator chasecam + if (player->spectator) // no spectator chasecam chasecam = false; // force chasecam off if (chasecam && !thiscam->chase) diff --git a/src/r_main.h b/src/r_main.h index b4845af18..b7b4c9fd5 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -41,7 +41,7 @@ extern size_t validcount, linecount, loopcount, framecount; // Lighting constants. // Now with 32 levels. -#define LIGHTLEVELS 32 +// LIGHTLEVELS is now defined in r_state.h #define LIGHTSEGSHIFT 3 #define MAXLIGHTSCALE 48 diff --git a/src/r_plane.c b/src/r_plane.c index 3ec74bc47..9ca8eb608 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -232,7 +232,7 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2) ds_colormap = planezlight[pindex]; if (encoremap && !currentplane->noencore) - ds_colormap += (256*32); + ds_colormap += COLORMAP_REMAPOFFSET; if (currentplane->extra_colormap) ds_colormap = currentplane->extra_colormap->colormap + (ds_colormap - colormaps); @@ -644,6 +644,8 @@ static void R_DrawSkyPlane(visplane_t *pl) // Because of this hack, sky is not affected // by sector colormaps (INVUL inverse mapping is not implemented in SRB2 so is irrelevant). dc_colormap = colormaps; + if (encoremap) + dc_colormap += COLORMAP_REMAPOFFSET; dc_texturemid = skytexturemid; dc_texheight = textureheight[skytexture] >>FRACBITS; diff --git a/src/r_segs.c b/src/r_segs.c index 8dcb61992..b0be67062 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -203,7 +203,7 @@ static void R_DrawWallSplats(void) pindex = MAXLIGHTSCALE - 1; dc_colormap = walllights[pindex]; if (encoremap && !(seg->linedef->flags & ML_TFERLINE)) - dc_colormap += (256*32); + dc_colormap += COLORMAP_REMAPOFFSET; if (frontsector->extra_colormap) dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps); @@ -578,7 +578,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) { dc_colormap = rlight->rcolormap; if (encoremap && !(ldef->flags & ML_TFERLINE)) - dc_colormap += (256*32); + dc_colormap += COLORMAP_REMAPOFFSET; continue; } @@ -599,7 +599,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) windowtop = windowbottom + 1; dc_colormap = rlight->rcolormap; if (encoremap && !(ldef->flags & ML_TFERLINE)) - dc_colormap += (256*32); + dc_colormap += COLORMAP_REMAPOFFSET; } windowbottom = realbot; if (windowtop < windowbottom) @@ -617,7 +617,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) dc_colormap = walllights[pindex]; if (encoremap && !(ldef->flags & ML_TFERLINE)) - dc_colormap += (256*32); + dc_colormap += COLORMAP_REMAPOFFSET; if (frontsector->extra_colormap) dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps); @@ -1163,7 +1163,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) { dc_colormap = rlight->rcolormap; if (encoremap && !(curline->linedef->flags & ML_TFERLINE)) - dc_colormap += (256*32); + dc_colormap += COLORMAP_REMAPOFFSET; } if (solid && windowtop < bheight) windowtop = bheight; @@ -1195,7 +1195,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) { dc_colormap = rlight->rcolormap; if (encoremap && !(curline->linedef->flags & ML_TFERLINE)) - dc_colormap += (256*32); + dc_colormap += COLORMAP_REMAPOFFSET; } } windowbottom = sprbotscreen; @@ -1216,7 +1216,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) dc_colormap = walllights[pindex]; if (encoremap && !(curline->linedef->flags & ML_TFERLINE)) - dc_colormap += (256*32); + dc_colormap += COLORMAP_REMAPOFFSET; if (pfloor->flags & FF_FOG && pfloor->master->frontsector->extra_colormap) dc_colormap = pfloor->master->frontsector->extra_colormap->colormap + (dc_colormap - colormaps); @@ -1476,7 +1476,7 @@ static void R_RenderSegLoop (void) dc_colormap = walllights[pindex]; if (encoremap && !(curline->linedef->flags & ML_TFERLINE)) - dc_colormap += (256*32); + dc_colormap += COLORMAP_REMAPOFFSET; dc_x = rw_x; dc_iscale = 0xffffffffu / (unsigned)rw_scale; diff --git a/src/r_state.h b/src/r_state.h index 1ae0adcf6..cb55e2c2b 100644 --- a/src/r_state.h +++ b/src/r_state.h @@ -44,6 +44,10 @@ extern UINT8 *encoremap; extern UINT8 invertmap[256]; #endif +#define LIGHTLEVELS 32 +#define COLORMAP_SIZE (256*LIGHTLEVELS) +#define COLORMAP_REMAPOFFSET COLORMAP_SIZE + // Boom colormaps. extern extracolormap_t *extra_colormaps; diff --git a/src/r_things.c b/src/r_things.c index c4e76303d..b72341191 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -863,7 +863,7 @@ static void R_DrawVisSprite(vissprite_t *vis) dc_colormap = colormaps; if (encoremap && !vis->mobj->color && !(vis->mobj->flags & MF_DONTENCOREMAP)) - dc_colormap += (256*32); + dc_colormap += COLORMAP_REMAPOFFSET; dc_texturemid = vis->texturemid; dc_texheight = 0; @@ -993,7 +993,7 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis) dc_colormap = colormaps; if (encoremap) - dc_colormap += (256*32); + dc_colormap += COLORMAP_REMAPOFFSET; dc_iscale = FixedDiv(FRACUNIT, vis->scale); dc_texturemid = vis->texturemid; @@ -1404,7 +1404,7 @@ static void R_ProjectSprite(mobj_t *thing) fixed_t scalestep; fixed_t offset, offset2; - fixed_t basetx; // drop shadows + fixed_t basetx, basetz; // drop shadows boolean papersprite = !!(thing->frame & FF_PAPERSPRITE); fixed_t paperoffset = 0, paperdistance = 0; angle_t centerangle = 0; @@ -1445,7 +1445,7 @@ static void R_ProjectSprite(mobj_t *thing) tr_x = thingxpos - viewx; tr_y = thingypos - viewy; - tz = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); // near/far distance + basetz = tz = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); // near/far distance // thing is behind view plane? if (!papersprite && (tz < FixedMul(MINZ, this_scale))) // papersprite clipping is handled later @@ -1911,7 +1911,7 @@ static void R_ProjectSprite(mobj_t *thing) R_SplitSprite(vis); if (oldthing->shadowscale && cv_shadow.value) - R_ProjectDropShadow(oldthing, vis, oldthing->shadowscale, basetx, tz); + R_ProjectDropShadow(oldthing, vis, oldthing->shadowscale, basetx, basetz); // Debug ++objectsdrawn; diff --git a/src/v_video.c b/src/v_video.c index f0c7e1a13..31c7eec95 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -1454,7 +1454,7 @@ void V_DrawCustomFadeScreen(const char *lump, UINT8 strength) if (lumpnum != LUMPERROR) { - clm = Z_MallocAlign((256 * 32), PU_STATIC, NULL, 8); + clm = Z_MallocAlign(COLORMAP_SIZE, PU_STATIC, NULL, 8); W_ReadLump(lumpnum, clm); if (clm != NULL) @@ -1505,7 +1505,7 @@ void V_EncoreInvertScreen(void) #ifdef HWRENDER if (rendermode != render_soft && rendermode != render_none) { - //HWR_EncoreInvertScreen(); + HWR_EncoreInvertScreen(); return; } #endif