about summary refs log tree commit diff
path: root/src/game/server
diff options
context:
space:
mode:
authoroy <Tom_Adams@web.de>2011-02-21 12:35:14 +0100
committeroy <Tom_Adams@web.de>2011-02-21 12:35:14 +0100
commit45eee0c8c2bb5af6629db9adefeecea88a547fb4 (patch)
treeb9040bbbc657c2f69de0e84cb102bc14643e797d /src/game/server
parent088ec3e2f3ba0419612846db8f3687f5e2de1348 (diff)
downloadzcatch-45eee0c8c2bb5af6629db9adefeecea88a547fb4.tar.gz
zcatch-45eee0c8c2bb5af6629db9adefeecea88a547fb4.zip
fixed spawning on crappy maps
Diffstat (limited to 'src/game/server')
-rw-r--r--src/game/server/gamecontroller.cpp71
-rw-r--r--src/game/server/gamecontroller.h1
2 files changed, 68 insertions, 4 deletions
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();