diff --git a/src/d_main.cpp b/src/d_main.cpp index 2e987a774..546a45d6f 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -94,7 +94,7 @@ #define ASSET_HASH_TEXTURES_KART 0xb4211b2f32b6a291 #define ASSET_HASH_CHARS_KART 0x1e68a3e01aa5c68b #define ASSET_HASH_MAPS_KART 0x38558ed00da41ce9 -#define ASSET_HASH_MAIN_PK3 0x07cf2f7ba7033674 +#define ASSET_HASH_MAIN_PK3 0xf7afa9636053a91a #define ASSET_HASH_MAPPATCH_PK3 0x0afd8afc6fc50175 #define ASSET_HASH_BONUSCHARS_KART 0x60e6f13d822a7461 #ifdef USE_PATCH_FILE diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 37679766c..341835a10 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1253,6 +1253,7 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_deadzonestyle[i]); CV_RegisterVar(&cv_litesteer[i]); CV_RegisterVar(&cv_turnsmooth[i]); + CV_RegisterVar(&cv_rumble[i]); } // filesrch.c diff --git a/src/d_player.h b/src/d_player.h index 102decf2c..c9ae4fd1c 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -564,6 +564,7 @@ struct player_t UINT8 driftboost; // (0 to 125) - Boost you get from drifting tic_t driftsparkGrowTimer; tic_t driftelapsed; // Elapsed time spent during a drift. + SINT8 driftlevel; // just for controller rumble for now fixed_t spinoutrot; // When a player spins out, this value increments modulus 360. diff --git a/src/g_game.c b/src/g_game.c index efc653668..7765fe507 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -349,21 +349,6 @@ typedef struct joystickvector2_s INT32 yaxis; } joystickvector2_t; -consvar_t cv_litesteer[MAXSPLITSCREENPLAYERS] = { - CVAR_INIT ("litesteer", "Off", CV_SAVE, CV_OnOff, NULL), - CVAR_INIT ("litesteer2", "Off", CV_SAVE, CV_OnOff, NULL), - CVAR_INIT ("litesteer3", "Off", CV_SAVE, CV_OnOff, NULL), - CVAR_INIT ("litesteer4", "Off", CV_SAVE, CV_OnOff, NULL) -}; - -static CV_PossibleValue_t turnsmooth_cons_t[] = {{2, "Slow"}, {1, "Fast"}, {0, "Off"}, {0, NULL}}; -consvar_t cv_turnsmooth[MAXSPLITSCREENPLAYERS] = { - CVAR_INIT ("turnsmoothing", "Off", CV_SAVE, turnsmooth_cons_t, NULL), - CVAR_INIT ("turnsmoothing2", "Off", CV_SAVE, turnsmooth_cons_t, NULL), - CVAR_INIT ("turnsmoothing3", "Off", CV_SAVE, turnsmooth_cons_t, NULL), - CVAR_INIT ("turnsmoothing4", "Off", CV_SAVE, turnsmooth_cons_t, NULL) -}; - INT16 prevmap, nextmap; INT16 kartmap2native[NEXTMAP_SPECIAL] = {0}, nativemap2kart[NEXTMAP_SPECIAL] = {0}; diff --git a/src/g_game.h b/src/g_game.h index f61668e9a..4cebfe969 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -94,9 +94,6 @@ extern consvar_t cv_resetspecialmusic; extern consvar_t cv_resume; -extern consvar_t cv_litesteer[MAXSPLITSCREENPLAYERS]; -extern consvar_t cv_turnsmooth[MAXSPLITSCREENPLAYERS]; - void weaponPrefChange(void); void weaponPrefChange2(void); void weaponPrefChange3(void); diff --git a/src/g_input.c b/src/g_input.c index 2b45c0690..bbe5f5205 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -21,11 +21,15 @@ #include "console.h" #include "i_joy.h" // JOYAXISRANGE #include "m_menu.h" // menustack +#include "i_system.h" +#include "g_game.h" +#include "v_video.h" #define MAXMOUSESENSITIVITY 100 // sensitivity steps static CV_PossibleValue_t mousesens_cons_t[] = {{1, "MIN"}, {MAXMOUSESENSITIVITY, "MAX"}, {0, NULL}}; static CV_PossibleValue_t onecontrolperkey_cons_t[] = {{1, "One"}, {2, "Several"}, {0, NULL}}; +static CV_PossibleValue_t turnsmooth_cons_t[] = {{2, "Slow"}, {1, "Fast"}, {0, "Off"}, {0, NULL}}; // mouse values are used once consvar_t cv_mousesens = CVAR_INIT ("mousesens", "20", CV_SAVE, mousesens_cons_t, NULL); @@ -33,6 +37,92 @@ consvar_t cv_mousesens2 = CVAR_INIT ("mousesens2", "20", CV_SAVE, mousesens_cons consvar_t cv_mouseysens = CVAR_INIT ("mouseysens", "20", CV_SAVE, mousesens_cons_t, NULL); consvar_t cv_mouseysens2 = CVAR_INIT ("mouseysens2", "20", CV_SAVE, mousesens_cons_t, NULL); consvar_t cv_controlperkey = CVAR_INIT ("controlperkey", "One", CV_SAVE, onecontrolperkey_cons_t, NULL); + +consvar_t cv_litesteer[MAXSPLITSCREENPLAYERS] = { + CVAR_INIT ("litesteer", "Off", CV_SAVE, CV_OnOff, NULL), + CVAR_INIT ("litesteer2", "Off", CV_SAVE, CV_OnOff, NULL), + CVAR_INIT ("litesteer3", "Off", CV_SAVE, CV_OnOff, NULL), + CVAR_INIT ("litesteer4", "Off", CV_SAVE, CV_OnOff, NULL) +}; + +consvar_t cv_turnsmooth[MAXSPLITSCREENPLAYERS] = { + CVAR_INIT ("turnsmoothing", "Off", CV_SAVE, turnsmooth_cons_t, NULL), + CVAR_INIT ("turnsmoothing2", "Off", CV_SAVE, turnsmooth_cons_t, NULL), + CVAR_INIT ("turnsmoothing3", "Off", CV_SAVE, turnsmooth_cons_t, NULL), + CVAR_INIT ("turnsmoothing4", "Off", CV_SAVE, turnsmooth_cons_t, NULL) +}; + +static void G_ResetPlayerDeviceRumble(INT32 player); +static void rumble_off_handle(void); +static void rumble_off_handle2(void); +static void rumble_off_handle3(void); +static void rumble_off_handle4(void); + +static void G_ResetPlayerGamepadIndicatorColor(INT32 player); +static void led_off_handle(void); +static void led_off_handle2(void); +static void led_off_handle3(void); +static void led_off_handle4(void); + +consvar_t cv_rumble[MAXSPLITSCREENPLAYERS] = { + CVAR_INIT ("rumble", "On", CV_SAVE, CV_OnOff, rumble_off_handle), + CVAR_INIT ("rumble2", "On", CV_SAVE, CV_OnOff, rumble_off_handle2), + CVAR_INIT ("rumble3", "On", CV_SAVE, CV_OnOff, rumble_off_handle3), + CVAR_INIT ("rumble4", "On", CV_SAVE, CV_OnOff, rumble_off_handle4) +}; + +static CV_PossibleValue_t gamepadled_cons_t[] = {{0, "Off"}, {1, "Skincolor"}, {2, "Mobjcolor"}, {0, NULL}}; +consvar_t cv_gamepadled[MAXSPLITSCREENPLAYERS] = { + CVAR_INIT ("gamepadled", "Skincolor", CV_SAVE|CV_CALL|CV_NOINIT, gamepadled_cons_t, led_off_handle), + CVAR_INIT ("gamepadled2", "Skincolor", CV_SAVE|CV_CALL|CV_NOINIT, gamepadled_cons_t, led_off_handle2), + CVAR_INIT ("gamepadled3", "Skincolor", CV_SAVE|CV_CALL|CV_NOINIT, gamepadled_cons_t, led_off_handle3), + CVAR_INIT ("gamepadled4", "Skincolor", CV_SAVE|CV_CALL|CV_NOINIT, gamepadled_cons_t, led_off_handle4) +}; + +static void rumble_off_handle(void) +{ + if (cv_rumble[0].value == 0) + G_ResetPlayerDeviceRumble(0); +} + +static void rumble_off_handle2(void) +{ + if (cv_rumble[1].value == 0) + G_ResetPlayerDeviceRumble(1); +} + +static void rumble_off_handle3(void) +{ + if (cv_rumble[2].value == 0) + G_ResetPlayerDeviceRumble(2); +} + +static void rumble_off_handle4(void) +{ + if (cv_rumble[3].value == 0) + G_ResetPlayerDeviceRumble(3); +} + +static void led_off_handle(void) +{ + G_ResetPlayerGamepadIndicatorColor(0); +} + +static void led_off_handle2(void) +{ + G_ResetPlayerGamepadIndicatorColor(1); +} + +static void led_off_handle3(void) +{ + G_ResetPlayerGamepadIndicatorColor(2); +} + +static void led_off_handle4(void) +{ + G_ResetPlayerGamepadIndicatorColor(3); +} + // current state of the keys // JOYAXISRANGE for fully pressed, 0 for not pressed INT32 gamekeydown[MAXDEVICES][NUMINPUTS]; @@ -410,6 +500,118 @@ static const char *gamecontrolname[num_gamecontrols] = #define NUMKEYNAMES (sizeof (keynames)/sizeof (keyname_t)) +static INT32 G_GetDeviceForPlayer(INT32 player) +{ + switch (player) + { + case 0: + return cv_usejoystick[0].value; + break; + case 1: + return cv_usejoystick[1].value; + break; + case 2: + return cv_usejoystick[2].value; + break; + case 3: + return cv_usejoystick[3].value; + break; + default: + return 0; + break; + } +} + +UINT16 G_GetSkinColor(INT32 playernum) +{ + if (gamestate == GS_LEVEL) + { + player_t *player = &players[displayplayers[playernum]]; + + if (player) + { + // make rgb rainbow vomit when invul or flash blue when grow + if ((cv_gamepadled[playernum].value == 2) && player->mo && player->mo->color) + return player->mo->color; + + // take actual player skincolour when ingame + if (player->skincolor) + return player->skincolor; + } + } + + // otherwise just fallback to whatever the cvar is + switch (playernum) + { + case 0: + return cv_playercolor[0].value; + case 1: + return cv_playercolor[1].value; + case 2: + return cv_playercolor[2].value; + case 3: + return cv_playercolor[3].value; + default: + return 0; + } + + return 0; +} + +void G_SetPlayerGamepadIndicatorColor(INT32 playernum, UINT16 color) +{ + UINT16 skincolor; + RGBA_t byte_color; + + I_Assert(playernum >= 0 && playernum < MAXSPLITSCREENPLAYERS); + + if (cv_gamepadled[playernum].value == 0) + { + return; + } + + skincolor = color ? color : G_GetSkinColor(playernum); + byte_color = V_GetColor(skincolors[skincolor].ramp[8]); + + I_SetGamepadIndicatorColor(playernum, byte_color.s.red, byte_color.s.green, byte_color.s.blue); +} + +static void G_ResetPlayerGamepadIndicatorColor(INT32 playernum) +{ + if (cv_gamepadled[playernum].value == 0) + { + I_SetGamepadIndicatorColor(playernum, 0, 0, 255); + } + else + G_SetPlayerGamepadIndicatorColor(playernum, 0); +} + +static void G_ResetPlayerDeviceRumble(INT32 player) +{ + INT32 device_id; + + device_id = G_GetDeviceForPlayer(player); + + if (device_id < 1) + { + return; + } + + I_GamepadRumble(device_id, 0, 0, 0); +} + +void G_PlayerDeviceRumble(INT32 playernum, UINT16 low_strength, UINT16 high_strength, UINT32 duration) +{ + I_Assert(playernum >= 0 && playernum < MAXSPLITSCREENPLAYERS); + + if (cv_rumble[playernum].value == 0) + { + return; + } + + I_GamepadRumble(playernum, low_strength, high_strength, duration); +} + // If keybind is necessary to navigate menus, it's on this list. boolean G_KeyBindIsNecessary(INT32 gc) { diff --git a/src/g_input.h b/src/g_input.h index e151732a2..23f3d9cc2 100644 --- a/src/g_input.h +++ b/src/g_input.h @@ -94,6 +94,10 @@ typedef enum extern consvar_t cv_mousesens, cv_mouseysens; extern consvar_t cv_mousesens2, cv_mouseysens2; extern consvar_t cv_controlperkey; +extern consvar_t cv_litesteer[MAXSPLITSCREENPLAYERS]; +extern consvar_t cv_turnsmooth[MAXSPLITSCREENPLAYERS]; +extern consvar_t cv_rumble[MAXSPLITSCREENPLAYERS]; +extern consvar_t cv_gamepadled[MAXSPLITSCREENPLAYERS]; // current state of the keys: JOYAXISRANGE or 0 when boolean. // Or anything inbetween for analog values @@ -124,6 +128,11 @@ extern const INT32 gcl_full[num_gcl_full]; // peace to my little coder fingers! // check a gamecontrol being active or not +UINT16 G_GetSkinColor(INT32 playernum); +void G_SetPlayerGamepadIndicatorColor(INT32 playernum, UINT16 color); +void G_ResetAllDeviceRumbles(void); +void G_PlayerDeviceRumble(INT32 playernum, UINT16 low_strength, UINT16 high_strength, UINT32 duration); + INT32 G_GetDevicePlayer(INT32 deviceID); INT32 G_AxisToKey(event_t *ev); diff --git a/src/i_system.h b/src/i_system.h index 48fef0f74..bf6e359a9 100644 --- a/src/i_system.h +++ b/src/i_system.h @@ -231,6 +231,7 @@ void I_InitJoystick4(void); /** \brief return the number of joystick on the system */ INT32 I_NumJoys(void); +extern INT32 numcontrollers; /** \brief The *I_GetJoyName function @@ -240,6 +241,9 @@ INT32 I_NumJoys(void); */ const char *I_GetJoyName(INT32 joyindex); +void I_GamepadRumble(INT32 playernum, UINT16 low_strength, UINT16 high_strength, UINT32 duration); +void I_SetGamepadIndicatorColor(INT32 playernum, UINT8 red, UINT8 green, UINT8 blue); + #ifndef NOMUMBLE #include "p_mobj.h" // mobj_t #include "s_sound.h" // listener_t diff --git a/src/k_kart.c b/src/k_kart.c index d98e0d401..28e235859 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -8895,14 +8895,17 @@ static void K_KartDrift(player_t *player, boolean onground) { case 1: boost = 20; + player->driftlevel = 1; break; case 2: boost = 50; + player->driftlevel = 2; if (cv_kartdriftsounds.value) S_StartSound(player->mo, sfx_kc5b); break; case 3: boost = 80; + player->driftlevel = 3; if (cv_kartdriftsounds.value) { S_StartSound(player->mo, sfx_kc5b); @@ -8913,6 +8916,7 @@ static void K_KartDrift(player_t *player, boolean onground) break; case 4: boost = 125; + player->driftlevel = 4; if (cv_kartdriftsounds.value) { S_StartSound(player->mo, sfx_kc5b); diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 3d936992f..6e8dd9aea 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -22,6 +22,7 @@ #include "m_random.h" #include "s_sound.h" #include "g_game.h" +#include "g_input.h" #include "m_menu.h" #include "y_inter.h" #include "hu_stuff.h" // HU_AddChatText @@ -5101,6 +5102,58 @@ static int lib_kSetPlayerItemCooldown(lua_State *L) return 0; } +// G_INPUT +//////////// + +static int lib_gSetPlayerGamepadIndicatorColor(lua_State *L) +{ + INT32 player = -1; + player_t *plr = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); // retrieve player + UINT16 color = (UINT16)luaL_checkinteger(L, 2); // skincolor + + for (int i = 0; i < MAXSPLITSCREENPLAYERS; ++i) + { + if (plr - players == displayplayers[i]) + { + player = i; + break; + } + } + + // Not a local player + if (player == -1) return 0; + + // pls update with color 0 when youre done with changing led stuff so it can get player color again + G_SetPlayerGamepadIndicatorColor(player, color); + + return 0; +} + +static int lib_gPlayerDeviceRumble(lua_State *L) +{ + INT32 player = -1; + player_t *plr = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); // retrieve player + UINT16 low_strength = (UINT16)luaL_checkinteger(L, 2); // low frequency rumble motor strenght + UINT16 high_strength = (UINT16)luaL_checkinteger(L, 3); // high frequency rumble motor strenght + UINT32 duration = (UINT32)luaL_optinteger(L, 4, 84); // duration of rumble in ms + + for (int i = 0; i < MAXSPLITSCREENPLAYERS; ++i) + { + if (plr - players == displayplayers[i]) + { + player = i; + break; + } + } + + // Not a local player + if (player == -1) return 0; + + G_PlayerDeviceRumble(player, low_strength, high_strength, duration); + + return 0; +} + static luaL_Reg lib[] = { {"print", lib_print}, {"chatprint", lib_chatprint}, @@ -5490,6 +5543,10 @@ static luaL_Reg lib[] = { // k_items {"K_SetPlayerItemCooldown", lib_kSetPlayerItemCooldown}, + //g_input + {"G_SetPlayerGamepadIndicatorColor",lib_gSetPlayerGamepadIndicatorColor}, + {"G_PlayerDeviceRumble",lib_gPlayerDeviceRumble}, + {NULL, NULL} }; diff --git a/src/m_menu.c b/src/m_menu.c index 6a0a9acda..a09171cf3 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -478,7 +478,14 @@ consvar_t cv_dummymultiplayer = CVAR_INIT ("dummymultiplayer", "0", CV_HIDEN, du consvar_t cv_dummyip = CVAR_INIT ("dummyip", "", CV_HIDEN, NULL, NULL); consvar_t cv_dummyname = CVAR_INIT ("dummyname", "", CV_HIDEN, NULL, NULL); consvar_t cv_dummyfollower = CVAR_INIT ("dummyfollower", "-1", CV_HIDEN, dummyfollower_cons_t, NULL); -consvar_t cv_dummycolor = CVAR_INIT ("dummycolor", "0", CV_HIDEN, dummycolor_cons_t, NULL); + +SINT8 dummycolorplayer = 0; +static void SetDummyColorPlayer(void) +{ + G_SetPlayerGamepadIndicatorColor(dummycolorplayer, cv_dummycolor.value); +} + +consvar_t cv_dummycolor = CVAR_INIT ("dummycolor", "0", CV_HIDEN, dummycolor_cons_t, SetDummyColorPlayer); static CV_PossibleValue_t dummyserverpage_cons_t[] = {{0, "MIN"}, {0, "MAX"}, {0, NULL}}; consvar_t cv_dummyserverpage = CVAR_INIT ("dummyserverpage", "0", CV_HIDEN, dummyserverpage_cons_t, NULL); @@ -7530,6 +7537,8 @@ INT32 MR_SetupMultiPlayer(INT32 arg) gridcss_skinmemory = cv_chooseskin.value; CV_SetValue(&cv_dummyfollower, cv_follower[arg].value); CV_SetValue(&cv_dummycolor, cv_playercolor[arg].value); + G_SetPlayerGamepadIndicatorColor(arg, cv_playercolor[arg].value); + dummycolorplayer = arg; Skinsort_option_Onchange(); @@ -7918,6 +7927,8 @@ INT32 MR_SetupControlsMenu(INT32 arg) M_SetItemCvar(MN_OP_CHANGECONTROLS, "DEAZS", &cv_deadzonestyle[arg]); M_SetItemCvar(MN_OP_CHANGECONTROLS, "TURNSMOOTHING", &cv_turnsmooth[arg]); M_SetItemCvar(MN_OP_CHANGECONTROLS, "LITESTEER", &cv_litesteer[arg]); + M_SetItemCvar(MN_OP_CHANGECONTROLS, "LEDCOLOR", &cv_gamepadled[arg]); + M_SetItemCvar(MN_OP_CHANGECONTROLS, "RUMBLE", &cv_rumble[arg]); M_SetItemVisible(MN_OP_CHANGECONTROLS, "TALK", player1); // Chat //M_SetItemVisible(MN_OP_CHANGECONTROLS, "TEAM", player1); // Team-chat diff --git a/src/p_enemy.c b/src/p_enemy.c index 31e091a51..4f7c75202 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -10987,7 +10987,7 @@ void A_SPBChase(void *thing) if (players[i].mo->health <= 0) continue; // dead - if (players[i].kartstuff[k_respawn]) + if (players[i].respawn) continue;*/ // respawning if ((gametyperules & GTR_WANTED) && (gametyperules & GTR_WANTEDSPB)) @@ -11030,7 +11030,7 @@ void A_SPBChase(void *thing) actor->lastlook = actor->tracer->player-players; // Save the player num for death scumming... - if (!P_IsObjectOnGround(actor->tracer) /*&& !actor->tracer->player->kartstuff[k_pogospring]*/) + if (!P_IsObjectOnGround(actor->tracer) /*&& !actor->tracer->player->pogospring*/) { // In the air you have no control; basically don't hit unless you make a near complete stop defspeed = (7 * actor->tracer->player->speed) / 8; diff --git a/src/p_tick.c b/src/p_tick.c index e9252c5ec..bbe8a88d8 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -501,6 +501,126 @@ static void P_RunThinkers(void) ps_acs_time = I_GetPreciseTime() - ps_acs_time; } +// Controller rumble! +// this keeps track of a bunch of things +// and makes your controller rumble accordingly +static void P_DeviceRumbleTick(void) +{ + UINT8 i; + + if (dedicated || numcontrollers == 0 || gamestate != GS_LEVEL) + { + return; + } + + for (i = 0; i <= splitscreen; i++) + { + if (!cv_usejoystick[i].value || !cv_rumble[i].value) + { + continue; + } + + if (camera[i].freecam) + { + continue; + } + + UINT16 low = 0, high = 0; + UINT16 lenght = 57; // in ms + + const player_t *player = &players[g_localplayers[i]]; + + // allow lua to do some crap for spectators + if (player->spectator || !player->mo) + { + continue; + } + + // reset the rumble if you exit or are ded lel + if (player->exiting || + player->playerstate == PST_DEAD || + player->respawn > 1) + { + G_PlayerDeviceRumble(i, low, high, 0); + continue; + } + + if (player->spinouttimer) + { + //low = high = FRACUNIT / 6; + low = high = FixedMul((FRACUNIT / 4), (FixedDiv(player->spinouttimer, (3*TICRATE / 2)))); // try do some some kinda fadeout + } + else if (player->sneakertimer > (sneakertime-(TICRATE/2))) + { + low = high = FRACUNIT / 8; + } + else if ((player->offroad) + && player->speed != 0 + && P_IsObjectOnGround(player->mo)) + { + // weaken this depending on if you got hyu or invinc + if (player->hyudorotimer) + { + high = FRACUNIT / 128; + } + else if (player->invincibilitytimer) + { + high = FRACUNIT / 64; + } + else + { + low = high = FRACUNIT / 64; + } + } + else if ((player->bananadrag > TICRATE) + && player->speed != 0 + && P_IsObjectOnGround(player->mo)) + { + if (leveltime & 1) // this is actually funny lel + high = FRACUNIT / 64; + } + + if (player->pflags & PF_BRAKEDRIFT) + { + high = CLAMP((high + FRACUNIT / 256), 0, UINT16_MAX); + } + + // pulse when gettin new driftlevel + if (player->driftcharge + && player->driftlevel) + { + high = CLAMP((high + FRACUNIT / 256), 0, UINT16_MAX); + + if (player->driftlevel == 2) + lenght = 114; + else if (player->driftlevel == 3) + lenght = 144; + else if (player->driftlevel == 4) + lenght = 174; + } + + // pulse when using rings + // let this come last + if ((player->cmd.buttons & BT_ATTACK) + && (player->itemflags & IF_USERINGS) + && (player->rings > 0 + && player->rings > player->rings-1 + && player->rings < player->rings+1) + ) + { + high = CLAMP((high + FRACUNIT / 256), 0, UINT16_MAX); + } + + // hack alert! i just dont want this thing constantly resetting the rumble lol + if (low == 0 && high == 0) + { + continue; + } + + G_PlayerDeviceRumble(i, low, high, lenght); + } +} + // // P_DoAutobalanceTeams() // @@ -792,6 +912,12 @@ void P_Ticker(boolean run) if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo)) P_PlayerAfterThink(&players[i]); + // Apply rumble to local players + if (!demo.playback) + { + P_DeviceRumbleTick(); + } + // run all the bot tickers if (server) { diff --git a/src/p_user.c b/src/p_user.c index 17ca7fa3a..e9f6dff94 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -3861,6 +3861,8 @@ void P_PlayerThink(player_t *player) I_Error("p_playerthink: players[%s].mo == NULL", sizeu1(playeri)); #endif + player->driftlevel = 0; // idk where to put this + // todo: Figure out what is actually causing these problems in the first place... if (player->mo->health <= 0 && player->playerstate == PST_LIVE) //you should be DEAD! { diff --git a/src/sdl/i_system.cpp b/src/sdl/i_system.cpp index 802854937..bef118037 100644 --- a/src/sdl/i_system.cpp +++ b/src/sdl/i_system.cpp @@ -286,6 +286,7 @@ static INT32 joystick_started[MAXSPLITSCREENPLAYERS] = {0,0,0,0}; /** \brief SDL info about joystick 1 */ SDLJoyInfo_t JoyInfo[MAXSPLITSCREENPLAYERS]; +INT32 numcontrollers = 0; SDL_GameController *ExJoystick[MAXGAMEPADS]; SDL_bool consolevent = SDL_FALSE; @@ -1487,6 +1488,44 @@ const char *I_GetJoyName(INT32 joyindex) return joyname; } +void I_GamepadRumble(INT32 playernum, UINT16 low_strength, UINT16 high_strength, UINT32 duration) +{ + #if !(SDL_VERSION_ATLEAST(2,0,14)) + (void)playernum; + (void)low_strength; + (void)high_strength; + (void)duration; + #else + SDL_GameController *controller = JoyInfo[playernum].dev; + + if (controller == NULL) + { + return; + } + + SDL_GameControllerRumble(controller, low_strength, high_strength, duration); + #endif +} + +void I_SetGamepadIndicatorColor(INT32 playernum, UINT8 red, UINT8 green, UINT8 blue) +{ + #if !(SDL_VERSION_ATLEAST(2,0,14)) + (void)playernum; + (void)red; + (void)green; + (void)blue; + #else + SDL_GameController *controller = JoyInfo[playernum].dev; + + if (controller == NULL) + { + return; + } + + SDL_GameControllerSetLED(controller, red, green, blue); + #endif +} + #ifndef NOMUMBLE #ifdef HAVE_MUMBLE // Best Mumble positional audio settings: diff --git a/src/sdl/i_video.cpp b/src/sdl/i_video.cpp index 2f4d64db1..aa7fa6494 100644 --- a/src/sdl/i_video.cpp +++ b/src/sdl/i_video.cpp @@ -1040,7 +1040,10 @@ void I_GetEvent(void) //////////////////////////////////////////////////////////// for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) + { I_InitJoystick(i); + G_SetPlayerGamepadIndicatorColor(i, G_GetSkinColor(i)); // gotta update the controller led again on reconnect + } //////////////////////////////////////////////////////////// @@ -1051,6 +1054,8 @@ void I_GetEvent(void) if (menustack[0] == MN_OP_JOYSTICKSET) MR_SetupJoystickMenu(0); + numcontrollers = I_NumJoys(); + for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) { if (JoyInfo[i].dev == newcontroller) @@ -1110,6 +1115,7 @@ void I_GetEvent(void) // update the menu if (menustack[0] == MN_OP_JOYSTICKSET) MR_SetupJoystickMenu(0); + numcontrollers = I_NumJoys(); break; case SDL_DROPFILE: dropped_filedir = evt.drop.file;