ddnet/src/game/server/gamemodes/ctf.cpp

243 lines
6.4 KiB
C++
Raw Normal View History

2010-05-29 07:25:38 +00:00
// copyright (c) 2007 magnus auvinen, see licence.txt for more info
#include <game/mapitems.h>
#include <game/server/entities/character.h>
#include <game/server/player.h>
#include <game/server/gamecontext.h>
#include "ctf.h"
2010-05-29 07:25:38 +00:00
CGameControllerCTF::CGameControllerCTF(class CGameContext *pGameServer)
: IGameController(pGameServer)
{
2010-05-29 07:25:38 +00:00
m_apFlags[0] = 0;
m_apFlags[1] = 0;
m_pGameType = "CTF";
m_GameFlags = GAMEFLAG_TEAMS|GAMEFLAG_FLAGS;
}
2010-05-29 07:25:38 +00:00
bool CGameControllerCTF::OnEntity(int Index, vec2 Pos)
2008-01-13 11:43:43 +00:00
{
2010-05-29 07:25:38 +00:00
if(IGameController::OnEntity(Index, Pos))
2008-01-13 11:43:43 +00:00
return true;
2010-05-29 07:25:38 +00:00
int Team = -1;
if(Index == ENTITY_FLAGSTAND_RED) Team = 0;
if(Index == ENTITY_FLAGSTAND_BLUE) Team = 1;
if(Team == -1)
2008-01-13 11:43:43 +00:00
return false;
2010-05-29 07:25:38 +00:00
CFlag *F = new CFlag(&GameServer()->m_World, Team);
F->m_StandPos = Pos;
F->m_Pos = Pos;
m_apFlags[Team] = F;
GameServer()->m_World.InsertEntity(F);
2008-01-13 11:43:43 +00:00
return true;
}
2010-05-29 07:25:38 +00:00
int CGameControllerCTF::OnCharacterDeath(class CCharacter *pVictim, class CPlayer *pKiller, int WeaponID)
{
2010-05-29 07:25:38 +00:00
IGameController::OnCharacterDeath(pVictim, pKiller, WeaponID);
int HadFlag = 0;
// drop flags
2010-05-29 07:25:38 +00:00
for(int i = 0; i < 2; i++)
{
2010-05-29 07:25:38 +00:00
CFlag *F = m_apFlags[i];
if(F && pKiller && pKiller->GetCharacter() && F->m_pCarryingCharacter == pKiller->GetCharacter())
2010-05-29 07:25:38 +00:00
HadFlag |= 2;
if(F && F->m_pCarryingCharacter == pVictim)
{
2010-05-29 07:25:38 +00:00
GameServer()->CreateSoundGlobal(SOUND_CTF_DROP);
F->m_DropTick = Server()->Tick();
F->m_pCarryingCharacter = 0;
2010-05-29 07:25:38 +00:00
F->m_Vel = vec2(0,0);
2007-12-11 21:19:52 +00:00
2010-05-29 07:25:38 +00:00
if(pKiller && pKiller->GetTeam() != pVictim->GetPlayer()->GetTeam())
pKiller->m_Score++;
2007-12-11 21:19:52 +00:00
2010-05-29 07:25:38 +00:00
HadFlag |= 1;
}
}
2010-05-29 07:25:38 +00:00
return HadFlag;
}
bool CGameControllerCTF::CanBeMovedOnBalance(int Cid)
{
CCharacter* Character = GameServer()->m_apPlayers[Cid]->GetCharacter();
if(Character)
{
for(int fi = 0; fi < 2; fi++)
{
CFlag *F = m_apFlags[fi];
if(F->m_pCarryingCharacter == Character)
2010-05-29 07:25:38 +00:00
return false;
}
}
return true;
}
2010-05-29 07:25:38 +00:00
void CGameControllerCTF::Tick()
{
2010-05-29 07:25:38 +00:00
IGameController::Tick();
2007-11-26 20:47:49 +00:00
2010-05-29 07:25:38 +00:00
DoTeamScoreWincheck();
for(int fi = 0; fi < 2; fi++)
{
2010-05-29 07:25:38 +00:00
CFlag *F = m_apFlags[fi];
2010-05-29 07:25:38 +00:00
if(!F)
2007-12-09 09:47:05 +00:00
continue;
// flag hits death-tile, reset it
2010-05-29 07:25:38 +00:00
if(GameServer()->Collision()->GetCollisionAt(F->m_Pos.x, F->m_Pos.y)&CCollision::COLFLAG_DEATH)
{
2010-05-29 07:25:38 +00:00
GameServer()->CreateSoundGlobal(SOUND_CTF_RETURN);
F->Reset();
continue;
}
//
if(F->m_pCarryingCharacter)
{
// update flag position
F->m_Pos = F->m_pCarryingCharacter->m_Pos;
2010-05-29 07:25:38 +00:00
if(m_apFlags[fi^1] && m_apFlags[fi^1]->m_AtStand)
{
if(distance(F->m_Pos, m_apFlags[fi^1]->m_Pos) < 28)
{
// CAPTURE! \o/
2010-05-29 07:25:38 +00:00
m_aTeamscore[fi^1] += 100;
F->m_pCarryingCharacter->GetPlayer()->m_Score += 5;
dbg_msg("game", "flag_capture player='%d:%s'",
F->m_pCarryingCharacter->GetPlayer()->GetCID(),
Server()->ClientName(F->m_pCarryingCharacter->GetPlayer()->GetCID()));
2010-05-29 07:25:38 +00:00
char Buf[512];
float CaptureTime = (Server()->Tick() - F->m_GrabTick)/(float)Server()->TickSpeed();
if(CaptureTime <= 60)
{
str_format(Buf, sizeof(Buf), "The %s flag was captured by %s (%d.%s%d seconds)", fi ? "blue" : "red", Server()->ClientName(F->m_pCarryingCharacter->GetPlayer()->GetCID()), (int)CaptureTime%60, ((int)(CaptureTime*100)%100)<10?"0":"", (int)(CaptureTime*100)%100);
}
else
{
str_format(Buf, sizeof(Buf), "The %s flag was captured by %s", fi ? "blue" : "red", Server()->ClientName(F->m_pCarryingCharacter->GetPlayer()->GetCID()));
}
2010-05-29 07:25:38 +00:00
GameServer()->SendChat(-1, -2, Buf);
for(int i = 0; i < 2; i++)
2010-05-29 07:25:38 +00:00
m_apFlags[i]->Reset();
2010-05-29 07:25:38 +00:00
GameServer()->CreateSoundGlobal(SOUND_CTF_CAPTURE);
}
2010-05-29 07:25:38 +00:00
}
}
else
{
2010-05-29 07:25:38 +00:00
CCharacter *apCloseCCharacters[MAX_CLIENTS];
int Num = GameServer()->m_World.FindEntities(F->m_Pos, 7.0f, (CEntity**)apCloseCCharacters, MAX_CLIENTS, NETOBJTYPE_CHARACTER);
2010-05-29 07:25:38 +00:00
for(int i = 0; i < Num; i++)
{
2010-05-29 07:25:38 +00:00
if(!apCloseCCharacters[i]->IsAlive() || apCloseCCharacters[i]->GetPlayer()->GetTeam() == -1 || GameServer()->Collision()->IntersectLine(F->m_Pos, apCloseCCharacters[i]->m_Pos, NULL, NULL))
continue;
2010-05-29 07:25:38 +00:00
if(apCloseCCharacters[i]->GetPlayer()->GetTeam() == F->m_Team)
{
// return the flag
2010-05-29 07:25:38 +00:00
if(!F->m_AtStand)
{
2010-05-29 07:25:38 +00:00
CCharacter *pChr = apCloseCCharacters[i];
pChr->GetPlayer()->m_Score += 1;
dbg_msg("game", "flag_return player='%d:%s'",
2010-05-29 07:25:38 +00:00
pChr->GetPlayer()->GetCID(),
Server()->ClientName(pChr->GetPlayer()->GetCID()));
2010-05-29 07:25:38 +00:00
GameServer()->CreateSoundGlobal(SOUND_CTF_RETURN);
F->Reset();
}
}
2008-11-08 09:02:35 +00:00
else
{
// take the flag
2010-05-29 07:25:38 +00:00
if(F->m_AtStand)
{
2010-05-29 07:25:38 +00:00
m_aTeamscore[fi^1]++;
F->m_GrabTick = Server()->Tick();
}
2010-05-29 07:25:38 +00:00
F->m_AtStand = 0;
F->m_pCarryingCharacter = apCloseCCharacters[i];
F->m_pCarryingCharacter->GetPlayer()->m_Score += 1;
dbg_msg("game", "flag_grab player='%d:%s'",
F->m_pCarryingCharacter->GetPlayer()->GetCID(),
Server()->ClientName(F->m_pCarryingCharacter->GetPlayer()->GetCID()));
2007-12-15 15:35:50 +00:00
for(int c = 0; c < MAX_CLIENTS; c++)
{
2010-05-29 07:25:38 +00:00
if(!GameServer()->m_apPlayers[c])
2007-12-15 15:35:50 +00:00
continue;
2010-05-29 07:25:38 +00:00
if(GameServer()->m_apPlayers[c]->GetTeam() == fi)
GameServer()->CreateSoundGlobal(SOUND_CTF_GRAB_EN, GameServer()->m_apPlayers[c]->GetCID());
2007-12-15 15:35:50 +00:00
else
2010-05-29 07:25:38 +00:00
GameServer()->CreateSoundGlobal(SOUND_CTF_GRAB_PL, GameServer()->m_apPlayers[c]->GetCID());
2007-12-15 15:35:50 +00:00
}
break;
}
}
if(!F->m_pCarryingCharacter && !F->m_AtStand)
{
2010-05-29 07:25:38 +00:00
if(Server()->Tick() > F->m_DropTick + Server()->TickSpeed()*30)
{
2010-05-29 07:25:38 +00:00
GameServer()->CreateSoundGlobal(SOUND_CTF_RETURN);
F->Reset();
}
else
{
2010-05-29 07:25:38 +00:00
F->m_Vel.y += GameServer()->m_World.m_Core.m_Tuning.m_Gravity;
GameServer()->Collision()->MoveBox(&F->m_Pos, &F->m_Vel, vec2(F->m_PhysSize, F->m_PhysSize), 0.5f);
}
}
}
}
}
// Flag
2010-05-29 07:25:38 +00:00
CFlag::CFlag(CGameWorld *pGameWorld, int Team)
: CEntity(pGameWorld, NETOBJTYPE_FLAG)
{
2010-05-29 07:25:38 +00:00
m_Team = Team;
m_ProximityRadius = m_PhysSize;
m_pCarryingCharacter = 0x0;
2010-05-29 07:25:38 +00:00
m_GrabTick = 0;
2010-05-29 07:25:38 +00:00
Reset();
}
2010-05-29 07:25:38 +00:00
void CFlag::Reset()
{
m_pCarryingCharacter = 0x0;
2010-05-29 07:25:38 +00:00
m_AtStand = 1;
m_Pos = m_StandPos;
m_Vel = vec2(0,0);
m_GrabTick = 0;
}
2010-05-29 07:25:38 +00:00
void CFlag::Snap(int SnappingClient)
{
2010-05-29 07:25:38 +00:00
CNetObj_Flag *pFlag = (CNetObj_Flag *)Server()->SnapNewItem(NETOBJTYPE_FLAG, m_Team, sizeof(CNetObj_Flag));
pFlag->m_X = (int)m_Pos.x;
pFlag->m_Y = (int)m_Pos.y;
pFlag->m_Team = m_Team;
pFlag->m_CarriedBy = -1;
2010-05-29 07:25:38 +00:00
if(m_AtStand)
pFlag->m_CarriedBy = -2;
else if(m_pCarryingCharacter && m_pCarryingCharacter->GetPlayer())
pFlag->m_CarriedBy = m_pCarryingCharacter->GetPlayer()->GetCID();
}