diff --git a/src/command.c b/src/command.c index 1439463c1..0145687be 100644 --- a/src/command.c +++ b/src/command.c @@ -36,6 +36,7 @@ #include "d_netfil.h" // findfile #include "r_data.h" // Color_cons_t #include "r_skins.h" +#include "m_random.h" //======== // protos. @@ -53,6 +54,8 @@ static void COM_Wait_f(void); static void COM_Help_f(void); static void COM_Toggle_f(void); static void COM_Add_f(void); +static void COM_Choose_f(void); +static void COM_ChooseWeighted_f(void); static void CV_EnforceExecVersion(void); static boolean CV_FilterVarByVersion(consvar_t *v, const char *valstr); @@ -361,6 +364,8 @@ void COM_Init(void) COM_AddCommand("help", COM_Help_f); COM_AddCommand("toggle", COM_Toggle_f); COM_AddCommand("add", COM_Add_f); + COM_AddCommand("choose", COM_Choose_f); + COM_AddCommand("chooseweighted", COM_ChooseWeighted_f); RegisterNetXCmd(XD_NETVAR, Got_NetVar); } @@ -1075,6 +1080,81 @@ static void COM_Add_f(void) CV_AddValue(cvar, atoi(COM_Argv(2))); } +static void COM_Choose_f(void) +{ + size_t na = COM_Argc(); + + if (na < 2) + { + CONS_Printf(M_GetText("choose [] [] [...]: Picks a command at random\n")); + return; + } + + COM_BufAddText(COM_Argv(M_RandomKey(na - 1) + 1)); + COM_BufAddText("\n"); +} + +static void COM_ChooseWeighted_f(void) +{ + size_t na = COM_Argc(); + size_t i, cmd; + const char *commands[40]; + INT32 weights[40]; + INT32 totalWeight = 0; + INT32 roll; + + if (na < 3) + { + CONS_Printf(M_GetText("chooseweighted [ ] [ ] [...]: Picks a command with weighted randomization\n")); + return; + } + + memset(weights, 0, sizeof(weights)); + + i = 1; + cmd = 0; + while (i < na) + { + commands[cmd] = COM_Argv(i); + + i++; + if (i >= na) + { + break; + } + + weights[cmd] = atoi(COM_Argv(i)); + totalWeight += weights[cmd]; + + i++; + cmd++; + } + + if (cmd == 0 || totalWeight <= 0) + { + return; + } + + roll = M_RandomRange(1, totalWeight); + + for (i = 0; i < cmd; i++) + { + if (roll <= weights[i]) + { + if (commands[i] == NULL) + { + break; + } + + COM_BufAddText(commands[i]); + COM_BufAddText("\n"); + break; + } + + roll -= weights[i]; + } +} + // ========================================================================= // VARIABLE SIZE BUFFERS // ========================================================================= diff --git a/src/console.c b/src/console.c index 80174692e..7cbcb85a9 100644 --- a/src/console.c +++ b/src/console.c @@ -34,7 +34,6 @@ #include "k_menu.h" #include "filesrch.h" #include "m_misc.h" -#include "m_random.h" #ifdef _WINDOWS #include "win32/win_main.h" @@ -244,81 +243,6 @@ static void CONS_Bind_f(void) bindtable[key] = Z_StrDup(COM_Argv(2)); } -static void CONS_Choose_f(void) -{ - size_t na = COM_Argc(); - - if (na < 2) - { - CONS_Printf(M_GetText("choose [] [] [...]: Picks a command at random\n")); - return; - } - - COM_BufAddText(COM_Argv(M_RandomKey(na - 1) + 1)); - COM_BufAddText("\n"); -} - -static void CONS_ChooseWeighted_f(void) -{ - size_t na = COM_Argc(); - size_t i, cmd; - const char *commands[40]; - INT32 weights[40]; - INT32 totalWeight = 0; - INT32 roll; - - if (na < 3) - { - CONS_Printf(M_GetText("chooseweighted [ ] [ ] [...]: Picks a command with weighted randomization\n")); - return; - } - - memset(weights, 0, sizeof(weights)); - - i = 1; - cmd = 0; - while (i < na) - { - commands[cmd] = COM_Argv(i); - - i++; - if (i >= na) - { - break; - } - - weights[cmd] = atoi(COM_Argv(i)); - totalWeight += weights[cmd]; - - i++; - cmd++; - } - - if (cmd == 0 || totalWeight <= 0) - { - return; - } - - roll = M_RandomRange(1, totalWeight); - - for (i = 0; i < cmd; i++) - { - if (roll <= weights[i]) - { - if (commands[i] == NULL) - { - break; - } - - COM_BufAddText(commands[i]); - COM_BufAddText("\n"); - break; - } - - roll -= weights[i]; - } -} - //====================================================================== // CONSOLE SETUP //====================================================================== @@ -521,8 +445,6 @@ void CON_Init(void) CV_RegisterVar(&cons_backpic); CV_RegisterVar(&cons_backcolor); COM_AddCommand("bind", CONS_Bind_f); - COM_AddCommand("choose", CONS_Choose_f); - COM_AddCommand("chooseweighted", CONS_ChooseWeighted_f); } else { diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 0f1f39fa7..ebd58844e 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -3276,17 +3276,17 @@ consvar_t cv_discordinvites = CVAR_INIT ("discordinvites", "Everyone", CV_SAVE|C static CV_PossibleValue_t resynchattempts_cons_t[] = {{1, "MIN"}, {20, "MAX"}, {0, "No"}, {0, NULL}}; -consvar_t cv_resynchattempts = CVAR_INIT ("resynchattempts", "10", CV_SAVE|CV_NETVAR, resynchattempts_cons_t, NULL); +consvar_t cv_resynchattempts = CVAR_INIT ("resynchattempts", "2", CV_SAVE|CV_NETVAR, resynchattempts_cons_t, NULL); consvar_t cv_blamecfail = CVAR_INIT ("blamecfail", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); // max file size to send to a player (in kilobytes) static CV_PossibleValue_t maxsend_cons_t[] = {{0, "MIN"}, {51200, "MAX"}, {0, NULL}}; -consvar_t cv_maxsend = CVAR_INIT ("maxsend", "4096", CV_SAVE|CV_NETVAR, maxsend_cons_t, NULL); +consvar_t cv_maxsend = CVAR_INIT ("maxsend", "51200", CV_SAVE|CV_NETVAR, maxsend_cons_t, NULL); consvar_t cv_noticedownload = CVAR_INIT ("noticedownload", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); // Speed of file downloading (in packets per tic) -static CV_PossibleValue_t downloadspeed_cons_t[] = {{0, "MIN"}, {32, "MAX"}, {0, NULL}}; -consvar_t cv_downloadspeed = CVAR_INIT ("downloadspeed", "16", CV_SAVE|CV_NETVAR, downloadspeed_cons_t, NULL); +static CV_PossibleValue_t downloadspeed_cons_t[] = {{1, "MIN"}, {300, "MAX"}, {0, NULL}}; +consvar_t cv_downloadspeed = CVAR_INIT ("downloadspeed", "32", CV_SAVE|CV_NETVAR, downloadspeed_cons_t, NULL); static void Got_AddPlayer(UINT8 **p, INT32 playernum); static void Got_RemovePlayer(UINT8 **p, INT32 playernum); @@ -4944,7 +4944,10 @@ static void GetPackets(void) if (netbuffer->packettype == PT_CLIENTJOIN && server) { - HandleConnect(node); + if (!levelloading) // Otherwise just ignore + { + HandleConnect(node); + } continue; } if (node == servernode && client && cl_mode != CL_SEARCHING) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index eb6e630c0..9dcc990a9 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -409,8 +409,6 @@ consvar_t cv_dualjawz = CVAR_INIT ("dualjawz", "On", CV_NETVAR|CV_CHEAT, C static CV_PossibleValue_t kartminimap_cons_t[] = {{0, "MIN"}, {10, "MAX"}, {0, NULL}}; consvar_t cv_kartminimap = CVAR_INIT ("kartminimap", "4", CV_SAVE, kartminimap_cons_t, NULL); consvar_t cv_kartcheck = CVAR_INIT ("kartcheck", "Yes", CV_SAVE, CV_YesNo, NULL); -static CV_PossibleValue_t kartinvinsfx_cons_t[] = {{0, "Music"}, {1, "SFX"}, {0, NULL}}; -consvar_t cv_kartinvinsfx = CVAR_INIT ("kartinvinsfx", "SFX", CV_SAVE, kartinvinsfx_cons_t, NULL); consvar_t cv_kartspeed = CVAR_INIT ("kartspeed", "Auto", CV_NETVAR|CV_CALL|CV_NOINIT, kartspeed_cons_t, KartSpeed_OnChange); static CV_PossibleValue_t kartbumpers_cons_t[] = {{1, "MIN"}, {12, "MAX"}, {0, NULL}}; consvar_t cv_kartbumpers = CVAR_INIT ("kartbumpers", "3", CV_NETVAR|CV_CHEAT, kartbumpers_cons_t, NULL); @@ -519,9 +517,9 @@ consvar_t cv_allowexitlevel = CVAR_INIT ("allowexitlevel", "No", CV_NETVAR, CV_Y consvar_t cv_netstat = CVAR_INIT ("netstat", "Off", 0, CV_OnOff, NULL); // show bandwidth statistics static CV_PossibleValue_t nettimeout_cons_t[] = {{TICRATE/7, "MIN"}, {60*TICRATE, "MAX"}, {0, NULL}}; -consvar_t cv_nettimeout = CVAR_INIT ("nettimeout", "105", CV_CALL|CV_SAVE, nettimeout_cons_t, NetTimeout_OnChange); +consvar_t cv_nettimeout = CVAR_INIT ("nettimeout", "210", CV_CALL|CV_SAVE, nettimeout_cons_t, NetTimeout_OnChange); //static CV_PossibleValue_t jointimeout_cons_t[] = {{5*TICRATE, "MIN"}, {60*TICRATE, "MAX"}, {0, NULL}}; -consvar_t cv_jointimeout = CVAR_INIT ("jointimeout", "105", CV_CALL|CV_SAVE, nettimeout_cons_t, JoinTimeout_OnChange); +consvar_t cv_jointimeout = CVAR_INIT ("jointimeout", "210", CV_CALL|CV_SAVE, nettimeout_cons_t, JoinTimeout_OnChange); consvar_t cv_maxping = CVAR_INIT ("maxdelay", "20", CV_SAVE, CV_Unsigned, NULL); consvar_t cv_lagless = CVAR_INIT ("lagless", "Off", CV_SAVE|CV_NETVAR|CV_CALL, CV_OnOff, Lagless_OnChange); diff --git a/src/d_netcmd.h b/src/d_netcmd.h index 3a67fc458..1cc3a61d4 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -83,7 +83,6 @@ extern consvar_t cv_tripleorbinaut, cv_quadorbinaut, cv_dualjawz; extern consvar_t cv_kartminimap; extern consvar_t cv_kartcheck; -extern consvar_t cv_kartinvinsfx; extern consvar_t cv_kartspeed; extern consvar_t cv_kartbumpers; extern consvar_t cv_kartfrantic; diff --git a/src/d_netfil.c b/src/d_netfil.c index ca2ee3886..dcce1767c 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -1007,7 +1007,6 @@ static void SV_EndFileSend(INT32 node) filestosend--; } -#define PACKETPERTIC net_bandwidth/(TICRATE*software_MAXPACKETLENGTH) #define FILEFRAGMENTSIZE (software_MAXPACKETLENGTH - (FILETXHEADER + BASEPACKETSIZE)) /** Handles file transmission @@ -1040,14 +1039,7 @@ void FileSendTicker(void) if (!filestosend) // No file to send return; - if (cv_downloadspeed.value) // New behavior - packetsent = cv_downloadspeed.value; - else // Old behavior - { - packetsent = PACKETPERTIC; - if (!packetsent) - packetsent = 1; - } + packetsent = cv_downloadspeed.value; netbuffer->packettype = PT_FILEFRAGMENT; diff --git a/src/d_player.h b/src/d_player.h index 5675dfb5e..7d0f20058 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -268,7 +268,9 @@ typedef enum #define TUMBLEBOUNCES 3 #define TUMBLEGRAVITY (4*FRACUNIT) -#define TRIPWIRETIME (TICRATE) +#define TRIPWIRETIME (15) + +#define BALLHOGINCREMENT (7) //} @@ -486,9 +488,11 @@ typedef struct player_s UINT16 flamemeter; // Flame Shield dash meter left UINT8 flamelength; // Flame Shield dash meter, number of segments + UINT16 ballhogcharge; // Ballhog charge up -- the higher this value, the more projectiles + UINT16 hyudorotimer; // Duration of the Hyudoro offroad effect itself SINT8 stealingtimer; // if >0 you are stealing, if <0 you are being stolen from - mobj_t *hoverhyudoro; // First hyudoro hovering next to player + mobj_t *hoverhyudoro; // First hyudoro hovering next to player UINT16 sneakertimer; // Duration of a Sneaker Boost (from Sneakers or level boosters) UINT8 numsneakers; // Number of stacked sneaker effects diff --git a/src/deh_tables.c b/src/deh_tables.c index 8ea363fd9..2fb952890 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -336,6 +336,7 @@ actionpointer_t actionpointers[] = {{A_ReaperThinker}, "A_REAPERTHINKER"}, {{A_FlameShieldPaper}, "A_FLAMESHIELDPAPER"}, {{A_InvincSparkleRotate}, "A_INVINCSPARKLEROTATE"}, + {{A_SpawnItemDebrisCloud}, "A_SPAWNITEMDEBRISCLOUD"}, {{NULL}, "NONE"}, @@ -3276,6 +3277,10 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_RANDOMITEMPOP4", //} + "S_ITEM_DEBRIS", + "S_ITEM_DEBRIS_CLOUD_SPAWNER1", + "S_ITEM_DEBRIS_CLOUD_SPAWNER2", + "S_ITEMICON", // Item capsules @@ -3758,8 +3763,20 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_GROW_PARTICLE", // Shrink - "S_SHRINK_GUN", + "S_SHRINK_POHBEE", + "S_SHRINK_POHBEE2", + "S_SHRINK_POHBEE3", + "S_SHRINK_POHBEE4", + "S_SHRINK_POHBEE5", + "S_SHRINK_POHBEE6", + "S_SHRINK_POHBEE7", + "S_SHRINK_POHBEE8", + "S_SHRINK_CHAIN", + + "S_SHRINK_GUN", + "S_SHRINK_GUN_OVERLAY", + "S_SHRINK_LASER", "S_SHRINK_PARTICLE", @@ -5296,6 +5313,8 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t "MT_BRAKEDRIFT", "MT_BRAKEDUST", "MT_DRIFTDUST", + "MT_ITEM_DEBRIS", + "MT_ITEM_DEBRIS_CLOUD_SPAWNER", "MT_DRIFTELECTRICITY", "MT_DRIFTELECTRICSPARK", "MT_JANKSPARK", diff --git a/src/info.c b/src/info.c index 9e8108f76..4a64fcb4a 100644 --- a/src/info.c +++ b/src/info.c @@ -530,6 +530,7 @@ char sprnames[NUMSPRITES + 1][5] = "RNDM", // Random Item Box "SBOX", // Sphere Box (for Battle) "RPOP", // Random Item Box Pop + "ITRI", // Item Box Debris "SGNS", // Signpost sparkle "FAST", // Speed boost trail "DSHR", // Speed boost dust release @@ -575,7 +576,9 @@ char sprnames[NUMSPRITES + 1][5] = "HYUU", // Hyudoro "GRWP", // Grow "POHB", // Shrink Poh-Bee - "SHRG", // Shrink gun / laser + "POHC", // Shrink Poh-Bee chain + "SHRG", // Shrink gun + "SHRL", // Shrink laser "SINK", // Kitchen Sink "SITR", // Kitchen Sink Trail "KBLN", // Battle Mode Bumper @@ -3846,7 +3849,7 @@ state_t states[NUMSTATES] = {SPR_RNDM, 18|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RANDOMITEM11}, // S_RANDOMITEM10 {SPR_RNDM, 20|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RANDOMITEM12}, // S_RANDOMITEM11 {SPR_RNDM, 22|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RANDOMITEM1}, // S_RANDOMITEM12 - {SPR_NULL, 0, 0, {A_ItemPop}, 0, 0, S_NULL}, // S_DEADRANDOMITEM + {SPR_NULL, 0, 0, {A_ItemPop}, 0, 0, S_RANDOMITEM1}, // S_DEADRANDOMITEM {SPR_SBOX, FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX2}, // S_SPHEREBOX1 {SPR_SBOX, 2|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX3}, // S_SPHEREBOX2 @@ -3867,6 +3870,10 @@ 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_ITRI, FF_FULLBRIGHT|FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 19, 1, S_NULL}, // S_ITEM_DEBRIS + {SPR_NULL, 0, 0, {A_Repeat}, 16, S_ITEM_DEBRIS_CLOUD_SPAWNER2, S_NULL}, // S_ITEM_DEBRIS_CLOUD_SPAWNER1 + {SPR_NULL, 0, 7, {A_SpawnItemDebrisCloud}, 20, 0, S_ITEM_DEBRIS_CLOUD_SPAWNER1}, // S_ITEM_DEBRIS_CLOUD_SPAWNER2 + {SPR_NULL, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_ITEMICON {SPR_ICAP, FF_ADD|0, -1, {NULL}, 0, 0, S_NULL}, // S_ITEMCAPSULE @@ -4319,10 +4326,22 @@ state_t states[NUMSTATES] = {SPR_GRWP, FF_FULLBRIGHT|FF_ANIMATE, 13, {NULL}, 7, 1, S_NULL}, // S_GROW_PARTICLE + {SPR_POHB, 0, 1, {NULL}, 0, 0, S_SHRINK_POHBEE2}, // S_SHRINK_POHBEE + {SPR_POHB, 1, 1, {NULL}, 0, 0, S_SHRINK_POHBEE3}, // S_SHRINK_POHBEE2 + {SPR_POHB, 0, 1, {NULL}, 0, 0, S_SHRINK_POHBEE4}, // S_SHRINK_POHBEE3 + {SPR_POHB, 2, 1, {NULL}, 0, 0, S_SHRINK_POHBEE5}, // S_SHRINK_POHBEE4 + {SPR_POHB, 0, 1, {NULL}, 0, 0, S_SHRINK_POHBEE6}, // S_SHRINK_POHBEE5 + {SPR_POHB, 3, 1, {NULL}, 0, 0, S_SHRINK_POHBEE7}, // S_SHRINK_POHBEE6 + {SPR_POHB, 0, 1, {NULL}, 0, 0, S_SHRINK_POHBEE8}, // S_SHRINK_POHBEE7 + {SPR_POHB, 2, 1, {NULL}, 0, 0, S_SHRINK_POHBEE}, // S_SHRINK_POHBEE8 + + {SPR_POHC, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SHRINK_CHAIN + {SPR_SHRG, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SHRINK_GUN - {SPR_POHB, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SHRINK_CHAIN - {SPR_SHRG, FF_FULLBRIGHT|1, -1, {NULL}, 0, 0, S_NULL}, // S_SHRINK_LASER - {SPR_SHRG, FF_FULLBRIGHT|2, -1, {NULL}, 0, 0, S_NULL}, // S_SHRINK_PARTICLE + {SPR_SHRG, FF_FULLBRIGHT|1, -1, {NULL}, 0, 0, S_NULL}, // S_SHRINK_GUN_OVERLAY + + {SPR_SHRL, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_SHRINK_LASER + {SPR_SHRL, FF_FULLBRIGHT|1, -1, {NULL}, 0, 0, S_NULL}, // S_SHRINK_PARTICLE {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 @@ -22531,7 +22550,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = MT_RANDOMITEMPOP, // damage sfx_None, // activesound MF_SLIDEME|MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags - S_NULL // raisestate + S_RANDOMITEM1 // raisestate }, { // MT_SPHEREBOX @@ -23128,6 +23147,60 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_ITEM_DEBRIS + -1, // doomednum + S_ITEM_DEBRIS, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 32*FRACUNIT, // radius + 32*FRACUNIT, // height + 0, // display offset + 0, // mass + 0, // damage + sfx_None, // activesound + MF_DONTENCOREMAP, // flags + S_NULL // raisestate + }, + + { // MT_ITEM_DEBRIS_CLOUD_SPAWNER + -1, // doomednum + S_ITEM_DEBRIS_CLOUD_SPAWNER1, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 32*FRACUNIT, // radius + 32*FRACUNIT, // height + 0, // display offset + 0, // mass + 0, // damage + sfx_None, // activesound + MF_NOSECTOR|MF_NOBLOCKMAP|MF_RUNSPAWNFUNC, // flags + S_NULL // raisestate + }, + { // MT_DRIFTELECTRICITY -1, // doomednum S_DRIFTELECTRICITY, // spawnstate @@ -23739,7 +23812,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_hogbom, // deathsound 80*FRACUNIT, // speed - 16*FRACUNIT, // radius + 26*FRACUNIT, // radius 32*FRACUNIT, // height 0, // display offset 100, // mass @@ -24075,7 +24148,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = { // MT_SHRINK_POHBEE -1, // doomednum - S_HYUDORO, // spawnstate + S_SHRINK_POHBEE, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -24096,7 +24169,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // mass 0, // damage sfx_None, // activesound - MF_NOCLIP|MF_NOCLIPTHING|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags + MF_NOCLIP|MF_NOCLIPTHING|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_DONTENCOREMAP|MF_NOSQUISH, // flags S_NULL // raisestate }, @@ -24216,7 +24289,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_tossed, // seesound 8, // reactiontime sfx_None, // attacksound - 256*FRACUNIT, // painstate + S_NULL, // painstate 100, // painchance sfx_None, // painsound S_NULL, // meleestate diff --git a/src/info.h b/src/info.h index 383dfd29f..6fe164c0e 100644 --- a/src/info.h +++ b/src/info.h @@ -289,6 +289,7 @@ enum actionnum A_REAPERTHINKER, A_FLAMESHIELDPAPER, A_INVINCSPARKLEROTATE, + A_SPAWNITEMDEBRISCLOUD, NUMACTIONS }; @@ -561,6 +562,7 @@ void A_ReaperThinker(); void A_MementosTPParticles(); void A_FlameShieldPaper(); void A_InvincSparkleRotate(); +void A_SpawnItemDebrisCloud(); extern boolean actionsoverridden[NUMACTIONS]; @@ -1074,6 +1076,7 @@ typedef enum sprite SPR_RNDM, // Random Item Box SPR_SBOX, // Sphere Box (for Battle) SPR_RPOP, // Random Item Box Pop + SPR_ITRI, // Item Box Debris SPR_SGNS, // Signpost sparkle SPR_FAST, // Speed boost trail SPR_DSHR, // Speed boost dust release @@ -1119,7 +1122,9 @@ typedef enum sprite SPR_HYUU, // Hyudoro SPR_GRWP, // Grow SPR_POHB, // Shrink Poh-Bee - SPR_SHRG, // Shrink gun / laser + SPR_POHC, // Shrink Poh-Bee chain + SPR_SHRG, // Shrink gun + SPR_SHRL, // Shrink laser SPR_SINK, // Kitchen Sink SPR_SITR, // Kitchen Sink Trail SPR_KBLN, // Battle Mode Bumper @@ -4268,6 +4273,10 @@ typedef enum state S_RANDOMITEMPOP4, //} + S_ITEM_DEBRIS, + S_ITEM_DEBRIS_CLOUD_SPAWNER1, + S_ITEM_DEBRIS_CLOUD_SPAWNER2, + S_ITEMICON, // Item capsules @@ -4750,8 +4759,20 @@ typedef enum state S_GROW_PARTICLE, // Shrink - S_SHRINK_GUN, + S_SHRINK_POHBEE, + S_SHRINK_POHBEE2, + S_SHRINK_POHBEE3, + S_SHRINK_POHBEE4, + S_SHRINK_POHBEE5, + S_SHRINK_POHBEE6, + S_SHRINK_POHBEE7, + S_SHRINK_POHBEE8, + S_SHRINK_CHAIN, + + S_SHRINK_GUN, + S_SHRINK_GUN_OVERLAY, + S_SHRINK_LASER, S_SHRINK_PARTICLE, @@ -6324,6 +6345,8 @@ typedef enum mobj_type MT_BRAKEDRIFT, MT_BRAKEDUST, MT_DRIFTDUST, + MT_ITEM_DEBRIS, + MT_ITEM_DEBRIS_CLOUD_SPAWNER, MT_DRIFTELECTRICITY, MT_DRIFTELECTRICSPARK, MT_JANKSPARK, diff --git a/src/k_collide.c b/src/k_collide.c index a23801ccc..9d582da59 100644 --- a/src/k_collide.c +++ b/src/k_collide.c @@ -11,6 +11,7 @@ #include "hu_stuff.h" // Sink snipe print #include "doomdef.h" // Sink snipe print #include "g_game.h" // Sink snipe print +#include "k_objects.h" angle_t K_GetCollideAngle(mobj_t *t1, mobj_t *t2) { @@ -265,8 +266,7 @@ boolean K_EggItemCollide(mobj_t *t1, mobj_t *t2) } else { - mobj_t *poof = P_SpawnMobj(t1->x, t1->y, t1->z, MT_EXPLODE); - S_StartSound(poof, t1->info->deathsound); + Obj_SpawnItemDebrisEffects(t1, t2); #if 0 // Eggbox snipe! diff --git a/src/k_hud.c b/src/k_hud.c index 9d9c4a418..96635584e 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -1206,6 +1206,16 @@ static void K_drawKartItem(void) else localpatch = kp_nodraw; } + else if (stplyr->ballhogcharge > 0) + { + itembar = stplyr->ballhogcharge; + maxl = (((stplyr->itemamount-1) * BALLHOGINCREMENT) + 1); + + if (leveltime & 1) + localpatch = kp_ballhog[offset]; + else + localpatch = kp_nodraw; + } else if (stplyr->rocketsneakertimer > 1) { itembar = stplyr->rocketsneakertimer; diff --git a/src/k_kart.c b/src/k_kart.c index edefc6895..e14995d05 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -241,7 +241,6 @@ void K_RegisterKartStuff(void) CV_RegisterVar(&cv_kartminimap); CV_RegisterVar(&cv_kartcheck); - CV_RegisterVar(&cv_kartinvinsfx); CV_RegisterVar(&cv_kartspeed); CV_RegisterVar(&cv_kartbumpers); CV_RegisterVar(&cv_kartfrantic); @@ -494,6 +493,10 @@ static void K_KartGetItemResult(player_t *player, SINT8 getitem) player->itemtype = KITEM_JAWZ; player->itemamount = 2; break; + case KITEM_BALLHOG: // Ballhog x5 + player->itemtype = KITEM_BALLHOG; + player->itemamount = 5; + break; default: if (getitem <= 0 || getitem >= NUMKARTRESULTS) // Sad (Fallback) { @@ -4228,7 +4231,6 @@ static mobj_t *K_SpawnKartMissile(mobj_t *source, mobjtype_t type, angle_t an, I if (source->player != NULL) { - if (source->player->itemscale == ITEMSCALE_SHRINK) { // Nerf the base item speed a bit. @@ -4341,6 +4343,11 @@ static mobj_t *K_SpawnKartMissile(mobj_t *source, mobjtype_t type, angle_t an, I S_StartSound(th, sfx_s3kbfl); S_StartSound(th, sfx_cdfm35); break; + case MT_BALLHOG: + // Contra spread shot scale up + th->destscale = th->destscale << 1; + th->scalespeed = abs(th->destscale - th->scale) / (2*TICRATE); + break; default: break; } @@ -5095,7 +5102,7 @@ static mobj_t *K_FindLastTrailMobj(player_t *player) return trail; } -mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t mapthing, INT32 defaultDir, INT32 altthrow) +mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t mapthing, INT32 defaultDir, INT32 altthrow, angle_t angleOffset) { mobj_t *mo; INT32 dir; @@ -5161,46 +5168,21 @@ mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t mapthing, if (missile) // Shootables { - if (mapthing == MT_BALLHOG) // Messy + if (dir == -1 && mapthing != MT_SPB) { - mo = NULL; // can't return multiple projectiles - if (dir == -1) - { - // Shoot backward - K_SpawnKartMissile(player->mo, mapthing, (player->mo->angle + ANGLE_180) - 0x06000000, 0, PROJSPEED/8); - K_SpawnKartMissile(player->mo, mapthing, (player->mo->angle + ANGLE_180) - 0x03000000, 0, PROJSPEED/8); - K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + ANGLE_180, 0, PROJSPEED/8); - K_SpawnKartMissile(player->mo, mapthing, (player->mo->angle + ANGLE_180) + 0x03000000, 0, PROJSPEED/8); - K_SpawnKartMissile(player->mo, mapthing, (player->mo->angle + ANGLE_180) + 0x06000000, 0, PROJSPEED/8); - } - else - { - // Shoot forward - K_SpawnKartMissile(player->mo, mapthing, player->mo->angle - 0x06000000, 0, PROJSPEED); - K_SpawnKartMissile(player->mo, mapthing, player->mo->angle - 0x03000000, 0, PROJSPEED); - K_SpawnKartMissile(player->mo, mapthing, player->mo->angle, 0, PROJSPEED); - K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + 0x03000000, 0, PROJSPEED); - K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + 0x06000000, 0, PROJSPEED); - } + // Shoot backward + mo = K_SpawnKartMissile(player->mo, mapthing, (player->mo->angle + ANGLE_180) + angleOffset, 0, PROJSPEED/8); } else { - if (dir == -1 && mapthing != MT_SPB) - { - // Shoot backward - mo = K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + ANGLE_180, 0, PROJSPEED/8); - } - else - { - // Shoot forward - mo = K_SpawnKartMissile(player->mo, mapthing, player->mo->angle, 0, PROJSPEED); - } + // Shoot forward + mo = K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + angleOffset, 0, PROJSPEED); + } - if (mapthing == MT_DROPTARGET && mo) - { - mo->reactiontime = TICRATE/2; - P_SetMobjState(mo, mo->info->painstate); - } + if (mapthing == MT_DROPTARGET && mo) + { + mo->reactiontime = TICRATE/2; + P_SetMobjState(mo, mo->info->painstate); } } else @@ -5796,7 +5778,7 @@ void K_DoInvincibility(player_t *player, tic_t time) } else //used to be "if (P_IsDisplayPlayer(player) == false)" { - S_StartSound(player->mo, (cv_kartinvinsfx.value ? sfx_alarmi : sfx_kinvnc)); + S_StartSound(player->mo, sfx_alarmi); } P_RestoreMusic(player); @@ -6152,6 +6134,10 @@ mobj_t *K_CreatePaperItem(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8 newType = KITEM_JAWZ; newAmount = 2; break; + case KITEM_BALLHOG: // Ballhog x5 + newType = KITEM_BALLHOG; + newAmount = 5; + break; default: newType = i; newAmount = 1; @@ -7012,20 +6998,10 @@ static void K_UpdateInvincibilitySounds(player_t *player) if (player->mo->health > 0 && !P_IsLocalPlayer(player)) // used to be !P_IsDisplayPlayer(player) { - if (cv_kartinvinsfx.value) - { - if (player->invincibilitytimer > 0) // Prioritize invincibility - sfxnum = sfx_alarmi; - else if (player->growshrinktimer > 0) - sfxnum = sfx_alarmg; - } - else - { - if (player->invincibilitytimer > 0) - sfxnum = sfx_kinvnc; - else if (player->growshrinktimer > 0) - sfxnum = sfx_kgrow; - } + if (player->invincibilitytimer > 0) // Prioritize invincibility + sfxnum = sfx_alarmi; + else if (player->growshrinktimer > 0) + sfxnum = sfx_alarmg; } if (sfxnum != sfx_None && !S_SoundPlaying(player->mo, sfxnum)) @@ -7036,8 +7012,6 @@ static void K_UpdateInvincibilitySounds(player_t *player) S_StopSoundByID(player->mo, this); STOPTHIS(sfx_alarmi); STOPTHIS(sfx_alarmg); - STOPTHIS(sfx_kinvnc); - STOPTHIS(sfx_kgrow); #undef STOPTHIS } @@ -8430,7 +8404,7 @@ INT16 K_UpdateSteeringValue(INT16 inputSteering, INT16 destSteering) // player->steering is the turning value, but with easing applied. // Keeps micro-turning from old easing, but isn't controller dependent. - const INT16 amount = KART_FULLTURN/4; + const INT16 amount = KART_FULLTURN/3; INT16 diff = destSteering - inputSteering; INT16 outputSteering = inputSteering; @@ -9024,7 +8998,7 @@ void K_StripItems(player_t *player) player->curshield = KSHIELD_NONE; player->bananadrag = 0; - + player->ballhogcharge = 0; player->sadtimer = 0; K_UpdateHnextList(player, true); @@ -9529,7 +9503,7 @@ void K_AdjustPlayerFriction(player_t *player) } // Wipeout slowdown - if (player->spinouttimer && player->wipeoutslow) + if (player->speed > 0 && player->spinouttimer && player->wipeoutslow) { if (player->offroad) player->mo->friction -= 4912; @@ -9744,7 +9718,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) { if (ATTACK_IS_DOWN) { - K_ThrowKartItem(player, false, MT_EGGMANITEM, -1, 0); + K_ThrowKartItem(player, false, MT_EGGMANITEM, -1, 0, 0); K_PlayAttackTaunt(player->mo); player->pflags &= ~PF_EGGMANOUT; K_UpdateHnextList(player, true); @@ -9852,7 +9826,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } else if (ATTACK_IS_DOWN && (player->pflags & PF_ITEMOUT)) // Banana x3 thrown { - K_ThrowKartItem(player, false, MT_BANANA, -1, 0); + K_ThrowKartItem(player, false, MT_BANANA, -1, 0, 0); K_PlayAttackTaunt(player->mo); player->itemamount--; K_UpdateHnextList(player, false); @@ -9915,7 +9889,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } else if (ATTACK_IS_DOWN && (player->pflags & PF_ITEMOUT)) // Orbinaut x3 thrown { - K_ThrowKartItem(player, true, MT_ORBINAUT, 1, 0); + K_ThrowKartItem(player, true, MT_ORBINAUT, 1, 0, 0); K_PlayAttackTaunt(player->mo); player->itemamount--; K_UpdateHnextList(player, false); @@ -9957,9 +9931,9 @@ void K_MoveKartPlayer(player_t *player, boolean onground) else if (ATTACK_IS_DOWN && HOLDING_ITEM && (player->pflags & PF_ITEMOUT)) // Jawz thrown { if (player->throwdir == 1 || player->throwdir == 0) - K_ThrowKartItem(player, true, MT_JAWZ, 1, 0); + K_ThrowKartItem(player, true, MT_JAWZ, 1, 0, 0); else if (player->throwdir == -1) // Throwing backward gives you a dud that doesn't home in - K_ThrowKartItem(player, true, MT_JAWZ_DUD, -1, 0); + K_ThrowKartItem(player, true, MT_JAWZ_DUD, -1, 0, 0); K_PlayAttackTaunt(player->mo); player->itemamount--; K_UpdateHnextList(player, false); @@ -9985,7 +9959,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } else if (ATTACK_IS_DOWN && (player->pflags & PF_ITEMOUT)) { - K_ThrowKartItem(player, false, MT_SSMINE, 1, 1); + K_ThrowKartItem(player, false, MT_SSMINE, 1, 1, 0); K_PlayAttackTaunt(player->mo); player->itemamount--; player->pflags &= ~PF_ITEMOUT; @@ -10020,7 +9994,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } else if (ATTACK_IS_DOWN && (player->pflags & PF_ITEMOUT)) { - K_ThrowKartItem(player, (player->throwdir > 0), MT_DROPTARGET, -1, 0); + K_ThrowKartItem(player, (player->throwdir > 0), MT_DROPTARGET, -1, 0, 0); K_PlayAttackTaunt(player->mo); player->itemamount--; player->pflags &= ~PF_ITEMOUT; @@ -10028,18 +10002,63 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } break; case KITEM_BALLHOG: - if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) + if (!HOLDING_ITEM && NO_HYUDORO) { - player->itemamount--; - K_ThrowKartItem(player, true, MT_BALLHOG, 1, 0); - K_PlayAttackTaunt(player->mo); + INT32 ballhogmax = ((player->itemamount-1) * BALLHOGINCREMENT) + 1; + + if ((cmd->buttons & BT_ATTACK) && (player->pflags & PF_HOLDREADY) + && (player->ballhogcharge < ballhogmax)) + { + player->ballhogcharge++; + } + else + { + if (cmd->buttons & BT_ATTACK) + { + player->pflags &= ~PF_HOLDREADY; + } + else + { + player->pflags |= PF_HOLDREADY; + } + + if (player->ballhogcharge > 0) + { + INT32 numhogs = min((player->ballhogcharge / BALLHOGINCREMENT) + 1, player->itemamount); + + if (numhogs <= 1) + { + player->itemamount--; + K_ThrowKartItem(player, true, MT_BALLHOG, 1, 0, 0); + } + else + { + angle_t cone = 0x01800000 * (numhogs-1); + angle_t offsetAmt = (cone * 2) / (numhogs-1); + angle_t angleOffset = cone; + INT32 i; + + player->itemamount -= numhogs; + + for (i = 0; i < numhogs; i++) + { + K_ThrowKartItem(player, true, MT_BALLHOG, 1, 0, angleOffset); + angleOffset -= offsetAmt; + } + } + + player->ballhogcharge = 0; + K_PlayAttackTaunt(player->mo); + player->pflags &= ~PF_HOLDREADY; + } + } } break; case KITEM_SPB: if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) { player->itemamount--; - K_ThrowKartItem(player, true, MT_SPB, 1, 0); + K_ThrowKartItem(player, true, MT_SPB, 1, 0, 0); K_PlayAttackTaunt(player->mo); } break; @@ -10076,7 +10095,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } else //used to be "if (P_IsDisplayPlayer(player) == false)" { - S_StartSound(player->mo, (cv_kartinvinsfx.value ? sfx_alarmg : sfx_kgrow)); + S_StartSound(player->mo, sfx_alarmg); } P_RestoreMusic(player); @@ -10141,7 +10160,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (player->bubbleblowup > bubbletime*2) { - K_ThrowKartItem(player, (player->throwdir > 0), MT_BUBBLESHIELDTRAP, -1, 0); + K_ThrowKartItem(player, (player->throwdir > 0), MT_BUBBLESHIELDTRAP, -1, 0, 0); K_PlayAttackTaunt(player->mo); player->bubbleblowup = 0; player->bubblecool = 0; @@ -10291,7 +10310,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } else if (ATTACK_IS_DOWN && HOLDING_ITEM && (player->pflags & PF_ITEMOUT)) // Sink thrown { - K_ThrowKartItem(player, false, MT_SINK, 1, 2); + K_ThrowKartItem(player, false, MT_SINK, 1, 2, 0); K_PlayAttackTaunt(player->mo); player->itemamount--; player->pflags &= ~PF_ITEMOUT; diff --git a/src/k_kart.h b/src/k_kart.h index 4529b2611..7b1e0f6ae 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -90,7 +90,7 @@ void K_SpawnWipeoutTrail(mobj_t *mo); void K_SpawnDraftDust(mobj_t *mo); void K_DriftDustHandling(mobj_t *spawner); void K_Squish(mobj_t *mo); -mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t mapthing, INT32 defaultDir, INT32 altthrow); +mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t mapthing, INT32 defaultDir, INT32 altthrow, angle_t angleOffset); void K_PuntMine(mobj_t *mine, mobj_t *punter); void K_DoSneaker(player_t *player, INT32 type); void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, UINT8 sound); diff --git a/src/k_menudef.c b/src/k_menudef.c index ed1e33c42..d97083509 100644 --- a/src/k_menudef.c +++ b/src/k_menudef.c @@ -871,9 +871,6 @@ menuitem_t OPTIONS_Sound[] = {IT_STRING | IT_CVAR, "Character Voices", "Set how often to play character voices in game.", NULL, {.cvar = &cv_kartvoices}, 0, 0}, - {IT_STRING | IT_CVAR, "Powerup Warning", "Set how to warn you from other player's powerups such as Invincibility.", - NULL, {.cvar = &cv_kartinvinsfx}, 0, 0}, - {IT_SPACE | IT_NOTHING, NULL, NULL, NULL, {NULL}, 0, 0}, diff --git a/src/k_objects.h b/src/k_objects.h index 7561c5d6e..8936850f9 100644 --- a/src/k_objects.h +++ b/src/k_objects.h @@ -15,6 +15,11 @@ void Obj_ShrinkGunRemoved(mobj_t *gun); boolean Obj_ShrinkLaserCollide(mobj_t *gun, mobj_t *victim); void Obj_CreateShrinkPohbees(player_t *owner); +/* Item Debris */ +void Obj_SpawnItemDebrisEffects(mobj_t *collectible, mobj_t *collector); +void Obj_ItemDebrisThink(mobj_t *debris); +fixed_t Obj_ItemDebrisBounce(mobj_t *debris, fixed_t momz); + /* SPB */ void Obj_SPBThink(mobj_t *spb); diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 7078b2258..cfab3696e 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -336,6 +336,8 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->flamemeter); else if (fastcmp(field,"flamelength")) lua_pushinteger(L, plr->flamelength); + else if (fastcmp(field,"ballhogcharge")) + lua_pushinteger(L, plr->ballhogcharge); else if (fastcmp(field,"hyudorotimer")) lua_pushinteger(L, plr->hyudorotimer); else if (fastcmp(field,"stealingtimer")) @@ -696,6 +698,8 @@ static int player_set(lua_State *L) plr->flamemeter = luaL_checkinteger(L, 3); else if (fastcmp(field,"flamelength")) plr->flamelength = luaL_checkinteger(L, 3); + else if (fastcmp(field,"ballhogcharge")) + plr->ballhogcharge = luaL_checkinteger(L, 3); else if (fastcmp(field,"hyudorotimer")) plr->hyudorotimer = luaL_checkinteger(L, 3); else if (fastcmp(field,"stealingtimer")) diff --git a/src/objects/Sourcefile b/src/objects/Sourcefile index 4f0dacad7..7053e83cf 100644 --- a/src/objects/Sourcefile +++ b/src/objects/Sourcefile @@ -1,3 +1,4 @@ hyudoro.c shrink.c +item-debris.c spb.c diff --git a/src/objects/item-debris.c b/src/objects/item-debris.c new file mode 100644 index 000000000..a5ddd5842 --- /dev/null +++ b/src/objects/item-debris.c @@ -0,0 +1,237 @@ +#include "../doomdef.h" +#include "../d_player.h" +#include "../m_random.h" +#include "../k_kart.h" +#include "../k_objects.h" +#include "../p_local.h" +#include "../r_main.h" +#include "../s_sound.h" + +// TODO: general function +static fixed_t K_GetPlayerSpeedRatio(player_t *player) +{ + return FixedDiv(player->speed, + K_GetKartSpeed(player, false, false)); +} + +#define debris_type(o) ((o)->extravalue1) +#define debris_bouncesleft(o) ((o)->threshold) + +enum { + DEBRIS_ALPHA, + DEBRIS_BETA, + + NUM_DEBRIS_TYPES +}; + +struct debris_config { + mobj_t * origin; + angle_t angle; + fixed_t speed; + fixed_t scale; + UINT8 type; +}; + +static fixed_t +get_speed_ratio (mobj_t *thing) +{ + return thing->player ? + K_GetPlayerSpeedRatio(thing->player) : FRACUNIT; +} + +static void +spawn_debris +( const struct debris_config * config, + INT32 angle) +{ + const fixed_t height_table[NUM_DEBRIS_TYPES] = { + 50*FRACUNIT, + 35*FRACUNIT, + }; + + mobj_t *debris = P_SpawnMobjFromMobj( + config->origin, 0, 0, 0, MT_ITEM_DEBRIS); + + debris_type(debris) = config->type; + debris_bouncesleft(debris) = 1; + + P_InstaThrust(debris, + config->angle + angle, + config->speed); + + P_SetObjectMomZ(debris, + FixedMul(config->scale, + height_table[config->type]), + false); + + debris->destscale = + FixedMul(config->scale, 3 * debris->scale); + P_SetScale(debris, debris->destscale); + + // Pass down color to dust particles + debris->color = config->origin->color; +} + +static void +spawn_cloud +( mobj_t * collectible, + mobj_t * collector, + fixed_t base_speed) +{ + const fixed_t min_speed = 90 * collectible->scale; + + const fixed_t scale = FixedDiv( + max(base_speed, min_speed), min_speed); + + const INT16 spacing = + (collectible->radius / 2) / collectible->scale; + + INT32 i; + + // Most of this code is from p_inter.c, MT_ITEMCAPSULE + + // dust effects + for (i = 0; i < 10; i++) + { + mobj_t *puff = P_SpawnMobjFromMobj( + collectible, + P_RandomRange(-spacing, spacing) * FRACUNIT, + P_RandomRange(-spacing, spacing) * FRACUNIT, + P_RandomRange(0, 4 * spacing) * FRACUNIT, + MT_SPINDASHDUST + ); + + puff->color = collector->color; + puff->colorized = true; + + puff->destscale = FixedMul(puff->destscale, scale); + P_SetScale(puff, puff->destscale); + + puff->momz = puff->scale * P_MobjFlip(puff); + + P_InitAngle(puff, R_PointToAngle2( + collectible->x, + collectible->y, + puff->x, + puff->y)); + + P_Thrust(puff, puff->angle, 3 * puff->scale); + + puff->momx += collector->momx; + puff->momy += collector->momy; + puff->momz += collector->momz; + } +} + +static void +rotate3d (mobj_t *debris) +{ + const UINT8 steps = 30; + + debris->rollangle = + M_RandomKey(steps) * (ANGLE_MAX / steps); +} + +void +Obj_SpawnItemDebrisEffects +( mobj_t * collectible, + mobj_t * collector) +{ + const fixed_t min_speed = 80 * collectible->scale; + + fixed_t base_speed = FixedMul(75 * mapobjectscale, + get_speed_ratio(collector)); + + struct debris_config config; + + // Delayed effect for puffs of smoke that stick to and + // glide off of the player + mobj_t *spawner = P_SpawnMobjFromMobj(collectible, + 0, 0, 0, MT_ITEM_DEBRIS_CLOUD_SPAWNER); + + P_SetTarget(&spawner->target, collector); + + config.origin = collectible; + config.angle = K_MomentumAngle(collector); + config.speed = max(base_speed, min_speed); + config.scale = FixedDiv(config.speed, min_speed); + + config.type = DEBRIS_ALPHA; + + spawn_debris(&config, ANGLE_11hh); + spawn_debris(&config, -(ANGLE_11hh)); + + config.type = DEBRIS_BETA; + + spawn_debris(&config, 3*ANGLE_22h/2); + spawn_debris(&config, 3*ANGLE_22h/4); + spawn_debris(&config, 0); + spawn_debris(&config, -(3*ANGLE_22h/4)); + spawn_debris(&config, -(3*ANGLE_22h/2)); + + spawn_cloud(collectible, collector, base_speed); + + S_StartSound(spawner, sfx_kc2e); + S_StartSound(spawner, sfx_s1c9); +} + +void +Obj_ItemDebrisThink (mobj_t *debris) +{ + const UINT8 frame = (debris->frame & FF_FRAMEMASK); + + if (debris->momz == 0) + { + P_KillMobj(debris, NULL, NULL, DMG_NORMAL); + return; + } + + rotate3d(debris); + + if (frame % 3 == 1) + { + mobj_t *ghost = P_SpawnGhostMobj(debris); + + ghost->fuse = 3; + } + + if (debris_type(debris) == DEBRIS_ALPHA) + { + mobj_t *dust = P_SpawnMobjFromMobj( + debris, 0, 0, 0, MT_SPINDASHDUST); + + P_SetScale(dust, (dust->destscale /= 3)); + + dust->color = debris->color; + dust->colorized = true; + + dust->momx = debris->momx / 4; + dust->momy = debris->momy / 4; + dust->momz = debris->momz / 4; + } +} + +fixed_t +Obj_ItemDebrisBounce +( mobj_t * debris, + fixed_t momz) +{ + if (debris_bouncesleft(debris) <= 0) + { + P_KillMobj(debris, NULL, NULL, DMG_NORMAL); + return 0; + } + + momz = -(momz); + + if (debris_type(debris) == DEBRIS_BETA) + { + momz /= 2; + } + + debris_bouncesleft(debris)--; + + S_StartSound(debris, sfx_cdfm47); + + return momz; +} diff --git a/src/objects/shrink.c b/src/objects/shrink.c index 017c19829..241164aa7 100644 --- a/src/objects/shrink.c +++ b/src/objects/shrink.c @@ -34,7 +34,7 @@ // vertical flip // -#define POHBEE_HOVER (256 << FRACBITS) +#define POHBEE_HOVER (128 << FRACBITS) #define POHBEE_SPEED (128 << FRACBITS) #define POHBEE_TIME (30 * TICRATE) #define POHBEE_DIST (4096 << FRACBITS) @@ -58,6 +58,7 @@ enum #define pohbee_waypoint_cur(o) ((o)->extravalue1) #define pohbee_waypoint_dest(o) ((o)->extravalue2) #define pohbee_height(o) ((o)->movefactor) +#define pohbee_destangle(o) ((o)->movedir) #define pohbee_owner(o) ((o)->target) #define pohbee_guns(o) ((o)->hnext) @@ -68,6 +69,7 @@ enum #define gun_pohbee(o) ((o)->target) #define gun_laser(o) ((o)->tracer) #define gun_chains(o) ((o)->hprev) +#define gun_overlay(o) ((o)->itnext) #define chain_index(o) ((o)->extravalue1) @@ -238,12 +240,13 @@ static void PohbeeSpawn(mobj_t *pohbee) } PohbeeMoveTo(pohbee, newX, newY, newZ); - pohbee->angle = K_MomentumAngle(pohbee); + pohbee_destangle(pohbee) = K_MomentumAngle(pohbee); if (finalize == true) { // Move to next state pohbee_mode(pohbee) = POHBEE_MODE_ACT; + pohbee_destangle(pohbee) += ANGLE_180; } if (pathfindsuccess == true) @@ -314,7 +317,7 @@ static void ShrinkLaserThinker(mobj_t *pohbee, mobj_t *gun, mobj_t *laser) mobj_t *particle = NULL; laser->renderflags &= ~RF_DONTDRAW; - laser->color = gun->color; + laser->color = ShrinkLaserColor(pohbee); if (leveltime & 1) { @@ -343,10 +346,20 @@ static void ShrinkLaserThinker(mobj_t *pohbee, mobj_t *gun, mobj_t *laser) particle->destscale = 0; //particle->momz = 2 * particle->scale * P_MobjFlip(particle); + + if (S_SoundPlaying(laser, sfx_beam01) == false) + { + S_StartSound(laser, sfx_beam01); + } } else { laser->renderflags |= RF_DONTDRAW; + + if (S_SoundPlaying(laser, sfx_beam01) == true) + { + S_StopSound(laser); + } } } @@ -386,6 +399,7 @@ static void DoGunChains(mobj_t *gun, mobj_t *pohbee) static void ShrinkGunThinker(mobj_t *gun) { mobj_t *pohbee = gun_pohbee(gun); + skincolornum_t gunColor = SKINCOLOR_GREY; if (pohbee == NULL || P_MobjWasRemoved(pohbee) == true) { @@ -393,8 +407,23 @@ static void ShrinkGunThinker(mobj_t *gun) return; } - gun->angle = pohbee->angle; - gun->color = ShrinkLaserColor(pohbee); + if (pohbee_mode(pohbee) == POHBEE_MODE_SPAWN) + { + gun->angle = pohbee->angle; + } + + if (pohbee_owner(pohbee) != NULL && P_MobjWasRemoved(pohbee_owner(pohbee)) == false + && pohbee_owner(pohbee)->player != NULL) + { + gunColor = pohbee_owner(pohbee)->player->skincolor; + } + + gun->color = gunColor; + + if (gun_overlay(gun) != NULL && P_MobjWasRemoved(gun_overlay(gun)) == false) + { + gun_overlay(gun)->color = ShrinkLaserColor(pohbee); + } DoGunSwing(gun, pohbee); @@ -411,6 +440,7 @@ void Obj_PohbeeThinker(mobj_t *pohbee) mobj_t *gun = NULL; pohbee->momx = pohbee->momy = pohbee->momz = 0; + pohbee->spritexscale = pohbee->spriteyscale = 2*FRACUNIT; switch (pohbee_mode(pohbee)) { @@ -432,6 +462,8 @@ void Obj_PohbeeThinker(mobj_t *pohbee) break; } + pohbee->angle += AngleDeltaSigned(pohbee_destangle(pohbee), pohbee->angle) / 8; + gun = pohbee_guns(pohbee); while (gun != NULL && P_MobjWasRemoved(gun) == false) { @@ -530,7 +562,7 @@ boolean Obj_ShrinkLaserCollide(mobj_t *gun, mobj_t *victim) } else //used to be "if (P_IsDisplayPlayer(victim->player) == false)" { - S_StartSound(victim, (cv_kartinvinsfx.value ? sfx_alarmg : sfx_kgrow)); + S_StartSound(victim, sfx_alarmg); } P_RestoreMusic(victim->player); @@ -654,6 +686,7 @@ static void CreatePohbee(player_t *owner, waypoint_t *start, waypoint_t *end, UI const UINT8 numSegs = segVal * (i + 1); mobj_t *gun = P_SpawnMobjFromMobj(pohbee, 0, 0, 0, MT_SHRINK_GUN); + mobj_t *overlay = NULL; mobj_t *laser = NULL; mobj_t *prevChain = NULL; @@ -663,6 +696,13 @@ static void CreatePohbee(player_t *owner, waypoint_t *start, waypoint_t *end, UI gun_numsegs(gun) = numSegs; gun_offset(gun) = P_RandomKey(GUN_SWINGTIME); + overlay = P_SpawnMobjFromMobj(gun, 0, 0, 0, MT_OVERLAY); + + P_SetTarget(&overlay->target, gun); + P_SetTarget(&gun_overlay(gun), overlay); + + P_SetMobjState(overlay, S_SHRINK_GUN_OVERLAY); + laser = P_SpawnMobjFromMobj(gun, 0, 0, 0, MT_SHRINK_LASER); P_SetTarget(&gun_laser(gun), laser); diff --git a/src/p_enemy.c b/src/p_enemy.c index 6fbbab61a..785286d2b 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -32,6 +32,7 @@ #include "k_battle.h" #include "k_respawn.h" #include "k_collide.h" +#include "k_objects.h" #ifdef HW3SOUND #include "hardware/hw3sound.h" @@ -325,6 +326,7 @@ void A_ReaperThinker(mobj_t *actor); void A_MementosTPParticles(mobj_t *actor); void A_FlameShieldPaper(mobj_t *actor); void A_InvincSparkleRotate(mobj_t *actor); +void A_SpawnItemDebrisCloud(mobj_t *actor); //for p_enemy.c @@ -13165,9 +13167,6 @@ void A_ItemPop(mobj_t *actor) { INT32 locvar1 = var1; - mobj_t *remains; - mobjtype_t explode; - if (LUA_CallAction(A_ITEMPOP, actor)) return; @@ -13184,63 +13183,28 @@ void A_ItemPop(mobj_t *actor) actor->flags |= MF_NOCLIP; P_SetThingPosition(actor); - // item explosion - explode = mobjinfo[actor->info->damage].mass; - remains = P_SpawnMobj(actor->x, actor->y, - ((actor->eflags & MFE_VERTICALFLIP) ? (actor->z + 3*(actor->height/4) - FixedMul(mobjinfo[explode].height, actor->scale)) : (actor->z + actor->height/4)), explode); - if (actor->eflags & MFE_VERTICALFLIP) - { - remains->eflags |= MFE_VERTICALFLIP; - remains->flags2 |= MF2_OBJECTFLIP; - } - remains->destscale = actor->destscale; - P_SetScale(remains, actor->scale); + // RF_DONTDRAW will flicker as the object's fuse gets + // closer to running out (see P_FuseThink) + actor->renderflags |= RF_DONTDRAW|RF_TRANS50; + actor->color = SKINCOLOR_GREY; + actor->colorized = true; - remains = P_SpawnMobj(actor->x, actor->y, actor->z, actor->info->damage); - remains->type = actor->type; // Transfer type information - P_UnsetThingPosition(remains); - if (sector_list) - { - P_DelSeclist(sector_list); - sector_list = NULL; - } - P_SetThingPosition(remains); - remains->destscale = actor->destscale; - P_SetScale(remains, actor->scale); - remains->flags = actor->flags; // Transfer flags - remains->flags2 = actor->flags2; // Transfer flags2 - remains->fuse = actor->fuse; // Transfer respawn timer - remains->cvmem = leveltime; - remains->threshold = actor->threshold; - if (remains->threshold != 69 && remains->threshold != 70) - { - remains->threshold = 68; - } - // To insure this information doesn't have to be rediscovered every time you look at this function... - // A threshold of 0 is for a "living", ordinary random item. - // 68 means regular popped random item debris. - // 69 used to mean old Karma Item behaviour (now you can replicate this with MF2_DONTRESPAWN). - // 70 is a powered up Overtime item. - remains->skin = NULL; - remains->spawnpoint = actor->spawnpoint; - - P_SetTarget(&tmthing, remains); - - if (actor->info->deathsound) - S_StartSound(remains, actor->info->deathsound); + Obj_SpawnItemDebrisEffects(actor, actor->target); if (locvar1 == 1) P_GivePlayerSpheres(actor->target->player, actor->extravalue1); else if (locvar1 == 0) actor->target->player->itemroulette = 1; - remains->flags2 &= ~MF2_AMBUSH; - // Here at mapload in battle? if ((gametyperules & GTR_BUMPERS) && (actor->flags2 & MF2_BOSSNOTRAP)) + { numgotboxes++; - P_RemoveMobj(actor); + // do not flicker back in just yet, handled by + // P_RespawnBattleBoxes eventually + P_SetMobjState(actor, S_INVISIBLE); + } } void A_JawzChase(mobj_t *actor) @@ -14014,3 +13978,81 @@ void A_InvincSparkleRotate(mobj_t *actor) ghost->fuse = 4; } } + +// Function: A_SpawnItemDebrisCloud +// +// Description: Spawns the poofs of an exploded item box. Target is a player to spawn the particles around. +// +// var1 = Copy extravalue2 / var1 fraction of target's momentum. +// var2 = unused +// +void +A_SpawnItemDebrisCloud (mobj_t *actor) +{ + INT32 locvar1 = var1; + + mobj_t *target = actor->target; + player_t *player; + + fixed_t kartspeed; + fixed_t fade; + + if (target == NULL || target->player == NULL) + { + return; + } + + player = target->player; + kartspeed = K_GetKartSpeed(player, false, false); + + // Scale around >50% top speed + fade = FixedMul(locvar1, (FixedDiv(player->speed, + kartspeed) - FRACUNIT/2) * 2); + + if (fade < 1) + { + fade = 1; + } + + if (actor->extravalue2 > fade) + { + actor->extravalue2 = fade; + } + + // MT_ITEM_DEBRIS_CLOUD_SPAWNER + // extravalue2 from A_Repeat + fade = actor->extravalue2 * FRACUNIT / locvar1; + + // Most of this code is from p_inter.c, MT_ITEMCAPSULE + + // dust effects + { + const INT16 spacing = + (target->radius / 2) / target->scale; + + mobj_t *puff = P_SpawnMobjFromMobj( + target, + P_RandomRange(-spacing, spacing) * FRACUNIT, + P_RandomRange(-spacing, spacing) * FRACUNIT, + P_RandomRange(0, 4 * spacing) * FRACUNIT, + MT_SPINDASHDUST + ); + + puff->color = target->color; + puff->colorized = true; + + puff->momz = puff->scale * P_MobjFlip(puff); + + P_InitAngle(puff, R_PointToAngle2( + target->x, + target->y, + puff->x, + puff->y)); + + P_Thrust(puff, puff->angle, 3 * puff->scale); + + puff->momx += FixedMul(target->momx, fade); + puff->momy += FixedMul(target->momy, fade); + puff->momz += FixedMul(target->momz, fade); + } +} diff --git a/src/p_inter.c b/src/p_inter.c index 438909980..d21fb1195 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -275,7 +275,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) special->momx = special->momy = special->momz = 0; P_SetTarget(&special->target, toucher); P_KillMobj(special, toucher, toucher, DMG_NORMAL); - break; + return; case MT_SPHEREBOX: if (!P_CanPickupItem(player, 0)) return; @@ -283,7 +283,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) special->momx = special->momy = special->momz = 0; P_SetTarget(&special->target, toucher); P_KillMobj(special, toucher, toucher, DMG_NORMAL); - break; + return; case MT_ITEMCAPSULE: if ((gametyperules & GTR_BUMPERS) && player->bumpers <= 0) return; @@ -1037,27 +1037,34 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget { if (target->flags & MF_MONITOR || target->type == MT_RANDOMITEM) { - UINT8 i; - P_SetTarget(&target->target, source); - for (i = 0; i < MAXPLAYERS; i++) + if (gametyperules & GTR_BUMPERS) { - if (&players[i] == source->player) - { - continue; - } - - if (playeringame[i] && !players[i].spectator && players[i].lives != 0) - { - break; - } + target->fuse = 2; } - - if (i < MAXPLAYERS) + else { - // Respawn items in multiplayer, don't respawn them when alone - target->fuse = 2*TICRATE + 2; + UINT8 i; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (&players[i] == source->player) + { + continue; + } + + if (playeringame[i] && !players[i].spectator && players[i].lives != 0) + { + break; + } + } + + if (i < MAXPLAYERS) + { + // Respawn items in multiplayer, don't respawn them when alone + target->fuse = 2*TICRATE + 2; + } } } } @@ -1416,7 +1423,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget // special behavior for SPB capsules if (target->threshold == KITEM_SPB) { - K_ThrowKartItem(player, true, MT_SPB, 1, 0); + K_ThrowKartItem(player, true, MT_SPB, 1, 0, 0); break; } diff --git a/src/p_mobj.c b/src/p_mobj.c index 042cdad01..15a318c37 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1209,6 +1209,9 @@ fixed_t P_GetMobjGravity(mobj_t *mo) case MT_KARMAFIREWORK: gravityadd /= 3; break; + case MT_ITEM_DEBRIS: + gravityadd *= 6; + break; default: break; } @@ -1563,7 +1566,10 @@ void P_XYMovement(mobj_t *mo) { mo->health--; if (mo->health == 0) + { + mo->scalespeed = mo->scale/12; mo->destscale = 0; + } } } //} @@ -2339,6 +2345,15 @@ boolean P_ZMovement(mobj_t *mo) mom.z = P_MobjFlip(mo)*FixedMul(5*FRACUNIT, mo->scale); else if (mo->type == MT_SPINFIRE) // elemental shield fire is another exception here ; + else if (mo->type == MT_ITEM_DEBRIS) + { + mom.z = Obj_ItemDebrisBounce(mo, mom.z); + + if (mom.z == 0) + { + return false; + } + } else if (mo->type == MT_DRIFTCLIP) { mom.z = -mom.z/2; @@ -7847,6 +7862,11 @@ static boolean P_MobjRegularThink(mobj_t *mobj) Obj_PohbeeThinker(mobj); break; } + case MT_ITEM_DEBRIS: + { + Obj_ItemDebrisThink(mobj); + break; + } case MT_ROCKETSNEAKER: if (!mobj->target || !mobj->target->health) { @@ -9214,7 +9234,7 @@ static boolean P_FuseThink(mobj_t *mobj) { ; } - else if ((gametyperules & GTR_BUMPERS) && (mobj->threshold != 70)) + else if ((gametyperules & GTR_BUMPERS) && (mobj->state == &states[S_INVISIBLE])) { break; } @@ -11057,7 +11077,6 @@ void P_RespawnBattleBoxes(void) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { mobj_t *box; - mobj_t *newmobj; if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) continue; @@ -11066,25 +11085,12 @@ void P_RespawnBattleBoxes(void) if (box->type != MT_RANDOMITEM || (box->flags2 & MF2_DONTRESPAWN) - || box->threshold != 68 - || box->fuse - || ((tic_t)box->cvmem+1 >= leveltime)) + || box->health > 0 + || box->fuse) continue; // only popped items - // Respawn from mapthing if you have one! - if (box->spawnpoint) - { - P_SpawnMapThing(box->spawnpoint); - newmobj = box->spawnpoint->mobj; // this is set to the new mobj in P_SpawnMapThing - } - else - { - newmobj = P_SpawnMobj(box->x, box->y, box->z, box->type); - } - - // Transfer flags2 (strongbox, objectflip, bossnotrap) - newmobj->flags2 = box->flags2; - P_RemoveMobj(box); // make sure they disappear + box->fuse = TICRATE; // flicker back in (A_ItemPop preps this effect) + P_SetMobjState(box, box->info->raisestate); if (numgotboxes > 0) numgotboxes--; // you've restored a box, remove it from the count @@ -12668,10 +12674,6 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean P_SetThingPosition(mobj); } } - else - { - P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_EXPLODE); - } break; } case MT_ITEMCAPSULE: diff --git a/src/p_saveg.c b/src/p_saveg.c index 5620178e1..da85dac77 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -320,6 +320,8 @@ static void P_NetArchivePlayers(void) WRITEUINT16(save_p, players[i].flamemeter); WRITEUINT8(save_p, players[i].flamelength); + WRITEUINT16(save_p, players[i].ballhogcharge); + WRITEUINT16(save_p, players[i].hyudorotimer); WRITESINT8(save_p, players[i].stealingtimer); @@ -609,6 +611,8 @@ static void P_NetUnArchivePlayers(void) players[i].flamemeter = READUINT16(save_p); players[i].flamelength = READUINT8(save_p); + players[i].ballhogcharge = READUINT16(save_p); + players[i].hyudorotimer = READUINT16(save_p); players[i].stealingtimer = READSINT8(save_p); diff --git a/src/p_user.c b/src/p_user.c index 299d42a4b..1e1cfcbcb 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1197,7 +1197,7 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj) ghost->sprite2 = mobj->sprite2; ghost->frame = mobj->frame; ghost->tics = -1; - ghost->renderflags |= tr_trans50 << RF_TRANSSHIFT; + ghost->renderflags = (mobj->renderflags & ~RF_TRANSMASK)|RF_TRANS50; ghost->fuse = ghost->info->damage; ghost->skin = mobj->skin; ghost->standingslope = mobj->standingslope; @@ -1207,6 +1207,11 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj) ghost->sprzoff = mobj->sprzoff; ghost->rollangle = mobj->rollangle; + ghost->spritexscale = mobj->spritexscale; + ghost->spriteyscale = mobj->spriteyscale; + ghost->spritexoffset = mobj->spritexoffset; + ghost->spriteyoffset = mobj->spriteyoffset; + if (mobj->flags2 & MF2_OBJECTFLIP) ghost->flags |= MF2_OBJECTFLIP; diff --git a/src/r_things.c b/src/r_things.c index c0e727fd9..c76f77129 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1788,8 +1788,14 @@ static void R_ProjectSprite(mobj_t *thing) if (spriterotangle && !(splat && !(thing->renderflags & RF_NOSPLATROLLANGLE))) { - rollangle = R_GetRollAngle(vflip - ? InvAngle(spriterotangle) : spriterotangle); + if ((papersprite && ang >= ANGLE_180) != vflip) + { + rollangle = R_GetRollAngle(InvAngle(spriterotangle)); + } + else + { + rollangle = R_GetRollAngle(spriterotangle); + } rotsprite = Patch_GetRotatedSprite(sprframe, (thing->frame & FF_FRAMEMASK), rot, flip, false, sprinfo, rollangle); if (rotsprite != NULL) diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index ad0452898..2361a5349 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -106,8 +106,10 @@ rendermode_t chosenrendermode = render_none; // set by command line arguments boolean highcolor = false; +static void Impl_SetVsync(void); + // synchronize page flipping with screen refresh -consvar_t cv_vidwait = CVAR_INIT ("vid_wait", "On", CV_SAVE, CV_OnOff, NULL); +consvar_t cv_vidwait = CVAR_INIT ("vid_wait", "On", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, Impl_SetVsync); static consvar_t cv_stretch = CVAR_INIT ("stretch", "Off", CV_SAVE|CV_NOSHOWHELP, CV_OnOff, NULL); static consvar_t cv_alwaysgrabmouse = CVAR_INIT ("alwaysgrabmouse", "Off", CV_SAVE, CV_OnOff, NULL); @@ -2002,3 +2004,11 @@ UINT32 I_GetRefreshRate(void) // trouble querying mode over and over again. return refresh_rate; } + +static void Impl_SetVsync(void) +{ +#if SDL_VERSION_ATLEAST(2,0,18) + if (renderer) + SDL_RenderSetVSync(renderer, cv_vidwait.value); +#endif +} diff --git a/src/sounds.c b/src/sounds.c index 351e1553f..1cff40633 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -1054,8 +1054,6 @@ sfxinfo_t S_sfx[NUMSFX] = {"kpogos", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Pogo Spring use {"alarmi", false, 255, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Invincibility alarm {"alarmg", false, 255, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Grow alarm - {"kinvnc", false, 255, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Invincibility music - {"kgrow", false, 255, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Grow music {"itrol1", true, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Roulette spinning {"itrol2", true, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"itrol3", true, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, @@ -1115,7 +1113,10 @@ sfxinfo_t S_sfx[NUMSFX] = {"ffbonc", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Shout message sound effect - {"sysmsg", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Server notification"}, + {"sysmsg", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Server notification"}, + + // Shrink laser beam + {"beam01", false, 32, 64, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // SRB2Kart - Engine sounds // Engine class A diff --git a/src/sounds.h b/src/sounds.h index e7248a369..cb9d3b671 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -1118,8 +1118,6 @@ typedef enum sfx_kpogos, sfx_alarmi, sfx_alarmg, - sfx_kinvnc, - sfx_kgrow, sfx_itrol1, sfx_itrol2, sfx_itrol3, @@ -1182,6 +1180,9 @@ typedef enum // Shout message sound effect sfx_sysmsg, + // Shrink laser + sfx_beam01, + // Next up: UNIQUE ENGINE SOUNDS! Hoooooo boy... // Engine class A - Low Speed, Low Weight sfx_krta00,