diff --git a/src/game/server/ddracechat.cpp b/src/game/server/ddracechat.cpp index bd10327d..d49048d3 100644 --- a/src/game/server/ddracechat.cpp +++ b/src/game/server/ddracechat.cpp @@ -447,6 +447,15 @@ void CGameContext::ConPractice(IConsole::IResult *pResult, void *pUserData) if(pSelf->ProcessSpamProtection(pResult->m_ClientID)) return; + if(!g_Config.m_SvPractice) + { + pSelf->Console()->Print( + IConsole::OUTPUT_LEVEL_STANDARD, + "print", + "Practice mode is disabled"); + return; + } + CGameTeams &Teams = ((CGameControllerDDRace*) pSelf->m_pController)->m_Teams; int Team = Teams.m_Core.Team(pResult->m_ClientID); diff --git a/src/game/server/ddracecommands.cpp b/src/game/server/ddracecommands.cpp index 6eeffa17..8edc75aa 100644 --- a/src/game/server/ddracecommands.cpp +++ b/src/game/server/ddracecommands.cpp @@ -499,7 +499,9 @@ void CGameContext::ConSetDDRTeam(IConsole::IResult *pResult, void *pUserData) if (Team < TEAM_FLOCK || Team >= TEAM_SUPER) return; - if(pController->m_Teams.m_Core.Team(Target) && pController->m_Teams.GetDDRaceState(pSelf->m_apPlayers[Target]) == DDRACE_STARTED) + CCharacter* pChr = pSelf->GetPlayerChar(Target); + + if((pController->m_Teams.m_Core.Team(Target) && pController->m_Teams.GetDDRaceState(pSelf->m_apPlayers[Target]) == DDRACE_STARTED) || (pChr && pController->m_Teams.IsPractice(pChr->Team()))) pSelf->m_apPlayers[Target]->KillCharacter(WEAPON_SELF); pController->m_Teams.SetForceCharacterTeam(Target, Team); diff --git a/src/game/server/entities/character.cpp b/src/game/server/entities/character.cpp index 60f3948c..17d76001 100644 --- a/src/game/server/entities/character.cpp +++ b/src/game/server/entities/character.cpp @@ -1939,6 +1939,12 @@ void CCharacter::DDraceTick() int ftile = GameServer()->Collision()->GetFTileIndex(index); if (IsGrounded() && tile != TILE_FREEZE && tile != TILE_DFREEZE && ftile != TILE_FREEZE && ftile != TILE_DFREEZE) { m_PrevSavePos = m_Pos; + for(int i = 0; i< NUM_WEAPONS; i++) + { + m_aPrevSaveWeapons[i].m_AmmoRegenStart = m_aWeapons[i].m_AmmoRegenStart; + m_aPrevSaveWeapons[i].m_Ammo = m_aWeapons[i].m_Ammo; + m_aPrevSaveWeapons[i].m_Got = m_aWeapons[i].m_Got; + } m_SetSavePos = true; } } @@ -2135,7 +2141,7 @@ void CCharacter::DDraceInit() void CCharacter::Rescue() { - if (m_SetSavePos && !m_Super && !m_DeepFreeze && IsGrounded() && m_Pos == m_PrevPos) { + if (m_SetSavePos && !m_Super) { if (m_LastRescue + g_Config.m_SvRescueDelay * Server()->TickSpeed() > Server()->Tick()) { char aBuf[256]; @@ -2144,18 +2150,22 @@ void CCharacter::Rescue() return; } - int index = GameServer()->Collision()->GetPureMapIndex(m_Pos); - if (GameServer()->Collision()->GetTileIndex(index) == TILE_FREEZE || GameServer()->Collision()->GetFTileIndex(index) == TILE_FREEZE) { - m_LastRescue = Server()->Tick(); - m_Core.m_Pos = m_PrevSavePos; - m_Pos = m_PrevSavePos; - m_PrevPos = m_PrevSavePos; - m_Core.m_Vel = vec2(0, 0); - m_Core.m_HookedPlayer = -1; - m_Core.m_HookState = HOOK_RETRACTED; - GameWorld()->ReleaseHooked(GetPlayer()->GetCID()); - m_Core.m_HookPos = m_Core.m_Pos; - UnFreeze(); + m_LastRescue = Server()->Tick(); + m_Core.m_Pos = m_PrevSavePos; + m_Pos = m_PrevSavePos; + m_PrevPos = m_PrevSavePos; + m_Core.m_Vel = vec2(0, 0); + m_Core.m_HookedPlayer = -1; + m_Core.m_HookState = HOOK_RETRACTED; + GameWorld()->ReleaseHooked(GetPlayer()->GetCID()); + m_Core.m_HookPos = m_Core.m_Pos; + UnFreeze(); + + for(int i = 0; i< NUM_WEAPONS; i++) + { + m_aWeapons[i].m_AmmoRegenStart = m_aPrevSaveWeapons[i].m_AmmoRegenStart; + m_aWeapons[i].m_Ammo = m_aPrevSaveWeapons[i].m_Ammo; + m_aWeapons[i].m_Got = m_aPrevSaveWeapons[i].m_Got; } } } diff --git a/src/game/server/entities/character.h b/src/game/server/entities/character.h index bd4474a5..30dce379 100644 --- a/src/game/server/entities/character.h +++ b/src/game/server/entities/character.h @@ -88,6 +88,8 @@ class CCharacter : public CEntity } m_aWeapons[NUM_WEAPONS]; + struct WeaponStat m_aPrevSaveWeapons[NUM_WEAPONS]; + int m_ActiveWeapon; int m_LastWeapon; int m_QueuedWeapon; diff --git a/src/game/server/save.cpp b/src/game/server/save.cpp index 49cb1bcb..83b818a4 100644 --- a/src/game/server/save.cpp +++ b/src/game/server/save.cpp @@ -429,7 +429,7 @@ CCharacter* CSaveTeam::MatchCharacter(char name[16], int SaveID) char* CSaveTeam::GetString() { - str_format(m_aString, sizeof(m_aString), "%d\t%d\t%d\t%d\t%d", m_TeamState, m_MembersCount, m_NumSwitchers, m_TeamLocked, m_Practice); + str_format(m_String, sizeof(m_String), "%d\t%d\t%d\t%d\t%d", m_TeamState, m_MembersCount, m_NumSwitchers, m_TeamLocked, m_Practice); for(int i = 0; i < m_MembersCount; i++) { @@ -443,8 +443,8 @@ char* CSaveTeam::GetString() for(int i=1; i < m_NumSwitchers+1; i++) { char aBuf[64]; - str_format(aBuf, sizeof(aBuf), "\n%d\t%d\t%d", m_Switchers[i].m_Status, m_pSwitchers[i].m_EndTime, m_pSwitchers[i].m_Type); - str_append(m_aString, aBuf, sizeof(m_aString)); + str_format(aBuf, sizeof(aBuf), "\n%d\t%d\t%d", m_Switchers[i].m_Status, m_Switchers[i].m_EndTime, m_Switchers[i].m_Type); + str_append(m_String, aBuf, sizeof(m_String)); } } diff --git a/src/game/server/teams.cpp b/src/game/server/teams.cpp index f7a49d8e..0234811e 100644 --- a/src/game/server/teams.cpp +++ b/src/game/server/teams.cpp @@ -243,6 +243,9 @@ bool CGameTeams::SetCharacterTeam(int ClientID, int Team) //if you begin race if (Character(ClientID)->m_DDRaceState != DDRACE_NONE && Team != TEAM_SUPER) return false; + //No cheating through noob filter with practice and then leaving team + if (m_Practice[m_Core.Team(ClientID)]) + return false; SetForceCharacterTeam(ClientID, Team); @@ -654,9 +657,13 @@ void CGameTeams::OnCharacterDeath(int ClientID, int Weapon) char aBuf[512]; str_format(aBuf, sizeof(aBuf), "Everyone in your locked team was killed because '%s' %s.", Server()->ClientName(ClientID), Weapon == WEAPON_SELF ? "killed" : "died"); + m_Practice[Team] = false; + for(int i = 0; i < MAX_CLIENTS; i++) if(m_Core.Team(i) == Team && GameServer()->m_apPlayers[i]) { + GameServer()->m_apPlayers[i]->m_VotedForPractice = false; + if(i != ClientID) { GameServer()->m_apPlayers[i]->KillCharacter(WEAPON_SELF); @@ -716,4 +723,6 @@ void CGameTeams::KillSavedTeam(int Team) // unlock team when last player leaves SetTeamLock(Team, false); ResetInvited(Team); + + m_Practice[Team] = false; } diff --git a/src/game/variables.h b/src/game/variables.h index a875d3a0..72d516ea 100644 --- a/src/game/variables.h +++ b/src/game/variables.h @@ -152,6 +152,7 @@ MACRO_CONFIG_INT(SvTeleportHoldHook, sv_teleport_hold_hook, 0, 0, 1, CFGFLAG_SER MACRO_CONFIG_INT(SvTeleportLoseWeapons, sv_teleport_lose_weapons, 0, 0, 1, CFGFLAG_SERVER|CFGFLAG_GAME, "Lose weapons when teleported (useful for some race maps)") MACRO_CONFIG_INT(SvRescue, sv_rescue, 0, 0, 1, CFGFLAG_SERVER, "Allow /rescue command so players can teleport themselves out of freeze") MACRO_CONFIG_INT(SvRescueDelay, sv_rescue_delay, 1, 0, 1000, CFGFLAG_SERVER, "Number of seconds between two rescues") +MACRO_CONFIG_INT(SvPractice, sv_practice, 1, 0, 1, CFGFLAG_SERVER, "Enable practice mode for teams. Means you can use /rescue, but in turn your rank doesn't count.", AUTHED_ADMIN) MACRO_CONFIG_INT(SvJoinVoteDelay, sv_join_vote_delay, 300, 0, 1000, CFGFLAG_SERVER, "Add a delay before recently joined players can call any vote or participate in a kick/spec vote (in seconds)") MACRO_CONFIG_INT(SvSpectatorSlots, sv_spectator_slots, 0, 0, 64, CFGFLAG_SERVER, "Number of slots to reserve for spectators") MACRO_CONFIG_INT(SvVotesPerTick, sv_votes_per_tick, 5, 1, 15, CFGFLAG_SERVER, "Number of vote options being sent per tick")