void CGameContext::ConJail(IConsole::IResult *pResult, void *pUserData)
{
	CGameContext *pSelf = (CGameContext *) pUserData;
	int Time = pResult->GetInteger(0);
	int JailID = pResult->GetVictim();
	char aBuf[200];

	if(Time < 20 || Time > 2419200)
	{
		pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Jail", "Set a time between 20 and 2419200 (4 weeks)");
		return;
	}

	CCharacter* pChr = pSelf->GetPlayerChar(JailID);
	if(pChr)
	{
		if(pChr->IsAlive())
		{
			pChr->GetPlayer()->m_AccData.m_Arrested = Time;
	
			if(Time)
			{
				str_format(aBuf, sizeof aBuf, "'%s' is arrested for %i secounds.", pSelf->Server()->ClientName(JailID), Time);
				pSelf->SendChat(-1, CHAT_ALL, aBuf);
				pChr->Die(pChr->GetPlayer()->GetCID(), WEAPON_GAME);
			
			}
		}
	}
}
Exemple #2
0
void CProjectile::Tick()
{
    float Pt = (Server()->Tick()-m_StartTick-1)/(float)Server()->TickSpeed();
    float Ct = (Server()->Tick()-m_StartTick)/(float)Server()->TickSpeed();
    vec2 PrevPos = GetPos(Pt);
    vec2 CurPos = GetPos(Ct);
    int Collide = GameServer()->Collision()->IntersectLine(PrevPos, CurPos, &CurPos, 0);
    CCharacter *OwnerChar = GameServer()->GetPlayerChar(m_Owner);
    CCharacter *TargetChr = GameServer()->m_World.IntersectCharacter(PrevPos, CurPos, 6.0f, CurPos, OwnerChar);

    m_LifeSpan--;

    if(TargetChr || Collide || m_LifeSpan < 0 || GameLayerClipped(CurPos))
    {
        if(m_LifeSpan >= 0 || m_Weapon == WEAPON_GRENADE)
            GameServer()->CreateSound(CurPos, m_SoundImpact);

        if(m_Explosive)
            GameServer()->CreateExplosion(CurPos, m_Owner, m_Weapon, false);

        else if(TargetChr && g_Config.m_SvInsta == 0)
            TargetChr->TakeDamage(m_Direction * max(0.001f, m_Force), m_Damage, m_Owner, m_Weapon);

        if(TargetChr && g_Config.m_SvInsta > 0)
            TargetChr->Die(m_Owner,m_Weapon);
        GameServer()->m_World.DestroyEntity(this);
    }
}
bool CLaserWall::HitCharacter(vec2 From, vec2 To)
{
	vec2 At;
	CCharacter *OwnerChar = GameServer()->GetPlayerChar(m_Owner);
	CCharacter *Hit = GameServer()->m_World.IntersectCharacter(From, To, 0.f, At, OwnerChar);

	if(!Hit)
		return false;

	Hit->Die(m_Owner, WEAPON_WORLD);
	return true;
}
Exemple #4
0
void CSingularity::Suck()
{
	float Len;
	
	CCharacter *p = (CCharacter *)GameServer()->m_World.FindFirst(CGameWorld::ENTTYPE_CHARACTER);
	for(; p; p = (CCharacter *)p->TypeNext())
	{
		if(!p || !p->IsAlive())
			continue;	
		
		Len = distance(m_Pos, p->m_Pos);
		if(Len < m_KillRange)
		{
			if(m_Owner > -1)
				p->Die(m_Owner,WEAPON_RIFLE);
			else
				p->Die(p->GetPlayer()->GetCID(),WEAPON_WORLD);
		}
		else if(Len < m_Range)
			p->SetVel(p->GetVel() + (normalize(m_Pos - p->m_Pos) * exp((m_Range - Len)/(m_Range/2.5f))));
	}

	// save CPU for projectiles
	if(m_SkipTick)
		return;
	
	CProjectile *s = (CProjectile *)GameServer()->m_World.FindFirst(CGameWorld::ENTTYPE_PROJECTILE);
	for(; s; s = (CProjectile *)s->TypeNext())
	{
		if(!s)
			continue;
		
		Len = distance(m_Pos, s->m_Pos);
		if(Len < m_Range*1.5)
			s->SetVel(s->GetVel() + ((normalize(m_Pos - s->m_Pos) * exp((m_Range*1.5 - Len)/(m_Range*0.6f)))*0.04f));
	}
}
void CBarrier::Tick()
{
	m_LifeSpan--;
	
	if(m_LifeSpan < 0)
	{
		GameServer()->m_World.DestroyEntity(this);
	}
	else
	{
		// Find other players
		for(CCharacter *p = (CCharacter*) GameWorld()->FindFirst(CGameWorld::ENTTYPE_CHARACTER); p; p = (CCharacter *)p->TypeNext())
		{
			if(!p->IsInfected()) continue;

			vec2 IntersectPos = closest_point_on_line(m_Pos, m_Pos2, p->m_Pos);
			float Len = distance(p->m_Pos, IntersectPos);
			if(Len < p->m_ProximityRadius+g_BarrierRadius)
			{
				//Check for portal traps
				if(p->GetClass() != PLAYERCLASS_UNDEAD && (Server()->Tick() - p->m_PortalTick) < Server()->TickSpeed()/2)
				{
					CPlayer* pPortalPlayer = GameServer()->m_apPlayers[p->m_LastPortalOwner];
					if(pPortalPlayer)
					{
						pPortalPlayer->IncreaseScore(1);
					}
				}
				
				//Check for hook traps. The case when the player is frozen is in the function Die()
				if(!p->IsFrozen())
				{
					for(CCharacter *pHook = (CCharacter*) GameWorld()->FindFirst(CGameWorld::ENTTYPE_CHARACTER); pHook; pHook = (CCharacter *)pHook->TypeNext())
					{
						if(p->GetPlayer() && pHook->GetPlayer() && pHook->m_Core.m_HookedPlayer == p->GetPlayer()->GetCID() && pHook->GetPlayer()->GetCID() != m_Owner)
						{
							pHook->GetPlayer()->IncreaseScore(1);
						}
					}
				}
				
				p->Die(m_Owner, WEAPON_HAMMER);
			}
		}
	}
}
Exemple #6
0
bool CLaser::HitCharacter(vec2 From, vec2 To)
{
	vec2 At;
	CCharacter *pOwnerChar = GameServer()->GetPlayerChar(m_Owner);
	CCharacter *pHit = GameServer()->m_World.IntersectCharacter(m_Pos, To, 0.f, At, pOwnerChar);
	if(!pHit)
		return false;

	m_From = From;
	m_Pos = At;
	m_Energy = -1;
	if(g_Config.m_SvInsta == 0)
		pHit->TakeDamage(vec2(0.f, 0.f), GameServer()->Tuning()->m_LaserDamage, m_Owner, WEAPON_RIFLE);
	else
		pHit->Die(m_Owner, WEAPON_RIFLE);
	return true;
}
Exemple #7
0
void CWall::Tick()
{
	CCharacter *pOwner = GameServer()->GetPlayerChar(m_Owner);

	m_Lifespan--;

	if(!pOwner || m_Lifespan<=0)
	{
		Reset();
		return;
	}	

	if(m_Counter >= pOwner->GetPlayer()->m_AccData.m_HammerWalls)
	{
		Reset();
		return;
	}	

	vec2 Intersection;
	CCharacter *pTargetChr = GameServer()->m_World.IntersectCharacter(m_Pos, m_Pos2, 1.0f, Intersection, 0x0);

	if(pTargetChr)
	{
		if(pTargetChr->Protected() || (pTargetChr == pOwner && pTargetChr->ActiveWeapon() == WEAPON_GUN))
		{
			Reset();
			return;
		}

		if(pTargetChr != pOwner && !pTargetChr->Protected() && !pTargetChr->m_God)
		{
			pTargetChr->Die(m_Owner, WEAPON_HAMMER);
			m_Counter++;
		}
	}

}
void CBarrier::Tick()
{
	m_LifeSpan--;
	
	if(m_LifeSpan < 0)
	{
		GameServer()->m_World.DestroyEntity(this);
	}
	
	{
		// Find other players
		for(CCharacter *p = (CCharacter*) GameWorld()->FindFirst(CGameWorld::ENTTYPE_CHARACTER); p; p = (CCharacter *)p->TypeNext())
		{
			if(!p->IsInfected()) continue;

			vec2 IntersectPos = closest_point_on_line(m_Pos, m_Pos2, p->m_Pos);
			float Len = distance(p->m_Pos, IntersectPos);
			if(Len < p->m_ProximityRadius+g_BarrierRadius)
			{
				p->Die(m_Owner, WEAPON_HAMMER);
			}
		}
	}
}
Exemple #9
0
void CGameControllerOpenFNG::DoInteractions()
{
	DoHookers();

	for(int i = 0; i < MAX_CLIENTS; i++)
	{
		CCharacter *pChr = CHAR(i);
		if (!pChr)
			continue;

		int FrzTicks = pChr->GetFreezeTicks();
		int Col = GameServer()->Collision()->GetCollisionAt(pChr->m_Pos.x, pChr->m_Pos.y);
		if (Col == TILE_SHRINE_ALL || Col == TILE_SHRINE_RED || Col == TILE_SHRINE_BLUE)
		{
			if (FrzTicks > 0 && m_aLastInteraction[i] < 0)
				pChr->Freeze(FrzTicks = 0);

			bool WasSacrificed = false;
			if (FrzTicks > 0)
			{
				int ShrineTeam = Col == TILE_SHRINE_RED ? TEAM_RED : Col == TILE_SHRINE_BLUE ? TEAM_BLUE : -1;
				HandleSacr(m_aLastInteraction[i], i, ShrineTeam);
				WasSacrificed = true;
			}

			pChr->Die(pChr->GetPlayer()->GetCID(), WEAPON_WORLD, WasSacrificed);
		}


		if (FrzTicks > 0)
		{
			if ((FrzTicks+1) % TS == 0) {
				int mask = -1;
				if (!CFG(MeltShowAll))
					mask = (int)~m_aCltMask[1-(pChr->GetPlayer()->GetTeam()&1)];

				GS->CreateDamageInd(pChr->m_Pos, 0, (FrzTicks+1) / TS, mask);

				if (CFG(ClickyMelt))
				{
					mask = -1;
					if (CFG(ClickyMelt) == 1)
						mask = (int)m_aCltMask[1-(pChr->GetPlayer()->GetTeam()&1)];

					GS->CreateSound(pChr->m_Pos, SOUND_WEAPON_NOAMMO, mask);
				}
			}

			if (FrzTicks == 1 && CFG(MeltSafeticks))
				pChr->SetEmote(EMOTE_SURPRISE, TICK + CFG(MeltSafeticks) + 1);

			m_aMoltenBy[i] = -1;

			if (m_aFrozenBy[i] != -1)
				continue;

			int Killer = pChr->WasFrozenBy();
			if (Killer < 0) //may happen then the gods are not pleased
			{
				m_aFrozenBy[i] = -1;
				continue;
			}

			m_aFrozenBy[i] = Killer;
			
			HandleFreeze(Killer, i);
		}
		else
		{
			m_aFrozenBy[i] = -1;

			int Melter = pChr->WasMoltenBy();
			if (Melter < 0)
				m_aMoltenBy[i] = -1;
			
			if (Melter == m_aMoltenBy[i])
				continue;

			m_aMoltenBy[i] = Melter;

			HandleMelt(Melter, i);
		}
	}
}
Exemple #10
0
void CGameControllerMOD::Tick()
{
	IGameController::Tick();
	
	m_HumanCounter = 0;
	m_InfectedCounter = 0;
	
	//Count type of players
	for(int i = 0; i < MAX_CLIENTS; i ++)
	{
		CPlayer *pPlayer = GameServer()->m_apPlayers[i];
		
		if(!pPlayer) continue;
		if(pPlayer->GetTeam() == TEAM_SPECTATORS) continue;
		
		if(pPlayer->IsInfected()) m_InfectedCounter++;
		else m_HumanCounter++;
	}
	
	m_InfectedStarted = false;
	
	//If the game can start ...
	if(m_GameOverTick == -1 && m_HumanCounter + m_InfectedCounter >= 2)
	{
		//If the infection started
		if(m_RoundStartTick + Server()->TickSpeed()*10 < Server()->Tick())
		{	
			m_InfectedStarted = true;
	
			for(int i = 0; i < MAX_CLIENTS; i ++)
			{
				CPlayer *pPlayer = GameServer()->m_apPlayers[i];
				
				if(!pPlayer) continue;
				if(pPlayer->GetTeam() == TEAM_SPECTATORS)
				{
					pPlayer->StartInfection();
				}
				else if(pPlayer->GetClass() == PLAYERCLASS_NONE)
				{
					pPlayer->SetClass(ChooseHumanClass(pPlayer));
					if(pPlayer->GetCharacter())
						pPlayer->GetCharacter()->IncreaseArmor(10);
				}
			}
			
			//If needed, infect players
			int nbInfectedNeeded = 2;
			if(m_InfectedCounter + m_HumanCounter < 4)
			{
				nbInfectedNeeded = 1;
			}
			
			while(m_InfectedCounter < nbInfectedNeeded)
			{
				float InfectionProb = 1.0/static_cast<float>(m_HumanCounter);
				float random = frandom();
				
				//Fair infection
				bool FairInfectionFound = false;
				for(int i = 0; i < MAX_CLIENTS; i ++)
				{
					CPlayer *pPlayer = GameServer()->m_apPlayers[i];
					
					if(!pPlayer) continue;
					if(pPlayer->GetTeam() == TEAM_SPECTATORS) continue;
					if(pPlayer->IsInfected()) continue;
					
					if(!Server()->IsClientInfectedBefore(i))
					{
						Server()->InfecteClient(i);
						GameServer()->m_apPlayers[i]->StartInfection();
						m_InfectedCounter++;
						m_HumanCounter--;
						
						GameServer()->SendChatTarget_Language_s(-1, "%s has been infected", Server()->ClientName(i));
						FairInfectionFound = true;
						break;
					}
				}
				
				//Unfair infection
				if(!FairInfectionFound)
				{
					for(int i = 0; i < MAX_CLIENTS; i ++)
					{
						CPlayer *pPlayer = GameServer()->m_apPlayers[i];
						
						if(!pPlayer) continue;
						if(pPlayer->GetTeam() == TEAM_SPECTATORS) continue;
						if(pPlayer->IsInfected()) continue;
						
						if(random < InfectionProb)
						{
							Server()->InfecteClient(i);
							GameServer()->m_apPlayers[i]->StartInfection();
							m_InfectedCounter++;
							m_HumanCounter--;
							
							GameServer()->SendChatTarget_Language_s(-1, "%s has been infected", Server()->ClientName(i));
							
							break;
						}
						else
						{
							random -= InfectionProb;
						}
					}
				}
			}
		}
		else
		{
			for(int i = 0; i < MAX_CLIENTS; i ++)
			{
				CPlayer *pPlayer = GameServer()->m_apPlayers[i];
				
				if(!pPlayer) continue;
				if(pPlayer->GetTeam() == TEAM_SPECTATORS)
				{
					pPlayer->SetClass(PLAYERCLASS_NONE);
				}
			}
		}
		
		//Win check
		if(m_InfectedStarted && m_HumanCounter == 0 && m_InfectedCounter > 1)
		{			
			float RoundDuration = static_cast<float>((Server()->Tick()-m_RoundStartTick)/((float)Server()->TickSpeed()))/60.0f;
			int Minutes = static_cast<int>(RoundDuration);
			int Seconds = static_cast<int>((RoundDuration - Minutes)*60.0f);
			
			GameServer()->SendChatTarget_Language_ii(-1, "Infected won the round in %i:%02i minutes", Minutes, Seconds);
			
			EndRound();
		}
		
		//Start the final explosion if the time is over
		if(m_InfectedStarted && !m_ExplosionStarted && g_Config.m_SvTimelimit > 0 && (Server()->Tick()-m_RoundStartTick) >= g_Config.m_SvTimelimit*Server()->TickSpeed()*60)
		{
			for(CCharacter *p = (CCharacter*) GameServer()->m_World.FindFirst(CGameWorld::ENTTYPE_CHARACTER); p; p = (CCharacter *)p->TypeNext())
			{
				if(p->IsInfected())
				{
					GameServer()->SendEmoticon(p->GetPlayer()->GetCID(), EMOTICON_GHOST);
				}
				else
				{
					GameServer()->SendEmoticon(p->GetPlayer()->GetCID(), EMOTICON_EYES);
				}
			}
			m_ExplosionStarted = true;
		}
		
		//Do the final explosion
		if(m_ExplosionStarted)
		{		
			bool NewExplosion = false;
			
			for(int j=0; j<m_MapHeight; j++)
			{
				for(int i=0; i<m_MapWidth; i++)
				{
					if((m_GrowingMap[j*m_MapWidth+i] & 1) && (
						(i > 0 && m_GrowingMap[j*m_MapWidth+i-1] & 2) ||
						(i < m_MapWidth-1 && m_GrowingMap[j*m_MapWidth+i+1] & 2) ||
						(j > 0 && m_GrowingMap[(j-1)*m_MapWidth+i] & 2) ||
						(j < m_MapHeight-1 && m_GrowingMap[(j+1)*m_MapWidth+i] & 2)
					))
					{
						NewExplosion = true;
						m_GrowingMap[j*m_MapWidth+i] |= 8;
						m_GrowingMap[j*m_MapWidth+i] &= ~1;
						if(rand()%10 == 0)
						{
							vec2 TilePos = vec2(16.0f, 16.0f) + vec2(i*32.0f, j*32.0f);
							GameServer()->CreateExplosion(TilePos, -1, WEAPON_GAME, true);
							GameServer()->CreateSound(TilePos, SOUND_GRENADE_EXPLODE);
						}
					}
				}
			}
			
			for(int j=0; j<m_MapHeight; j++)
			{
				for(int i=0; i<m_MapWidth; i++)
				{
					if(m_GrowingMap[j*m_MapWidth+i] & 8)
					{
						m_GrowingMap[j*m_MapWidth+i] &= ~8;
						m_GrowingMap[j*m_MapWidth+i] |= 2;
					}
				}
			}
			
			for(CCharacter *p = (CCharacter*) GameServer()->m_World.FindFirst(CGameWorld::ENTTYPE_CHARACTER); p; p = (CCharacter *)p->TypeNext())
			{
				if(!p->IsInfected())
					continue;
				
				int tileX = static_cast<int>(round(p->m_Pos.x))/32;
				int tileY = static_cast<int>(round(p->m_Pos.y))/32;
				
				if(tileX < 0) tileX = 0;
				if(tileX >= m_MapWidth) tileX = m_MapWidth-1;
				if(tileY < 0) tileY = 0;
				if(tileY >= m_MapHeight) tileY = m_MapHeight-1;
				
				if(m_GrowingMap[tileY*m_MapWidth+tileX] & 2 && p->GetPlayer())
				{
					p->Die(p->GetPlayer()->GetCID(), WEAPON_GAME);
				}
			}
		
			//If no more explosions, game over, decide who win
			if(!NewExplosion)
			{
				if(m_HumanCounter)
				{
					if(m_HumanCounter <= 1)
					{
						GameServer()->SendChatTarget_Language(-1, "One human won the round");
					}
					else
					{
						GameServer()->SendChatTarget_Language_i(-1, "%i humans won the round", m_HumanCounter);
					}
					
					for(int i = 0; i < MAX_CLIENTS; i ++)
					{
						CPlayer *pPlayer = GameServer()->m_apPlayers[i];
						
						if(!pPlayer) continue;
						if(pPlayer->GetTeam() == TEAM_SPECTATORS) continue;
						
						if(!pPlayer->IsInfected())
						{
							pPlayer->IncreaseScore(5);
							pPlayer->m_WinAsHuman++;
							
							GameServer()->SendChatTarget_Language(i, "You have survived, +5 points");
						}
					}
				}
				else
				{
					GameServer()->SendChatTarget_Language_ii(-1, "Infected won the round in %i:%02i minutes", g_Config.m_SvTimelimit, 0);
				}
				
				EndRound();
			}
		}
	}
	else
	{
		m_RoundStartTick = Server()->Tick();
	}
}
Exemple #11
0
bool CLaser::HitCharacter(vec2 From, vec2 To)
{
	vec2 At;
	CCharacter *OwnerChar = GameServer()->GetPlayerChar(m_Owner);
	CCharacter *Hit = GameServer()->m_World.IntersectCharacter(m_Pos, To, 0.f, At, OwnerChar);

	if(!Hit)
		return false;

	if(!OwnerChar)
	{
		if(Hit->m_GameZone && Hit->m_Frozen && m_Type == WEAPON_RIFLE)
			Hit->Unfreeze();
		else if(m_Type == WEAPON_RIFLE)
			Hit->TakeDamage(vec2(0.f, 0.f), GameServer()->Tuning()->m_LaserDamage, m_Owner, WEAPON_RIFLE);
		return false;
	}

	//CCharacter *pTarget = GameServer()->GetPlayerChar(Hit->GetPlayer()->GetCID());

	m_From = From;
	m_Pos = At;
	m_Energy = -1;

	if(m_Type == WEAPON_SHOTGUN)
	{
		Hit->m_Core.m_Vel + normalize(From - Hit->m_Core.m_Pos) * 10;
		return true;
	}

	if(OwnerChar->GetPlayer()->m_Insta && Hit->GetPlayer()->m_Insta)
		Hit->Die(OwnerChar->GetPlayer()->GetCID(), WEAPON_RIFLE);
	else if(Hit->m_GameZone && OwnerChar->m_GameZone && Hit->m_Frozen)
		Hit->Unfreeze();
	else if(OwnerChar->m_JailRifle && !Hit->GetPlayer()->m_Insta && !OwnerChar->m_GameZone)
	{
		char zBuf[200];
	    Hit->GetPlayer()->m_AccData.m_Arrested = 300;
		Hit->Die(OwnerChar->GetPlayer()->GetCID(), WEAPON_RIFLE);
  		str_format(zBuf, sizeof zBuf, "'%s' is arrested now", Server()->ClientName(Hit->GetPlayer()->GetCID()));
		GameServer()->SendChat(-1, CGameContext::CHAT_ALL, zBuf);
	}
	else if(!OwnerChar->GetPlayer()->m_Insta && !Hit->GetPlayer()->m_Insta)
		Hit->TakeDamage(vec2(0.f, 0.f), GameServer()->Tuning()->m_LaserDamage, m_Owner, WEAPON_RIFLE);
	
	// City
	if(OwnerChar && !Hit->GetPlayer()->m_AccData.m_Arrested && !Hit->GetPlayer()->m_Insta && !Hit->Protected())
	{
		if(GameServer()->m_apPlayers[m_Owner]->m_AccData.m_RifleSwap && !OwnerChar->GetPlayer()->m_Insta)
		{
			if(!OwnerChar->Protected() && !OwnerChar->m_JailRifle && !OwnerChar->GetPlayer()->m_AccData.m_Arrested)
			{
				vec2 TempPos = OwnerChar->m_Pos;
				OwnerChar->m_Core.m_Pos = Hit->m_Pos;
				Hit->m_Core.m_Pos = TempPos;
			}
		}
	}

	return true;
}
Exemple #12
0
void CCharacter::FireWeapon()
{
	if(m_ReloadTimer != 0)
		return;

	DoWeaponSwitch();
	vec2 Direction = normalize(vec2(m_LatestInput.m_TargetX, m_LatestInput.m_TargetY));

	bool FullAuto = false;
	if(g_Config.m_SvFullauto & 1 << (m_ActiveWeapon)/*m_ActiveWeapon == WEAPON_GRENADE || m_ActiveWeapon == WEAPON_SHOTGUN || m_ActiveWeapon == WEAPON_RIFLE*/)
		FullAuto = true;


	// check if we gonna fire
	bool WillFire = false;
	if(CountInput(m_LatestPrevInput.m_Fire, m_LatestInput.m_Fire).m_Presses)
		WillFire = true;

	if(FullAuto && (m_LatestInput.m_Fire&1) && m_aWeapons[m_ActiveWeapon].m_Ammo)
		WillFire = true;

	if(!WillFire)
		return;

	// check for ammo
	if(!m_aWeapons[m_ActiveWeapon].m_Ammo)
	{
		// 125ms is a magical limit of how fast a human can click
		m_ReloadTimer = 125 * Server()->TickSpeed() / 1000;
		if(m_LastNoAmmoSound+Server()->TickSpeed() <= Server()->Tick())
		{
			GameServer()->CreateSound(m_Pos, SOUND_WEAPON_NOAMMO);
			m_LastNoAmmoSound = Server()->Tick();
		}
		return;
	}

	vec2 ProjStartPos = m_Pos+Direction*m_ProximityRadius*0.75f;

	switch(m_ActiveWeapon)
	{
		case WEAPON_HAMMER:
		{
			// reset objects Hit
			m_NumObjectsHit = 0;
			GameServer()->CreateSound(m_Pos, SOUND_HAMMER_FIRE);

			CCharacter *apEnts[MAX_CLIENTS];
			int Hits = 0;
			int Num = GameServer()->m_World.FindEntities(ProjStartPos, m_ProximityRadius*0.5f, (CEntity**)apEnts,
														MAX_CLIENTS, CGameWorld::ENTTYPE_CHARACTER);

			for (int i = 0; i < Num; ++i)
			{
				CCharacter *pTarget = apEnts[i];

				if ((pTarget == this) || GameServer()->Collision()->IntersectLine(ProjStartPos, pTarget->m_Pos, NULL, NULL))
					continue;

				// set his velocity to fast upward (for now)
				if(length(pTarget->m_Pos-ProjStartPos) > 0.0f)
					GameServer()->CreateHammerHit(pTarget->m_Pos-normalize(pTarget->m_Pos-ProjStartPos)*m_ProximityRadius*0.5f);
				else
					GameServer()->CreateHammerHit(ProjStartPos);

				vec2 Dir;
				if (length(pTarget->m_Pos - m_Pos) > 0.0f)
					Dir = normalize(pTarget->m_Pos - m_Pos);
				else
					Dir = vec2(0.f, -1.f);
				if(g_Config.m_SvInsta == 0)
					pTarget->TakeDamage(vec2(0.f, -1.f) + normalize(Dir + vec2(0.f, -1.1f)) * 10.0f, g_pData->m_Weapons.m_Hammer.m_pBase->m_Damage,
						m_pPlayer->GetCID(), m_ActiveWeapon);
				else
					pTarget->Die(m_pPlayer->GetCID(), m_ActiveWeapon);
				Hits++;
			}

			// if we Hit anything, we have to wait for the reload
			if(Hits)
				m_ReloadTimer = Server()->TickSpeed()/3;

		} break;

		case WEAPON_GUN:
		{
			CProjectile *pProj = new CProjectile(GameWorld(), WEAPON_GUN,
				m_pPlayer->GetCID(),
				ProjStartPos,
				Direction,
				(int)(Server()->TickSpeed()*GameServer()->Tuning()->m_GunLifetime),
				1, 0, 0, -1, WEAPON_GUN);

			// pack the Projectile and send it to the client Directly
			CNetObj_Projectile p;
			pProj->FillInfo(&p);

			CMsgPacker Msg(NETMSGTYPE_SV_EXTRAPROJECTILE);
			Msg.AddInt(1);
			for(unsigned i = 0; i < sizeof(CNetObj_Projectile)/sizeof(int); i++)
				Msg.AddInt(((int *)&p)[i]);

			Server()->SendMsg(&Msg, 0, m_pPlayer->GetCID());

			GameServer()->CreateSound(m_Pos, SOUND_GUN_FIRE);
		} break;

		case WEAPON_SHOTGUN:
		{
			int ShotSpread = 2;

			CMsgPacker Msg(NETMSGTYPE_SV_EXTRAPROJECTILE);
			Msg.AddInt(ShotSpread*2+1);

			for(int i = -ShotSpread; i <= ShotSpread; ++i)
			{
				float Spreading[] = {-0.185f, -0.070f, 0, 0.070f, 0.185f};
				float a = GetAngle(Direction);
				a += Spreading[i+2];
				float v = 1-(absolute(i)/(float)ShotSpread);
				float Speed = mix((float)GameServer()->Tuning()->m_ShotgunSpeeddiff, 1.0f, v);
				CProjectile *pProj = new CProjectile(GameWorld(), WEAPON_SHOTGUN,
					m_pPlayer->GetCID(),
					ProjStartPos,
					vec2(cosf(a), sinf(a))*Speed,
					(int)(Server()->TickSpeed()*GameServer()->Tuning()->m_ShotgunLifetime),
					1, 0, 0, -1, WEAPON_SHOTGUN);

				// pack the Projectile and send it to the client Directly
				CNetObj_Projectile p;
				pProj->FillInfo(&p);

				for(unsigned i = 0; i < sizeof(CNetObj_Projectile)/sizeof(int); i++)
					Msg.AddInt(((int *)&p)[i]);
			}

			Server()->SendMsg(&Msg, 0,m_pPlayer->GetCID());

			GameServer()->CreateSound(m_Pos, SOUND_SHOTGUN_FIRE);
		} break;

		case WEAPON_GRENADE:
		{
			CProjectile *pProj = new CProjectile(GameWorld(), WEAPON_GRENADE,
				m_pPlayer->GetCID(),
				ProjStartPos,
				Direction,
				(int)(Server()->TickSpeed()*GameServer()->Tuning()->m_GrenadeLifetime),
				1, true, 0, SOUND_GRENADE_EXPLODE, WEAPON_GRENADE);

			// pack the Projectile and send it to the client Directly
			CNetObj_Projectile p;
			pProj->FillInfo(&p);

			CMsgPacker Msg(NETMSGTYPE_SV_EXTRAPROJECTILE);
			Msg.AddInt(1);
			for(unsigned i = 0; i < sizeof(CNetObj_Projectile)/sizeof(int); i++)
				Msg.AddInt(((int *)&p)[i]);
			Server()->SendMsg(&Msg, 0, m_pPlayer->GetCID());

			GameServer()->CreateSound(m_Pos, SOUND_GRENADE_FIRE);
		} break;

		case WEAPON_RIFLE:
		{
			new CLaser(GameWorld(), m_Pos, Direction, GameServer()->Tuning()->m_LaserReach, m_pPlayer->GetCID());
			GameServer()->CreateSound(m_Pos, SOUND_RIFLE_FIRE);
		} break;

		case WEAPON_NINJA:
		{
			// reset Hit objects
			m_NumObjectsHit = 0;

			m_Ninja.m_ActivationDir = Direction;
			m_Ninja.m_CurrentMoveTime = g_pData->m_Weapons.m_Ninja.m_Movetime * Server()->TickSpeed() / 1000;
			m_Ninja.m_OldVelAmount = length(m_Core.m_Vel);

			GameServer()->CreateSound(m_Pos, SOUND_NINJA_FIRE);
		} break;

	}

	m_AttackTick = Server()->Tick();

	if(m_aWeapons[m_ActiveWeapon].m_Ammo > 0) // -1 == unlimited
		m_aWeapons[m_ActiveWeapon].m_Ammo--;

	if(!m_ReloadTimer)
		m_ReloadTimer = g_pData->m_Weapons.m_aId[m_ActiveWeapon].m_Firedelay * Server()->TickSpeed() / 1000;
}
void CGameControllerMOD::Tick()
{
	IGameController::Tick();
	
	//Check session
	{
		CPlayerIterator<PLAYERITER_ALL> Iter(GameServer()->m_apPlayers);
		while(Iter.Next())
		{
			//Update session
			IServer::CClientSession* pSession = Server()->GetClientSession(Iter.ClientID());
			if(pSession)
			{
				if(!Server()->GetClientMemory(Iter.ClientID(), CLIENTMEMORY_SESSION_PROCESSED))
				{
					//The client already participated to this round,
					//and he exit the game as infected.
					//To avoid cheating, we assign to him the same class again.
					if(
						m_InfectedStarted &&
						pSession->m_RoundId == m_RoundId &&
						pSession->m_Class > END_HUMANCLASS
					)
					{
						Iter.Player()->SetClass(pSession->m_Class);
					}
					
					Server()->SetClientMemory(Iter.ClientID(), CLIENTMEMORY_SESSION_PROCESSED, true);
				}
				
				pSession->m_Class = Iter.Player()->GetClass();
				pSession->m_RoundId = GameServer()->m_pController->GetRoundId();
			}
		}
	}
	
	UpdatePlayerCounter();
	
	m_InfectedStarted = false;
	
	//If the game can start ...
	if(m_GameOverTick == -1 && m_HumanCounter + m_InfectedCounter >= 2)
	{
		//If the infection started
		if(IsInfectionStarted())
		{
			bool StartInfectionTrigger = (m_RoundStartTick + Server()->TickSpeed()*10 == Server()->Tick());
			
			GameServer()->EnableTargetToKill();
			
			if(m_pHeroFlag)
				m_pHeroFlag->Show();
			
			m_InfectedStarted = true;
	
			CPlayerIterator<PLAYERITER_INGAME> Iter(GameServer()->m_apPlayers);
			while(Iter.Next())
			{
				if(Iter.Player()->GetClass() == PLAYERCLASS_NONE)
				{
					if(StartInfectionTrigger)
					{
						Iter.Player()->SetClass(ChooseHumanClass(Iter.Player()));
						if(Iter.Player()->GetCharacter())
							Iter.Player()->GetCharacter()->IncreaseArmor(10);
					}
					else
						Iter.Player()->StartInfection();
				}
			}
			
			int NumNeededInfection = m_NumFirstInfected;
			
			while(m_InfectedCounter < NumNeededInfection)
			{
				float InfectionProb = 1.0/static_cast<float>(m_HumanCounter);
				float random = frandom();
				
				//Fair infection
				bool FairInfectionFound = false;
				
				Iter.Reset();
				while(Iter.Next())
				{
					if(Iter.Player()->IsInfected()) continue;
					
					if(!Server()->IsClientInfectedBefore(Iter.ClientID()))
					{
						Server()->InfecteClient(Iter.ClientID());
						Iter.Player()->StartInfection();
						m_InfectedCounter++;
						m_HumanCounter--;
						
						GameServer()->SendChatTarget_Localization(-1, CHATCATEGORY_INFECTION, _("{str:VictimName} has been infected"),
							"VictimName", Server()->ClientName(Iter.ClientID()),
							NULL
						);
						FairInfectionFound = true;
						break;
					}
				}
				
				//Unfair infection
				if(!FairInfectionFound)
				{
					Iter.Reset();
					while(Iter.Next())
					{
						if(Iter.Player()->IsInfected()) continue;
						
						if(random < InfectionProb)
						{
							Server()->InfecteClient(Iter.ClientID());
							Iter.Player()->StartInfection();
							m_InfectedCounter++;
							m_HumanCounter--;
							
							GameServer()->SendChatTarget_Localization(-1, CHATCATEGORY_INFECTION, _("{str:VictimName} has been infected"), "VictimName", Server()->ClientName(Iter.ClientID()), NULL);
							
							break;
						}
						else
						{
							random -= InfectionProb;
						}
					}
				}
			}
		}
		else
		{
			if(m_pHeroFlag)
				m_pHeroFlag->Show();
			
			GameServer()->DisableTargetToKill();
			
			CPlayerIterator<PLAYERITER_SPECTATORS> IterSpec(GameServer()->m_apPlayers);
			while(IterSpec.Next())
			{
				IterSpec.Player()->SetClass(PLAYERCLASS_NONE);
			}
		}
		
		//Win check
		if(m_InfectedStarted && m_HumanCounter == 0 && m_InfectedCounter > 1)
		{			
			int Seconds = (Server()->Tick()-m_RoundStartTick)/((float)Server()->TickSpeed());
			
			GameServer()->SendChatTarget_Localization(-1, CHATCATEGORY_INFECTED, _("Infected won the round in {sec:RoundDuration}"), "RoundDuration", &Seconds, NULL);
			
			EndRound();
		}
		
		//Start the final explosion if the time is over
		if(m_InfectedStarted && !m_ExplosionStarted && g_Config.m_SvTimelimit > 0 && (Server()->Tick()-m_RoundStartTick) >= g_Config.m_SvTimelimit*Server()->TickSpeed()*60)
		{
			for(CCharacter *p = (CCharacter*) GameServer()->m_World.FindFirst(CGameWorld::ENTTYPE_CHARACTER); p; p = (CCharacter *)p->TypeNext())
			{
				if(p->IsInfected())
				{
					GameServer()->SendEmoticon(p->GetPlayer()->GetCID(), EMOTICON_GHOST);
				}
				else
				{
					GameServer()->SendEmoticon(p->GetPlayer()->GetCID(), EMOTICON_EYES);
				}
			}
			m_ExplosionStarted = true;
		}
		
		//Do the final explosion
		if(m_ExplosionStarted)
		{		
			bool NewExplosion = false;
			
			for(int j=0; j<m_MapHeight; j++)
			{
				for(int i=0; i<m_MapWidth; i++)
				{
					if((m_GrowingMap[j*m_MapWidth+i] & 1) && (
						(i > 0 && m_GrowingMap[j*m_MapWidth+i-1] & 2) ||
						(i < m_MapWidth-1 && m_GrowingMap[j*m_MapWidth+i+1] & 2) ||
						(j > 0 && m_GrowingMap[(j-1)*m_MapWidth+i] & 2) ||
						(j < m_MapHeight-1 && m_GrowingMap[(j+1)*m_MapWidth+i] & 2)
					))
					{
						NewExplosion = true;
						m_GrowingMap[j*m_MapWidth+i] |= 8;
						m_GrowingMap[j*m_MapWidth+i] &= ~1;
						if(rand()%10 == 0)
						{
							vec2 TilePos = vec2(16.0f, 16.0f) + vec2(i*32.0f, j*32.0f);
							GameServer()->CreateExplosion(TilePos, -1, WEAPON_GAME, true);
							GameServer()->CreateSound(TilePos, SOUND_GRENADE_EXPLODE);
						}
					}
				}
			}
			
			for(int j=0; j<m_MapHeight; j++)
			{
				for(int i=0; i<m_MapWidth; i++)
				{
					if(m_GrowingMap[j*m_MapWidth+i] & 8)
					{
						m_GrowingMap[j*m_MapWidth+i] &= ~8;
						m_GrowingMap[j*m_MapWidth+i] |= 2;
					}
				}
			}
			
			for(CCharacter *p = (CCharacter*) GameServer()->m_World.FindFirst(CGameWorld::ENTTYPE_CHARACTER); p; p = (CCharacter *)p->TypeNext())
			{
				if(!p->IsInfected())
					continue;
				
				int tileX = static_cast<int>(round(p->m_Pos.x))/32;
				int tileY = static_cast<int>(round(p->m_Pos.y))/32;
				
				if(tileX < 0) tileX = 0;
				if(tileX >= m_MapWidth) tileX = m_MapWidth-1;
				if(tileY < 0) tileY = 0;
				if(tileY >= m_MapHeight) tileY = m_MapHeight-1;
				
				if(m_GrowingMap[tileY*m_MapWidth+tileX] & 2 && p->GetPlayer())
				{
					p->Die(p->GetPlayer()->GetCID(), WEAPON_GAME);
				}
			}
		
			//If no more explosions, game over, decide who win
			if(!NewExplosion)
			{
				if(m_HumanCounter)
				{
					GameServer()->SendChatTarget_Localization_P(-1, CHATCATEGORY_HUMANS, m_HumanCounter, _P("One human won the round", "{int:NumHumans} humans won the round"), "NumHumans", &m_HumanCounter, NULL);
					
					CPlayerIterator<PLAYERITER_INGAME> Iter(GameServer()->m_apPlayers);
					while(Iter.Next())
					{
						if(!Iter.Player()->IsInfected())
						{
							//TAG_SCORE
							Server()->RoundStatistics()->OnScoreEvent(Iter.ClientID(), SCOREEVENT_HUMAN_SURVIVE, Iter.Player()->GetClass());
							Server()->RoundStatistics()->SetPlayerAsWinner(Iter.ClientID());
							GameServer()->SendScoreSound(Iter.ClientID());
							Iter.Player()->m_WinAsHuman++;
							
							GameServer()->SendChatTarget_Localization(Iter.ClientID(), CHATCATEGORY_SCORE, _("You have survived, +5 points"), NULL);
						}
					}
				}
				else
				{
					int Seconds = g_Config.m_SvTimelimit*60;
					GameServer()->SendChatTarget_Localization(-1, CHATCATEGORY_INFECTED, _("Infected won the round in {sec:RoundDuration}"), "RoundDuration", &Seconds, NULL);
				}
				
				EndRound();
			}
		}
	}
	else
	{
		GameServer()->DisableTargetToKill();
		
		if(m_pHeroFlag)
			m_pHeroFlag->Show();
		
		m_RoundStartTick = Server()->Tick();
	}
}