void CServer::ProcessClientPacket(CNetChunk *pPacket) { int ClientID = pPacket->m_ClientID; NETADDR Addr; CUnpacker Unpacker; Unpacker.Reset(pPacket->m_pData, pPacket->m_DataSize); // unpack msgid and system flag int Msg = Unpacker.GetInt(); int Sys = Msg&1; Msg >>= 1; if(Unpacker.Error()) return; if(Sys) { // system message if(Msg == NETMSG_INFO) { if(m_aClients[ClientID].m_State == CClient::STATE_AUTH) { char aVersion[64]; str_copy(aVersion, Unpacker.GetString(CUnpacker::SANITIZE_CC), 64); bool CustClt = str_comp(aVersion, GameServer()->NetVersionCust()) == 0; dbg_msg("es", "%s client connected!", CustClt?"cust":"vanilla"); if(!CustClt && str_comp(aVersion, GameServer()->NetVersion()) != 0) { // wrong version char aReason[256]; str_format(aReason, sizeof(aReason), "Wrong version. Server is running '%s' and client '%s'", GameServer()->NetVersion(), aVersion); m_NetServer.Drop(ClientID, aReason); return; } const char *pPassword = Unpacker.GetString(CUnpacker::SANITIZE_CC); if(g_Config.m_Password[0] != 0 && str_comp(g_Config.m_Password, pPassword) != 0) { // wrong password m_NetServer.Drop(ClientID, "Wrong password"); return; } m_aClients[ClientID].m_State = CClient::STATE_CONNECTING; m_aClients[ClientID].m_CustClt = CustClt; SendMap(ClientID); } } else if(Msg == NETMSG_REQUEST_MAP_DATA) { int Chunk = Unpacker.GetInt(); int ChunkSize = 1024-128; int Offset = Chunk * ChunkSize; int Last = 0; // drop faulty map data requests if(Chunk < 0 || Offset > m_CurrentMapSize) return; if(Offset+ChunkSize >= m_CurrentMapSize) { ChunkSize = m_CurrentMapSize-Offset; if(ChunkSize < 0) ChunkSize = 0; Last = 1; } CMsgPacker Msg(NETMSG_MAP_DATA); Msg.AddInt(Last); Msg.AddInt(m_CurrentMapCrc); Msg.AddInt(Chunk); Msg.AddInt(ChunkSize); Msg.AddRaw(&m_pCurrentMapData[Offset], ChunkSize); SendMsgEx(&Msg, MSGFLAG_VITAL|MSGFLAG_FLUSH, ClientID, true); if(g_Config.m_Debug) { char aBuf[256]; str_format(aBuf, sizeof(aBuf), "sending chunk %d with size %d", Chunk, ChunkSize); Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "server", aBuf); } } else if(Msg == NETMSG_READY) { if(m_aClients[ClientID].m_State == CClient::STATE_CONNECTING) { Addr = m_NetServer.ClientAddr(ClientID); char aAddrStr[NETADDR_MAXSTRSIZE]; net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr)); char aBuf[256]; str_format(aBuf, sizeof(aBuf), "player is ready. ClientID=%x addr=%s", ClientID, aAddrStr); Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "server", aBuf); m_aClients[ClientID].m_State = CClient::STATE_READY; GameServer()->OnClientConnected(ClientID); SendConnectionReady(ClientID); } } else if(Msg == NETMSG_ENTERGAME) { if(m_aClients[ClientID].m_State == CClient::STATE_READY && GameServer()->IsClientReady(ClientID)) { Addr = m_NetServer.ClientAddr(ClientID); char aAddrStr[NETADDR_MAXSTRSIZE]; net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr)); char aBuf[256]; str_format(aBuf, sizeof(aBuf), "player has entered the game. ClientID=%x addr=%s", ClientID, aAddrStr); Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); m_aClients[ClientID].m_State = CClient::STATE_INGAME; GameServer()->OnClientEnter(ClientID); } } else if(Msg == NETMSG_INPUT) { CClient::CInput *pInput; int64 TagTime; m_aClients[ClientID].m_LastAckedSnapshot = Unpacker.GetInt(); int IntendedTick = Unpacker.GetInt(); int Size = Unpacker.GetInt(); // check for errors if(Unpacker.Error() || Size/4 > MAX_INPUT_SIZE) return; if(m_aClients[ClientID].m_LastAckedSnapshot > 0) m_aClients[ClientID].m_SnapRate = CClient::SNAPRATE_FULL; if(m_aClients[ClientID].m_Snapshots.Get(m_aClients[ClientID].m_LastAckedSnapshot, &TagTime, 0, 0) >= 0) m_aClients[ClientID].m_Latency = (int)(((time_get()-TagTime)*1000)/time_freq()); // add message to report the input timing // skip packets that are old if(IntendedTick > m_aClients[ClientID].m_LastInputTick) { int TimeLeft = ((TickStartTime(IntendedTick)-time_get())*1000) / time_freq(); CMsgPacker Msg(NETMSG_INPUTTIMING); Msg.AddInt(IntendedTick); Msg.AddInt(TimeLeft); SendMsgEx(&Msg, 0, ClientID, true); } m_aClients[ClientID].m_LastInputTick = IntendedTick; pInput = &m_aClients[ClientID].m_aInputs[m_aClients[ClientID].m_CurrentInput]; if(IntendedTick <= Tick()) IntendedTick = Tick()+1; pInput->m_GameTick = IntendedTick; for(int i = 0; i < Size/4; i++) pInput->m_aData[i] = Unpacker.GetInt(); mem_copy(m_aClients[ClientID].m_LatestInput.m_aData, pInput->m_aData, MAX_INPUT_SIZE*sizeof(int)); m_aClients[ClientID].m_CurrentInput++; m_aClients[ClientID].m_CurrentInput %= 200; // call the mod with the fresh input data if(m_aClients[ClientID].m_State == CClient::STATE_INGAME) GameServer()->OnClientDirectInput(ClientID, m_aClients[ClientID].m_LatestInput.m_aData); } else if(Msg == NETMSG_RCON_CMD) { const char *pCmd = Unpacker.GetString(); if(Unpacker.Error() == 0 && m_aClients[ClientID].m_Authed) { char aBuf[256]; str_format(aBuf, sizeof(aBuf), "ClientID=%d rcon='%s'", ClientID, pCmd); Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "server", aBuf); m_RconClientID = ClientID; Console()->ExecuteLine(pCmd); m_RconClientID = -1; } } else if(Msg == NETMSG_RCON_AUTH) { const char *pPw; Unpacker.GetString(); // login name, not used pPw = Unpacker.GetString(CUnpacker::SANITIZE_CC); if(Unpacker.Error() == 0) { if(g_Config.m_SvRconPassword[0] == 0) { SendRconLine(ClientID, "No rcon password set on server. Set sv_rcon_password to enable the remote console."); } else if(str_comp(pPw, g_Config.m_SvRconPassword) == 0) { CMsgPacker Msg(NETMSG_RCON_AUTH_STATUS); Msg.AddInt(1); SendMsgEx(&Msg, MSGFLAG_VITAL, ClientID, true); m_aClients[ClientID].m_Authed = 1; SendRconLine(ClientID, "Authentication successful. Remote console access granted."); char aBuf[256]; str_format(aBuf, sizeof(aBuf), "ClientID=%d authed", ClientID); Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); } else if(g_Config.m_SvRconMaxTries) { m_aClients[ClientID].m_AuthTries++; char aBuf[128]; str_format(aBuf, sizeof(aBuf), "Wrong password %d/%d.", m_aClients[ClientID].m_AuthTries, g_Config.m_SvRconMaxTries); SendRconLine(ClientID, aBuf); if(m_aClients[ClientID].m_AuthTries >= g_Config.m_SvRconMaxTries) { if(!g_Config.m_SvRconBantime) m_NetServer.Drop(ClientID, "Too many remote console authentication tries"); else { NETADDR Addr = m_NetServer.ClientAddr(ClientID); BanAdd(Addr, g_Config.m_SvRconBantime*60, "Too many remote console authentication tries"); } } } else { SendRconLine(ClientID, "Wrong password."); } } } else if(Msg == NETMSG_PING) { CMsgPacker Msg(NETMSG_PING_REPLY); SendMsgEx(&Msg, 0, ClientID, true); } else { if(g_Config.m_Debug) { char aHex[] = "0123456789ABCDEF"; char aBuf[512]; for(int b = 0; b < pPacket->m_DataSize && b < 32; b++) { aBuf[b*3] = aHex[((const unsigned char *)pPacket->m_pData)[b]>>4]; aBuf[b*3+1] = aHex[((const unsigned char *)pPacket->m_pData)[b]&0xf]; aBuf[b*3+2] = ' '; aBuf[b*3+3] = 0; } char aBufMsg[256]; str_format(aBufMsg, sizeof(aBufMsg), "strange message ClientID=%d msg=%d data_size=%d", ClientID, Msg, pPacket->m_DataSize); Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "server", aBufMsg); Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "server", aBuf); } } }
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)) { int EventID = GameServer()->m_pLua->m_pEventListener->CreateEventStack(); GameServer()->m_pLua->m_pEventListener->GetParameters(EventID)->FindFree()->Set(m_Owner); GameServer()->m_pLua->m_pEventListener->GetParameters(EventID)->FindFree()->Set(m_Weapon); GameServer()->m_pLua->m_pEventListener->GetParameters(EventID)->FindFree()->Set(CurPos.x); GameServer()->m_pLua->m_pEventListener->GetParameters(EventID)->FindFree()->Set(CurPos.y); GameServer()->m_pLua->m_pEventListener->GetParameters(EventID)->FindFree()->Set(m_StartTick); GameServer()->m_pLua->m_pEventListener->GetParameters(EventID)->FindFree()->Set(m_Direction.x); GameServer()->m_pLua->m_pEventListener->GetParameters(EventID)->FindFree()->Set(m_Direction.y); if (TargetChr) GameServer()->m_pLua->m_pEventListener->GetParameters(EventID)->FindFree()->Set(TargetChr->GetPlayer()->GetCID()); else GameServer()->m_pLua->m_pEventListener->GetParameters(EventID)->FindFree()->Set(-1); GameServer()->m_pLua->m_pEventListener->GetParameters(EventID)->FindFree()->Set(Collide); GameServer()->m_pLua->m_pEventListener->GetParameters(EventID)->FindFree()->Set(m_ID); GameServer()->m_pLua->m_pEventListener->OnEvent("OnProjectileDestroy"); if (GameServer()->m_pLua->m_pEventListener->GetReturns(EventID)->m_aVars[0].IsNumeric() && GameServer()->m_pLua->m_pEventListener->GetReturns(EventID)->m_aVars[0].GetInteger() == 1) return; if(m_LifeSpan >= 0 || m_Weapon == WEAPON_GRENADE) GameServer()->CreateSound(CurPos, m_SoundImpact); if(m_Explosive && GameServer()->m_pLua->m_pEventListener->GetReturns(EventID)->m_aVars[1].GetInteger() == 0) GameServer()->CreateExplosion(CurPos, m_Owner, m_Weapon, false); else if(TargetChr) TargetChr->TakeDamage(m_Direction * max(0.001f, m_Force), m_Damage, m_Owner, m_Weapon); GameServer()->m_World.DestroyEntity(this); } }
void CGameControllerOpenFNG::HandleSacr(int Killer, int Victim, int ShrineTeam) {//assertion: Killer >= 0, victim anyways CCharacter *pVictim = CHAR(Victim); if (!pVictim) //due to HandleFreeze, i suspect this COULD also possibly happen. { D("no pVictim in HandleSacr(%d, %d, %d)", Killer, Victim, ShrineTeam); return; } int FailTeam = pVictim->GetPlayer()->GetTeam(); bool Wrong = ShrineTeam != -1 && FailTeam == ShrineTeam; m_aTeamscore[1-FailTeam] += Wrong?CFG(WrongSacrTeamscore):(ShrineTeam == -1 ? CFG(SacrTeamscore) : CFG(RightSacrTeamscore)); if (!Wrong) { if (CFG(SacrSound) == 1) GameServer()->CreateSoundGlobal(SOUND_CTF_CAPTURE); else if (CFG(SacrSound) == 2) GameServer()->CreateSound(pVictim->m_Pos, SOUND_CTF_CAPTURE); } if (((Wrong && CFG(WrongSacrTeamscore)) || (!Wrong && (ShrineTeam == -1 ? CFG(SacrTeamscore) : CFG(RightSacrTeamscore)))) && CFG(SacrBroadcast)) { char aBuf[64]; str_format(aBuf, sizeof aBuf, "%s sacrificed%s (%+d)", GetTeamName(1-FailTeam), Wrong?" in wrong shrine":(ShrineTeam == -1 ? "" : ", pleasing their gods"), Wrong?CFG(WrongSacrTeamscore):(ShrineTeam == -1 ? CFG(SacrTeamscore):CFG(RightSacrTeamscore))); m_Broadcast.Update(-1, aBuf, CFG(BroadcastTime) * TS); } CPlayer *pPlKiller = TPLAYER(Killer); CPlayer *pPlVictim = TPLAYER(Victim); if (!pPlKiller || !pVictim) return; pPlKiller->m_Score += Wrong ? CFG(WrongSacrScore) : (ShrineTeam == -1 ? CFG(SacrScore) : CFG(RightSacrScore)); pPlVictim->m_Score += Wrong ? CFG(WrongSacrScoreVic) : (ShrineTeam == -1 ? CFG(SacrScoreVic) : CFG(RightSacrScoreVic)); SendFreezeKill(Killer, Victim, WEAPON_NINJA); if (Wrong && pPlKiller->GetCharacter() && CFG(PunishWrongSacr)) { pPlKiller->GetCharacter()->Freeze(CFG(PunishWrongSacr) * TS); GS->CreateSound(pPlKiller->GetCharacter()->m_Pos, SOUND_PLAYER_PAIN_LONG); GS->SendChatTarget(pPlKiller->GetCID(), "The gods are not pleased with this sacrifice!"); } if (!Wrong && pPlKiller->GetCharacter()) pPlKiller->GetCharacter()->SetEmote(EMOTE_HAPPY, TICK + TS * 2); if (pPlKiller->GetCharacter() && CFG(SacrLoltext) && ((!Wrong && CFG(SacrScore)) || (Wrong && CFG(WrongSacrScore)))) { char aBuf[64]; str_format(aBuf, sizeof aBuf, "%+d", Wrong?CFG(WrongSacrScore):(ShrineTeam == -1 ? CFG(SacrScore) : CFG(RightSacrScore))); GS->CreateLolText(pPlKiller->GetCharacter(), false, vec2(0.f, -50.f), vec2(0.f, 0.f), 50, aBuf); } if(!Wrong && pPlKiller->GetCharacter()) GameServer()->GetPlayerChar(Killer)->AddSpree(); }
int CGameControllerMOD::ChooseInfectedClass(CPlayer* pPlayer) { float random = frandom(); float TotalProbInfectedClass = m_TotalProbInfectedClass; //Get information about existing infected int nbInfected = 0; bool thereIsAWitch = false; bool thereIsAnUndead = 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()) nbInfected++; if(pPlayer->GetClass() == PLAYERCLASS_WITCH) thereIsAWitch = true; if(pPlayer->GetClass() == PLAYERCLASS_UNDEAD) thereIsAnUndead = true; } //Check if hunters are enabled bool hunterEnabled = true; if(Server()->GetClassAvailability(PLAYERCLASS_HUNTER) == 0) { TotalProbInfectedClass -= m_ClassProbability[PLAYERCLASS_HUNTER]; hunterEnabled = false; } //Check if ghost are enabled bool ghostEnabled = true; if(Server()->GetClassAvailability(PLAYERCLASS_GHOST) == 0) { TotalProbInfectedClass -= m_ClassProbability[PLAYERCLASS_GHOST]; ghostEnabled = false; } //Check if spider are enabled bool spiderEnabled = true; if(Server()->GetClassAvailability(PLAYERCLASS_SPIDER) == 0) { TotalProbInfectedClass -= m_ClassProbability[PLAYERCLASS_SPIDER]; spiderEnabled = false; } //Check if boomers are enabled bool boomerEnabled = true; if(Server()->GetClassAvailability(PLAYERCLASS_BOOMER) == 0) { TotalProbInfectedClass -= m_ClassProbability[PLAYERCLASS_BOOMER]; boomerEnabled = false; } //Check if undeads are enabled bool undeadEnabled = true; if(nbInfected < 2 || thereIsAnUndead || (Server()->GetClassAvailability(PLAYERCLASS_UNDEAD) == 0) || !pPlayer->m_WasHumanThisRound) { TotalProbInfectedClass -= m_ClassProbability[PLAYERCLASS_UNDEAD]; undeadEnabled = false; } //Check if witches are enabled bool witchEnabled = true; if(nbInfected < 2 || thereIsAWitch || (Server()->GetClassAvailability(PLAYERCLASS_WITCH) == 0) || !pPlayer->m_WasHumanThisRound) { TotalProbInfectedClass -= m_ClassProbability[PLAYERCLASS_WITCH]; witchEnabled = false; } random *= TotalProbInfectedClass; //Find the random class if(undeadEnabled) { random -= m_ClassProbability[PLAYERCLASS_UNDEAD]; if(random < 0.0f) { GameServer()->SendBroadcast_Language(-1, "The undead is coming!"); GameServer()->CreateSoundGlobal(SOUND_CTF_CAPTURE); return PLAYERCLASS_UNDEAD; } } if(witchEnabled) { random -= m_ClassProbability[PLAYERCLASS_WITCH]; if(random < 0.0f) { GameServer()->SendBroadcast_Language(-1, "The witch is coming!"); GameServer()->CreateSoundGlobal(SOUND_CTF_CAPTURE); return PLAYERCLASS_WITCH; } } if(boomerEnabled) { random -= m_ClassProbability[PLAYERCLASS_BOOMER]; if(random < 0.0f) { return PLAYERCLASS_BOOMER; } } if(ghostEnabled) { random -= m_ClassProbability[PLAYERCLASS_GHOST]; if(random < 0.0f) { return PLAYERCLASS_GHOST; } } if(spiderEnabled) { random -= m_ClassProbability[PLAYERCLASS_SPIDER]; if(random < 0.0f) { return PLAYERCLASS_SPIDER; } } if(hunterEnabled) { random -= m_ClassProbability[PLAYERCLASS_HUNTER]; if(random < 0.0f) { return PLAYERCLASS_HUNTER; } } return PLAYERCLASS_SMOKER; }
void CMercenaryBomb::Reset() { GameServer()->m_World.DestroyEntity(this); }
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 CGameControllerMOD::PreSpawn(CPlayer* pPlayer, vec2 *pOutPos) { // spectators can't spawn if(pPlayer->GetTeam() == TEAM_SPECTATORS) return false; if(m_InfectedStarted) { pPlayer->StartInfection(); } else { pPlayer->m_WasHumanThisRound = true; } if(pPlayer->IsInfected() && m_ExplosionStarted) return false; if(m_InfectedStarted && pPlayer->IsInfected() && rand()%3 > 0) { for(int i = 0; i < MAX_CLIENTS; i ++) { CPlayer *pWitch = GameServer()->m_apPlayers[i]; if(!pWitch) continue; if(pWitch->GetCID() == pPlayer->GetCID()) continue; if(pWitch->GetClass() != PLAYERCLASS_WITCH) continue; if(!pWitch->GetCharacter()) continue; vec2 spawnTile = vec2(16.0f, 16.0f) + vec2( static_cast<float>(static_cast<int>(round(pWitch->GetCharacter()->m_Pos.x))/32)*32.0, static_cast<float>(static_cast<int>(round(pWitch->GetCharacter()->m_Pos.y))/32)*32.0); for(int j=-1; j<=1; j++) { if(IsSpawnable(vec2(spawnTile.x + j*32.0, spawnTile.y-64.0))) { *pOutPos = spawnTile + vec2(j*32.0, -64.0); return true; } if(IsSpawnable(vec2(spawnTile.x + j*32.0, spawnTile.y+64.0))) { *pOutPos = spawnTile + vec2(j*32.0, 64.0); return true; } if(IsSpawnable(vec2(spawnTile.x-64.0, spawnTile.y + j*32.0))) { *pOutPos = spawnTile + vec2(-64.0, j*32.0); return true; } if(IsSpawnable(vec2(spawnTile.x+64.0, spawnTile.y + j*32.0))) { *pOutPos = spawnTile + vec2(64.0, j*32.0); return true; } } } } CSpawnEval Eval; int Team = (pPlayer->IsInfected() ? TEAM_RED : TEAM_BLUE); Eval.m_FriendlyTeam = Team; // first try own team spawn, then normal spawn and then enemy EvaluateSpawnType(&Eval, Team); *pOutPos = Eval.m_Pos; return Eval.m_Got; }
void CPlayer::Tick() { if(!IsDummy() && !Server()->ClientIngame(m_ClientID)) return; Server()->SetClientScore(m_ClientID, m_Score); // do latency stuff { IServer::CClientInfo Info; if(Server()->GetClientInfo(m_ClientID, &Info)) { m_Latency.m_Accum += Info.m_Latency; m_Latency.m_AccumMax = max(m_Latency.m_AccumMax, Info.m_Latency); m_Latency.m_AccumMin = min(m_Latency.m_AccumMin, Info.m_Latency); } // each second if(Server()->Tick()%Server()->TickSpeed() == 0) { m_Latency.m_Avg = m_Latency.m_Accum/Server()->TickSpeed(); m_Latency.m_Max = m_Latency.m_AccumMax; m_Latency.m_Min = m_Latency.m_AccumMin; m_Latency.m_Accum = 0; m_Latency.m_AccumMin = 1000; m_Latency.m_AccumMax = 0; } } if(m_pCharacter && !m_pCharacter->IsAlive()) { delete m_pCharacter; m_pCharacter = 0; } if(!GameServer()->m_pController->IsGamePaused()) { if(!m_pCharacter && m_Team == TEAM_SPECTATORS && m_SpectatorID == SPEC_FREEVIEW) m_ViewPos -= vec2(clamp(m_ViewPos.x-m_LatestActivity.m_TargetX, -500.0f, 500.0f), clamp(m_ViewPos.y-m_LatestActivity.m_TargetY, -400.0f, 400.0f)); if(!m_pCharacter && m_DieTick+Server()->TickSpeed()*3 <= Server()->Tick() && !m_DeadSpecMode) Respawn(); if(m_pCharacter) { if(m_pCharacter->IsAlive()) m_ViewPos = m_pCharacter->m_Pos; } else if(m_Spawning && m_RespawnTick <= Server()->Tick()) TryRespawn(); if(!m_DeadSpecMode && m_LastActionTick != Server()->Tick()) ++m_InactivityTickCounter; } else { ++m_RespawnTick; ++m_DieTick; ++m_ScoreStartTick; ++m_LastActionTick; ++m_TeamChangeTick; } }
void CPickup::Tick() { // wait for respawn if(m_SpawnTick > 0) { if(Server()->Tick() > m_SpawnTick) { // respawn m_SpawnTick = -1; if(m_Type == POWERUP_WEAPON) GameServer()->CreateSound(m_Pos, SOUND_WEAPON_SPAWN); } else return; } // Check if a player intersected us CCharacter *pChr = GameServer()->m_World.ClosestCharacter(m_Pos, 20.0f, 0); if(pChr && pChr->IsAlive()) { // player picked us up, is someone was hooking us, let them go int RespawnTime = -1; switch (m_Type) { case POWERUP_HEALTH: if(pChr->IncreaseHealth(1)) { GameServer()->CreateSound(m_Pos, SOUND_PICKUP_HEALTH); RespawnTime = g_pData->m_aPickups[m_Type].m_Respawntime; } break; case POWERUP_ARMOR: if(pChr->IncreaseArmor(1)) { GameServer()->CreateSound(m_Pos, SOUND_PICKUP_ARMOR); RespawnTime = g_pData->m_aPickups[m_Type].m_Respawntime; } break; case POWERUP_WEAPON: if(m_Subtype >= 0 && m_Subtype < NUM_WEAPONS) { if(pChr->GiveWeapon(m_Subtype, 10)) { RespawnTime = g_pData->m_aPickups[m_Type].m_Respawntime; if(m_Subtype == WEAPON_GRENADE) GameServer()->CreateSound(m_Pos, SOUND_PICKUP_GRENADE); else if(m_Subtype == WEAPON_SHOTGUN) GameServer()->CreateSound(m_Pos, SOUND_PICKUP_SHOTGUN); else if(m_Subtype == WEAPON_RIFLE) GameServer()->CreateSound(m_Pos, SOUND_PICKUP_SHOTGUN); if(pChr->GetPlayer()) GameServer()->SendWeaponPickup(pChr->GetPlayer()->GetCID(), m_Subtype); } } break; case POWERUP_NINJA: { // activate ninja on target player pChr->GiveNinja(); RespawnTime = g_pData->m_aPickups[m_Type].m_Respawntime; // loop through all players, setting their emotes CEntity *apEnts[64]; int Num = GameServer()->m_World.FindEntities(vec2(0, 0), 1000000, apEnts, 64, NETOBJTYPE_CHARACTER); for (int i = 0; i < Num; ++i) { CCharacter *pC = static_cast<CCharacter *>(apEnts[i]); if (pC != pChr) pC->SetEmote(EMOTE_SURPRISE, Server()->Tick() + Server()->TickSpeed()); } pChr->SetEmote(EMOTE_ANGRY, Server()->Tick() + 1200 * Server()->TickSpeed() / 1000); break; } default: break; }; if(RespawnTime >= 0) { dbg_msg("game", "pickup player='%d:%s' item=%d/%d", pChr->GetPlayer()->GetCID(), Server()->ClientName(pChr->GetPlayer()->GetCID()), m_Type, m_Subtype); m_SpawnTick = Server()->Tick() + Server()->TickSpeed() * RespawnTime; } } }
void CDragger::Move() { if (m_Target && (!m_Target->IsAlive() || (m_Target->IsAlive() && (m_Target->m_Super || m_Target->IsPaused() || (m_Layer == LAYER_SWITCH && m_Number && !GameServer()->Collision()->m_pSwitchers[m_Number].m_Status[m_Target->Team()]))))) m_Target = 0; mem_zero(m_SoloEnts, sizeof(m_SoloEnts)); CCharacter *TempEnts[MAX_CLIENTS]; int Num = GameServer()->m_World.FindEntities(m_Pos, g_Config.m_SvDraggerRange, (CEntity**) m_SoloEnts, MAX_CLIENTS, CGameWorld::ENTTYPE_CHARACTER); mem_copy(TempEnts, m_SoloEnts, sizeof(TempEnts)); int Id = -1; int MinLen = 0; CCharacter *Temp; for (int i = 0; i < Num; i++) { Temp = m_SoloEnts[i]; if (Temp->Team() != m_CaughtTeam) { m_SoloEnts[i] = 0; continue; } if (m_Layer == LAYER_SWITCH && m_Number && !GameServer()->Collision()->m_pSwitchers[m_Number].m_Status[Temp->Team()]) { m_SoloEnts[i] = 0; continue; } int Res = m_NW ? GameServer()->Collision()->IntersectNoLaserNW(m_Pos, Temp->m_Pos, 0, 0) : GameServer()->Collision()->IntersectNoLaser(m_Pos, Temp->m_Pos, 0, 0); if (Res == 0) { int Len = length(Temp->m_Pos - m_Pos); if (MinLen == 0 || MinLen > Len) { MinLen = Len; Id = i; } if (!Temp->Teams()->m_Core.GetSolo(Temp->GetPlayer()->GetCID())) m_SoloEnts[i] = 0; } else { m_SoloEnts[i] = 0; } } if (!m_Target) m_Target = Id != -1 ? TempEnts[Id] : 0; if (m_Target) { for (int i = 0; i < MAX_CLIENTS; i++) { if (m_SoloEnts[i] == m_Target) m_SoloEnts[i] = 0; } } }
void CDragger::Drag() { if (m_Target) { CCharacter *Target = m_Target; for (int i = -1; i < MAX_CLIENTS; i++) { if (i >= 0) Target = m_SoloEnts[i]; if (!Target) continue; int Res = 0; if (!m_NW) Res = GameServer()->Collision()->IntersectNoLaser(m_Pos, Target->m_Pos, 0, 0); else Res = GameServer()->Collision()->IntersectNoLaserNW(m_Pos, Target->m_Pos, 0, 0); if (Res || length(m_Pos - Target->m_Pos) > g_Config.m_SvDraggerRange) { Target = 0; if (i == -1) m_Target = 0; else m_SoloEnts[i] = 0; } else if (length(m_Pos - Target->m_Pos) > 28) { vec2 Temp = Target->Core()->m_Vel + (normalize(m_Pos - Target->m_Pos) * m_Strength); if (Temp.x > 0 && ((Target->m_TileIndex == TILE_STOP && Target->m_TileFlags == ROTATION_270) || (Target->m_TileIndexL == TILE_STOP && Target->m_TileFlagsL == ROTATION_270) || (Target->m_TileIndexL == TILE_STOPS && (Target->m_TileFlagsL == ROTATION_90 || Target->m_TileFlagsL == ROTATION_270)) || (Target->m_TileIndexL == TILE_STOPA) || (Target->m_TileFIndex == TILE_STOP && Target->m_TileFFlags == ROTATION_270) || (Target->m_TileFIndexL == TILE_STOP && Target->m_TileFFlagsL == ROTATION_270) || (Target->m_TileFIndexL == TILE_STOPS && (Target->m_TileFFlagsL == ROTATION_90 || Target->m_TileFFlagsL == ROTATION_270)) || (Target->m_TileFIndexL == TILE_STOPA) || (Target->m_TileSIndex == TILE_STOP && Target->m_TileSFlags == ROTATION_270) || (Target->m_TileSIndexL == TILE_STOP && Target->m_TileSFlagsL == ROTATION_270) || (Target->m_TileSIndexL == TILE_STOPS && (Target->m_TileSFlagsL == ROTATION_90 || Target->m_TileSFlagsL == ROTATION_270)) || (Target->m_TileSIndexL == TILE_STOPA))) Temp.x = 0; if (Temp.x < 0 && ((Target->m_TileIndex == TILE_STOP && Target->m_TileFlags == ROTATION_90) || (Target->m_TileIndexR == TILE_STOP && Target->m_TileFlagsR == ROTATION_90) || (Target->m_TileIndexR == TILE_STOPS && (Target->m_TileFlagsR == ROTATION_90 || Target->m_TileFlagsR == ROTATION_270)) || (Target->m_TileIndexR == TILE_STOPA) || (Target->m_TileFIndex == TILE_STOP && Target->m_TileFFlags == ROTATION_90) || (Target->m_TileFIndexR == TILE_STOP && Target->m_TileFFlagsR == ROTATION_90) || (Target->m_TileFIndexR == TILE_STOPS && (Target->m_TileFFlagsR == ROTATION_90 || Target->m_TileFFlagsR == ROTATION_270)) || (Target->m_TileFIndexR == TILE_STOPA) || (Target->m_TileSIndex == TILE_STOP && Target->m_TileSFlags == ROTATION_90) || (Target->m_TileSIndexR == TILE_STOP && Target->m_TileSFlagsR == ROTATION_90) || (Target->m_TileSIndexR == TILE_STOPS && (Target->m_TileSFlagsR == ROTATION_90 || Target->m_TileSFlagsR == ROTATION_270)) || (Target->m_TileSIndexR == TILE_STOPA))) Temp.x = 0; if (Temp.y < 0 && ((Target->m_TileIndex == TILE_STOP && Target->m_TileFlags == ROTATION_180) || (Target->m_TileIndexB == TILE_STOP && Target->m_TileFlagsB == ROTATION_180) || (Target->m_TileIndexB == TILE_STOPS && (Target->m_TileFlagsB == ROTATION_0 || Target->m_TileFlagsB == ROTATION_180)) || (Target->m_TileIndexB == TILE_STOPA) || (Target->m_TileFIndex == TILE_STOP && Target->m_TileFFlags == ROTATION_180) || (Target->m_TileFIndexB == TILE_STOP && Target->m_TileFFlagsB == ROTATION_180) || (Target->m_TileFIndexB == TILE_STOPS && (Target->m_TileFFlagsB == ROTATION_0 || Target->m_TileFFlagsB == ROTATION_180)) || (Target->m_TileFIndexB == TILE_STOPA) || (Target->m_TileSIndex == TILE_STOP && Target->m_TileSFlags == ROTATION_180) || (Target->m_TileSIndexB == TILE_STOP && Target->m_TileSFlagsB == ROTATION_180) || (Target->m_TileSIndexB == TILE_STOPS && (Target->m_TileSFlagsB == ROTATION_0 || Target->m_TileSFlagsB == ROTATION_180)) || (Target->m_TileSIndexB == TILE_STOPA))) Temp.y = 0; if (Temp.y > 0 && ((Target->m_TileIndex == TILE_STOP && Target->m_TileFlags == ROTATION_0) || (Target->m_TileIndexT == TILE_STOP && Target->m_TileFlagsT == ROTATION_0) || (Target->m_TileIndexT == TILE_STOPS && (Target->m_TileFlagsT == ROTATION_0 || Target->m_TileFlagsT == ROTATION_180)) || (Target->m_TileIndexT == TILE_STOPA) || (Target->m_TileFIndex == TILE_STOP && Target->m_TileFFlags == ROTATION_0) || (Target->m_TileFIndexT == TILE_STOP && Target->m_TileFFlagsT == ROTATION_0) || (Target->m_TileFIndexT == TILE_STOPS && (Target->m_TileFFlagsT == ROTATION_0 || Target->m_TileFFlagsT == ROTATION_180)) || (Target->m_TileFIndexT == TILE_STOPA) || (Target->m_TileSIndex == TILE_STOP && Target->m_TileSFlags == ROTATION_0) || (Target->m_TileSIndexT == TILE_STOP && Target->m_TileSFlagsT == ROTATION_0) || (Target->m_TileSIndexT == TILE_STOPS && (Target->m_TileSFlagsT == ROTATION_0 || Target->m_TileSFlagsT == ROTATION_180)) || (Target->m_TileSIndexT == TILE_STOPA))) Temp.y = 0; Target->Core()->m_Vel = Temp; } } } }
void CDragger::Snap(int SnappingClient) { if (((CGameControllerDDRace*) GameServer()->m_pController)->m_Teams.GetTeamState( m_CaughtTeam) == CGameTeams::TEAMSTATE_EMPTY) return; CCharacter *Target = m_Target; for (int i = 0; i < MAX_CLIENTS; i++) { if (m_SoloIDs[i] == -1) break; Server()->SnapFreeID(m_SoloIDs[i]); m_SoloIDs[i] = -1; } int pos = 0; for (int i = -1; i < MAX_CLIENTS; i++) { if (i >= 0) { Target = m_SoloEnts[i]; if (!Target) continue; } if (Target) { if (NetworkClipped(SnappingClient, m_Pos) && NetworkClipped(SnappingClient, Target->m_Pos)) continue; } else if (NetworkClipped(SnappingClient, m_Pos)) continue; CCharacter * Char = GameServer()->GetPlayerChar(SnappingClient); if(SnappingClient > -1 && (GameServer()->m_apPlayers[SnappingClient]->GetTeam() == -1 || GameServer()->m_apPlayers[SnappingClient]->IsPaused()) && GameServer()->m_apPlayers[SnappingClient]->m_SpectatorID != SPEC_FREEVIEW) Char = GameServer()->GetPlayerChar(GameServer()->m_apPlayers[SnappingClient]->m_SpectatorID); int Tick = (Server()->Tick() % Server()->TickSpeed()) % 11; if (Char && Char->IsAlive() && (m_Layer == LAYER_SWITCH && m_Number && !GameServer()->Collision()->m_pSwitchers[m_Number].m_Status[Char->Team()] && (!Tick))) continue; if (Char && Char->IsAlive()) { if (Char->Team() != m_CaughtTeam) continue; } else { // send to spectators only active draggers and some inactive from team 0 if (!((Target && Target->IsAlive()) || m_CaughtTeam == 0)) continue; } if (Char && Char->IsAlive() && Target && Target->IsAlive() && Target->GetPlayer()->GetCID() != Char->GetPlayer()->GetCID() && !Char->GetPlayer()->m_ShowOthers && (Char->Teams()->m_Core.GetSolo(SnappingClient) || Char->Teams()->m_Core.GetSolo(Target->GetPlayer()->GetCID()))) { continue; } CNetObj_Laser *obj; if (i == -1) { obj = static_cast<CNetObj_Laser *>(Server()->SnapNewItem( NETOBJTYPE_LASER, m_ID, sizeof(CNetObj_Laser))); } else { m_SoloIDs[pos] = Server()->SnapNewID(); obj = static_cast<CNetObj_Laser *>(Server()->SnapNewItem( // TODO: Have to free IDs again? NETOBJTYPE_LASER, m_SoloIDs[pos], sizeof(CNetObj_Laser))); pos++; } if (!obj) continue; obj->m_X = (int)m_Pos.x; obj->m_Y = (int)m_Pos.y; if (Target) { obj->m_FromX = (int)Target->m_Pos.x; obj->m_FromY = (int)Target->m_Pos.y; } else { obj->m_FromX = (int)m_Pos.x; obj->m_FromY = (int)m_Pos.y; } int StartTick = m_EvalTick; if (StartTick < Server()->Tick() - 4) StartTick = Server()->Tick() - 4; else if (StartTick > Server()->Tick()) StartTick = Server()->Tick(); obj->m_StartTick = StartTick; } }
void CDigitanksEntity::Think() { BaseClass::Think(); if (m_flNextDirtyOrigin > 0 && GameServer()->GetGameTime() > m_flNextDirtyOrigin) { DirtyVisibility(); m_flNextDirtyOrigin = 0; } if (m_flNextDirtyArea > 0 && GameServer()->GetGameTime() > m_flNextDirtyArea) { CDigitanksEntity* pOther = this; while (true) { pOther = CBaseEntity::FindClosest<CDigitanksEntity>(GetGlobalOrigin(), pOther); if (!pOther) break; if (pOther == this) continue; if (pOther->Distance(GetGlobalOrigin()) > VisibleRange() + DigitanksGame()->FogPenetrationDistance()) break; pOther->DirtyVisibility(); } m_flNextDirtyArea = 0; } if (GameNetwork()->IsHost() && !IsAlive() && GameServer()->GetGameTime() > m_flTimeKilled + 1.0f) { GameServer()->Delete(this); if (DigitanksGame()->GetTerrain()->IsPointOverHole(GetGlobalOrigin())) { CWreckage* pWreckage = CreateWreckage(); if (pWreckage) { pWreckage->FellIntoHole(); if (DigitanksGame()->GetGameType() == GAMETYPE_ARTILLERY) pWreckage->SetScale(2); } } else if (DigitanksGame()->GetGameType() == GAMETYPE_ARTILLERY) { switch (RandomInt(0, 8)) { case 0: case 6: case 7: case 8: default: { for (size_t i = 0; i < 8; i++) { CDebris* pDebris = GameServer()->Create<CDebris>("CDebris"); pDebris->SetGlobalOrigin(GetGlobalOrigin()); } CWreckage* pWreckage = CreateWreckage(); pWreckage->SetScale(2); DigitanksGame()->GetOverheadCamera()->Shake(GetGlobalOrigin(), 3); break; } case 1: { CProjectile* pProjectile = GameServer()->Create<CLargeShell>("CLargeShell"); pProjectile->SetOwner(NULL); pProjectile->SetGlobalOrigin(GetGlobalOrigin()); pProjectile->Explode(); break; } case 2: { CProjectile* pProjectile = GameServer()->Create<CAOEShell>("CAOEShell"); pProjectile->SetOwner(NULL); pProjectile->SetGlobalOrigin(GetGlobalOrigin()); pProjectile->Explode(); break; } case 3: { CProjectile* pProjectile = GameServer()->Create<CClusterBomb>("CClusterBomb"); pProjectile->SetOwner(NULL); pProjectile->SetGlobalOrigin(GetGlobalOrigin()); pProjectile->Explode(); break; } case 4: { CProjectile* pProjectile = GameServer()->Create<CEarthshaker>("CEarthshaker"); pProjectile->SetOwner(NULL); pProjectile->SetGlobalOrigin(GetGlobalOrigin()); pProjectile->Explode(); break; } case 5: { CProjectile* pProjectile = GameServer()->Create<CTractorBomb>("CTractorBomb"); pProjectile->SetOwner(NULL); pProjectile->SetGlobalOrigin(GetGlobalOrigin()); pProjectile->Explode(); break; } } } else { // Strategy mode CreateWreckage(); } } m_hCageParticles.SetActive(IsImprisoned() && GetVisibility() > 0.1f); }
void CDigitanksEntity::OnRender(CGameRenderingContext* pContext) const { BaseClass::OnRender(pContext); if (GameServer()->GetRenderer()->IsRenderingTransparent() && IsImprisoned()) { CGameRenderingContext c(GameServer()->GetRenderer(), true); c.SetBackCulling(false); c.SetBlend(BLEND_ADDITIVE); c.Scale(GetBoundingRadius(), GetBoundingRadius(), GetBoundingRadius()); c.Rotate((float)GameServer()->GetGameTime() * 90, Vector(0, 0, 1)); float flVisibility = GetVisibility() * 0.6f; c.UseProgram("scroll"); c.SetUniform("iTexture", 0); c.SetUniform("flAlpha", flVisibility); c.SetUniform("flTime", (float)-GameServer()->GetGameTime()); c.SetUniform("flSpeed", 1.0f); c.RenderModel(m_iCageModel, this); } if (GameServer()->GetRenderer()->IsRenderingTransparent() && IsImprisoned()) { CGameRenderingContext c(GameServer()->GetRenderer(), true); c.SetBackCulling(false); c.SetBlend(BLEND_ADDITIVE); c.Scale(GetBoundingRadius()+1, GetBoundingRadius()+1, GetBoundingRadius()+1); c.Rotate(-(float)GameServer()->GetGameTime() * 90, Vector(0, 0, 1)); float flVisibility = GetVisibility() * 0.6f; c.UseProgram("scroll"); c.SetUniform("iTexture", 0); c.SetUniform("flAlpha", flVisibility); c.SetUniform("flTime", (float)-GameServer()->GetGameTime()); c.SetUniform("flSpeed", 1.0f); c.RenderModel(m_iCageModel); } if (!GameServer()->GetRenderer()->IsRenderingTransparent()) return; if (!DigitanksGame()->GetTerrain()->GetBit(CTerrain::WorldToArraySpace(GetGlobalOrigin().x), CTerrain::WorldToArraySpace(GetGlobalOrigin().y), TB_TREE)) return; if (GetVisibility() < 0.6f) return; CGameRenderingContext c(GameServer()->GetRenderer(), true); c.SetBlend(BLEND_NONE); c.SetAlpha(1); c.BindTexture(0); TStubbed("Tank outlines in trees"); /* // Draw outlines of objects in trees. glPushAttrib( GL_ALL_ATTRIB_BITS ); glDisable( GL_TEXTURE_2D ); glEnable( GL_POLYGON_OFFSET_FILL ); glPolygonOffset( -3.5f, -3.5f ); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glDepthMask(true); glEnable(GL_DEPTH_TEST); pContext->RenderModel(GetModel()); glDisable( GL_POLYGON_OFFSET_FILL ); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDepthMask(false); glEnable(GL_DEPTH_TEST); glLineWidth( 2.0f ); glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); glColor3ubv( Color(0, 0, 0) ); pContext->RenderModel(GetModel()); glPopAttrib(); */ }
void CCharacter::Destroy() { GameServer()->m_World.m_Core.m_apCharacters[m_pPlayer->GetCID()] = 0; m_Alive = false; }
void CLaser::Reset() { GameServer()->m_World.DestroyEntity(this); }
CGameControllerMOD::CGameControllerMOD(class CGameContext *pGameServer) : IGameController(pGameServer) { m_pGameType = "InfClass"; srand (time(0)); m_TotalProbInfectedClass = 0.0; m_ClassProbability[PLAYERCLASS_SMOKER] = 1.0f; m_TotalProbInfectedClass += m_ClassProbability[PLAYERCLASS_SMOKER]; m_ClassProbability[PLAYERCLASS_HUNTER] = 0.6666f * m_ClassProbability[PLAYERCLASS_SMOKER]; m_TotalProbInfectedClass += m_ClassProbability[PLAYERCLASS_HUNTER]; m_ClassProbability[PLAYERCLASS_BOOMER] = 0.6666f * m_ClassProbability[PLAYERCLASS_SMOKER]; m_TotalProbInfectedClass += m_ClassProbability[PLAYERCLASS_BOOMER]; m_ClassProbability[PLAYERCLASS_GHOST] = 0.25f * m_ClassProbability[PLAYERCLASS_SMOKER]; m_TotalProbInfectedClass += m_ClassProbability[PLAYERCLASS_GHOST]; m_ClassProbability[PLAYERCLASS_SPIDER] = 0.25f * m_ClassProbability[PLAYERCLASS_SMOKER]; m_TotalProbInfectedClass += m_ClassProbability[PLAYERCLASS_SPIDER]; m_ClassProbability[PLAYERCLASS_WITCH] = 0.25f * m_ClassProbability[PLAYERCLASS_SMOKER]; m_TotalProbInfectedClass += m_ClassProbability[PLAYERCLASS_WITCH]; m_ClassProbability[PLAYERCLASS_UNDEAD] = 0.20f * m_ClassProbability[PLAYERCLASS_SMOKER]; m_TotalProbInfectedClass += m_ClassProbability[PLAYERCLASS_UNDEAD]; m_TotalProbHumanClass = 0.0; m_ClassProbability[PLAYERCLASS_ENGINEER] = 1.0f; m_TotalProbHumanClass += m_ClassProbability[PLAYERCLASS_ENGINEER]; m_ClassProbability[PLAYERCLASS_SOLDIER] = 1.0f; m_TotalProbHumanClass += m_ClassProbability[PLAYERCLASS_SOLDIER]; m_ClassProbability[PLAYERCLASS_MERCENARY] = 1.0f; m_TotalProbHumanClass += m_ClassProbability[PLAYERCLASS_MERCENARY]; m_ClassProbability[PLAYERCLASS_SNIPER] = 1.0f; m_TotalProbHumanClass += m_ClassProbability[PLAYERCLASS_SNIPER]; m_ClassProbability[PLAYERCLASS_SCIENTIST] = 0.5f; m_TotalProbHumanClass += m_ClassProbability[PLAYERCLASS_SCIENTIST]; m_ClassProbability[PLAYERCLASS_NINJA] = 0.5f; m_TotalProbHumanClass += m_ClassProbability[PLAYERCLASS_NINJA]; m_ClassProbability[PLAYERCLASS_MEDIC] = 0.5f; m_TotalProbHumanClass += m_ClassProbability[PLAYERCLASS_MEDIC]; m_GrowingMap = 0; m_ExplosionStarted = false; m_MapWidth = GameServer()->Collision()->GetWidth(); m_MapHeight = GameServer()->Collision()->GetHeight(); m_GrowingMap = new int[m_MapWidth*m_MapHeight]; m_HumanCounter = 0; m_InfectedCounter = 0; m_InfectedStarted = false; for(int j=0; j<m_MapHeight; j++) { for(int i=0; i<m_MapWidth; i++) { vec2 TilePos = vec2(16.0f, 16.0f) + vec2(i*32.0f, j*32.0f); if(GameServer()->Collision()->CheckPoint(TilePos)) { m_GrowingMap[j*m_MapWidth+i] = 4; } else { m_GrowingMap[j*m_MapWidth+i] = 1; } } } }
void CLaser::Tick() { if(Server()->Tick() > m_EvalTick+(Server()->TickSpeed()*GameServer()->Tuning()->m_LaserBounceDelay)/1000.0f) DoBounce(); }
void CGameControllerMOD::Snap(int SnappingClient) { CNetObj_GameInfo *pGameInfoObj = (CNetObj_GameInfo *)Server()->SnapNewItem(NETOBJTYPE_GAMEINFO, 0, sizeof(CNetObj_GameInfo)); if(!pGameInfoObj) return; pGameInfoObj->m_GameFlags = m_GameFlags; pGameInfoObj->m_GameStateFlags = 0; if(m_GameOverTick != -1) pGameInfoObj->m_GameStateFlags |= GAMESTATEFLAG_GAMEOVER; if(m_SuddenDeath) pGameInfoObj->m_GameStateFlags |= GAMESTATEFLAG_SUDDENDEATH; if(GameServer()->m_World.m_Paused) pGameInfoObj->m_GameStateFlags |= GAMESTATEFLAG_PAUSED; pGameInfoObj->m_RoundStartTick = m_RoundStartTick; pGameInfoObj->m_WarmupTimer = m_Warmup; pGameInfoObj->m_ScoreLimit = g_Config.m_SvScorelimit; pGameInfoObj->m_TimeLimit = g_Config.m_SvTimelimit; pGameInfoObj->m_RoundNum = (str_length(g_Config.m_SvMaprotation) && g_Config.m_SvRoundsPerMap) ? g_Config.m_SvRoundsPerMap : 0; pGameInfoObj->m_RoundCurrent = m_RoundCount+1; //Generate class mask int ClassMask = 0; { int Defender = 0; int Medic = 0; int Support = 0; for(int i = 0; i < MAX_CLIENTS; i ++) { CPlayer *pPlayer = GameServer()->m_apPlayers[i]; if(!pPlayer) continue; if(pPlayer->GetTeam() == TEAM_SPECTATORS) continue; switch(pPlayer->GetClass()) { case PLAYERCLASS_NINJA: case PLAYERCLASS_MERCENARY: case PLAYERCLASS_SNIPER: Support++; break; case PLAYERCLASS_ENGINEER: case PLAYERCLASS_SOLDIER: case PLAYERCLASS_SCIENTIST: Defender++; break; case PLAYERCLASS_MEDIC: Medic++; break; } } if(Defender < g_Config.m_InfDefenderLimit) ClassMask |= CMapConverter::MASK_DEFENDER; if(Medic < g_Config.m_InfMedicLimit) ClassMask |= CMapConverter::MASK_MEDIC; if(Support < g_Config.m_InfSupportLimit) ClassMask |= CMapConverter::MASK_SUPPORT; } if(GameServer()->m_apPlayers[SnappingClient] && GameServer()->m_apPlayers[SnappingClient]->m_InClassChooserMenu) { int Item = GameServer()->m_apPlayers[SnappingClient]->m_MenuClassChooserItem; int Timer = ((CMapConverter::TIMESHIFT_MENUCLASS + (Item+1) + ClassMask*CMapConverter::TIMESHIFT_MENUCLASS_MASK)*60 + 30)*Server()->TickSpeed(); pGameInfoObj->m_RoundStartTick = Server()->Tick() - Timer; pGameInfoObj->m_TimeLimit = 0; } CNetObj_GameData *pGameDataObj = (CNetObj_GameData *)Server()->SnapNewItem(NETOBJTYPE_GAMEDATA, 0, sizeof(CNetObj_GameData)); if(!pGameDataObj) return; //Search for witch 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->GetClass() == PLAYERCLASS_WITCH) { pGameDataObj->m_FlagCarrierRed = i; } } pGameDataObj->m_FlagCarrierBlue = FLAG_ATSTAND; }
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; }
int CGameControllerMOD::ChooseHumanClass(CPlayer* pPlayer) { float random = frandom(); float TotalProbHumanClass = m_TotalProbHumanClass; //Get information about existing infected int nbSupport = 0; int nbMedic = 0; int nbDefender = 0; for(int i = 0; i < MAX_CLIENTS; i++) { CPlayer *pPlayer = GameServer()->m_apPlayers[i]; if(!pPlayer) continue; if(pPlayer->GetTeam() == TEAM_SPECTATORS) continue; switch(pPlayer->GetClass()) { case PLAYERCLASS_NINJA: case PLAYERCLASS_MERCENARY: case PLAYERCLASS_SNIPER: nbSupport++; break; case PLAYERCLASS_MEDIC: nbMedic++; break; case PLAYERCLASS_ENGINEER: case PLAYERCLASS_SOLDIER: case PLAYERCLASS_SCIENTIST: nbDefender++; break; } } bool defenderEnabled = true; if(nbDefender >= g_Config.m_InfDefenderLimit) { TotalProbHumanClass -= m_ClassProbability[PLAYERCLASS_ENGINEER]; TotalProbHumanClass -= m_ClassProbability[PLAYERCLASS_SOLDIER]; TotalProbHumanClass -= m_ClassProbability[PLAYERCLASS_SCIENTIST]; defenderEnabled = false; } bool supportEnabled = true; if(nbSupport >= g_Config.m_InfSupportLimit) { TotalProbHumanClass -= m_ClassProbability[PLAYERCLASS_NINJA]; TotalProbHumanClass -= m_ClassProbability[PLAYERCLASS_MERCENARY]; TotalProbHumanClass -= m_ClassProbability[PLAYERCLASS_SNIPER]; supportEnabled = false; } bool medicEnabled = true; if(nbMedic >= g_Config.m_InfMedicLimit) { TotalProbHumanClass -= m_ClassProbability[PLAYERCLASS_MEDIC]; medicEnabled = false; } if(defenderEnabled) { random -= m_ClassProbability[PLAYERCLASS_ENGINEER]/TotalProbHumanClass; if(random < 0.0f) { return PLAYERCLASS_ENGINEER; } random -= m_ClassProbability[PLAYERCLASS_SOLDIER]/TotalProbHumanClass; if(random < 0.0f) { return PLAYERCLASS_SOLDIER; } random -= m_ClassProbability[PLAYERCLASS_SCIENTIST]/TotalProbHumanClass; if(random < 0.0f) { return PLAYERCLASS_SCIENTIST; } } if(medicEnabled) { random -= m_ClassProbability[PLAYERCLASS_MEDIC]/TotalProbHumanClass; if(random < 0.0f) { return PLAYERCLASS_MEDIC; } } if(supportEnabled) { random -= m_ClassProbability[PLAYERCLASS_NINJA]/TotalProbHumanClass; if(random < 0.0f) { return PLAYERCLASS_NINJA; } random -= m_ClassProbability[PLAYERCLASS_MERCENARY]/TotalProbHumanClass; if(random < 0.0f) { return PLAYERCLASS_MERCENARY; } random -= m_ClassProbability[PLAYERCLASS_SNIPER]/TotalProbHumanClass; if(random < 0.0f) { return PLAYERCLASS_SNIPER; } } return PLAYERCLASS_ENGINEER; }
void CCharacter::HandleNinja() { if(m_ActiveWeapon != WEAPON_NINJA) return; vec2 Direction = normalize(vec2(m_LatestInput.m_TargetX, m_LatestInput.m_TargetY)); if ((Server()->Tick() - m_Ninja.m_ActivationTick) > (g_pData->m_Weapons.m_Ninja.m_Duration * Server()->TickSpeed() / 1000)) { // time's up, return m_aWeapons[WEAPON_NINJA].m_Got = false; m_ActiveWeapon = m_LastWeapon; if(m_ActiveWeapon == WEAPON_NINJA) m_ActiveWeapon = WEAPON_GUN; SetWeapon(m_ActiveWeapon); return; } // force ninja Weapon SetWeapon(WEAPON_NINJA); m_Ninja.m_CurrentMoveTime--; if (m_Ninja.m_CurrentMoveTime == 0) { // reset velocity m_Core.m_Vel *= 0.2f; } if (m_Ninja.m_CurrentMoveTime > 0) { // Set velocity m_Core.m_Vel = m_Ninja.m_ActivationDir * g_pData->m_Weapons.m_Ninja.m_Velocity; vec2 OldPos = m_Pos; GameServer()->Collision()->MoveBox(&m_Core.m_Pos, &m_Core.m_Vel, vec2(m_ProximityRadius, m_ProximityRadius), 0.f); // reset velocity so the client doesn't predict stuff m_Core.m_Vel = vec2(0.f, 0.f); // check if we Hit anything along the way { CCharacter *aEnts[MAX_CLIENTS]; vec2 Dir = m_Pos - OldPos; float Radius = m_ProximityRadius * 2.0f; vec2 Center = OldPos + Dir * 0.5f; int Num = GameServer()->m_World.FindEntities(Center, Radius, (CEntity**)aEnts, MAX_CLIENTS, CGameWorld::ENTTYPE_CHARACTER); for (int i = 0; i < Num; ++i) { if (aEnts[i] == this) continue; // make sure we haven't Hit this object before bool bAlreadyHit = false; for (int j = 0; j < m_NumObjectsHit; j++) { if (m_apHitObjects[j] == aEnts[i]) bAlreadyHit = true; } if (bAlreadyHit) continue; // check so we are sufficiently close if (distance(aEnts[i]->m_Pos, m_Pos) > (m_ProximityRadius * 2.0f)) continue; // Hit a player, give him damage and stuffs... GameServer()->CreateSound(aEnts[i]->m_Pos, SOUND_NINJA_HIT); // set his velocity to fast upward (for now) if(m_NumObjectsHit < 10) m_apHitObjects[m_NumObjectsHit++] = aEnts[i]; aEnts[i]->TakeDamage(vec2(0, 10.0f), g_pData->m_Weapons.m_Ninja.m_pBase->m_Damage, m_pPlayer->GetCID(), WEAPON_NINJA); } } return; } return; }
void CPickup::Tick() { // wait for respawn //if(m_SpawnTick > 0) - 12.5. if(m_SpawnTick > 0 && !m_Dropable && !m_Flashing) { if(Server()->Tick() > m_SpawnTick && !m_SkipAutoRespawn) { // respawn m_SpawnTick = -1; if(m_Type == POWERUP_WEAPON) GameServer()->CreateSound(m_Pos, SOUND_WEAPON_SPAWN); } else return; } // item drops from enemies if (m_Dropable) { if (m_Life > 0) m_Life--; else { m_SpawnTick = 999; return; } if (m_Life < 100) m_Flashing = true; } // a small visual effect before pickup disappears if (m_Flashing) { m_FlashTimer--; if (m_FlashTimer <= 0) m_FlashTimer = 20; if (m_FlashTimer > 10) m_SpawnTick = 999; else m_SpawnTick = -1; } // physics if (m_Dropable) { m_Vel.y += 0.5f; bool Grounded = false; if(GameServer()->Collision()->CheckPoint(m_Pos.x+12, m_Pos.y+12+5)) Grounded = true; if(GameServer()->Collision()->CheckPoint(m_Pos.x-12, m_Pos.y+12+5)) Grounded = true; if (Grounded) m_Vel.x *= 0.8f; else m_Vel.x *= 0.99f; GameServer()->Collision()->MoveBox(&m_Pos, &m_Vel, vec2(24.0f, 24.0f), 0.4f); } // Check if a player intersected us CCharacter *pChr = GameServer()->m_World.ClosestCharacter(m_Pos, 20.0f, 0); if(pChr && pChr->IsAlive()) // && !pChr->GetPlayer()->m_pAI) { // player picked us up, is someone was hooking us, let them go int RespawnTime = -1; switch (m_Type) { case POWERUP_HEALTH: if (m_Subtype > 0 && m_Owner >= 0 && m_Owner < MAX_CLIENTS && GameServer()->m_apPlayers[m_Owner]) { int Team = GameServer()->m_apPlayers[m_Owner]->GetTeam(); if (Team != pChr->GetPlayer()->GetTeam()) { if (m_Subtype == 1) GameServer()->CreateExplosion(m_Pos, m_Owner, WEAPON_HAMMER, false, false); if (m_Subtype == 2) { CSuperexplosion *S = new CSuperexplosion(&GameServer()->m_World, m_Pos, m_Owner, WEAPON_HAMMER, 1); GameServer()->m_World.InsertEntity(S); } GameServer()->CreateSound(m_Pos, SOUND_PICKUP_HEALTH); RespawnTime = g_pData->m_aPickups[m_Type].m_Respawntime; m_Life = 0; m_Flashing = false; m_Subtype = 0; break; } } if(pChr->IncreaseHealth(10)) { GameServer()->CreateSound(m_Pos, SOUND_PICKUP_HEALTH); RespawnTime = g_pData->m_aPickups[m_Type].m_Respawntime; m_Life = 0; m_Flashing = false; } else if (pChr->GetPlayer()->GotAbility(STORE_HEALTH) && pChr->StoreHealth()) { GameServer()->CreateSound(m_Pos, SOUND_PICKUP_HEALTH); RespawnTime = g_pData->m_aPickups[m_Type].m_Respawntime; m_Life = 0; m_Flashing = false; } break; case POWERUP_ARMOR: if(pChr->IncreaseArmor(1)) { GameServer()->CreateSound(m_Pos, SOUND_PICKUP_ARMOR); RespawnTime = g_pData->m_aPickups[m_Type].m_Respawntime; m_Life = 0; m_Flashing = false; } break; case POWERUP_WEAPON: if(m_Subtype >= 0 && m_Subtype < NUM_CUSTOMWEAPONS) { int Parent = aCustomWeapon[m_Subtype].m_ParentWeapon; if (Parent < 0 || Parent >= NUM_WEAPONS) { RespawnTime = g_pData->m_aPickups[m_Type].m_Respawntime; m_Life = 0; m_Flashing = false; break; } if (pChr->GiveCustomWeapon(m_Subtype, 0.2f + frandom()*0.3f)) { if(Parent == WEAPON_GRENADE) GameServer()->CreateSound(m_Pos, SOUND_PICKUP_GRENADE); else GameServer()->CreateSound(m_Pos, SOUND_PICKUP_SHOTGUN); if(pChr->GetPlayer()) { //GameServer()->SendWeaponPickup(pChr->GetPlayer()->GetCID(), Parent); char aBuf[256]; str_format(aBuf, sizeof(aBuf), "Picked up %s", aCustomWeapon[m_Subtype].m_Name); GameServer()->SendChatTarget(pChr->GetPlayer()->GetCID(), aBuf); } RespawnTime = g_pData->m_aPickups[m_Type].m_Respawntime; m_Life = 0; m_Flashing = false; } else { if (pChr->GiveAmmo(&m_Subtype, 0.125f + frandom()*0.15f)) { char aBuf[256]; str_format(aBuf, sizeof(aBuf), "Picked up ammo for %s", aCustomWeapon[m_Subtype].m_Name); GameServer()->SendChatTarget(pChr->GetPlayer()->GetCID(), aBuf); RespawnTime = g_pData->m_aPickups[m_Type].m_Respawntime; m_Life = 0; m_Flashing = false; } } /*if(pChr->GiveWeapon(m_Subtype, 10)) // !pChr->m_WeaponPicked && { RespawnTime = g_pData->m_aPickups[m_Type].m_Respawntime; //pChr->m_WeaponPicked = true; if(m_Subtype == WEAPON_GRENADE) GameServer()->CreateSound(m_Pos, SOUND_PICKUP_GRENADE); else if(m_Subtype == WEAPON_SHOTGUN) GameServer()->CreateSound(m_Pos, SOUND_PICKUP_SHOTGUN); else if(m_Subtype == WEAPON_RIFLE) GameServer()->CreateSound(m_Pos, SOUND_PICKUP_SHOTGUN); if(pChr->GetPlayer()) GameServer()->SendWeaponPickup(pChr->GetPlayer()->GetCID(), m_Subtype); }*/ } break; // sword not in use, instead snap weapon to look like sword case POWERUP_NINJA: { /* // activate ninja on target player pChr->GiveNinja(); RespawnTime = g_pData->m_aPickups[m_Type].m_Respawntime; // loop through all players, setting their emotes CCharacter *pC = static_cast<CCharacter *>(GameServer()->m_World.FindFirst(CGameWorld::ENTTYPE_CHARACTER)); for(; pC; pC = (CCharacter *)pC->TypeNext()) { if (pC != pChr) pC->SetEmote(EMOTE_SURPRISE, Server()->Tick() + Server()->TickSpeed()); } pChr->SetEmote(EMOTE_ANGRY, Server()->Tick() + 1200 * Server()->TickSpeed() / 1000); m_Flashing = false; break; */ } default: break; }; if(RespawnTime >= 0) { char aBuf[256]; str_format(aBuf, sizeof(aBuf), "pickup player='%d:%s' item=%d/%d", pChr->GetPlayer()->GetCID(), Server()->ClientName(pChr->GetPlayer()->GetCID()), m_Type, m_Subtype); GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf); m_SpawnTick = Server()->Tick() + Server()->TickSpeed() * RespawnTime; } } }
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(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; GameServer()->CreateSound(m_Pos, SOUND_WEAPON_NOAMMO); 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); 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); 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_AttackTick = Server()->Tick(); m_Ninja.m_ActivationDir = Direction; m_Ninja.m_CurrentMoveTime = g_pData->m_Weapons.m_Ninja.m_Movetime * Server()->TickSpeed() / 1000; 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 CProjectile::Reset() { GameServer()->m_World.DestroyEntity(this); }
void CCharacter::TickDefered() { // advance the dummy { CWorldCore TempWorld; m_ReckoningCore.Init(&TempWorld, GameServer()->Collision()); m_ReckoningCore.Tick(false); m_ReckoningCore.Move(); m_ReckoningCore.Quantize(); } //lastsentcore vec2 StartPos = m_Core.m_Pos; vec2 StartVel = m_Core.m_Vel; bool StuckBefore = GameServer()->Collision()->TestBox(m_Core.m_Pos, vec2(28.0f, 28.0f)); m_Core.Move(); bool StuckAfterMove = GameServer()->Collision()->TestBox(m_Core.m_Pos, vec2(28.0f, 28.0f)); m_Core.Quantize(); bool StuckAfterQuant = GameServer()->Collision()->TestBox(m_Core.m_Pos, vec2(28.0f, 28.0f)); m_Pos = m_Core.m_Pos; if(!StuckBefore && (StuckAfterMove || StuckAfterQuant)) { // Hackish solution to get rid of strict-aliasing warning union { float f; unsigned u; }StartPosX, StartPosY, StartVelX, StartVelY; StartPosX.f = StartPos.x; StartPosY.f = StartPos.y; StartVelX.f = StartVel.x; StartVelY.f = StartVel.y; char aBuf[256]; str_format(aBuf, sizeof(aBuf), "STUCK!!! %d %d %d %f %f %f %f %x %x %x %x", StuckBefore, StuckAfterMove, StuckAfterQuant, StartPos.x, StartPos.y, StartVel.x, StartVel.y, StartPosX.u, StartPosY.u, StartVelX.u, StartVelY.u); GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf); } int Events = m_Core.m_TriggeredEvents; int Mask = CmaskAllExceptOne(m_pPlayer->GetCID()); if(Events&COREEVENT_GROUND_JUMP) GameServer()->CreateSound(m_Pos, SOUND_PLAYER_JUMP, Mask); if(Events&COREEVENT_HOOK_ATTACH_PLAYER) GameServer()->CreateSound(m_Pos, SOUND_HOOK_ATTACH_PLAYER, CmaskAll()); if(Events&COREEVENT_HOOK_ATTACH_GROUND) GameServer()->CreateSound(m_Pos, SOUND_HOOK_ATTACH_GROUND, Mask); if(Events&COREEVENT_HOOK_HIT_NOHOOK) GameServer()->CreateSound(m_Pos, SOUND_HOOK_NOATTACH, Mask); if(m_pPlayer->GetTeam() == TEAM_SPECTATORS) { m_Pos.x = m_Input.m_TargetX; m_Pos.y = m_Input.m_TargetY; } // update the m_SendCore if needed { CNetObj_Character Predicted; CNetObj_Character Current; mem_zero(&Predicted, sizeof(Predicted)); mem_zero(&Current, sizeof(Current)); m_ReckoningCore.Write(&Predicted); m_Core.Write(&Current); // only allow dead reackoning for a top of 3 seconds if(m_ReckoningTick+Server()->TickSpeed()*3 < Server()->Tick() || mem_comp(&Predicted, &Current, sizeof(CNetObj_Character)) != 0) { m_ReckoningTick = Server()->Tick(); m_SendCore = m_Core; m_ReckoningCore = m_Core; } } }
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); } } }
bool CCharacter::TakeDamage(vec2 Force, int Dmg, int From, int Weapon) { m_Core.m_Vel += Force; if(GameServer()->m_pController->IsFriendlyFire(m_pPlayer->GetCID(), From) && !g_Config.m_SvTeamdamage) return false; // m_pPlayer only inflicts half damage on self if(From == m_pPlayer->GetCID()) Dmg = max(1, Dmg/2); m_DamageTaken++; // create healthmod indicator if(Server()->Tick() < m_DamageTakenTick+25) { // make sure that the damage indicators doesn't group together GameServer()->CreateDamageInd(m_Pos, m_DamageTaken*0.25f, Dmg); } else { m_DamageTaken = 0; GameServer()->CreateDamageInd(m_Pos, 0, Dmg); } if(Dmg) { if(m_Armor) { if(Dmg > 1) { m_Health--; Dmg--; } if(Dmg > m_Armor) { Dmg -= m_Armor; m_Armor = 0; } else { m_Armor -= Dmg; Dmg = 0; } } m_Health -= Dmg; } m_DamageTakenTick = Server()->Tick(); // do damage Hit sound if(From >= 0 && From != m_pPlayer->GetCID() && GameServer()->m_apPlayers[From]) GameServer()->CreateSound(GameServer()->m_apPlayers[From]->m_ViewPos, SOUND_HIT, CmaskOne(From)); // check for death if(m_Health <= 0) { Die(From, Weapon); // set attacker's face to happy (taunt!) if (From >= 0 && From != m_pPlayer->GetCID() && GameServer()->m_apPlayers[From]) { CCharacter *pChr = GameServer()->m_apPlayers[From]->GetCharacter(); if (pChr) { pChr->m_EmoteType = EMOTE_HAPPY; pChr->m_EmoteStop = Server()->Tick() + Server()->TickSpeed(); } } return false; } if (Dmg > 2) GameServer()->CreateSound(m_Pos, SOUND_PLAYER_PAIN_LONG); else GameServer()->CreateSound(m_Pos, SOUND_PLAYER_PAIN_SHORT); m_EmoteType = EMOTE_PAIN; m_EmoteStop = Server()->Tick() + 500 * Server()->TickSpeed() / 1000; return true; }
void IGameController::ResetGame() { GameServer()->m_World.m_ResetRequested = true; }
void CServer::DoSnapshot() { GameServer()->OnPreSnap(); // create snapshot for demo recording if(m_DemoRecorder.IsRecording()) { char aData[CSnapshot::MAX_SIZE]; int SnapshotSize; // build snap and possibly add some messages m_SnapshotBuilder.Init(); GameServer()->OnSnap(-1); SnapshotSize = m_SnapshotBuilder.Finish(aData); // write snapshot m_DemoRecorder.RecordSnapshot(Tick(), aData, SnapshotSize); } // create snapshots for all clients for(int i = 0; i < MAX_CLIENTS; i++) { // client must be ingame to recive snapshots if(m_aClients[i].m_State != CClient::STATE_INGAME) continue; // this client is trying to recover, don't spam snapshots if(m_aClients[i].m_SnapRate == CClient::SNAPRATE_RECOVER && (Tick()%50) != 0) continue; // this client is trying to recover, don't spam snapshots if(m_aClients[i].m_SnapRate == CClient::SNAPRATE_INIT && (Tick()%10) != 0) continue; { char aData[CSnapshot::MAX_SIZE]; CSnapshot *pData = (CSnapshot*)aData; // Fix compiler warning for strict-aliasing char aDeltaData[CSnapshot::MAX_SIZE]; char aCompData[CSnapshot::MAX_SIZE]; int SnapshotSize; int Crc; static CSnapshot EmptySnap; CSnapshot *pDeltashot = &EmptySnap; int DeltashotSize; int DeltaTick = -1; int DeltaSize; m_SnapshotBuilder.Init(); GameServer()->OnSnap(i); // finish snapshot SnapshotSize = m_SnapshotBuilder.Finish(pData); Crc = pData->Crc(); // remove old snapshos // keep 3 seconds worth of snapshots m_aClients[i].m_Snapshots.PurgeUntil(m_CurrentGameTick-SERVER_TICK_SPEED*3); // save it the snapshot m_aClients[i].m_Snapshots.Add(m_CurrentGameTick, time_get(), SnapshotSize, pData, 0); // find snapshot that we can preform delta against EmptySnap.Clear(); { DeltashotSize = m_aClients[i].m_Snapshots.Get(m_aClients[i].m_LastAckedSnapshot, 0, &pDeltashot, 0); if(DeltashotSize >= 0) DeltaTick = m_aClients[i].m_LastAckedSnapshot; else { // no acked package found, force client to recover rate if(m_aClients[i].m_SnapRate == CClient::SNAPRATE_FULL) m_aClients[i].m_SnapRate = CClient::SNAPRATE_RECOVER; } } // create delta DeltaSize = m_SnapshotDelta.CreateDelta(pDeltashot, pData, aDeltaData); if(DeltaSize) { // compress it int SnapshotSize; const int MaxSize = MAX_SNAPSHOT_PACKSIZE; int NumPackets; SnapshotSize = CVariableInt::Compress(aDeltaData, DeltaSize, aCompData); NumPackets = (SnapshotSize+MaxSize-1)/MaxSize; for(int n = 0, Left = SnapshotSize; Left; n++) { int Chunk = Left < MaxSize ? Left : MaxSize; Left -= Chunk; if(NumPackets == 1) { CMsgPacker Msg(NETMSG_SNAPSINGLE); Msg.AddInt(m_CurrentGameTick); Msg.AddInt(m_CurrentGameTick-DeltaTick); Msg.AddInt(Crc); Msg.AddInt(Chunk); Msg.AddRaw(&aCompData[n*MaxSize], Chunk); SendMsgEx(&Msg, MSGFLAG_FLUSH, i, true); } else { CMsgPacker Msg(NETMSG_SNAP); Msg.AddInt(m_CurrentGameTick); Msg.AddInt(m_CurrentGameTick-DeltaTick); Msg.AddInt(NumPackets); Msg.AddInt(n); Msg.AddInt(Crc); Msg.AddInt(Chunk); Msg.AddRaw(&aCompData[n*MaxSize], Chunk); SendMsgEx(&Msg, MSGFLAG_FLUSH, i, true); } } } else { CMsgPacker Msg(NETMSG_SNAPEMPTY); Msg.AddInt(m_CurrentGameTick); Msg.AddInt(m_CurrentGameTick-DeltaTick); SendMsgEx(&Msg, MSGFLAG_FLUSH, i, true); } } } GameServer()->OnPostSnap(); }