diff --git a/src/game/server/ddracechat.cpp b/src/game/server/ddracechat.cpp index b15d1f03c..f2dee502d 100644 --- a/src/game/server/ddracechat.cpp +++ b/src/game/server/ddracechat.cpp @@ -1222,7 +1222,29 @@ void CGameContext::ConSetTimerType(IConsole::IResult *pResult, void *pUserData) } pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD,"timer",aBuf); } -void CGameContext::ConProtectedKill(IConsole::IResult *pResult, void *pUserData){ + +void CGameContext::ConRescue(IConsole::IResult *pResult, void *pUserData) +{ + CGameContext *pSelf = (CGameContext *) pUserData; + if (!CheckClientID(pResult->m_ClientID)) + return; + CPlayer *pPlayer = pSelf->m_apPlayers[pResult->m_ClientID]; + if (!pPlayer) + return; + CCharacter* pChr = pPlayer->GetCharacter(); + if (!pChr) + return; + + if (!g_Config.m_SvAllowRescue) { + pSelf->SendChatTarget(pPlayer->GetCID(), "Rescue is not enabled on this server"); + return; + } + + pChr->Rescue(); +} + +void CGameContext::ConProtectedKill(IConsole::IResult *pResult, void *pUserData) +{ CGameContext *pSelf = (CGameContext *) pUserData; if (!CheckClientID(pResult->m_ClientID)) return; diff --git a/src/game/server/ddracechat.h b/src/game/server/ddracechat.h index a1d92fd75..ae55330e0 100644 --- a/src/game/server/ddracechat.h +++ b/src/game/server/ddracechat.h @@ -41,6 +41,8 @@ CHAT_COMMAND("saytime", "?r", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSayTime, this, "Pr CHAT_COMMAND("saytimeall", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSayTimeAll, this, "Publicly messages everyone your current time in this current running race") CHAT_COMMAND("time", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConTime, this, "Privately shows you your current time in this current running race in the broadcast message") CHAT_COMMAND("timer", "?s", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSetTimerType, this, "Personal Setting of showing time in either broadcast or game/round timer, timer s, where s = broadcast for broadcast, gametimer for game/round timer, cycle for cycle, both for both, none for no timer and nothing to show current status") +CHAT_COMMAND("r", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConRescue, this, "Teleport yourself out of freeze (use sv_allow_rescue 1 to enable this feature)") +CHAT_COMMAND("rescue", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConRescue, this, "Teleport yourself out of freeze (use sv_allow_rescue 1 to enable this feature)") CHAT_COMMAND("kill", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConProtectedKill, this, "Kill yourself") diff --git a/src/game/server/entities/character.cpp b/src/game/server/entities/character.cpp index 95f2588ef..50f37622f 100644 --- a/src/game/server/entities/character.cpp +++ b/src/game/server/entities/character.cpp @@ -114,6 +114,17 @@ bool CCharacter::IsGrounded() return true; if(GameServer()->Collision()->CheckPoint(m_Pos.x-m_ProximityRadius/2, m_Pos.y+m_ProximityRadius/2+5)) return true; + + int index = GameServer()->Collision()->GetPureMapIndex(vec2(m_Pos.x, m_Pos.y+m_ProximityRadius/2+4)); + int tile = GameServer()->Collision()->GetTileIndex(index); + int flags = GameServer()->Collision()->GetTileFlags(index); + if(tile == TILE_STOPA || (tile == TILE_STOP && flags == ROTATION_0) || (tile ==TILE_STOPS && (flags == ROTATION_0 || flags == ROTATION_180))) + return true; + tile = GameServer()->Collision()->GetFTileIndex(index); + flags = GameServer()->Collision()->GetFTileFlags(index); + if(tile == TILE_STOPA || (tile == TILE_STOP && flags == ROTATION_0) || (tile ==TILE_STOPS && (flags == ROTATION_0 || flags == ROTATION_180))) + return true; + return false; } @@ -1993,7 +2004,18 @@ void CCharacter::DDRaceTick() } HandleTuneLayer(); // need this before coretick - + + // look for save position for rescue feature + if(g_Config.m_SvAllowRescue) { + int index = GameServer()->Collision()->GetPureMapIndex(m_Pos); + int tile = GameServer()->Collision()->GetTileIndex(index); + int ftile = GameServer()->Collision()->GetFTileIndex(index); + if(IsGrounded() && tile != TILE_FREEZE && tile != TILE_DFREEZE && ftile != TILE_FREEZE && ftile != TILE_DFREEZE) { + m_PrevSavePos = m_Pos; + m_SetSavePos = true; + } + } + m_Core.m_Id = GetPlayer()->GetCID(); } @@ -2127,6 +2149,7 @@ void CCharacter::DDRaceInit() m_Paused = false; m_DDRaceState = DDRACE_NONE; m_PrevPos = m_Pos; + m_SetSavePos = false; m_LastBroadcast = 0; m_TeamBeforeSuper = 0; m_Core.m_Id = GetPlayer()->GetCID(); @@ -2162,3 +2185,19 @@ void CCharacter::DDRaceInit() } } } + +void CCharacter::Rescue() +{ + if (m_SetSavePos && !m_Super && !m_DeepFreeze && IsGrounded() && m_Pos == m_PrevPos) { + int index = GameServer()->Collision()->GetPureMapIndex(m_Pos); + if (GameServer()->Collision()->GetTileIndex(index) == TILE_FREEZE || GameServer()->Collision()->GetFTileIndex(index) == TILE_FREEZE) { + m_Core.m_Pos =m_PrevSavePos; + m_Core.m_Vel = vec2(0, 0); + m_Core.m_HookedPlayer = -1; + m_Core.m_HookState = HOOK_RETRACTED; + m_Core.m_TriggeredEvents |= COREEVENT_HOOK_RETRACT; + GameWorld()->ReleaseHooked(GetPlayer()->GetCID()); + m_Core.m_HookPos = m_Core.m_Pos; + } + } +} diff --git a/src/game/server/entities/character.h b/src/game/server/entities/character.h index bd6ab95e2..ea737be84 100644 --- a/src/game/server/entities/character.h +++ b/src/game/server/entities/character.h @@ -79,6 +79,8 @@ public: void SetEmote(int Emote, int Tick); + void Rescue(); + int NeededFaketuning() {return m_NeededFaketuning;} bool IsAlive() const { return m_Alive; } bool IsPaused() const { return m_Paused; } @@ -165,6 +167,10 @@ private: void HandleBroadcast(); void HandleTuneLayer(); void SendZoneMsgs(); + + bool m_SetSavePos; + vec2 m_PrevSavePos; + public: CGameTeams* Teams(); void Pause(bool Pause); diff --git a/src/game/server/gamecontext.h b/src/game/server/gamecontext.h index f1455af13..2a44cdaea 100644 --- a/src/game/server/gamecontext.h +++ b/src/game/server/gamecontext.h @@ -301,6 +301,7 @@ private: static void ConSayTimeAll(IConsole::IResult *pResult, void *pUserData); static void ConTime(IConsole::IResult *pResult, void *pUserData); static void ConSetTimerType(IConsole::IResult *pResult, void *pUserData); + static void ConRescue(IConsole::IResult *pResult, void *pUserData); static void ConProtectedKill(IConsole::IResult *pResult, void *pUserData); diff --git a/src/game/variables.h b/src/game/variables.h index 22421f8e3..81c167547 100644 --- a/src/game/variables.h +++ b/src/game/variables.h @@ -142,6 +142,8 @@ MACRO_CONFIG_STR(SvServerType, sv_server_type, 64, "none", CFGFLAG_SERVER, "Type MACRO_CONFIG_INT(SvSendVotesPerTick, sv_send_votes_per_tick, 5, 1, 15, CFGFLAG_SERVER, "Number of vote options being send per tick") +MACRO_CONFIG_INT(SvAllowRescue, sv_allow_rescue, 0, 0, 1, CFGFLAG_SERVER, "Allow /rescue command so players can teleport themselves out of freeze"); + // debug #ifdef CONF_DEBUG // this one can crash the server if not used correctly MACRO_CONFIG_INT(DbgDummies, dbg_dummies, 0, 0, 15, CFGFLAG_SERVER, "")