diff --git a/src/d_player.h b/src/d_player.h index 86f4c718b..91989279c 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -506,8 +506,8 @@ typedef struct player_s SINT8 lastjawztarget; // (-1 to 15) - Last person you target with jawz, for playing the target switch sfx UINT8 jawztargetdelay; // (0 to 5) - Delay for Jawz target switching, to make it less twitchy - UINT8 confirmInflictor; // Player ID that dealt damage to you - UINT8 confirmInflictorDelay; // Delay before playing the sound + UINT8 confirmVictim; // Player ID that you dealt damage to + UINT8 confirmVictimDelay; // Delay before playing the sound UINT8 trickpanel; // Trick panel state UINT8 tricktime; // Increases while you're tricking. You can't input any trick until it's reached a certain threshold diff --git a/src/k_kart.c b/src/k_kart.c index e6df044ac..531c66830 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2824,91 +2824,107 @@ void K_PlayOvertakeSound(mobj_t *source) K_RegularVoiceTimers(source->player); } -void K_PlayPainSound(mobj_t *source) +void K_PlayPainSound(mobj_t *source, mobj_t *other) { sfxenum_t pick = P_RandomKey(2); // Gotta roll the RNG every time this is called for sync reasons + sfxenum_t sfx_id = ((skin_t *)source->skin)->soundsid[S_sfx[sfx_khurt1 + pick].skinsound]; + boolean alwaysHear = false; + + if (other != NULL && P_MobjWasRemoved(other) == false && other->player != NULL) + { + alwaysHear = P_IsDisplayPlayer(other->player); + } + if (cv_kartvoices.value) - S_StartSound(source, sfx_khurt1 + pick); + { + S_StartSound(alwaysHear ? NULL : source, sfx_id); + } K_RegularVoiceTimers(source->player); } -void K_PlayHitEmSound(mobj_t *source, mobj_t *victim) +void K_PlayHitEmSound(mobj_t *source, mobj_t *other) { - const boolean victimIsLocal = (victim != NULL && P_IsDisplayPlayer(victim->player) == true); + sfxenum_t sfx_id = ((skin_t *)source->skin)->soundsid[S_sfx[sfx_khitem].skinsound]; + boolean alwaysHear = false; - if (source->player->follower) + if (other != NULL && P_MobjWasRemoved(other) == false && other->player != NULL) { - follower_t fl = followers[source->player->followerskin]; - source->player->follower->movecount = fl.hitconfirmtime; // movecount is used to play the hitconfirm animation for followers. + alwaysHear = P_IsDisplayPlayer(other->player); } if (cv_kartvoices.value) { - if (victimIsLocal == false) - { - S_StartSound(source, sfx_khitem); - } - } - else - { - S_StartSound(source, sfx_s1c9); // The only lost gameplay functionality with voices disabled + S_StartSound(alwaysHear ? NULL : source, sfx_id); } K_RegularVoiceTimers(source->player); +} - if (victim != NULL && victim->player != NULL) +void K_TryHurtSoundExchange(mobj_t *victim, mobj_t *attacker) +{ + if (victim == NULL || P_MobjWasRemoved(victim) == true || victim->player == NULL) { - victim->player->confirmInflictor = source->player - players; - victim->player->confirmInflictorDelay = TICRATE/2; + return; + } + + // In a perfect world we could move this here, but there's + // a few niche situations where we want a pain sound from + // the victim, but no confirm sound from the attacker. + // (ex: DMG_STING) + + //K_PlayPainSound(victim, attacker); + + if (attacker == NULL || P_MobjWasRemoved(attacker) == true || attacker->player == NULL) + { + return; + } + + attacker->player->confirmVictim = (victim->player - players); + attacker->player->confirmVictimDelay = TICRATE/2; + + if (attacker->player->follower != NULL) + { + const follower_t *fl = &followers[attacker->player->followerskin]; + attacker->player->follower->movecount = fl->hitconfirmtime; // movecount is used to play the hitconfirm animation for followers. } } void K_PlayPowerGloatSound(mobj_t *source) { if (cv_kartvoices.value) + { S_StartSound(source, sfx_kgloat); + } K_RegularVoiceTimers(source->player); } static void K_HandleDelayedHitByEm(player_t *player) { - if (player->confirmInflictorDelay == 0) + if (player->confirmVictimDelay == 0) { return; } - player->confirmInflictorDelay--; + player->confirmVictimDelay--; - if (player->confirmInflictorDelay == 0 - && P_IsDisplayPlayer(player) == true - && cv_kartvoices.value) + if (player->confirmVictimDelay == 0) { - player_t *inflictor = NULL; + mobj_t *victim = NULL; - if (player->confirmInflictor >= MAXPLAYERS) + if (player->confirmVictim < MAXPLAYERS && playeringame[player->confirmVictim]) { - return; + player_t *victimPlayer = &players[player->confirmVictim]; + + if (victimPlayer != NULL && victimPlayer->spectator == false) + { + victim = victimPlayer->mo; + } } - if (!playeringame[player->confirmInflictor]) - { - return; - } - - inflictor = &players[player->confirmInflictor]; - if (inflictor == NULL || inflictor->spectator) - { - return; - } - - if (inflictor->mo != NULL && P_MobjWasRemoved(inflictor->mo) == false) - { - sfxenum_t sfx_id = ((skin_t *)inflictor->mo->skin)->soundsid[S_sfx[sfx_khitem].skinsound]; - S_StartSound(NULL, sfx_id); - } + K_PlayHitEmSound(player->mo, victim); } } diff --git a/src/k_kart.h b/src/k_kart.h index 00c36ea76..bab501200 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -154,8 +154,9 @@ void K_HandleDirectionalInfluence(player_t *player); void K_PlayAttackTaunt(mobj_t *source); void K_PlayBoostTaunt(mobj_t *source); void K_PlayOvertakeSound(mobj_t *source); -void K_PlayPainSound(mobj_t *source); -void K_PlayHitEmSound(mobj_t *source, mobj_t *victim); +void K_PlayPainSound(mobj_t *source, mobj_t *other); +void K_PlayHitEmSound(mobj_t *source, mobj_t *other); +void K_TryHurtSoundExchange(mobj_t *victim, mobj_t *attacker); void K_PlayPowerGloatSound(mobj_t *source); fixed_t K_ItemScaleForPlayer(player_t *player); diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 301665e45..e172ea978 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -3339,23 +3339,37 @@ static int lib_kOvertakeSound(lua_State *L) static int lib_kPainSound(lua_State *L) { mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + mobj_t *other = NULL; NOHUD if (!mobj->player) return luaL_error(L, "K_PlayPainSound: mobj_t isn't a player object."); //Nothing bad would happen if we let it run the func, but telling why it ain't doing anything is helpful. - K_PlayPainSound(mobj); + if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) + other = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); + K_PlayPainSound(mobj, other); return 0; } static int lib_kHitEmSound(lua_State *L) { mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); - mobj_t *victim = NULL; + mobj_t *other = NULL; NOHUD if (!mobj->player) return luaL_error(L, "K_PlayHitEmSound: mobj_t isn't a player object."); //Nothing bad would happen if we let it run the func, but telling why it ain't doing anything is helpful. if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) - victim = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); - K_PlayHitEmSound(mobj, victim); + other = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); + K_PlayHitEmSound(mobj, other); + return 0; +} + +static int lib_kTryHurtSoundExchange(lua_State *L) +{ + mobj_t *victim = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + mobj_t *attacker = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); + NOHUD + if (!victim->player) + return luaL_error(L, "K_TryHurtSoundExchange: mobj_t isn't a player object."); //Nothing bad would happen if we let it run the func, but telling why it ain't doing anything is helpful. + K_TryHurtSoundExchange(victim, attacker); return 0; } @@ -4037,6 +4051,7 @@ static luaL_Reg lib[] = { {"K_PlayLossSound", lib_kLossSound}, {"K_PlayPainSound", lib_kPainSound}, {"K_PlayHitEmSound", lib_kHitEmSound}, + {"K_TryHurtSoundExchange", lib_kTryHurtSoundExchange}, {"K_IsPlayerLosing",lib_kIsPlayerLosing}, {"K_IsPlayerWanted",lib_kIsPlayerWanted}, {"K_KartBouncing",lib_kKartBouncing}, diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 19b9b4463..7078b2258 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -362,10 +362,10 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->lastjawztarget); else if (fastcmp(field,"jawztargetdelay")) lua_pushinteger(L, plr->jawztargetdelay); - else if (fastcmp(field,"confirmInflictor")) - lua_pushinteger(L, plr->confirmInflictor); - else if (fastcmp(field,"confirmInflictorDelay")) - lua_pushinteger(L, plr->confirmInflictorDelay); + else if (fastcmp(field,"confirmVictim")) + lua_pushinteger(L, plr->confirmVictim); + else if (fastcmp(field,"confirmVictimDelay")) + lua_pushinteger(L, plr->confirmVictimDelay); else if (fastcmp(field,"glanceDir")) lua_pushinteger(L, plr->glanceDir); else if (fastcmp(field,"trickpanel")) @@ -722,10 +722,10 @@ static int player_set(lua_State *L) plr->lastjawztarget = luaL_checkinteger(L, 3); else if (fastcmp(field,"jawztargetdelay")) plr->jawztargetdelay = luaL_checkinteger(L, 3); - else if (fastcmp(field,"confirmInflictor")) - plr->confirmInflictor = luaL_checkinteger(L, 3); - else if (fastcmp(field,"confirmInflictorDelay")) - plr->confirmInflictorDelay = luaL_checkinteger(L, 3); + else if (fastcmp(field,"confirmVictim")) + plr->confirmVictim = luaL_checkinteger(L, 3); + else if (fastcmp(field,"confirmVictimDelay")) + plr->confirmVictimDelay = luaL_checkinteger(L, 3); else if (fastcmp(field,"glanceDir")) plr->glanceDir = luaL_checkinteger(L, 3); else if (fastcmp(field,"trickpanel")) diff --git a/src/p_inter.c b/src/p_inter.c index b90593c2b..57c4f816c 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2012,7 +2012,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da source->player->invincibilitytimer += kinvextend; } - K_PlayHitEmSound(source, target); + K_TryHurtSoundExchange(target, source); K_BattleAwardHit(source->player, player, inflictor, takeBumpers); K_TakeBumpersFromPlayer(source->player, player, takeBumpers); @@ -2085,14 +2085,14 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da player->flashing = K_GetKartFlashing(player); } - P_PlayRinglossSound(player->mo); + P_PlayRinglossSound(target); if (ringburst > 0) { P_PlayerRingBurst(player, ringburst); } - K_PlayPainSound(player->mo); + K_PlayPainSound(target, source); if ((hardhit == true) || (cv_kartdebughuddrop.value && !modeattacking)) { diff --git a/src/p_saveg.c b/src/p_saveg.c index 22e94a419..72101fc9c 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -339,8 +339,8 @@ static void P_NetArchivePlayers(void) WRITESINT8(save_p, players[i].lastjawztarget); WRITEUINT8(save_p, players[i].jawztargetdelay); - WRITEUINT8(save_p, players[i].confirmInflictor); - WRITEUINT8(save_p, players[i].confirmInflictorDelay); + WRITEUINT8(save_p, players[i].confirmVictim); + WRITEUINT8(save_p, players[i].confirmVictimDelay); WRITEUINT8(save_p, players[i].trickpanel); WRITEUINT8(save_p, players[i].tricktime); @@ -626,8 +626,8 @@ static void P_NetUnArchivePlayers(void) players[i].lastjawztarget = READSINT8(save_p); players[i].jawztargetdelay = READUINT8(save_p); - players[i].confirmInflictor = READUINT8(save_p); - players[i].confirmInflictorDelay = READUINT8(save_p); + players[i].confirmVictim = READUINT8(save_p); + players[i].confirmVictimDelay = READUINT8(save_p); players[i].trickpanel = READUINT8(save_p); players[i].tricktime = READUINT8(save_p);