mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
cv_antigrief
- Increments a timer on human players who aren't making progress, does it even faster if they're going backwards.
- Only applies in:
- Netgames
- GTR_CIRCUIT after the timer starts
- If there's no timelimit, pointlimit, or K_Cooperative (because unproductive behaviour there will be punished by other rules)
- The rate at which this changes needs trial and error, but getting the feature functional is more important to start out with.
- If this timer reaches cv_antigrief's value in seconds , the player gets a "Grief Strike"
- This doesn't happen if:
- There's only one active player in the server, so FREE PLAY permits mappers to test what increments/decrements the counter
- Turn `debugwaypoints` on to observe this
- The cvar is set to 0
- Less than 3 grief strikes is a forced spectate
- Anything more is a kick via "automatic grief detection"
- Unless your node is the host (or an admin)
- Remove grief strike strike for finishing normally
# Conflicts:
# src/d_clisrv.h
This commit is contained in:
parent
d4dbc1fe30
commit
ab68be49e1
14 changed files with 168 additions and 2 deletions
|
|
@ -3369,6 +3369,10 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
|
|||
HU_AddChatText(va("\x82*%s left the game", player_names[pnum]), false);
|
||||
kickreason = KR_LEAVE;
|
||||
break;
|
||||
case KICK_MSG_GRIEF:
|
||||
HU_AddChatText(va("\x82*%s has been kicked (Automatic grief detection)", player_names[pnum]), false);
|
||||
kickreason = KR_KICK;
|
||||
break;
|
||||
case KICK_MSG_BANNED:
|
||||
HU_AddChatText(va("\x82*%s has been banned (No reason given)", player_names[pnum]), false);
|
||||
kickreason = KR_BAN;
|
||||
|
|
@ -3414,8 +3418,12 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
|
|||
M_StartMessage(M_GetText("Server closed connection\n(Synch failure)\nPress (B)\n"), NULL, MM_NOTHING);
|
||||
else if (msg == KICK_MSG_PING_HIGH)
|
||||
M_StartMessage(M_GetText("Server closed connection\n(Broke delay limit)\nPress (B)\n"), NULL, MM_NOTHING);
|
||||
else if (msg == KICK_MSG_TIMEOUT) // this one will probably never be seen?
|
||||
M_StartMessage(M_GetText("Connection timed out\n\nPress (B)\n"), NULL, MM_NOTHING);
|
||||
else if (msg == KICK_MSG_BANNED)
|
||||
M_StartMessage(M_GetText("You have been banned by the server\n\nPress (B)\n"), NULL, MM_NOTHING);
|
||||
else if (msg == KICK_MSG_CUSTOM_KICK)
|
||||
M_StartMessage(M_GetText("You have been kicked\n(Automatic grief detection)\nPress (B)\n"), NULL, MM_NOTHING);
|
||||
else if (msg == KICK_MSG_CUSTOM_KICK)
|
||||
M_StartMessage(va(M_GetText("You have been kicked\n(%s)\nPress (B)\n"), reason), NULL, MM_NOTHING);
|
||||
else if (msg == KICK_MSG_CUSTOM_BAN)
|
||||
|
|
|
|||
|
|
@ -468,6 +468,7 @@ typedef enum
|
|||
KICK_MSG_CUSTOM_BAN, // Ban message w/ custom reason
|
||||
KICK_MSG_TIMEOUT, // Player's connection timed out
|
||||
KICK_MSG_PING_HIGH, // Player hit the ping limit
|
||||
KICK_MSG_GRIEF, // Player was detected by antigrief
|
||||
KICK_MSG_CON_FAIL, // Player failed to resync game state
|
||||
KICK_MSG_SIGFAIL, // Player failed signature check
|
||||
KICK_MSG__MAX // Number of unique messages
|
||||
|
|
|
|||
|
|
@ -266,6 +266,9 @@ static CV_PossibleValue_t spectatorreentry_cons_t[] = {{0, "MIN"}, {10*60, "MAX"
|
|||
consvar_t cv_spectatorreentry = CVAR_INIT ("spectatorreentry", "30", CV_NETVAR, spectatorreentry_cons_t, NULL);
|
||||
consvar_t cv_duelspectatorreentry = CVAR_INIT ("duelspectatorreentry", "180", CV_NETVAR, spectatorreentry_cons_t, NULL);
|
||||
|
||||
static CV_PossibleValue_t antigrief_cons_t[] = {{10, "MIN"}, {120, "MAX"}, {0, "Off"}, {0, NULL}};
|
||||
consvar_t cv_antigrief = CVAR_INIT ("antigrief", "30", CV_NETVAR, antigrief_cons_t, NULL);
|
||||
|
||||
consvar_t cv_startinglives = CVAR_INIT ("startinglives", "3", CV_NETVAR|CV_CHEAT|CV_NOSHOWHELP, startingliveslimit_cons_t, NULL);
|
||||
|
||||
static CV_PossibleValue_t respawntime_cons_t[] = {{1, "MIN"}, {30, "MAX"}, {0, "Off"}, {0, NULL}};
|
||||
|
|
@ -794,6 +797,7 @@ void D_RegisterServerCommands(void)
|
|||
CV_RegisterVar(&cv_maxplayers);
|
||||
CV_RegisterVar(&cv_spectatorreentry);
|
||||
CV_RegisterVar(&cv_duelspectatorreentry);
|
||||
CV_RegisterVar(&cv_antigrief);
|
||||
CV_RegisterVar(&cv_respawntime);
|
||||
|
||||
// d_clisrv
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ extern consvar_t cv_mute;
|
|||
extern consvar_t cv_pause;
|
||||
|
||||
extern consvar_t cv_restrictskinchange, cv_allowteamchange, cv_maxplayers, cv_respawntime;
|
||||
extern consvar_t cv_spectatorreentry, cv_duelspectatorreentry;
|
||||
extern consvar_t cv_spectatorreentry, cv_duelspectatorreentry, cv_antigrief;
|
||||
|
||||
// SRB2kart items
|
||||
extern consvar_t cv_items[NUMKARTRESULTS-1];
|
||||
|
|
|
|||
|
|
@ -504,6 +504,7 @@ struct player_t
|
|||
UINT8 oldposition; // Used for taunting when you pass someone
|
||||
UINT8 positiondelay; // Used for position number, so it can grow when passing
|
||||
UINT32 distancetofinish;
|
||||
UINT32 distancetofinishprev;
|
||||
waypoint_t *currentwaypoint;
|
||||
waypoint_t *nextwaypoint;
|
||||
respawnvars_t respawn; // Respawn info
|
||||
|
|
@ -693,6 +694,9 @@ struct player_t
|
|||
|
||||
tic_t spectatorReentry;
|
||||
|
||||
UINT32 griefValue;
|
||||
UINT8 griefStrikes;
|
||||
|
||||
UINT8 typing_timer; // Counts down while keystrokes are not emitted
|
||||
UINT8 typing_duration; // How long since resumed timer
|
||||
|
||||
|
|
|
|||
|
|
@ -2478,6 +2478,9 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
|
||||
tic_t spectatorReentry;
|
||||
|
||||
UINT32 griefValue;
|
||||
UINT8 griefStrikes;
|
||||
|
||||
UINT8 splitscreenindex;
|
||||
boolean spectator;
|
||||
boolean bot;
|
||||
|
|
@ -2658,6 +2661,9 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
|
||||
spectatorReentry = (betweenmaps ? 0 : players[player].spectatorReentry);
|
||||
|
||||
griefValue = players[player].griefValue;
|
||||
griefStrikes = players[player].griefStrikes;
|
||||
|
||||
if (!betweenmaps)
|
||||
{
|
||||
follower = players[player].follower;
|
||||
|
|
@ -2739,6 +2745,8 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
p->botvars.controller = UINT16_MAX;
|
||||
|
||||
p->spectatorReentry = spectatorReentry;
|
||||
p->griefValue = griefValue;
|
||||
p->griefStrikes = griefStrikes;
|
||||
|
||||
memcpy(&p->itemRoulette, &itemRoulette, sizeof (p->itemRoulette));
|
||||
memcpy(&p->respawn, &respawn, sizeof (p->respawn));
|
||||
|
|
|
|||
|
|
@ -5116,6 +5116,11 @@ static void K_DrawWaypointDebugger(void)
|
|||
if (stplyr != &players[displayplayers[0]]) // only for p1
|
||||
return;
|
||||
|
||||
if (netgame)
|
||||
{
|
||||
V_DrawString(8, 146, 0, va("Online griefing: [%u, %u]", stplyr->griefValue/TICRATE, stplyr->griefStrikes));
|
||||
}
|
||||
|
||||
V_DrawString(8, 156, 0, va("Current Waypoint ID: %d", K_GetWaypointID(stplyr->currentwaypoint)));
|
||||
V_DrawString(8, 166, 0, va("Next Waypoint ID: %d", K_GetWaypointID(stplyr->nextwaypoint)));
|
||||
V_DrawString(8, 176, 0, va("Finishline Distance: %d", stplyr->distancetofinish));
|
||||
|
|
|
|||
|
|
@ -8578,6 +8578,9 @@ void K_UpdateDistanceFromFinishLine(player_t *const player)
|
|||
player->nextwaypoint = nextwaypoint;
|
||||
}
|
||||
|
||||
// Update prev value (used for grief prevention code)
|
||||
player->distancetofinishprev = player->distancetofinish;
|
||||
|
||||
// nextwaypoint is now the waypoint that is in front of us
|
||||
if ((player->exiting && !(player->pflags & PF_NOCONTEST)) || player->spectator)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -225,6 +225,8 @@ static int player_get(lua_State *L)
|
|||
lua_pushinteger(L, plr->positiondelay);
|
||||
else if (fastcmp(field,"distancetofinish"))
|
||||
lua_pushinteger(L, plr->distancetofinish);
|
||||
else if (fastcmp(field,"distancetofinishprev"))
|
||||
lua_pushinteger(L, plr->distancetofinishprev);
|
||||
else if (fastcmp(field,"airtime"))
|
||||
lua_pushinteger(L, plr->airtime);
|
||||
else if (fastcmp(field,"flashing"))
|
||||
|
|
@ -502,6 +504,10 @@ static int player_get(lua_State *L)
|
|||
lua_pushinteger(L, plr->jointime);
|
||||
else if (fastcmp(field,"spectatorReentry"))
|
||||
lua_pushinteger(L, plr->spectatorReentry);
|
||||
else if (fastcmp(field,"griefValue"))
|
||||
lua_pushinteger(L, plr->griefValue);
|
||||
else if (fastcmp(field,"griefStrikes"))
|
||||
lua_pushinteger(L, plr->griefStrikes);
|
||||
else if (fastcmp(field,"splitscreenindex"))
|
||||
lua_pushinteger(L, plr->splitscreenindex);
|
||||
#ifdef HWRENDER
|
||||
|
|
@ -613,6 +619,8 @@ static int player_set(lua_State *L)
|
|||
plr->positiondelay = luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"distancetofinish"))
|
||||
return NOSET;
|
||||
else if (fastcmp(field,"distancetofinishprev"))
|
||||
return NOSET;
|
||||
else if (fastcmp(field,"airtime"))
|
||||
plr->airtime = luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"flashing"))
|
||||
|
|
@ -884,6 +892,10 @@ static int player_set(lua_State *L)
|
|||
return NOSET;
|
||||
else if (fastcmp(field,"spectatorReentry"))
|
||||
plr->spectatorReentry = (UINT32)luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"griefValue"))
|
||||
plr->griefValue = (UINT32)luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"griefStrikes"))
|
||||
plr->griefStrikes = (UINT8)luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"splitscreenindex"))
|
||||
return NOSET;
|
||||
#ifdef HWRENDER
|
||||
|
|
|
|||
|
|
@ -210,6 +210,7 @@ void P_PlayerThink(player_t *player);
|
|||
void P_PlayerAfterThink(player_t *player);
|
||||
void P_DoPlayerExit(player_t *player);
|
||||
void P_DoTimeOver(player_t *player);
|
||||
void P_CheckRaceGriefing(player_t *player, boolean dopunishment);
|
||||
|
||||
void P_ResetPlayerCheats(void);
|
||||
|
||||
|
|
|
|||
|
|
@ -11774,6 +11774,8 @@ void P_SpawnPlayer(INT32 playernum)
|
|||
P_SetScale(mobj, mobj->destscale);
|
||||
P_FlashPal(p, 0, 0); // Resets
|
||||
|
||||
p->griefValue = 0;
|
||||
|
||||
K_InitStumbleIndicator(p);
|
||||
|
||||
K_InitSliptideZipIndicator(p);
|
||||
|
|
|
|||
|
|
@ -196,6 +196,8 @@ static void P_NetArchivePlayers(savebuffer_t *save)
|
|||
WRITEUINT32(save->p, players[i].jointime);
|
||||
|
||||
WRITEUINT32(save->p, players[i].spectatorReentry);
|
||||
WRITEUINT32(save->p, players[i].griefValue);
|
||||
WRITEUINT8(save->p, players[i].griefStrikes);
|
||||
|
||||
WRITEUINT8(save->p, players[i].splitscreenindex);
|
||||
|
||||
|
|
@ -274,6 +276,7 @@ static void P_NetArchivePlayers(savebuffer_t *save)
|
|||
WRITEUINT8(save->p, players[i].oldposition);
|
||||
WRITEUINT8(save->p, players[i].positiondelay);
|
||||
WRITEUINT32(save->p, players[i].distancetofinish);
|
||||
WRITEUINT32(save->p, players[i].distancetofinishprev);
|
||||
WRITEUINT32(save->p, K_GetWaypointHeapIndex(players[i].currentwaypoint));
|
||||
WRITEUINT32(save->p, K_GetWaypointHeapIndex(players[i].nextwaypoint));
|
||||
WRITEUINT32(save->p, players[i].airtime);
|
||||
|
|
@ -601,6 +604,8 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
|
|||
players[i].jointime = READUINT32(save->p);
|
||||
|
||||
players[i].spectatorReentry = READUINT32(save->p);
|
||||
players[i].griefValue = READUINT32(save->p);
|
||||
players[i].griefStrikes = READUINT8(save->p);
|
||||
|
||||
players[i].splitscreenindex = READUINT8(save->p);
|
||||
|
||||
|
|
@ -653,6 +658,7 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
|
|||
players[i].oldposition = READUINT8(save->p);
|
||||
players[i].positiondelay = READUINT8(save->p);
|
||||
players[i].distancetofinish = READUINT32(save->p);
|
||||
players[i].distancetofinishprev = READUINT32(save->p);
|
||||
players[i].currentwaypoint = (waypoint_t *)(size_t)READUINT32(save->p);
|
||||
players[i].nextwaypoint = (waypoint_t *)(size_t)READUINT32(save->p);
|
||||
players[i].airtime = READUINT32(save->p);
|
||||
|
|
|
|||
21
src/p_tick.c
21
src/p_tick.c
|
|
@ -781,7 +781,7 @@ void P_Ticker(boolean run)
|
|||
// Run any "after all the other thinkers" stuff
|
||||
{
|
||||
player_t *finishingPlayers[MAXPLAYERS];
|
||||
UINT8 numFinishingPlayers = 0;
|
||||
UINT8 numingame = 0, numFinishingPlayers = 0;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
|
|
@ -789,6 +789,11 @@ void P_Ticker(boolean run)
|
|||
{
|
||||
P_PlayerAfterThink(&players[i]);
|
||||
|
||||
if (players[i].spectator == true)
|
||||
continue;
|
||||
|
||||
numingame++;
|
||||
|
||||
// Check for the number of ties for first place after every player has thunk run for this tic
|
||||
if (players[i].exiting == 1 && players[i].position == 1 &&
|
||||
(players[i].pflags & (PF_HITFINISHLINE|PF_NOCONTEST)) == PF_HITFINISHLINE)
|
||||
|
|
@ -798,11 +803,25 @@ void P_Ticker(boolean run)
|
|||
}
|
||||
}
|
||||
|
||||
if ((netgame) // Antigrief is supposed to apply?
|
||||
&& !(K_Cooperative() || timelimitintics > 0 || g_pointlimit > 0) // There are rules that will punish a griefing player
|
||||
&& (gametyperules & GTR_CIRCUIT) && (leveltime > starttime)) // The following only detects race griefing
|
||||
{
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
|
||||
{
|
||||
if (players[i].spectator == true)
|
||||
continue;
|
||||
|
||||
if (players[i].exiting || (players[i].pflags & PF_NOCONTEST))
|
||||
continue;
|
||||
|
||||
if (players[i].bot == true)
|
||||
continue;
|
||||
|
||||
P_CheckRaceGriefing(&players[i], (numingame > 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
93
src/p_user.c
93
src/p_user.c
|
|
@ -1267,6 +1267,12 @@ void P_DoPlayerExit(player_t *player)
|
|||
return;
|
||||
}
|
||||
|
||||
if (player->griefStrikes > 0)
|
||||
{
|
||||
// Remove a strike for finishing a race normally
|
||||
player->griefStrikes--;
|
||||
}
|
||||
|
||||
if (P_IsLocalPlayer(player) && (!player->spectator && !demo.playback))
|
||||
{
|
||||
legitimateexit = true;
|
||||
|
|
@ -3792,6 +3798,12 @@ void P_DoTimeOver(player_t *player)
|
|||
return;
|
||||
}
|
||||
|
||||
if (player->griefStrikes > 0)
|
||||
{
|
||||
// Remove a strike for finishing a race normally
|
||||
player->griefStrikes--;
|
||||
}
|
||||
|
||||
if (P_IsLocalPlayer(player) && !demo.playback)
|
||||
{
|
||||
legitimateexit = true; // SRB2kart: losing a race is still seeing it through to the end :p
|
||||
|
|
@ -4586,6 +4598,87 @@ void P_PlayerAfterThink(player_t *player)
|
|||
player->mo->pmomz = 0;
|
||||
}
|
||||
|
||||
void P_CheckRaceGriefing(player_t *player, boolean dopunishment)
|
||||
{
|
||||
const UINT32 griefMax = cv_antigrief.value * TICRATE;
|
||||
const UINT8 n = player - players;
|
||||
|
||||
const fixed_t requireDist = (12*player->mo->scale) / FRACUNIT;
|
||||
INT32 progress = player->distancetofinishprev - player->distancetofinish;
|
||||
boolean exceptions = (
|
||||
player->flashing != 0
|
||||
|| player->mo->hitlag != 0
|
||||
|| player->airtime > 3*TICRATE/2
|
||||
|| (player->justbumped > 0 && player->justbumped < bumptime-1)
|
||||
);
|
||||
|
||||
// Don't punish if the cvar is turned off,
|
||||
// otherwise NOBODY would be able to play!
|
||||
if (griefMax == 0)
|
||||
{
|
||||
dopunishment = false;
|
||||
}
|
||||
|
||||
if (!exceptions && (progress < requireDist))
|
||||
{
|
||||
// If antigrief is disabled, we don't want the
|
||||
// player getting into a hole so deep no amount
|
||||
// of good behaviour could ever make up for it.
|
||||
if (player->griefValue < griefMax)
|
||||
{
|
||||
// Making no progress, start counting against you.
|
||||
player->griefValue++;
|
||||
if (progress < -requireDist && player->griefValue < griefMax)
|
||||
{
|
||||
// Making NEGATIVE progress? Start counting even harder.
|
||||
player->griefValue++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (player->griefValue > 0)
|
||||
{
|
||||
// Playing normally.
|
||||
player->griefValue--;
|
||||
}
|
||||
|
||||
if (dopunishment && player->griefValue > griefMax)
|
||||
{
|
||||
if (player->griefStrikes < 3)
|
||||
{
|
||||
player->griefStrikes++;
|
||||
}
|
||||
|
||||
player->griefValue = 0;
|
||||
|
||||
if (server)
|
||||
{
|
||||
if (player->griefStrikes == 3 && playernode[n] != servernode
|
||||
#ifndef DEVELOP
|
||||
&& !IsPlayerAdmin(n)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
// Send kick
|
||||
SendKick(n, KICK_MSG_GRIEF);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Send spectate
|
||||
changeteam_union NetPacket;
|
||||
UINT16 usvalue;
|
||||
|
||||
NetPacket.value.l = NetPacket.value.b = 0;
|
||||
NetPacket.packet.newteam = 0;
|
||||
NetPacket.packet.playernum = n;
|
||||
NetPacket.packet.verification = true;
|
||||
|
||||
usvalue = SHORT(NetPacket.value.l|NetPacket.value.b);
|
||||
SendNetXCmd(XD_TEAMCHANGE, &usvalue, sizeof(usvalue));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void P_SetPlayerAngle(player_t *player, angle_t angle)
|
||||
{
|
||||
P_ForceLocalAngle(player, angle);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue