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); } } } }
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; }
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); } } } }
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; }
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); } } } }
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); } } }
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(); } }
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; }
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(); } }