From 45eee0c8c2bb5af6629db9adefeecea88a547fb4 Mon Sep 17 00:00:00 2001 From: oy Date: Mon, 21 Feb 2011 12:35:14 +0100 Subject: fixed spawning on crappy maps --- src/game/server/gamecontroller.cpp | 71 +++++++++++++++++++++++++++++++++++--- src/game/server/gamecontroller.h | 1 + 2 files changed, 68 insertions(+), 4 deletions(-) (limited to 'src/game') diff --git a/src/game/server/gamecontroller.cpp b/src/game/server/gamecontroller.cpp index 7dcd869a..e51b503c 100644 --- a/src/game/server/gamecontroller.cpp +++ b/src/game/server/gamecontroller.cpp @@ -57,16 +57,16 @@ float IGameController::EvaluateSpawnPos(CSpawnEval *pEval, vec2 Pos) return Score; } -void IGameController::EvaluateSpawnType(CSpawnEval *pEval, int T) +void IGameController::EvaluateSpawnType(CSpawnEval *pEval, int Type) { // get spawn point - for(int i = 0; i < m_aNumSpawnPoints[T]; i++) + for(int i = 0; i < m_aNumSpawnPoints[Type]; i++) { // check if the position is occupado - if(GameServer()->m_World.FindEntities(m_aaSpawnPoints[T][i], 64, 0, 1, CGameWorld::ENTTYPE_CHARACTER)) + if(GameServer()->m_World.FindEntities(m_aaSpawnPoints[Type][i], 64, 0, 1, CGameWorld::ENTTYPE_CHARACTER)) continue; - vec2 P = m_aaSpawnPoints[T][i]; + vec2 P = m_aaSpawnPoints[Type][i]; float S = EvaluateSpawnPos(pEval, P); if(!pEval->m_Got || pEval->m_Score > S) { @@ -77,6 +77,47 @@ void IGameController::EvaluateSpawnType(CSpawnEval *pEval, int T) } } +void IGameController::FindFreeSpawn(CSpawnEval *pEval, int Type) +{ + // pick the spawn point that is least occupied and has free space for spawning around it + for(int i = 0; i < m_aNumSpawnPoints[Type]; i++) + { + + CCharacter *aEnts[MAX_CLIENTS]; + int Num = GameServer()->m_World.FindEntities(m_aaSpawnPoints[Type][i], 64, (CEntity**)aEnts, MAX_CLIENTS, CGameWorld::ENTTYPE_CHARACTER); + float Score = 0.0f; + for(int c = 0; c < Num; ++c) + Score += 96.0f - distance(aEnts[c]->m_Pos, m_aaSpawnPoints[Type][i]); + + if(!pEval->m_Got || pEval->m_Score > Score) + { + // start, left, up, right, down + vec2 Positions[5] = { vec2(0.0f, 0.0f), vec2(-32.0f, 0.0f), vec2(0.0f, -32.0f), vec2(32.0f, 0.0f), vec2(0.0f, 32.0f) }; + + // check for free space + int Result = -1; + for(int Index = 0; Index < 5 && Result == -1; ++Index) + { + Result = Index; + for(int c = 0; c < Num; ++c) + if(GameServer()->Collision()->CheckPoint(m_aaSpawnPoints[Type][i]+Positions[Index]) || + distance(aEnts[c]->m_Pos, m_aaSpawnPoints[Type][i]+Positions[Index]) <= aEnts[c]->m_ProximityRadius) + { + Result = -1; + break; + } + } + + if(Result == -1) + continue; // try next spawn point + + pEval->m_Got = true; + pEval->m_Score = Score; + pEval->m_Pos = m_aaSpawnPoints[Type][i]+Positions[Result]; + } + } +} + bool IGameController::CanSpawn(int Team, vec2 *pOutPos) { CSpawnEval Eval; @@ -104,6 +145,28 @@ bool IGameController::CanSpawn(int Team, vec2 *pOutPos) EvaluateSpawnType(&Eval, 1); EvaluateSpawnType(&Eval, 2); } + + // handle crappy maps + if(!Eval.m_Got) + { + if(IsTeamplay()) + { + // first try own team spawn, then normal spawn and then enemy + FindFreeSpawn(&Eval, 1+(Team&1)); + if(!Eval.m_Got) + { + FindFreeSpawn(&Eval, 0); + if(!Eval.m_Got) + FindFreeSpawn(&Eval, 1+((Team+1)&1)); + } + } + else + { + FindFreeSpawn(&Eval, 0); + FindFreeSpawn(&Eval, 1); + FindFreeSpawn(&Eval, 2); + } + } *pOutPos = Eval.m_Pos; return Eval.m_Got; diff --git a/src/game/server/gamecontroller.h b/src/game/server/gamecontroller.h index 36989454..c999f84e 100644 --- a/src/game/server/gamecontroller.h +++ b/src/game/server/gamecontroller.h @@ -39,6 +39,7 @@ protected: float EvaluateSpawnPos(CSpawnEval *pEval, vec2 Pos); void EvaluateSpawnType(CSpawnEval *pEval, int Type); + void FindFreeSpawn(CSpawnEval *pEval, int Type); bool EvaluateSpawn(class CPlayer *pP, vec2 *pPos); void CycleMap(); -- cgit 1.4.1