void CGameClient::OnGameOver() { if(Client()->State() != IClient::STATE_DEMOPLAYBACK && g_Config.m_ClEditor == 0) Client()->AutoScreenshot_Start(); }
boost::statechart::result MPLobby::react(const LobbyChat& msg) { if (TRACE_EXECUTION) DebugLogger() << "(HumanClientFSM) MPLobby.LobbyChat"; Client().GetClientUI()->GetMultiPlayerLobbyWnd()->ChatMessage(msg.m_message.SendingPlayer(), msg.m_message.Text()); return discard_event(); }
boost::statechart::result WaitingForGameStart::react(const GameStart& msg) { if (TRACE_EXECUTION) DebugLogger() << "(HumanClientFSM) WaitingForGameStart.GameStart"; bool loaded_game_data; bool ui_data_available; SaveGameUIData ui_data; bool save_state_string_available; std::string save_state_string; // ignored - used by AI but not by human client OrderSet orders; bool single_player_game = false; int empire_id = ALL_EMPIRES; int current_turn = INVALID_GAME_TURN; Client().PlayerStatus().clear(); ExtractMessageData(msg.m_message, single_player_game, empire_id, current_turn, Empires(), GetUniverse(), GetSpeciesManager(), GetCombatLogManager(), GetSupplyManager(), Client().Players(), orders, loaded_game_data, ui_data_available, ui_data, save_state_string_available, save_state_string, Client().GetGalaxySetupData()); DebugLogger() << "Extracted GameStart message for turn: " << current_turn << " with empire: " << empire_id; Client().SetSinglePlayerGame(single_player_game); Client().SetEmpireID(empire_id); Client().SetCurrentTurn(current_turn); Client().StartGame(); std::swap(Client().Orders(), orders); // bring back orders planned in the current turn, they will be applied later, after some basic turn initialization if (loaded_game_data && ui_data_available) Client().GetClientUI()->RestoreFromSaveData(ui_data); // if I am the host on the first turn, do an autosave. on later turns, will // have just loaded save, so don't need to autosave. might also have just // loaded a turn 1 autosave, but not sure how to check for that here... if (Client().CurrentTurn() == 1 && Client().Networking().PlayerIsHost(Client().PlayerID())) Client().Autosave(); return transit<PlayingTurn>(); }
void CScoreboard::OnRender() { // check if we need to reset the player stats if(!m_SkipPlayerStatsReset && m_pClient->m_Snap.m_pGameData && m_pClient->m_Snap.m_pGameData->m_GameStartTick == Client()->GameTick()) { m_SkipPlayerStatsReset = true; for(int i = 0; i < MAX_CLIENTS; i++) ResetPlayerStats(i); } else if(m_SkipPlayerStatsReset && m_pClient->m_Snap.m_pGameData && m_pClient->m_Snap.m_pGameData->m_GameStartTick != Client()->GameTick()) m_SkipPlayerStatsReset = false; // postpone the active state till the render area gets updated during the rendering if(m_Activate) { m_Active = true; m_Activate = false; } // close the motd if we actively wanna look on the scoreboard if(m_Active) m_pClient->m_pMotd->Clear(); if(!Active()) return; // don't render scoreboard if menu or motd is open if(m_pClient->m_pMenus->IsActive() || m_pClient->m_pMotd->IsActive()) return; CUIRect Screen = *UI()->Screen(); Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h); float Width = Screen.w; float y = 85.f; float w = 364.0f; float FontSize = 86.0f; const char* pCustomRedClanName = GetClanName(TEAM_RED); const char* pCustomBlueClanName = GetClanName(TEAM_BLUE); const char* pRedClanName = pCustomRedClanName ? pCustomRedClanName : Localize("Red team"); const char* pBlueClanName = pCustomBlueClanName ? pCustomBlueClanName : Localize("Blue team"); if(m_pClient->m_Snap.m_pGameData) { if(!(m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_TEAMS)) { float ScoreboardHeight = RenderScoreboard(Width/2-w/2, y, w, 0, 0, -1); float SpectatorHeight = RenderSpectators(Width/2-w/2, y+3.0f+ScoreboardHeight, w); RenderGoals(Width/2-w/2, y+3.0f+ScoreboardHeight, w); // scoreboard size m_TotalRect.x = Width/2-w/2; m_TotalRect.y = y; m_TotalRect.w = w; m_TotalRect.h = ScoreboardHeight+SpectatorHeight+3.0f; } else if(m_pClient->m_Snap.m_pGameDataTeam) { float ScoreboardHeight = RenderScoreboard(Width/2-w-1.5f, y, w, TEAM_RED, pRedClanName, -1); RenderScoreboard(Width/2+1.5f, y, w, TEAM_BLUE, pBlueClanName, 1); float SpectatorHeight = RenderSpectators(Width/2-w-1.5f, y+3.0f+ScoreboardHeight, w*2.0f+3.0f); RenderGoals(Width/2-w-1.5f, y+3.0f+ScoreboardHeight, w*2.0f+3.0f); // scoreboard size m_TotalRect.x = Width/2-w-1.5f; m_TotalRect.y = y; m_TotalRect.w = w*2.0f+3.0f; m_TotalRect.h = ScoreboardHeight+SpectatorHeight+3.0f; } } Width = 400*3.0f*Graphics()->ScreenAspect(); Graphics()->MapScreen(0, 0, Width, 400*3.0f); if(m_pClient->m_Snap.m_pGameData && (m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_TEAMS) && m_pClient->m_Snap.m_pGameDataTeam) { if(m_pClient->m_Snap.m_pGameData->m_GameStateFlags&GAMESTATEFLAG_GAMEOVER) { char aText[256]; if(m_pClient->m_Snap.m_pGameDataTeam->m_TeamscoreRed > m_pClient->m_Snap.m_pGameDataTeam->m_TeamscoreBlue) str_format(aText, sizeof(aText), Localize("%s wins!"), pRedClanName); else if(m_pClient->m_Snap.m_pGameDataTeam->m_TeamscoreBlue > m_pClient->m_Snap.m_pGameDataTeam->m_TeamscoreRed) str_format(aText, sizeof(aText), Localize("%s wins!"), pBlueClanName); else str_copy(aText, Localize("Draw!"), sizeof(aText)); float tw = TextRender()->TextWidth(0, FontSize, aText, -1, -1.0f); TextRender()->Text(0, Width/2-tw/2, 39, FontSize, aText, -1.0f); } else if(m_pClient->m_Snap.m_pGameData->m_GameStateFlags&GAMESTATEFLAG_ROUNDOVER) { char aText[256]; str_copy(aText, Localize("Round over!"), sizeof(aText)); float tw = TextRender()->TextWidth(0, FontSize, aText, -1, -1.0f); TextRender()->Text(0, Width/2-tw/2, 39, FontSize, aText, -1.0f); m_SkipPlayerStatsReset = true; } } RenderRecordingNotification((Width/7)*4); }
void CMenus::RenderDemoList(CUIRect MainView) { static int s_Inited = 0; if(!s_Inited) { DemolistPopulate(); DemolistOnUpdate(true); s_Inited = 1; } char aFooterLabel[128] = {0}; if(m_DemolistSelectedIndex >= 0) { CDemoItem *Item = &m_lDemos[m_DemolistSelectedIndex]; if(str_comp(Item->m_aFilename, "..") == 0) str_copy(aFooterLabel, Localize("Parent Folder"), sizeof(aFooterLabel)); else if(m_DemolistSelectedIsDir) str_copy(aFooterLabel, Localize("Folder"), sizeof(aFooterLabel)); else { if(!Item->m_InfosLoaded) { char aBuffer[512]; str_format(aBuffer, sizeof(aBuffer), "%s/%s", m_aCurrentDemoFolder, Item->m_aFilename); Item->m_Valid = DemoPlayer()->GetDemoInfo(Storage(), aBuffer, Item->m_StorageType, &Item->m_Info); Item->m_InfosLoaded = true; } if(!Item->m_Valid) str_copy(aFooterLabel, Localize("Invalid Demo"), sizeof(aFooterLabel)); else str_copy(aFooterLabel, Localize("Demo details"), sizeof(aFooterLabel)); } } // render background RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_ALL, 10.0f); MainView.Margin(10.0f, &MainView); CUIRect ButtonBar, RefreshRect, PlayRect, DeleteRect, RenameRect, FileIcon, ListBox; MainView.HSplitBottom(ms_ButtonHeight+5.0f, &MainView, &ButtonBar); ButtonBar.HSplitTop(5.0f, 0, &ButtonBar); ButtonBar.VSplitRight(130.0f, &ButtonBar, &PlayRect); ButtonBar.VSplitLeft(130.0f, &RefreshRect, &ButtonBar); ButtonBar.VSplitLeft(10.0f, 0, &ButtonBar); ButtonBar.VSplitLeft(120.0f, &DeleteRect, &ButtonBar); ButtonBar.VSplitLeft(10.0f, 0, &ButtonBar); ButtonBar.VSplitLeft(120.0f, &RenameRect, &ButtonBar); MainView.HSplitBottom(140.0f, &ListBox, &MainView); // render demo info MainView.VMargin(5.0f, &MainView); MainView.HSplitBottom(5.0f, &MainView, 0); RenderTools()->DrawUIRect(&MainView, vec4(0,0,0,0.15f), CUI::CORNER_B, 4.0f); if(!m_DemolistSelectedIsDir && m_DemolistSelectedIndex >= 0 && m_lDemos[m_DemolistSelectedIndex].m_Valid) { CUIRect Left, Right, Labels; MainView.Margin(20.0f, &MainView); MainView.VSplitMid(&Labels, &MainView); // left side Labels.HSplitTop(20.0f, &Left, &Labels); Left.VSplitLeft(150.0f, &Left, &Right); UI()->DoLabelScaled(&Left, Localize("Created:"), 14.0f, -1); UI()->DoLabelScaled(&Right, m_lDemos[m_DemolistSelectedIndex].m_Info.m_aTimestamp, 14.0f, -1); Labels.HSplitTop(5.0f, 0, &Labels); Labels.HSplitTop(20.0f, &Left, &Labels); Left.VSplitLeft(150.0f, &Left, &Right); UI()->DoLabelScaled(&Left, Localize("Type:"), 14.0f, -1); UI()->DoLabelScaled(&Right, m_lDemos[m_DemolistSelectedIndex].m_Info.m_aType, 14.0f, -1); Labels.HSplitTop(5.0f, 0, &Labels); Labels.HSplitTop(20.0f, &Left, &Labels); Left.VSplitLeft(150.0f, &Left, &Right); UI()->DoLabelScaled(&Left, Localize("Length:"), 14.0f, -1); int Length = ((m_lDemos[m_DemolistSelectedIndex].m_Info.m_aLength[0]<<24)&0xFF000000) | ((m_lDemos[m_DemolistSelectedIndex].m_Info.m_aLength[1]<<16)&0xFF0000) | ((m_lDemos[m_DemolistSelectedIndex].m_Info.m_aLength[2]<<8)&0xFF00) | (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aLength[3]&0xFF); char aBuf[64]; str_format(aBuf, sizeof(aBuf), "%d:%02d", Length/60, Length%60); UI()->DoLabelScaled(&Right, aBuf, 14.0f, -1); Labels.HSplitTop(5.0f, 0, &Labels); Labels.HSplitTop(20.0f, &Left, &Labels); Left.VSplitLeft(150.0f, &Left, &Right); UI()->DoLabelScaled(&Left, Localize("Version:"), 14.0f, -1); str_format(aBuf, sizeof(aBuf), "%d", m_lDemos[m_DemolistSelectedIndex].m_Info.m_Version); UI()->DoLabelScaled(&Right, aBuf, 14.0f, -1); // right side Labels = MainView; Labels.HSplitTop(20.0f, &Left, &Labels); Left.VSplitLeft(150.0f, &Left, &Right); UI()->DoLabelScaled(&Left, Localize("Map:"), 14.0f, -1); UI()->DoLabelScaled(&Right, m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapName, 14.0f, -1); Labels.HSplitTop(5.0f, 0, &Labels); Labels.HSplitTop(20.0f, &Left, &Labels); Left.VSplitLeft(20.0f, 0, &Left); Left.VSplitLeft(130.0f, &Left, &Right); UI()->DoLabelScaled(&Left, Localize("Size:"), 14.0f, -1); unsigned Size = (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapSize[0]<<24) | (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapSize[1]<<16) | (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapSize[2]<<8) | (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapSize[3]); str_format(aBuf, sizeof(aBuf), Localize("%d Bytes"), Size); UI()->DoLabelScaled(&Right, aBuf, 14.0f, -1); Labels.HSplitTop(5.0f, 0, &Labels); Labels.HSplitTop(20.0f, &Left, &Labels); Left.VSplitLeft(20.0f, 0, &Left); Left.VSplitLeft(130.0f, &Left, &Right); UI()->DoLabelScaled(&Left, Localize("Crc:"), 14.0f, -1); unsigned Crc = (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapCrc[0]<<24) | (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapCrc[1]<<16) | (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapCrc[2]<<8) | (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapCrc[3]); str_format(aBuf, sizeof(aBuf), "%08x", Crc); UI()->DoLabelScaled(&Right, aBuf, 14.0f, -1); Labels.HSplitTop(5.0f, 0, &Labels); Labels.HSplitTop(20.0f, &Left, &Labels); Left.VSplitLeft(150.0f, &Left, &Right); UI()->DoLabelScaled(&Left, Localize("Netversion:"), 14.0f, -1); UI()->DoLabelScaled(&Right, m_lDemos[m_DemolistSelectedIndex].m_Info.m_aNetversion, 14.0f, -1); } static int s_DemoListId = 0; static float s_ScrollValue = 0; UiDoListboxStart(&s_DemoListId, &ListBox, 17.0f, Localize("Demos"), aFooterLabel, m_lDemos.size(), 1, m_DemolistSelectedIndex, s_ScrollValue); for(sorted_array<CDemoItem>::range r = m_lDemos.all(); !r.empty(); r.pop_front()) { CListboxItem Item = UiDoListboxNextItem((void*)(&r.front())); if(Item.m_Visible) { Item.m_Rect.VSplitLeft(Item.m_Rect.h, &FileIcon, &Item.m_Rect); Item.m_Rect.VSplitLeft(5.0f, 0, &Item.m_Rect); DoButton_Icon(IMAGE_FILEICONS, r.front().m_IsDir?SPRITE_FILE_FOLDER:SPRITE_FILE_DEMO1, &FileIcon); UI()->DoLabel(&Item.m_Rect, r.front().m_aName, Item.m_Rect.h*ms_FontmodHeight, -1); } } bool Activated = false; m_DemolistSelectedIndex = UiDoListboxEnd(&s_ScrollValue, &Activated); DemolistOnUpdate(false); static int s_RefreshButton = 0; if(DoButton_Menu(&s_RefreshButton, Localize("Refresh"), 0, &RefreshRect)) { DemolistPopulate(); DemolistOnUpdate(false); } static int s_PlayButton = 0; if(DoButton_Menu(&s_PlayButton, m_DemolistSelectedIsDir?Localize("Open"):Localize("Play"), 0, &PlayRect) || Activated) { if(m_DemolistSelectedIndex >= 0) { if(m_DemolistSelectedIsDir) // folder { if(str_comp(m_lDemos[m_DemolistSelectedIndex].m_aFilename, "..") == 0) // parent folder fs_parent_dir(m_aCurrentDemoFolder); else // sub folder { char aTemp[256]; str_copy(aTemp, m_aCurrentDemoFolder, sizeof(aTemp)); str_format(m_aCurrentDemoFolder, sizeof(m_aCurrentDemoFolder), "%s/%s", aTemp, m_lDemos[m_DemolistSelectedIndex].m_aFilename); m_DemolistStorageType = m_lDemos[m_DemolistSelectedIndex].m_StorageType; } DemolistPopulate(); DemolistOnUpdate(true); } else // file { char aBuf[512]; str_format(aBuf, sizeof(aBuf), "%s/%s", m_aCurrentDemoFolder, m_lDemos[m_DemolistSelectedIndex].m_aFilename); const char *pError = Client()->DemoPlayer_Play(aBuf, m_lDemos[m_DemolistSelectedIndex].m_StorageType); if(pError) PopupMessage(Localize("Error"), str_comp(pError, "error loading demo") ? pError : Localize("Error loading demo"), Localize("Ok")); else { UI()->SetActiveItem(0); return; } } } } if(!m_DemolistSelectedIsDir) { static int s_DeleteButton = 0; if(DoButton_Menu(&s_DeleteButton, Localize("Delete"), 0, &DeleteRect) || m_DeletePressed) { if(m_DemolistSelectedIndex >= 0) { UI()->SetActiveItem(0); m_Popup = POPUP_DELETE_DEMO; return; } } static int s_RenameButton = 0; if(DoButton_Menu(&s_RenameButton, Localize("Rename"), 0, &RenameRect)) { if(m_DemolistSelectedIndex >= 0) { UI()->SetActiveItem(0); m_Popup = POPUP_RENAME_DEMO; str_copy(m_aCurrentDemoFile, m_lDemos[m_DemolistSelectedIndex].m_aFilename, sizeof(m_aCurrentDemoFile)); return; } } } }
int CControls::SnapInput(int *pData) { static int64 LastSendTime = 0; bool Send = false; // update player state if(m_pClient->m_pChat->IsActive()) m_InputData.m_PlayerFlags = PLAYERFLAG_CHATTING; else if(m_pClient->m_pMenus->IsActive()) m_InputData.m_PlayerFlags = PLAYERFLAG_IN_MENU; else m_InputData.m_PlayerFlags = PLAYERFLAG_PLAYING; if(m_pClient->m_pScoreboard->Active()) m_InputData.m_PlayerFlags |= PLAYERFLAG_SCOREBOARD; if(m_LastData.m_PlayerFlags != m_InputData.m_PlayerFlags) Send = true; m_LastData.m_PlayerFlags = m_InputData.m_PlayerFlags; // we freeze the input if chat or menu is activated if(!(m_InputData.m_PlayerFlags&PLAYERFLAG_PLAYING)) { OnReset(); mem_copy(pData, &m_InputData, sizeof(m_InputData)); // send once a second just to be sure if(time_get() > LastSendTime + time_freq()) Send = true; } else { m_InputData.m_TargetX = (int)m_MousePos.x; m_InputData.m_TargetY = (int)m_MousePos.y; if(!m_InputData.m_TargetX && !m_InputData.m_TargetY) { m_InputData.m_TargetX = 1; m_MousePos.x = 1; } // set direction m_InputData.m_Direction = 0; if(m_InputDirectionLeft && !m_InputDirectionRight) m_InputData.m_Direction = -1; if(!m_InputDirectionLeft && m_InputDirectionRight) m_InputData.m_Direction = 1; // stress testing if(g_Config.m_DbgStress) { float t = Client()->LocalTime(); mem_zero(&m_InputData, sizeof(m_InputData)); m_InputData.m_Direction = ((int)t/2)&1; m_InputData.m_Jump = ((int)t); m_InputData.m_Fire = ((int)(t*10)); m_InputData.m_Hook = ((int)(t*2))&1; m_InputData.m_WantedWeapon = ((int)t)%NUM_WEAPONS; m_InputData.m_TargetX = (int)(sinf(t*3)*100.0f); m_InputData.m_TargetY = (int)(cosf(t*3)*100.0f); } // check if we need to send input if(m_InputData.m_Direction != m_LastData.m_Direction) Send = true; else if(m_InputData.m_Jump != m_LastData.m_Jump) Send = true; else if(m_InputData.m_Fire != m_LastData.m_Fire) Send = true; else if(m_InputData.m_Hook != m_LastData.m_Hook) Send = true; else if(m_InputData.m_WantedWeapon != m_LastData.m_WantedWeapon) Send = true; else if(m_InputData.m_NextWeapon != m_LastData.m_NextWeapon) Send = true; else if(m_InputData.m_PrevWeapon != m_LastData.m_PrevWeapon) Send = true; // send at at least 10hz if(time_get() > LastSendTime + time_freq()/25) Send = true; } // copy and return size m_LastData = m_InputData; if(!Send) return 0; LastSendTime = time_get(); mem_copy(pData, &m_InputData, sizeof(m_InputData)); return sizeof(m_InputData); }
void CMenus::RenderStartMenu(CUIRect MainView) { // render logo Graphics()->TextureSet(g_pData->m_aImages[IMAGE_BANNER].m_Id); Graphics()->QuadsBegin(); Graphics()->SetColor(1,1,1,1); IGraphics::CQuadItem QuadItem(MainView.w/2-140, 60, 280, 70); Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); CUIRect TopMenu, BottomMenu; MainView.VMargin(MainView.w/2-190.0f, &TopMenu); TopMenu.HSplitTop(365.0f, &TopMenu, &BottomMenu); //TopMenu.HSplitBottom(145.0f, &TopMenu, 0); RenderTools()->DrawUIRect4(&TopMenu, vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.25f), vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 10.0f); TopMenu.HSplitTop(145.0f, 0, &TopMenu); CUIRect Button; int NewPage = -1; TopMenu.HSplitBottom(40.0f, &TopMenu, &Button); static CButtonContainer s_SettingsButton; if(DoButton_Menu(&s_SettingsButton, Localize("Settings"), 0, &Button, g_Config.m_ClShowStartMenuImages ? "settings" : 0, CUI::CORNER_ALL, 10.0f, 0.5f)) NewPage = PAGE_SETTINGS; /*TopMenu.HSplitBottom(5.0f, &TopMenu, 0); // little space TopMenu.HSplitBottom(40.0f, &TopMenu, &Bottom); static int s_LocalServerButton = 0; if(g_Config.m_ClShowStartMenuImages) { if(DoButton_MenuImage(&s_LocalServerButton, Localize("Local server"), 0, &Button, "local_server", 10.0f, 0.5f)) { } } else { if(DoButton_Menu(&s_LocalServerButton, Localize("Local server"), 0, &Button, CUI::CORNER_ALL, 10.0f, 0.5f)) { } }*/ TopMenu.HSplitBottom(5.0f, &TopMenu, 0); // little space TopMenu.HSplitBottom(40.0f, &TopMenu, &Button); static CButtonContainer s_DemoButton; if(DoButton_Menu(&s_DemoButton, Localize("Demos"), 0, &Button, g_Config.m_ClShowStartMenuImages ? "demos" : 0, CUI::CORNER_ALL, 10.0f, 0.5f)) { NewPage = PAGE_DEMOS; DemolistPopulate(); DemolistOnUpdate(false); } TopMenu.HSplitBottom(5.0f, &TopMenu, 0); // little space TopMenu.HSplitBottom(40.0f, &TopMenu, &Button); static CButtonContainer s_MapEditorButton; if(DoButton_Menu(&s_MapEditorButton, Localize("Editor"), 0, &Button, g_Config.m_ClShowStartMenuImages ? "editor" : 0, CUI::CORNER_ALL, 10.0f, 0.5f)) { g_Config.m_ClEditor = 1; Input()->MouseModeRelative(); } TopMenu.HSplitBottom(5.0f, &TopMenu, 0); // little space TopMenu.HSplitBottom(40.0f, &TopMenu, &Button); static CButtonContainer s_PlayButton; if(DoButton_Menu(&s_PlayButton, Localize("Play"), 0, &Button, g_Config.m_ClShowStartMenuImages ? "play_game" : 0, CUI::CORNER_ALL, 10.0f, 0.5f) || m_EnterPressed) NewPage = g_Config.m_UiBrowserPage; BottomMenu.HSplitTop(90.0f, 0, &BottomMenu); RenderTools()->DrawUIRect4(&BottomMenu, vec4(0.0f, 0.0f, 0.0f, 0.25f), vec4(0.0f, 0.0f, 0.0f, 0.25f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 10.0f); BottomMenu.HSplitTop(40.0f, &Button, &TopMenu); static CButtonContainer s_QuitButton; if(DoButton_Menu(&s_QuitButton, Localize("Quit"), 0, &Button, 0, CUI::CORNER_ALL, 10.0f, 0.5f) || m_EscapePressed) m_Popup = POPUP_QUIT; // render version CUIRect Version; MainView.HSplitBottom(50.0f, 0, &Version); Version.VMargin(50.0f, &Version); char aBuf[64]; if(str_comp(Client()->LatestVersion(), "0") != 0) { str_format(aBuf, sizeof(aBuf), Localize("Teeworlds %s is out! Download it at www.teeworlds.com!"), Client()->LatestVersion()); TextRender()->TextColor(1.0f, 0.4f, 0.4f, 1.0f); UI()->DoLabelScaled(&Version, aBuf, 14.0f, CUI::ALIGN_CENTER); TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); } UI()->DoLabelScaled(&Version, GAME_VERSION, 14.0f, CUI::ALIGN_RIGHT); if(NewPage != -1) SetMenuPage(NewPage); }
void CGameClient::OnInit() { // set the language g_Localization.Load(g_Config.m_ClLanguagefile, Storage(), Console()); // init all components for(int i = 0; i < m_All.m_Num; i++) m_All.m_paComponents[i]->OnInit(); // setup item sizes for(int i = 0; i < NUM_NETOBJTYPES; i++) Client()->SnapSetStaticsize(i, m_NetObjHandler.GetObjSize(i)); int64 Start = time_get(); // load default font static CFont *pDefaultFont = 0; char aFilename[512]; IOHANDLE File = Storage()->OpenFile("fonts/DejaVuSans.ttf", IOFLAG_READ, IStorage::TYPE_ALL, aFilename, sizeof(aFilename)); if(File) { io_close(File); pDefaultFont = TextRender()->LoadFont(aFilename); TextRender()->SetDefaultFont(pDefaultFont); } if(!pDefaultFont) Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "gameclient", "failed to load font. filename='fonts/DejaVuSans.ttf'"); g_Config.m_ClThreadsoundloading = 0; // setup load amount gs_LoadTotal = g_pData->m_NumImages; gs_LoadCurrent = 0; if(!g_Config.m_ClThreadsoundloading) gs_LoadTotal += g_pData->m_NumSounds; // load textures for(int i = 0; i < g_pData->m_NumImages; i++) { g_GameClient.m_pMenus->RenderLoading(gs_LoadCurrent/(float)gs_LoadTotal); g_pData->m_aImages[i].m_Id = Graphics()->LoadTexture(g_pData->m_aImages[i].m_pFilename, IStorage::TYPE_ALL, CImageInfo::FORMAT_AUTO, 0); gs_LoadCurrent++; } // load skins ::gs_Skins.Init(); // TODO: Refactor: fix threaded loading of sounds again // load sounds { bool DoRender = true; for(int s = 0; s < g_pData->m_NumSounds; s++) { if(DoRender) g_GameClient.m_pMenus->RenderLoading(gs_LoadCurrent/(float)gs_LoadTotal); for(int i = 0; i < g_pData->m_aSounds[s].m_NumSounds; i++) { int Id = Sound()->LoadWV(g_pData->m_aSounds[s].m_aSounds[i].m_pFilename); g_pData->m_aSounds[s].m_aSounds[i].m_Id = Id; } if(DoRender) gs_LoadCurrent++; } } /*if(config.cl_threadsoundloading) thread_create(load_sounds_thread, 0); else load_sounds_thread((void*)1);*/ for(int i = 0; i < m_All.m_Num; i++) m_All.m_paComponents[i]->OnReset(); int64 End = time_get(); char aBuf[256]; str_format(aBuf, sizeof(aBuf), "initialisation finished after %.2fms", ((End-Start)*1000)/(float)time_freq()); Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "gameclient", aBuf); m_ServerMode = SERVERMODE_PURE; }
void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker) { // special messages if(MsgId == NETMSGTYPE_SV_EXTRAPROJECTILE) { /* int num = msg_unpack_int(); for(int k = 0; k < num; k++) { NETOBJ_PROJECTILE proj; for(unsigned i = 0; i < sizeof(NETOBJ_PROJECTILE)/sizeof(int); i++) ((int *)&proj)[i] = msg_unpack_int(); if(msg_unpack_error()) return; if(extraproj_num != MAX_EXTRA_PROJECTILES) { extraproj_projectiles[extraproj_num] = proj; extraproj_num++; } } return;*/ } else if(MsgId == NETMSGTYPE_SV_TUNEPARAMS) { // unpack the new tuning CTuningParams NewTuning; int *pParams = (int *)&NewTuning; for(unsigned i = 0; i < sizeof(CTuningParams)/sizeof(int); i++) pParams[i] = pUnpacker->GetInt(); // check for unpacking errors if(pUnpacker->Error()) return; m_ServerMode = SERVERMODE_PURE; // apply new tuning m_Tuning = NewTuning; return; } void *pRawMsg = m_NetObjHandler.SecureUnpackMsg(MsgId, pUnpacker); if(!pRawMsg) { char aBuf[256]; str_format(aBuf, sizeof(aBuf), "dropped weird message '%s' (%d), failed on '%s'", m_NetObjHandler.GetMsgName(MsgId), MsgId, m_NetObjHandler.FailedMsgOn()); Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client", aBuf); return; } // TODO: this should be done smarter for(int i = 0; i < m_All.m_Num; i++) m_All.m_paComponents[i]->OnMessage(MsgId, pRawMsg); if(MsgId == NETMSGTYPE_SV_READYTOENTER) { Client()->EnterGame(); } else if (MsgId == NETMSGTYPE_SV_EMOTICON) { CNetMsg_Sv_Emoticon *pMsg = (CNetMsg_Sv_Emoticon *)pRawMsg; // apply m_aClients[pMsg->m_Cid].m_Emoticon = pMsg->m_Emoticon; m_aClients[pMsg->m_Cid].m_EmoticonStart = Client()->GameTick(); } else if(MsgId == NETMSGTYPE_SV_SOUNDGLOBAL) { if(m_SuppressEvents) return; // don't enqueue pseudo-global sounds from demos (created by PlayAndRecord) CNetMsg_Sv_SoundGlobal *pMsg = (CNetMsg_Sv_SoundGlobal *)pRawMsg; if(pMsg->m_Soundid == SOUND_CTF_DROP || pMsg->m_Soundid == SOUND_CTF_RETURN || pMsg->m_Soundid == SOUND_CTF_CAPTURE || pMsg->m_Soundid == SOUND_CTF_GRAB_EN || pMsg->m_Soundid == SOUND_CTF_GRAB_PL) g_GameClient.m_pSounds->Enqueue(pMsg->m_Soundid); else g_GameClient.m_pSounds->Play(CSounds::CHN_GLOBAL, pMsg->m_Soundid, 1.0f, vec2(0,0)); } }
void CSpectator::OnRender() { if(!m_Active) { if(m_WasActive) { if(m_SelectedSpectatorID != NO_SELECTION) Spectate(m_SelectedSpectatorID); m_WasActive = false; } return; } if(!m_pClient->m_Snap.m_SpecInfo.m_Active && Client()->State() != IClient::STATE_DEMOPLAYBACK) { m_Active = false; m_WasActive = false; return; } m_WasActive = true; m_SelectedSpectatorID = NO_SELECTION; // draw background float Width = 400*3.0f*Graphics()->ScreenAspect(); float Height = 400*3.0f; float ObjWidth = 300.0f; float FontSize = 20.0f; float BigFontSize = 20.0f; float StartY = -190.0f; float LineHeight = 60.0f; float TeeSizeMod = 1.0f; float RoundRadius = 30.0f; bool Selected = false; int TotalPlayers = 0; int PerLine = 8; float BoxMove = -10.0f; for(int i = 0; i < MAX_CLIENTS; ++i) { if(!m_pClient->m_Snap.m_paInfoByDDTeam[i] || m_pClient->m_Snap.m_paInfoByDDTeam[i]->m_Team == TEAM_SPECTATORS) continue; ++TotalPlayers; } if (TotalPlayers > 32) { FontSize = 18.0f; LineHeight = 30.0f; TeeSizeMod = 0.7f; PerLine = 16; RoundRadius = 10.0f; BoxMove = 3.0f; } if (TotalPlayers > 16) { ObjWidth = 600.0f; } Graphics()->MapScreen(0, 0, Width, Height); Graphics()->BlendNormal(); Graphics()->TextureSet(-1); Graphics()->QuadsBegin(); Graphics()->SetColor(0.0f, 0.0f, 0.0f, 0.3f); RenderTools()->DrawRoundRect(Width/2.0f-ObjWidth, Height/2.0f-300.0f, ObjWidth*2, 600.0f, 20.0f); Graphics()->QuadsEnd(); // clamp mouse position to selector area m_SelectorMouse.x = clamp(m_SelectorMouse.x, -(ObjWidth - 20.0f), ObjWidth - 20.0f); m_SelectorMouse.y = clamp(m_SelectorMouse.y, -280.0f, 280.0f); // draw selections if((Client()->State() == IClient::STATE_DEMOPLAYBACK && m_pClient->m_DemoSpecID == SPEC_FREEVIEW) || m_pClient->m_Snap.m_SpecInfo.m_SpectatorID == SPEC_FREEVIEW) { Graphics()->TextureSet(-1); Graphics()->QuadsBegin(); Graphics()->SetColor(1.0f, 1.0f, 1.0f, 0.25f); RenderTools()->DrawRoundRect(Width/2.0f-(ObjWidth - 20.0f), Height/2.0f-280.0f, 270.0f, 60.0f, 20.0f); Graphics()->QuadsEnd(); } if(Client()->State() == IClient::STATE_DEMOPLAYBACK && m_pClient->m_DemoSpecID == SPEC_FOLLOW) { Graphics()->TextureSet(-1); Graphics()->QuadsBegin(); Graphics()->SetColor(1.0f, 1.0f, 1.0f, 0.25f); RenderTools()->DrawRoundRect(Width/2.0f-(ObjWidth - 310.0f), Height/2.0f-280.0f, 270.0f, 60.0f, 20.0f); Graphics()->QuadsEnd(); } if(m_SelectorMouse.x >= -(ObjWidth-20.0f) && m_SelectorMouse.x <= -(ObjWidth-290+10.0f) && m_SelectorMouse.y >= -280.0f && m_SelectorMouse.y <= -220.0f) { m_SelectedSpectatorID = SPEC_FREEVIEW; Selected = true; } TextRender()->TextColor(1.0f, 1.0f, 1.0f, Selected?1.0f:0.5f); TextRender()->Text(0, Width/2.0f-(ObjWidth-60.0f), Height/2.0f-280.f + (60.f - BigFontSize) / 2.f, BigFontSize, Localize("Free-View"), -1); if(Client()->State() == IClient::STATE_DEMOPLAYBACK) { Selected = false; if(m_SelectorMouse.x > -(ObjWidth-290.0f) && m_SelectorMouse.x <= -(ObjWidth-590.0f) && m_SelectorMouse.y >= -280.0f && m_SelectorMouse.y <= -220.0f) { m_SelectedSpectatorID = SPEC_FOLLOW; Selected = true; } TextRender()->TextColor(1.0f, 1.0f, 1.0f, Selected?1.0f:0.5f); TextRender()->Text(0, Width/2.0f-(ObjWidth-350.0f), Height/2.0f-280.0f + (60.f - BigFontSize) / 2.f, BigFontSize, Localize("Follow"), -1); } float x = -(ObjWidth - 30.0f), y = StartY; int OldDDTeam = -1; for(int i = 0, Count = 0; i < MAX_CLIENTS; ++i) { if(!m_pClient->m_Snap.m_paInfoByDDTeam[i] || m_pClient->m_Snap.m_paInfoByDDTeam[i]->m_Team == TEAM_SPECTATORS) continue; ++Count; if(Count == PerLine + 1 || (Count > PerLine + 1 && (Count-1)%PerLine == 0)) { x += 290.0f; y = StartY; } const CNetObj_PlayerInfo *pInfo = m_pClient->m_Snap.m_paInfoByDDTeam[i]; int DDTeam = m_pClient->m_Teams.Team(pInfo->m_ClientID); int NextDDTeam = 0; for(int j = i + 1; j < MAX_CLIENTS; j++) { const CNetObj_PlayerInfo *pInfo2 = m_pClient->m_Snap.m_paInfoByDDTeam[j]; if(!pInfo2 || pInfo2->m_Team == TEAM_SPECTATORS) continue; NextDDTeam = m_pClient->m_Teams.Team(pInfo2->m_ClientID); break; } if (OldDDTeam == -1) { for (int j = i - 1; j >= 0; j--) { const CNetObj_PlayerInfo *pInfo2 = m_pClient->m_Snap.m_paInfoByDDTeam[j]; if(!pInfo2 || pInfo2->m_Team == TEAM_SPECTATORS) continue; OldDDTeam = m_pClient->m_Teams.Team(pInfo2->m_ClientID); break; } } if (DDTeam != TEAM_FLOCK) { Graphics()->TextureSet(-1); Graphics()->QuadsBegin(); ColorRGBA rgb = color_cast<ColorRGBA>(ColorHSLA(DDTeam / 64.0f, 1.0f, 0.5f, 0.5f)); Graphics()->SetColor(rgb); int Corners = 0; if (OldDDTeam != DDTeam) Corners |= CUI::CORNER_TL | CUI::CORNER_TR; if (NextDDTeam != DDTeam) Corners |= CUI::CORNER_BL | CUI::CORNER_BR; RenderTools()->DrawRoundRectExt(Width/2.0f+x-10.0f, Height/2.0f+y+BoxMove, 270.0f, LineHeight, RoundRadius, Corners); Graphics()->QuadsEnd(); } OldDDTeam = DDTeam; if((Client()->State() == IClient::STATE_DEMOPLAYBACK && m_pClient->m_DemoSpecID == m_pClient->m_Snap.m_paInfoByDDTeam[i]->m_ClientID) || (Client()->State() != IClient::STATE_DEMOPLAYBACK && m_pClient ->m_Snap.m_SpecInfo.m_SpectatorID == m_pClient->m_Snap.m_paInfoByDDTeam[i]->m_ClientID)) { Graphics()->TextureSet(-1); Graphics()->QuadsBegin(); Graphics()->SetColor(1.0f, 1.0f, 1.0f, 0.25f); RenderTools()->DrawRoundRect(Width/2.0f+x-10.0f, Height/2.0f+y+BoxMove, 270.0f, LineHeight, RoundRadius); Graphics()->QuadsEnd(); } Selected = false; if(m_SelectorMouse.x >= x-10.0f && m_SelectorMouse.x < x+260.0f && m_SelectorMouse.y >= y-(LineHeight/6.0f) && m_SelectorMouse.y < y+(LineHeight*5.0f/6.0f)) { m_SelectedSpectatorID = m_pClient->m_Snap.m_paInfoByDDTeam[i]->m_ClientID; Selected = true; } float TeeAlpha; if(Client()->State() == IClient::STATE_DEMOPLAYBACK && !m_pClient->m_Snap.m_aCharacters[m_pClient->m_Snap.m_paInfoByDDTeam[i]->m_ClientID].m_Active) { TextRender()->TextColor(1.0f, 1.0f, 1.0f, 0.25f); TeeAlpha = 0.5f; } else { TextRender()->TextColor(1.0f, 1.0f, 1.0f, Selected?1.0f:0.5f); TeeAlpha = 1.0f; } TextRender()->Text(0, Width/2.0f+x+50.0f, Height / 2.0f + y + BoxMove + (LineHeight - FontSize) / 2.f, FontSize, m_pClient->m_aClients[m_pClient->m_Snap.m_paInfoByDDTeam[i]->m_ClientID].m_aName, 220.0f); // flag if(m_pClient->m_Snap.m_pGameInfoObj->m_GameFlags&GAMEFLAG_FLAGS && m_pClient->m_Snap.m_pGameDataObj && (m_pClient->m_Snap.m_pGameDataObj->m_FlagCarrierRed == m_pClient->m_Snap.m_paInfoByDDTeam[i]->m_ClientID || m_pClient->m_Snap.m_pGameDataObj->m_FlagCarrierBlue == m_pClient->m_Snap.m_paInfoByDDTeam[i]->m_ClientID)) { Graphics()->BlendNormal(); Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id); Graphics()->QuadsBegin(); RenderTools()->SelectSprite(m_pClient->m_Snap.m_paInfoByDDTeam[i]->m_Team==TEAM_RED ? SPRITE_FLAG_BLUE : SPRITE_FLAG_RED, SPRITE_FLAG_FLIP_X); float Size = LineHeight; IGraphics::CQuadItem QuadItem(Width/2.0f+x-LineHeight/5.0f, Height/2.0f+y-LineHeight/3.0f, Size/2.0f, Size); Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); } CTeeRenderInfo TeeInfo = m_pClient->m_aClients[m_pClient->m_Snap.m_paInfoByDDTeam[i]->m_ClientID].m_RenderInfo; TeeInfo.m_Size *= TeeSizeMod; RenderTools()->RenderTee(CAnimState::GetIdle(), &TeeInfo, EMOTE_NORMAL, vec2(1.0f, 0.0f), vec2(Width/2.0f+x+20.0f, Height/2.0f+y+20.0f), TeeAlpha); y += LineHeight; } TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); // draw cursor Graphics()->TextureSet(g_pData->m_aImages[IMAGE_CURSOR].m_Id); Graphics()->QuadsBegin(); Graphics()->SetColor(1.0f, 1.0f, 1.0f, 1.0f); IGraphics::CQuadItem QuadItem(m_SelectorMouse.x+Width/2.0f, m_SelectorMouse.y+Height/2.0f, 48.0f, 48.0f); Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); }
void CGameClient::SendKill(int ClientId) { CNetMsg_Cl_Kill Msg; Client()->SendPackMsg(&Msg, MSGFLAG_VITAL); }
TEST_F(DiscoveringResourcesTestFixtures, findResourceAfterInit){ Client c2 = Client(); EXPECT_FALSE(c2.hasResourceDiscovered(ls->getResourceURI())); }
void CGameConsole::OnRender() { CUIRect Screen = *UI()->Screen(); float ConsoleMaxHeight = Screen.h*3/5.0f; float ConsoleHeight; float Progress = (TimeNow()-(m_StateChangeEnd-m_StateChangeDuration))/float(m_StateChangeDuration); if (Progress >= 1.0f) { if (m_ConsoleState == CONSOLE_CLOSING) m_ConsoleState = CONSOLE_CLOSED; else if (m_ConsoleState == CONSOLE_OPENING) m_ConsoleState = CONSOLE_OPEN; Progress = 1.0f; } if (m_ConsoleState == CONSOLE_OPEN && g_Config.m_ClEditor) Toggle(CONSOLETYPE_LOCAL); if (m_ConsoleState == CONSOLE_CLOSED) return; if (m_ConsoleState == CONSOLE_OPEN) Input()->MouseModeAbsolute(); float ConsoleHeightScale; if (m_ConsoleState == CONSOLE_OPENING) ConsoleHeightScale = ConsoleScaleFunc(Progress); else if (m_ConsoleState == CONSOLE_CLOSING) ConsoleHeightScale = ConsoleScaleFunc(1.0f-Progress); else //if (console_state == CONSOLE_OPEN) ConsoleHeightScale = ConsoleScaleFunc(1.0f); ConsoleHeight = ConsoleHeightScale*ConsoleMaxHeight; Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h); // do console shadow Graphics()->TextureSet(-1); Graphics()->QuadsBegin(); IGraphics::CColorVertex Array[4] = { IGraphics::CColorVertex(0, 0,0,0, 0.5f), IGraphics::CColorVertex(1, 0,0,0, 0.5f), IGraphics::CColorVertex(2, 0,0,0, 0.0f), IGraphics::CColorVertex(3, 0,0,0, 0.0f)}; Graphics()->SetColorVertex(Array, 4); IGraphics::CQuadItem QuadItem(0, ConsoleHeight, Screen.w, 10.0f); Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); // do background Graphics()->TextureSet(g_pData->m_aImages[IMAGE_CONSOLE_BG].m_Id); Graphics()->QuadsBegin(); Graphics()->SetColor(0.2f, 0.2f, 0.2f,0.9f); if(m_ConsoleType == CONSOLETYPE_REMOTE) Graphics()->SetColor(0.4f, 0.2f, 0.2f,0.9f); Graphics()->QuadsSetSubset(0,-ConsoleHeight*0.075f,Screen.w*0.075f*0.5f,0); QuadItem = IGraphics::CQuadItem(0, 0, Screen.w, ConsoleHeight); Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); // do small bar shadow Graphics()->TextureSet(-1); Graphics()->QuadsBegin(); Array[0] = IGraphics::CColorVertex(0, 0,0,0, 0.0f); Array[1] = IGraphics::CColorVertex(1, 0,0,0, 0.0f); Array[2] = IGraphics::CColorVertex(2, 0,0,0, 0.25f); Array[3] = IGraphics::CColorVertex(3, 0,0,0, 0.25f); Graphics()->SetColorVertex(Array, 4); QuadItem = IGraphics::CQuadItem(0, ConsoleHeight-20, Screen.w, 10); Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); // do the lower bar Graphics()->TextureSet(g_pData->m_aImages[IMAGE_CONSOLE_BAR].m_Id); Graphics()->QuadsBegin(); Graphics()->SetColor(1.0f, 1.0f, 1.0f, 0.9f); Graphics()->QuadsSetSubset(0,0.1f,Screen.w*0.015f,1-0.1f); QuadItem = IGraphics::CQuadItem(0,ConsoleHeight-10.0f,Screen.w,10.0f); Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); ConsoleHeight -= 22.0f; CInstance *pConsole = CurrentConsole(); { float FontSize = 10.0f; float RowHeight = FontSize*1.25f; float x = 3; float y = ConsoleHeight - RowHeight - 5.0f; CRenderInfo Info; Info.m_pSelf = this; Info.m_WantedCompletion = pConsole->m_CompletionChosen; Info.m_EnumCount = 0; Info.m_Offset = pConsole->m_CompletionRenderOffset; Info.m_Width = Screen.w; Info.m_pCurrentCmd = pConsole->m_aCompletionBuffer; TextRender()->SetCursor(&Info.m_Cursor, x+Info.m_Offset, y+RowHeight+2.0f, FontSize, TEXTFLAG_RENDER); // render prompt CTextCursor Cursor; TextRender()->SetCursor(&Cursor, x, y, FontSize, TEXTFLAG_RENDER); const char *pPrompt = "> "; if(m_ConsoleType == CONSOLETYPE_REMOTE) { if(Client()->State() == IClient::STATE_ONLINE) { if(Client()->RconAuthed()) pPrompt = "rcon> "; else pPrompt = "ENTER PASSWORD> "; } else pPrompt = "NOT CONNECTED> "; } TextRender()->TextEx(&Cursor, pPrompt, -1); x = Cursor.m_X; // render console input (wrap line) int Lines = TextRender()->TextLineCount(0, FontSize, pConsole->m_Input.GetString(), Screen.w - 10.0f - x); y -= (Lines - 1) * FontSize; TextRender()->SetCursor(&Cursor, x, y, FontSize, TEXTFLAG_RENDER); Cursor.m_LineWidth = Screen.w - 10.0f - x; //hide rcon password char aInputString[256]; str_copy(aInputString, pConsole->m_Input.GetString(), sizeof(aInputString)); if(m_ConsoleType == CONSOLETYPE_REMOTE && Client()->State() == IClient::STATE_ONLINE && !Client()->RconAuthed()) { for(int i = 0; i < pConsole->m_Input.GetLength(); ++i) aInputString[i] = '*'; } TextRender()->TextEx(&Cursor, aInputString, pConsole->m_Input.GetCursorOffset()); static float MarkerOffset = TextRender()->TextWidth(0, FontSize, "|", -1)/3; CTextCursor Marker = Cursor; Marker.m_X -= MarkerOffset; TextRender()->TextEx(&Marker, "|", -1); TextRender()->TextEx(&Cursor, aInputString+pConsole->m_Input.GetCursorOffset(), -1); // render possible commands if(m_ConsoleType == CONSOLETYPE_LOCAL || Client()->RconAuthed()) { if(pConsole->m_Input.GetString()[0] != 0) { m_pConsole->PossibleCommands(pConsole->m_aCompletionBuffer, pConsole->m_CompletionFlagmask, m_ConsoleType != CGameConsole::CONSOLETYPE_LOCAL && Client()->RconAuthed() && Client()->UseTempRconCommands(), PossibleCommandsRenderCallback, &Info); pConsole->m_CompletionRenderOffset = Info.m_Offset; if(Info.m_EnumCount <= 0) { if(pConsole->m_IsCommand) { char aBuf[512]; str_format(aBuf, sizeof(aBuf), "Help: %s ", pConsole->m_aCommandHelp); TextRender()->TextEx(&Info.m_Cursor, aBuf, -1); TextRender()->TextColor(0.75f, 0.75f, 0.75f, 1); str_format(aBuf, sizeof(aBuf), "Syntax: %s %s", pConsole->m_aCommandName, pConsole->m_aCommandParams); TextRender()->TextEx(&Info.m_Cursor, aBuf, -1); } } } } TextRender()->TextColor(1,1,1,1); // render log (actual page, wrap lines) CInstance::CBacklogEntry *pEntry = pConsole->m_Backlog.Last(); float OffsetY = 0.0f; float LineOffset = 1.0f; for(int Page = 0; Page <= pConsole->m_BacklogActPage; ++Page, OffsetY = 0.0f) { while(pEntry) { // get y offset (calculate it if we haven't yet) if(pEntry->m_YOffset < 0.0f) { TextRender()->SetCursor(&Cursor, 0.0f, 0.0f, FontSize, 0); Cursor.m_LineWidth = Screen.w-10; TextRender()->TextEx(&Cursor, pEntry->m_aText, -1); pEntry->m_YOffset = Cursor.m_Y+Cursor.m_FontSize+LineOffset; } OffsetY += pEntry->m_YOffset; // next page when lines reach the top if(y-OffsetY <= RowHeight) break; // just render output from actual backlog page (render bottom up) if(Page == pConsole->m_BacklogActPage) { TextRender()->SetCursor(&Cursor, 0.0f, y-OffsetY, FontSize, TEXTFLAG_RENDER); Cursor.m_LineWidth = Screen.w-10.0f; TextRender()->TextEx(&Cursor, pEntry->m_aText, -1); } pEntry = pConsole->m_Backlog.Prev(pEntry); } // actual backlog page number is too high, render last available page (current checked one, render top down) if(!pEntry && Page < pConsole->m_BacklogActPage) { pConsole->m_BacklogActPage = Page; pEntry = pConsole->m_Backlog.First(); while(OffsetY > 0.0f && pEntry) { TextRender()->SetCursor(&Cursor, 0.0f, y-OffsetY, FontSize, TEXTFLAG_RENDER); Cursor.m_LineWidth = Screen.w-10.0f; TextRender()->TextEx(&Cursor, pEntry->m_aText, -1); OffsetY -= pEntry->m_YOffset; pEntry = pConsole->m_Backlog.Next(pEntry); } break; } } // render page char aBuf[128]; str_format(aBuf, sizeof(aBuf), Localize("-Page %d-"), pConsole->m_BacklogActPage+1); TextRender()->Text(0, 10.0f, 0.0f, FontSize, aBuf, -1); // render version str_format(aBuf, sizeof(aBuf), "v%s", GAME_VERSION); float Width = TextRender()->TextWidth(0, FontSize, aBuf, -1); TextRender()->Text(0, Screen.w-Width-10.0f, 0.0f, FontSize, aBuf, -1); } }
void CGameClient::OnNewSnapshot() { // clear out the invalid pointers mem_zero(&m_Snap, sizeof(m_Snap)); // secure snapshot { int Num = Client()->SnapNumItems(IClient::SNAP_CURRENT); for(int Index = 0; Index < Num; Index++) { IClient::CSnapItem Item; const void *pData = Client()->SnapGetItem(IClient::SNAP_CURRENT, Index, &Item); if(m_NetObjHandler.ValidateObj(Item.m_Type, pData, Item.m_DataSize) != 0) { if(g_Config.m_Debug) { char aBuf[256]; str_format(aBuf, sizeof(aBuf), "invalidated index=%d type=%d (%s) size=%d id=%d", Index, Item.m_Type, m_NetObjHandler.GetObjName(Item.m_Type), Item.m_DataSize, Item.m_ID); Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf); } Client()->SnapInvalidateItem(IClient::SNAP_CURRENT, Index); } } } ProcessEvents(); if(g_Config.m_DbgStress) { if((Client()->GameTick()%100) == 0) { char aMessage[64]; int MsgLen = random_int()%(sizeof(aMessage)-1); for(int i = 0; i < MsgLen; i++) aMessage[i] = 'a'+(random_int()%('z'-'a')); aMessage[MsgLen] = 0; CNetMsg_Cl_Say Msg; Msg.m_Mode = random_int()&1; Msg.m_Target = -1; Msg.m_pMessage = aMessage; Client()->SendPackMsg(&Msg, MSGFLAG_VITAL); } } CTuningParams StandardTuning; if(Client()->State() == IClient::STATE_DEMOPLAYBACK) { m_Tuning = StandardTuning; mem_zero(&m_GameInfo, sizeof(m_GameInfo)); } // go trough all the items in the snapshot and gather the info we want { int Num = Client()->SnapNumItems(IClient::SNAP_CURRENT); for(int i = 0; i < Num; i++) { IClient::CSnapItem Item; const void *pData = Client()->SnapGetItem(IClient::SNAP_CURRENT, i, &Item); // demo items if(Client()->State() == IClient::STATE_DEMOPLAYBACK) { if(Item.m_Type == NETOBJTYPE_DE_CLIENTINFO) { const CNetObj_De_ClientInfo *pInfo = (const CNetObj_De_ClientInfo *)pData; int ClientID = Item.m_ID; CClientData *pClient = &m_aClients[ClientID]; if(pInfo->m_Local) m_LocalClientID = ClientID; pClient->m_Active = true; pClient->m_Team = pInfo->m_Team; IntsToStr(pInfo->m_aName, 4, pClient->m_aName); IntsToStr(pInfo->m_aClan, 3, pClient->m_aClan); pClient->m_Country = pInfo->m_Country; for(int p = 0; p < NUM_SKINPARTS; p++) { IntsToStr(pInfo->m_aaSkinPartNames[p], 6, pClient->m_aaSkinPartNames[p]); pClient->m_aUseCustomColors[p] = pInfo->m_aUseCustomColors[p]; pClient->m_aSkinPartColors[p] = pInfo->m_aSkinPartColors[p]; } m_GameInfo.m_NumPlayers++; // calculate team-balance if(pClient->m_Team != TEAM_SPECTATORS) m_GameInfo.m_aTeamSize[pClient->m_Team]++; } else if(Item.m_Type == NETOBJTYPE_DE_GAMEINFO) { const CNetObj_De_GameInfo *pInfo = (const CNetObj_De_GameInfo *)pData; m_GameInfo.m_GameFlags = pInfo->m_GameFlags; m_GameInfo.m_ScoreLimit = pInfo->m_ScoreLimit; m_GameInfo.m_TimeLimit = pInfo->m_TimeLimit; m_GameInfo.m_MatchNum = pInfo->m_MatchNum; m_GameInfo.m_MatchCurrent = pInfo->m_MatchCurrent; } else if(Item.m_Type == NETOBJTYPE_DE_TUNEPARAMS) { const CNetObj_De_TuneParams *pInfo = (const CNetObj_De_TuneParams *)pData; mem_copy(&m_Tuning, pInfo->m_aTuneParams, sizeof(m_Tuning)); m_ServerMode = SERVERMODE_PURE; } } // network items if(Item.m_Type == NETOBJTYPE_PLAYERINFO) { const CNetObj_PlayerInfo *pInfo = (const CNetObj_PlayerInfo *)pData; int ClientID = Item.m_ID; if(m_aClients[ClientID].m_Active) { m_Snap.m_paPlayerInfos[ClientID] = pInfo; m_Snap.m_aInfoByScore[ClientID].m_pPlayerInfo = pInfo; m_Snap.m_aInfoByScore[ClientID].m_ClientID = ClientID; if(m_LocalClientID == ClientID) { m_Snap.m_pLocalInfo = pInfo; if(m_aClients[ClientID].m_Team == TEAM_SPECTATORS) { m_Snap.m_SpecInfo.m_Active = true; m_Snap.m_SpecInfo.m_SpecMode = SPEC_FREEVIEW; m_Snap.m_SpecInfo.m_SpectatorID = -1; } } } } else if(Item.m_Type == NETOBJTYPE_CHARACTER) { const void *pOld = Client()->SnapFindItem(IClient::SNAP_PREV, NETOBJTYPE_CHARACTER, Item.m_ID); m_Snap.m_aCharacters[Item.m_ID].m_Cur = *((const CNetObj_Character *)pData); // clamp ammo count for non ninja weapon if(m_Snap.m_aCharacters[Item.m_ID].m_Cur.m_Weapon != WEAPON_NINJA) m_Snap.m_aCharacters[Item.m_ID].m_Cur.m_AmmoCount = clamp(m_Snap.m_aCharacters[Item.m_ID].m_Cur.m_AmmoCount, 0, 10); if(pOld) { m_Snap.m_aCharacters[Item.m_ID].m_Active = true; m_Snap.m_aCharacters[Item.m_ID].m_Prev = *((const CNetObj_Character *)pOld); if(m_Snap.m_aCharacters[Item.m_ID].m_Prev.m_Tick) EvolveCharacter(&m_Snap.m_aCharacters[Item.m_ID].m_Prev, Client()->PrevGameTick()); if(m_Snap.m_aCharacters[Item.m_ID].m_Cur.m_Tick) EvolveCharacter(&m_Snap.m_aCharacters[Item.m_ID].m_Cur, Client()->GameTick()); } if(Item.m_ID != m_LocalClientID || Client()->State() == IClient::STATE_DEMOPLAYBACK) ProcessTriggeredEvents(m_Snap.m_aCharacters[Item.m_ID].m_Cur.m_TriggeredEvents, vec2(m_Snap.m_aCharacters[Item.m_ID].m_Cur.m_X, m_Snap.m_aCharacters[Item.m_ID].m_Cur.m_Y)); } else if(Item.m_Type == NETOBJTYPE_SPECTATORINFO) { m_Snap.m_pSpectatorInfo = (const CNetObj_SpectatorInfo *)pData; m_Snap.m_pPrevSpectatorInfo = (const CNetObj_SpectatorInfo *)Client()->SnapFindItem(IClient::SNAP_PREV, NETOBJTYPE_SPECTATORINFO, Item.m_ID); m_Snap.m_SpecInfo.m_Active = true; m_Snap.m_SpecInfo.m_SpecMode = m_Snap.m_pSpectatorInfo->m_SpecMode; m_Snap.m_SpecInfo.m_SpectatorID = m_Snap.m_pSpectatorInfo->m_SpectatorID; } else if(Item.m_Type == NETOBJTYPE_GAMEDATA) { m_Snap.m_pGameData = (const CNetObj_GameData *)pData; static bool s_GameOver = 0; if(!s_GameOver && m_Snap.m_pGameData->m_GameStateFlags&GAMESTATEFLAG_GAMEOVER) OnGameOver(); else if(s_GameOver && !(m_Snap.m_pGameData->m_GameStateFlags&GAMESTATEFLAG_GAMEOVER)) OnStartGame(); s_GameOver = m_Snap.m_pGameData->m_GameStateFlags&GAMESTATEFLAG_GAMEOVER; } else if(Item.m_Type == NETOBJTYPE_GAMEDATATEAM) { m_Snap.m_pGameDataTeam = (const CNetObj_GameDataTeam *)pData; } else if(Item.m_Type == NETOBJTYPE_GAMEDATAFLAG) { m_Snap.m_pGameDataFlag = (const CNetObj_GameDataFlag *)pData; m_Snap.m_GameDataFlagSnapID = Item.m_ID; } else if(Item.m_Type == NETOBJTYPE_FLAG) m_Snap.m_paFlags[Item.m_ID%2] = (const CNetObj_Flag *)pData; } } // setup local pointers if(m_LocalClientID >= 0) { CSnapState::CCharacterInfo *c = &m_Snap.m_aCharacters[m_LocalClientID]; if(c->m_Active) { m_Snap.m_pLocalCharacter = &c->m_Cur; m_Snap.m_pLocalPrevCharacter = &c->m_Prev; m_LocalCharacterPos = vec2(m_Snap.m_pLocalCharacter->m_X, m_Snap.m_pLocalCharacter->m_Y); } else if(Client()->SnapFindItem(IClient::SNAP_PREV, NETOBJTYPE_CHARACTER, m_LocalClientID)) { // player died m_pControls->OnPlayerDeath(); } } else { m_Snap.m_SpecInfo.m_Active = true; if(Client()->State() == IClient::STATE_DEMOPLAYBACK && DemoPlayer()->GetDemoType() == IDemoPlayer::DEMOTYPE_SERVER && m_DemoSpecID != -1 && m_Snap.m_aCharacters[m_DemoSpecID].m_Active) { m_Snap.m_SpecInfo.m_SpecMode = SPEC_PLAYER; m_Snap.m_SpecInfo.m_SpectatorID = m_DemoSpecID; } else { if (m_DemoSpecMode == SPEC_PLAYER) { m_Snap.m_SpecInfo.m_SpecMode = SPEC_FREEVIEW; m_Snap.m_SpecInfo.m_SpectatorID = -1; } else { m_Snap.m_SpecInfo.m_SpecMode = m_DemoSpecMode; m_Snap.m_SpecInfo.m_SpectatorID = m_DemoSpecID; } } } // sort player infos by score for(int k = 0; k < MAX_CLIENTS-1; k++) // ffs, bubblesort { for(int i = 0; i < MAX_CLIENTS-k-1; i++) { if(m_Snap.m_aInfoByScore[i+1].m_pPlayerInfo && (!m_Snap.m_aInfoByScore[i].m_pPlayerInfo || m_Snap.m_aInfoByScore[i].m_pPlayerInfo->m_Score < m_Snap.m_aInfoByScore[i+1].m_pPlayerInfo->m_Score)) { CPlayerInfoItem Tmp = m_Snap.m_aInfoByScore[i]; m_Snap.m_aInfoByScore[i] = m_Snap.m_aInfoByScore[i+1]; m_Snap.m_aInfoByScore[i+1] = Tmp; } } } // calc some player stats for(int i = 0; i < MAX_CLIENTS; ++i) { if(!m_Snap.m_paPlayerInfos[i]) continue; // count not ready players if((m_Snap.m_pGameData->m_GameStateFlags&(GAMESTATEFLAG_STARTCOUNTDOWN|GAMESTATEFLAG_PAUSED|GAMESTATEFLAG_WARMUP)) && m_Snap.m_pGameData->m_GameStateEndTick == 0 && m_aClients[i].m_Team != TEAM_SPECTATORS && !(m_Snap.m_paPlayerInfos[i]->m_PlayerFlags&PLAYERFLAG_READY)) m_Snap.m_NotReadyCount++; // count alive players per team if((m_GameInfo.m_GameFlags&GAMEFLAG_SURVIVAL) && m_aClients[i].m_Team != TEAM_SPECTATORS && !(m_Snap.m_paPlayerInfos[i]->m_PlayerFlags&PLAYERFLAG_DEAD)) m_Snap.m_AliveCount[m_aClients[i].m_Team]++; } if(Client()->State() == IClient::STATE_DEMOPLAYBACK) { for(int i = 0; i < MAX_CLIENTS; ++i) { if(m_aClients[i].m_Active) m_aClients[i].UpdateRenderInfo(this, true); } } CServerInfo CurrentServerInfo; Client()->GetServerInfo(&CurrentServerInfo); if(str_comp(CurrentServerInfo.m_aGameType, "DM") != 0 && str_comp(CurrentServerInfo.m_aGameType, "TDM") != 0 && str_comp(CurrentServerInfo.m_aGameType, "CTF") != 0 && str_comp(CurrentServerInfo.m_aGameType, "LMS") != 0 && str_comp(CurrentServerInfo.m_aGameType, "SUR") != 0) m_ServerMode = SERVERMODE_MOD; else if(mem_comp(&StandardTuning, &m_Tuning, sizeof(CTuningParams)) == 0) m_ServerMode = SERVERMODE_PURE; else m_ServerMode = SERVERMODE_PUREMOD; }
void CHud::RenderHealthAndAmmo(const CNetObj_Character *pCharacter) { if(!pCharacter) return; float x = 5; float y = 5; int i; IGraphics::CQuadItem Array[10]; Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id); Graphics()->WrapClamp(); Graphics()->QuadsBegin(); Graphics()->SetColor(1.0f, 1.0f, 1.0f, 1.0f); // render ammo if(pCharacter->m_Weapon == WEAPON_NINJA) { const int Max = g_pData->m_Weapons.m_Ninja.m_Duration * Client()->GameTickSpeed() / 1000; float NinjaProgress = clamp(pCharacter->m_AmmoCount-Client()->GameTick(), 0, Max) / (float)Max; RenderNinjaBar(x, y+24.f, NinjaProgress); } else { RenderTools()->SelectSprite(g_pData->m_Weapons.m_aId[pCharacter->m_Weapon%NUM_WEAPONS].m_pSpriteProj); if(pCharacter->m_Weapon == WEAPON_GRENADE) { for(i = 0; i < min(pCharacter->m_AmmoCount, 10); i++) Array[i] = IGraphics::CQuadItem(x+1+i*12, y+24, 10, 10); } else { for(i = 0; i < min(pCharacter->m_AmmoCount, 10); i++) Array[i] = IGraphics::CQuadItem(x+i*12, y+24, 12, 12); } Graphics()->QuadsDrawTL(Array, i); } int h = 0; // render health RenderTools()->SelectSprite(SPRITE_HEALTH_FULL); for(; h < min(pCharacter->m_Health, 10); h++) Array[h] = IGraphics::CQuadItem(x+h*12,y,12,12); Graphics()->QuadsDrawTL(Array, h); i = 0; RenderTools()->SelectSprite(SPRITE_HEALTH_EMPTY); for(; h < 10; h++) Array[i++] = IGraphics::CQuadItem(x+h*12,y,12,12); Graphics()->QuadsDrawTL(Array, i); // render armor meter h = 0; RenderTools()->SelectSprite(SPRITE_ARMOR_FULL); for(; h < min(pCharacter->m_Armor, 10); h++) Array[h] = IGraphics::CQuadItem(x+h*12,y+12,12,12); Graphics()->QuadsDrawTL(Array, h); i = 0; RenderTools()->SelectSprite(SPRITE_ARMOR_EMPTY); for(; h < 10; h++) Array[i++] = IGraphics::CQuadItem(x+h*12,y+12,12,12); Graphics()->QuadsDrawTL(Array, i); Graphics()->QuadsEnd(); Graphics()->WrapNormal(); }
void CGameClient::OnGameOver() { if(Client()->State() != IClient::STATE_DEMOPLAYBACK) Client()->AutoScreenshot_Start(); }
void CHud::RenderPauseTimer() { if((m_pClient->m_Snap.m_pGameData->m_GameStateFlags&(GAMESTATEFLAG_STARTCOUNTDOWN|GAMESTATEFLAG_PAUSED)) == GAMESTATEFLAG_PAUSED) { char aBuf[256]; const char *pText = Localize("Game paused"); float FontSize = 20.0f; float w = TextRender()->TextWidth(0, FontSize, pText, -1, -1.0f); TextRender()->Text(0, 150*Graphics()->ScreenAspect()+-w/2, 50, FontSize, pText, -1.0f); FontSize = 16.0f; if(m_pClient->m_Snap.m_pGameData->m_GameStateEndTick == 0) { if(m_pClient->m_Snap.m_NotReadyCount == 1) str_format(aBuf, sizeof(aBuf), Localize("%d player not ready"), m_pClient->m_Snap.m_NotReadyCount); else if(m_pClient->m_Snap.m_NotReadyCount > 1) str_format(aBuf, sizeof(aBuf), Localize("%d players not ready"), m_pClient->m_Snap.m_NotReadyCount); else return; RenderReadyUpNotification(); } else { float Seconds = static_cast<float>(m_pClient->m_Snap.m_pGameData->m_GameStateEndTick-Client()->GameTick())/SERVER_TICK_SPEED; if(Seconds < 5) str_format(aBuf, sizeof(aBuf), "%.1f", Seconds); else str_format(aBuf, sizeof(aBuf), "%d", round_to_int(Seconds)); } w = TextRender()->TextWidth(0, FontSize, aBuf, -1, -1.0f); TextRender()->Text(0, 150*Graphics()->ScreenAspect()+-w/2, 75, FontSize, aBuf, -1.0f); } }
void CGameClient::OnStartGame() { if(Client()->State() != IClient::STATE_DEMOPLAYBACK) Client()->DemoRecorder_HandleAutoStart(); }
void GWindow::Pour() { GRegion Client(GetClient()); GRegion Update; bool HasTools = false; GViewI *v; { GRegion Tools; for (v = Children.First(); v; v = Children.Next()) { GView *k = dynamic_cast<GView*>(v); if (k && k->_IsToolBar) { GRect OldPos = v->GetPos(); Update.Union(&OldPos); if (HasTools) { // 2nd and later toolbars if (v->Pour(Tools)) { if (!v->Visible()) { v->Visible(true); } if (OldPos != v->GetPos()) { // position has changed update... v->Invalidate(); } Tools.Subtract(&v->GetPos()); Update.Subtract(&v->GetPos()); } } else { // First toolbar if (v->Pour(Client)) { HasTools = true; if (!v->Visible()) { v->Visible(true); } if (OldPos != v->GetPos()) { v->Invalidate(); } GRect Bar(v->GetPos()); Bar.x2 = GetClient().x2; Tools = Bar; Tools.Subtract(&v->GetPos()); Client.Subtract(&Bar); Update.Subtract(&Bar); } } } } } for (v = Children.First(); v; v = Children.Next()) { GView *k = dynamic_cast<GView*>(v); if (!(k && k->_IsToolBar)) { GRect OldPos = v->GetPos(); Update.Union(&OldPos); if (v->Pour(Client)) { if (!v->Visible()) { v->Visible(true); } if (OldPos != v->GetPos()) { // position has changed update... v->Invalidate(); } Client.Subtract(&v->GetPos()); Update.Subtract(&v->GetPos()); } else { // make the view not visible // v->Visible(FALSE); } } } for (int i=0; i<Update.Length(); i++) { Invalidate(Update[i]); } }
void CGameClient::OnNewSnapshot() { m_NewTick = true; // clear out the invalid pointers mem_zero(&g_GameClient.m_Snap, sizeof(g_GameClient.m_Snap)); m_Snap.m_LocalCid = -1; // secure snapshot { int Num = Client()->SnapNumItems(IClient::SNAP_CURRENT); for(int Index = 0; Index < Num; Index++) { IClient::CSnapItem Item; void *pData = Client()->SnapGetItem(IClient::SNAP_CURRENT, Index, &Item); if(m_NetObjHandler.ValidateObj(Item.m_Type, pData, Item.m_DataSize) != 0) { if(g_Config.m_Debug) { char aBuf[256]; str_format(aBuf, sizeof(aBuf), "invalidated index=%d type=%d (%s) size=%d id=%d", Index, Item.m_Type, m_NetObjHandler.GetObjName(Item.m_Type), Item.m_DataSize, Item.m_Id); Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf); } Client()->SnapInvalidateItem(IClient::SNAP_CURRENT, Index); } } } ProcessEvents(); if(g_Config.m_DbgStress) { if((Client()->GameTick()%100) == 0) { char aMessage[64]; int MsgLen = rand()%(sizeof(aMessage)-1); for(int i = 0; i < MsgLen; i++) aMessage[i] = 'a'+(rand()%('z'-'a')); aMessage[MsgLen] = 0; CNetMsg_Cl_Say Msg; Msg.m_Team = rand()&1; Msg.m_pMessage = aMessage; Client()->SendPackMsg(&Msg, MSGFLAG_VITAL); } } // go trough all the items in the snapshot and gather the info we want { m_Snap.m_aTeamSize[TEAM_RED] = m_Snap.m_aTeamSize[TEAM_BLUE] = 0; int Num = Client()->SnapNumItems(IClient::SNAP_CURRENT); for(int i = 0; i < Num; i++) { IClient::CSnapItem Item; const void *pData = Client()->SnapGetItem(IClient::SNAP_CURRENT, i, &Item); if(Item.m_Type == NETOBJTYPE_CLIENTINFO) { const CNetObj_ClientInfo *pInfo = (const CNetObj_ClientInfo *)pData; int Cid = Item.m_Id; IntsToStr(&pInfo->m_Name0, 6, m_aClients[Cid].m_aName); IntsToStr(&pInfo->m_Skin0, 6, m_aClients[Cid].m_aSkinName); m_aClients[Cid].m_UseCustomColor = pInfo->m_UseCustomColor; m_aClients[Cid].m_ColorBody = pInfo->m_ColorBody; m_aClients[Cid].m_ColorFeet = pInfo->m_ColorFeet; // prepare the info if(m_aClients[Cid].m_aSkinName[0] == 'x' || m_aClients[Cid].m_aSkinName[1] == '_') str_copy(m_aClients[Cid].m_aSkinName, "default", 64); m_aClients[Cid].m_SkinInfo.m_ColorBody = m_pSkins->GetColorV4(m_aClients[Cid].m_ColorBody); m_aClients[Cid].m_SkinInfo.m_ColorFeet = m_pSkins->GetColorV4(m_aClients[Cid].m_ColorFeet); m_aClients[Cid].m_SkinInfo.m_Size = 64; // find new skin m_aClients[Cid].m_SkinId = g_GameClient.m_pSkins->Find(m_aClients[Cid].m_aSkinName); if(m_aClients[Cid].m_SkinId < 0) { m_aClients[Cid].m_SkinId = g_GameClient.m_pSkins->Find("default"); if(m_aClients[Cid].m_SkinId < 0) m_aClients[Cid].m_SkinId = 0; } if(m_aClients[Cid].m_UseCustomColor) m_aClients[Cid].m_SkinInfo.m_Texture = g_GameClient.m_pSkins->Get(m_aClients[Cid].m_SkinId)->m_ColorTexture; else { m_aClients[Cid].m_SkinInfo.m_Texture = g_GameClient.m_pSkins->Get(m_aClients[Cid].m_SkinId)->m_OrgTexture; m_aClients[Cid].m_SkinInfo.m_ColorBody = vec4(1,1,1,1); m_aClients[Cid].m_SkinInfo.m_ColorFeet = vec4(1,1,1,1); } m_aClients[Cid].UpdateRenderInfo(); g_GameClient.m_Snap.m_NumPlayers++; } else if(Item.m_Type == NETOBJTYPE_PLAYERINFO) { const CNetObj_PlayerInfo *pInfo = (const CNetObj_PlayerInfo *)pData; m_aClients[pInfo->m_ClientId].m_Team = pInfo->m_Team; m_Snap.m_paPlayerInfos[pInfo->m_ClientId] = pInfo; if(pInfo->m_Local) { m_Snap.m_LocalCid = Item.m_Id; m_Snap.m_pLocalInfo = pInfo; if(pInfo->m_Team == TEAM_SPECTATORS) m_Snap.m_Spectate = true; } // calculate team-balance if(pInfo->m_Team != TEAM_SPECTATORS) m_Snap.m_aTeamSize[pInfo->m_Team]++; } else if(Item.m_Type == NETOBJTYPE_CHARACTER) { const void *pOld = Client()->SnapFindItem(IClient::SNAP_PREV, NETOBJTYPE_CHARACTER, Item.m_Id); if(pOld) { m_Snap.m_aCharacters[Item.m_Id].m_Active = true; m_Snap.m_aCharacters[Item.m_Id].m_Prev = *((const CNetObj_Character *)pOld); m_Snap.m_aCharacters[Item.m_Id].m_Cur = *((const CNetObj_Character *)pData); if(m_Snap.m_aCharacters[Item.m_Id].m_Prev.m_Tick) Evolve(&m_Snap.m_aCharacters[Item.m_Id].m_Prev, Client()->PrevGameTick()); if(m_Snap.m_aCharacters[Item.m_Id].m_Cur.m_Tick) Evolve(&m_Snap.m_aCharacters[Item.m_Id].m_Cur, Client()->GameTick()); } } else if(Item.m_Type == NETOBJTYPE_GAME) { static int s_GameOver = 0; m_Snap.m_pGameobj = (CNetObj_Game *)pData; if(s_GameOver == 0 && m_Snap.m_pGameobj->m_GameOver != 0) OnGameOver(); else if(s_GameOver != 0 && m_Snap.m_pGameobj->m_GameOver == 0) OnStartGame(); s_GameOver = m_Snap.m_pGameobj->m_GameOver; } else if(Item.m_Type == NETOBJTYPE_FLAG) m_Snap.m_paFlags[Item.m_Id%2] = (const CNetObj_Flag *)pData; } } // setup local pointers if(m_Snap.m_LocalCid >= 0) { CSnapState::CCharacterInfo *c = &m_Snap.m_aCharacters[m_Snap.m_LocalCid]; if(c->m_Active) { m_Snap.m_pLocalCharacter = &c->m_Cur; m_Snap.m_pLocalPrevCharacter = &c->m_Prev; m_LocalCharacterPos = vec2(m_Snap.m_pLocalCharacter->m_X, m_Snap.m_pLocalCharacter->m_Y); } else if(Client()->SnapFindItem(IClient::SNAP_PREV, NETOBJTYPE_CHARACTER, m_Snap.m_LocalCid)) { // player died m_pControls->OnPlayerDeath(); } } else m_Snap.m_Spectate = true; CTuningParams StandardTuning; CServerInfo CurrentServerInfo; Client()->GetServerInfo(&CurrentServerInfo); if(CurrentServerInfo.m_aGameType[0] != '0') { if(str_comp(CurrentServerInfo.m_aGameType, "DM") != 0 && str_comp(CurrentServerInfo.m_aGameType, "TDM") != 0 && str_comp(CurrentServerInfo.m_aGameType, "CTF") != 0) m_ServerMode = SERVERMODE_MOD; else if(mem_comp(&StandardTuning, &m_Tuning, sizeof(CTuningParams)) == 0) m_ServerMode = SERVERMODE_PURE; else m_ServerMode = SERVERMODE_PUREMOD; } }
int main( int argc, char ** argv ) { NETRESOURCE nr = {0}; DWORD dwRetVal = 0; int c = 0; char host[32] = {0}; LOGINFO LogInfo = {0}; while ( ( c = getopt( argc, argv, "h:u:p:e:") ) != -1 ) { switch ( c ) { // 目标ip case 'h': strncpy( host, optarg, 32 ); break; // 用户名 case 'u': strncpy( LogInfo.szUserName, optarg, NAME_LEN ); break; // 密码 case 'p': strncpy( LogInfo.szPassword, optarg, PASSWD_LEN ); break; // cmd case 'e': strncpy( LogInfo.szExcuteCmd, optarg, CMD_LEN ); break; default: break; } } char szRemoteName[MAX_PATH] = {0}; if ( host[0] ) sprintf( szRemoteName, "\\\\%s\\%s", host, ADMIN ); else usage(); if ( !LogInfo.szUserName[0] || !LogInfo.szPassword[0] ) usage(); nr.dwType = RESOURCETYPE_ANY; nr.lpLocalName = NULL; nr.lpRemoteName = szRemoteName; nr.lpProvider = NULL; dwRetVal = WNetAddConnection3( NULL, &nr, LogInfo.szPassword, LogInfo.szUserName, 0 ); if ( dwRetVal != NO_ERROR ) { int a = GetLastError(); return -1; } InstallRemoteService( host ); Client( host, &LogInfo ); WNetCancelConnection( nr.lpRemoteName, TRUE ); return 0; }
void CGameClient::OnPredict() { // store the previous values so we can detect prediction errors CCharacterCore BeforePrevChar = m_PredictedPrevChar; CCharacterCore BeforeChar = m_PredictedChar; // we can't predict without our own id or own character if(m_Snap.m_LocalCid == -1 || !m_Snap.m_aCharacters[m_Snap.m_LocalCid].m_Active) return; // don't predict anything if we are paused if(m_Snap.m_pGameobj && m_Snap.m_pGameobj->m_Paused) { if(m_Snap.m_pLocalCharacter) m_PredictedChar.Read(m_Snap.m_pLocalCharacter); if(m_Snap.m_pLocalPrevCharacter) m_PredictedPrevChar.Read(m_Snap.m_pLocalPrevCharacter); return; } // repredict character CWorldCore World; World.m_Tuning = m_Tuning; // search for players for(int i = 0; i < MAX_CLIENTS; i++) { if(!m_Snap.m_aCharacters[i].m_Active) continue; g_GameClient.m_aClients[i].m_Predicted.Init(&World, Collision()); World.m_apCharacters[i] = &g_GameClient.m_aClients[i].m_Predicted; g_GameClient.m_aClients[i].m_Predicted.Read(&m_Snap.m_aCharacters[i].m_Cur); } // predict for(int Tick = Client()->GameTick()+1; Tick <= Client()->PredGameTick(); Tick++) { // fetch the local if(Tick == Client()->PredGameTick() && World.m_apCharacters[m_Snap.m_LocalCid]) m_PredictedPrevChar = *World.m_apCharacters[m_Snap.m_LocalCid]; // first calculate where everyone should move for(int c = 0; c < MAX_CLIENTS; c++) { if(!World.m_apCharacters[c]) continue; mem_zero(&World.m_apCharacters[c]->m_Input, sizeof(World.m_apCharacters[c]->m_Input)); if(m_Snap.m_LocalCid == c) { // apply player input int *pInput = Client()->GetInput(Tick); if(pInput) World.m_apCharacters[c]->m_Input = *((CNetObj_PlayerInput*)pInput); World.m_apCharacters[c]->Tick(true); } else World.m_apCharacters[c]->Tick(false); } // move all players and quantize their data for(int c = 0; c < MAX_CLIENTS; c++) { if(!World.m_apCharacters[c]) continue; World.m_apCharacters[c]->Move(); World.m_apCharacters[c]->Quantize(); } // check if we want to trigger effects if(Tick > m_LastNewPredictedTick) { m_LastNewPredictedTick = Tick; m_NewPredictedTick = true; if(m_Snap.m_LocalCid != -1 && World.m_apCharacters[m_Snap.m_LocalCid]) { vec2 Pos = World.m_apCharacters[m_Snap.m_LocalCid]->m_Pos; int Events = World.m_apCharacters[m_Snap.m_LocalCid]->m_TriggeredEvents; if(Events&COREEVENT_GROUND_JUMP) g_GameClient.m_pSounds->PlayAndRecord(CSounds::CHN_WORLD, SOUND_PLAYER_JUMP, 1.0f, Pos); /*if(events&COREEVENT_AIR_JUMP) { GameClient.effects->air_jump(pos); GameClient.sounds->play_and_record(SOUNDS::CHN_WORLD, SOUND_PLAYER_AIRJUMP, 1.0f, pos); }*/ //if(events&COREEVENT_HOOK_LAUNCH) snd_play_random(CHN_WORLD, SOUND_HOOK_LOOP, 1.0f, pos); //if(events&COREEVENT_HOOK_ATTACH_PLAYER) snd_play_random(CHN_WORLD, SOUND_HOOK_ATTACH_PLAYER, 1.0f, pos); if(Events&COREEVENT_HOOK_ATTACH_GROUND) g_GameClient.m_pSounds->PlayAndRecord(CSounds::CHN_WORLD, SOUND_HOOK_ATTACH_GROUND, 1.0f, Pos); if(Events&COREEVENT_HOOK_HIT_NOHOOK) g_GameClient.m_pSounds->PlayAndRecord(CSounds::CHN_WORLD, SOUND_HOOK_NOATTACH, 1.0f, Pos); //if(events&COREEVENT_HOOK_RETRACT) snd_play_random(CHN_WORLD, SOUND_PLAYER_JUMP, 1.0f, pos); } } if(Tick == Client()->PredGameTick() && World.m_apCharacters[m_Snap.m_LocalCid]) m_PredictedChar = *World.m_apCharacters[m_Snap.m_LocalCid]; } if(g_Config.m_Debug && g_Config.m_ClPredict && m_PredictedTick == Client()->PredGameTick()) { CNetObj_CharacterCore Before = {0}, Now = {0}, BeforePrev = {0}, NowPrev = {0}; BeforeChar.Write(&Before); BeforePrevChar.Write(&BeforePrev); m_PredictedChar.Write(&Now); m_PredictedPrevChar.Write(&NowPrev); if(mem_comp(&Before, &Now, sizeof(CNetObj_CharacterCore)) != 0) { Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client", "prediction error"); for(unsigned i = 0; i < sizeof(CNetObj_CharacterCore)/sizeof(int); i++) if(((int *)&Before)[i] != ((int *)&Now)[i]) { char aBuf[256]; str_format(aBuf, sizeof(aBuf), " %d %d %d (%d %d)", i, ((int *)&Before)[i], ((int *)&Now)[i], ((int *)&BeforePrev)[i], ((int *)&NowPrev)[i]); Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client", aBuf); } } } m_PredictedTick = Client()->PredGameTick(); }
void CMenus::RenderDemoPlayer(CUIRect MainView) { const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo(); const float SeekBarHeight = 15.0f; const float ButtonbarHeight = 20.0f; const float NameBarHeight = 20.0f; const float Margins = 5.0f; float TotalHeight; if(m_MenuActive) TotalHeight = SeekBarHeight+ButtonbarHeight+NameBarHeight+Margins*3; else TotalHeight = SeekBarHeight+Margins*2; MainView.HSplitBottom(TotalHeight, 0, &MainView); MainView.VSplitLeft(50.0f, 0, &MainView); MainView.VSplitRight(450.0f, &MainView, 0); RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_T, 10.0f); MainView.Margin(5.0f, &MainView); CUIRect SeekBar, ButtonBar, NameBar; int CurrentTick = pInfo->m_CurrentTick - pInfo->m_FirstTick; int TotalTicks = pInfo->m_LastTick - pInfo->m_FirstTick; if(m_MenuActive) { MainView.HSplitTop(SeekBarHeight, &SeekBar, &ButtonBar); ButtonBar.HSplitTop(Margins, 0, &ButtonBar); ButtonBar.HSplitBottom(NameBarHeight, &ButtonBar, &NameBar); NameBar.HSplitTop(4.0f, 0, &NameBar); } else SeekBar = MainView; // do seekbar { static int s_SeekBarID = 0; void *id = &s_SeekBarID; char aBuffer[128]; RenderTools()->DrawUIRect(&SeekBar, vec4(0,0,0,0.5f), CUI::CORNER_ALL, 5.0f); float Amount = CurrentTick/(float)TotalTicks; CUIRect FilledBar = SeekBar; FilledBar.w = 10.0f + (FilledBar.w-10.0f)*Amount; RenderTools()->DrawUIRect(&FilledBar, vec4(1,1,1,0.5f), CUI::CORNER_ALL, 5.0f); str_format(aBuffer, sizeof(aBuffer), "%d:%02d / %d:%02d", CurrentTick/SERVER_TICK_SPEED/60, (CurrentTick/SERVER_TICK_SPEED)%60, TotalTicks/SERVER_TICK_SPEED/60, (TotalTicks/SERVER_TICK_SPEED)%60); UI()->DoLabel(&SeekBar, aBuffer, SeekBar.h*0.70f, 0); // do the logic int Inside = UI()->MouseInside(&SeekBar); if(UI()->ActiveItem() == id) { if(!UI()->MouseButton(0)) UI()->SetActiveItem(0); else { static float PrevAmount = 0.0f; float Amount = (UI()->MouseX()-SeekBar.x)/(float)SeekBar.w; if(Amount > 0.0f && Amount < 1.0f && absolute(PrevAmount-Amount) >= 0.01f) { PrevAmount = Amount; m_pClient->OnReset(); m_pClient->m_SuppressEvents = true; DemoPlayer()->SetPos(Amount); m_pClient->m_SuppressEvents = false; } } } else if(UI()->HotItem() == id) { if(UI()->MouseButton(0)) UI()->SetActiveItem(id); } if(Inside) UI()->SetHotItem(id); } if(CurrentTick == TotalTicks) { m_pClient->OnReset(); DemoPlayer()->Pause(); DemoPlayer()->SetPos(0); } bool IncreaseDemoSpeed = false, DecreaseDemoSpeed = false; if(m_MenuActive) { // do buttons CUIRect Button; // combined play and pause button ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar); static int s_PlayPauseButton = 0; if(!pInfo->m_Paused) { if(DoButton_Sprite(&s_PlayPauseButton, IMAGE_DEMOBUTTONS, SPRITE_DEMOBUTTON_PAUSE, false, &Button, CUI::CORNER_ALL)) DemoPlayer()->Pause(); } else { if(DoButton_Sprite(&s_PlayPauseButton, IMAGE_DEMOBUTTONS, SPRITE_DEMOBUTTON_PLAY, false, &Button, CUI::CORNER_ALL)) DemoPlayer()->Unpause(); } // stop button ButtonBar.VSplitLeft(Margins, 0, &ButtonBar); ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar); static int s_ResetButton = 0; if(DoButton_Sprite(&s_ResetButton, IMAGE_DEMOBUTTONS, SPRITE_DEMOBUTTON_STOP, false, &Button, CUI::CORNER_ALL)) { m_pClient->OnReset(); DemoPlayer()->Pause(); DemoPlayer()->SetPos(0); } // slowdown ButtonBar.VSplitLeft(Margins, 0, &ButtonBar); ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar); static int s_SlowDownButton = 0; if(DoButton_Sprite(&s_SlowDownButton, IMAGE_DEMOBUTTONS, SPRITE_DEMOBUTTON_SLOWER, 0, &Button, CUI::CORNER_ALL) || Input()->KeyPresses(KEY_MOUSE_WHEEL_DOWN)) DecreaseDemoSpeed = true; // fastforward ButtonBar.VSplitLeft(Margins, 0, &ButtonBar); ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar); static int s_FastForwardButton = 0; if(DoButton_Sprite(&s_FastForwardButton, IMAGE_DEMOBUTTONS, SPRITE_DEMOBUTTON_FASTER, 0, &Button, CUI::CORNER_ALL)) IncreaseDemoSpeed = true; // speed meter ButtonBar.VSplitLeft(Margins*3, 0, &ButtonBar); char aBuffer[64]; if(pInfo->m_Speed >= 1.0f) str_format(aBuffer, sizeof(aBuffer), "x%.0f", pInfo->m_Speed); else str_format(aBuffer, sizeof(aBuffer), "x%.2f", pInfo->m_Speed); UI()->DoLabel(&ButtonBar, aBuffer, Button.h*0.7f, -1); // close button ButtonBar.VSplitRight(ButtonbarHeight*3, &ButtonBar, &Button); static int s_ExitButton = 0; if(DoButton_DemoPlayer(&s_ExitButton, Localize("Close"), 0, &Button)) Client()->Disconnect(); // demo name char aBuf[128]; str_format(aBuf, sizeof(aBuf), Localize("Demofile: %s"), DemoPlayer()->GetDemoName()); CTextCursor Cursor; TextRender()->SetCursor(&Cursor, NameBar.x, NameBar.y, Button.h*0.5f, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END); Cursor.m_LineWidth = MainView.w; TextRender()->TextEx(&Cursor, aBuf, -1); } if(IncreaseDemoSpeed || Input()->KeyPresses(KEY_MOUSE_WHEEL_UP)) { if(pInfo->m_Speed < 0.1f) DemoPlayer()->SetSpeed(0.1f); else if(pInfo->m_Speed < 0.25f) DemoPlayer()->SetSpeed(0.25f); else if(pInfo->m_Speed < 0.5f) DemoPlayer()->SetSpeed(0.5f); else if(pInfo->m_Speed < 0.75f) DemoPlayer()->SetSpeed(0.75f); else if(pInfo->m_Speed < 1.0f) DemoPlayer()->SetSpeed(1.0f); else if(pInfo->m_Speed < 2.0f) DemoPlayer()->SetSpeed(2.0f); else if(pInfo->m_Speed < 4.0f) DemoPlayer()->SetSpeed(4.0f); else DemoPlayer()->SetSpeed(8.0f); } else if(DecreaseDemoSpeed || Input()->KeyPresses(KEY_MOUSE_WHEEL_DOWN)) { if(pInfo->m_Speed > 4.0f) DemoPlayer()->SetSpeed(4.0f); else if(pInfo->m_Speed > 2.0f) DemoPlayer()->SetSpeed(2.0f); else if(pInfo->m_Speed > 1.0f) DemoPlayer()->SetSpeed(1.0f); else if(pInfo->m_Speed > 0.75f) DemoPlayer()->SetSpeed(0.75f); else if(pInfo->m_Speed > 0.5f) DemoPlayer()->SetSpeed(0.5f); else if(pInfo->m_Speed > 0.25f) DemoPlayer()->SetSpeed(0.25f); else if(pInfo->m_Speed > 0.1f) DemoPlayer()->SetSpeed(0.1f); else DemoPlayer()->SetSpeed(0.05f); } }
void CGameClient::SendSwitchTeam(int Team) { CNetMsg_Cl_SetTeam Msg; Msg.m_Team = Team; Client()->SendPackMsg(&Msg, MSGFLAG_VITAL); }
void CEmoticon::OnRender() { if(!m_Active) { if(m_WasActive && m_SelectedEmote != -1) Emote(m_SelectedEmote); if(m_WasActive && m_SelectedEyeEmote != -1) EyeEmote(m_SelectedEyeEmote); m_WasActive = false; return; } if(m_pClient->m_Snap.m_SpecInfo.m_Active) { m_Active = false; m_WasActive = false; return; } m_WasActive = true; if (length(m_SelectorMouse) > 170.0f) m_SelectorMouse = normalize(m_SelectorMouse) * 170.0f; float SelectedAngle = GetAngle(m_SelectorMouse) + 2*pi/24; if (SelectedAngle < 0) SelectedAngle += 2*pi; m_SelectedEmote = -1; m_SelectedEyeEmote = -1; if (length(m_SelectorMouse) > 110.0f) m_SelectedEmote = (int)(SelectedAngle / (2*pi) * NUM_EMOTICONS); else if(length(m_SelectorMouse) > 40.0f) m_SelectedEyeEmote = (int)(SelectedAngle / (2*pi) * NUM_EMOTES); CUIRect Screen = *UI()->Screen(); Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h); Graphics()->BlendNormal(); Graphics()->TextureSet(-1); Graphics()->QuadsBegin(); Graphics()->SetColor(0,0,0,0.3f); DrawCircle(Screen.w/2, Screen.h/2, 190.0f, 64); Graphics()->QuadsEnd(); Graphics()->TextureSet(g_pData->m_aImages[IMAGE_EMOTICONS].m_Id); Graphics()->QuadsBegin(); for (int i = 0; i < NUM_EMOTICONS; i++) { float Angle = 2*pi*i/NUM_EMOTICONS; if (Angle > pi) Angle -= 2*pi; bool Selected = m_SelectedEmote == i; float Size = Selected ? 80.0f : 50.0f; float NudgeX = 150.0f * cosf(Angle); float NudgeY = 150.0f * sinf(Angle); RenderTools()->SelectSprite(SPRITE_OOP + i); IGraphics::CQuadItem QuadItem(Screen.w/2 + NudgeX, Screen.h/2 + NudgeY, Size, Size); Graphics()->QuadsDraw(&QuadItem, 1); } Graphics()->QuadsEnd(); CServerInfo pServerInfo; Client()->GetServerInfo(&pServerInfo); if((IsDDRace(&pServerInfo) || IsDDNet(&pServerInfo) || IsPlus(&pServerInfo)) && g_Config.m_ClEyeWheel) { Graphics()->TextureSet(-1); Graphics()->QuadsBegin(); Graphics()->SetColor(1.0,1.0,1.0,0.3f); DrawCircle(Screen.w/2, Screen.h/2, 100.0f, 64); Graphics()->QuadsEnd(); CTeeRenderInfo *pTeeInfo = &m_pClient->m_aClients[m_pClient->m_LocalIDs[g_Config.m_ClDummy]].m_RenderInfo; Graphics()->TextureSet(pTeeInfo->m_Texture); for (int i = 0; i < NUM_EMOTES; i++) { float Angle = 2*pi*i/NUM_EMOTES; if (Angle > pi) Angle -= 2*pi; bool Selected = m_SelectedEyeEmote == i; float NudgeX = 70.0f * cosf(Angle); float NudgeY = 70.0f * sinf(Angle); pTeeInfo->m_Size = Selected ? 64.0f : 48.0f; RenderTools()->RenderTee(CAnimState::GetIdle(), pTeeInfo, i, vec2(-1,0), vec2(Screen.w/2 + NudgeX, Screen.h/2 + NudgeY)); pTeeInfo->m_Size = 64.0f; } Graphics()->TextureSet(-1); Graphics()->QuadsBegin(); Graphics()->SetColor(0,0,0,0.3f); DrawCircle(Screen.w/2, Screen.h/2, 30.0f, 64); Graphics()->QuadsEnd(); } else m_SelectedEyeEmote = -1; Graphics()->TextureSet(g_pData->m_aImages[IMAGE_CURSOR].m_Id); Graphics()->QuadsBegin(); Graphics()->SetColor(1,1,1,1); IGraphics::CQuadItem QuadItem(m_SelectorMouse.x+Screen.w/2,m_SelectorMouse.y+Screen.h/2,24,24); Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); }
void CHud::RenderScoreHud() { // render small score hud if(!(m_pClient->m_Snap.m_pGameData->m_GameStateFlags&(GAMESTATEFLAG_ROUNDOVER|GAMESTATEFLAG_GAMEOVER))) { int GameFlags = m_pClient->m_GameInfo.m_GameFlags; float Whole = 300*Graphics()->ScreenAspect(); float StartY = 229.0f; if(GameFlags&GAMEFLAG_TEAMS && m_pClient->m_Snap.m_pGameDataTeam) { char aScoreTeam[2][32]; str_format(aScoreTeam[TEAM_RED], sizeof(aScoreTeam)/2, "%d", m_pClient->m_Snap.m_pGameDataTeam->m_TeamscoreRed); str_format(aScoreTeam[TEAM_BLUE], sizeof(aScoreTeam)/2, "%d", m_pClient->m_Snap.m_pGameDataTeam->m_TeamscoreBlue); float aScoreTeamWidth[2] = { TextRender()->TextWidth(0, 14.0f, aScoreTeam[TEAM_RED], -1, -1.0f), TextRender()->TextWidth(0, 14.0f, aScoreTeam[TEAM_BLUE], -1, -1.0f) }; float ScoreWidthMax = max(max(aScoreTeamWidth[TEAM_RED], aScoreTeamWidth[TEAM_BLUE]), TextRender()->TextWidth(0, 14.0f, "100", -1, -1.0f)); float Split = 3.0f; float ImageSize = GameFlags&GAMEFLAG_FLAGS ? 16.0f : Split; for(int t = 0; t < NUM_TEAMS; t++) { // draw box CUIRect Rect = {Whole-ScoreWidthMax-ImageSize-2*Split, StartY+t*20, ScoreWidthMax+ImageSize+2*Split, 18.0f}; Graphics()->BlendNormal(); RenderTools()->DrawUIRect(&Rect, t == 0 ? vec4(1.0f, 0.0f, 0.0f, 0.25f) : vec4(0.0f, 0.0f, 1.0f, 0.25f), CUI::CORNER_L, 5.0f); // draw score TextRender()->Text(0, Whole-ScoreWidthMax+(ScoreWidthMax-aScoreTeamWidth[t])/2-Split, StartY+t*20, 14.0f, aScoreTeam[t], -1.0f); if(GameFlags&GAMEFLAG_SURVIVAL) { // draw number of alive players char aBuf[32]; str_format(aBuf, sizeof(aBuf), m_pClient->m_Snap.m_AliveCount[t]==1 ? Localize("%d player left") : Localize("%d players left"), m_pClient->m_Snap.m_AliveCount[t]); float w = TextRender()->TextWidth(0, 8.0f, aBuf, -1, -1.0f); TextRender()->Text(0, min(Whole-w-1.0f, Whole-ScoreWidthMax-ImageSize-2*Split), StartY+(t+1)*20.0f-3.0f, 8.0f, aBuf, -1.0f); } StartY += 8.0f; } if(GameFlags&GAMEFLAG_FLAGS && m_pClient->m_Snap.m_pGameDataFlag) { int FlagCarrier[2] = { m_pClient->m_Snap.m_pGameDataFlag->m_FlagCarrierRed, m_pClient->m_Snap.m_pGameDataFlag->m_FlagCarrierBlue }; int FlagDropTick[2] = { m_pClient->m_Snap.m_pGameDataFlag->m_FlagDropTickRed, m_pClient->m_Snap.m_pGameDataFlag->m_FlagDropTickBlue }; StartY = 229.0f; for(int t = 0; t < 2; t++) { int BlinkTimer = (FlagDropTick[t] != 0 && (Client()->GameTick()-FlagDropTick[t])/Client()->GameTickSpeed() >= 25) ? 10 : 20; if(FlagCarrier[t] == FLAG_ATSTAND || (FlagCarrier[t] == FLAG_TAKEN && ((Client()->GameTick()/BlinkTimer)&1))) { // draw flag Graphics()->BlendNormal(); Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id); Graphics()->QuadsBegin(); RenderTools()->SelectSprite(t==0?SPRITE_FLAG_RED:SPRITE_FLAG_BLUE); IGraphics::CQuadItem QuadItem(Whole-ScoreWidthMax-ImageSize, StartY+1.0f+t*20, ImageSize/2, ImageSize); Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); } else if(FlagCarrier[t] >= 0) { // draw name of the flag holder int ID = FlagCarrier[t]%MAX_CLIENTS; char aName[64]; str_format(aName, sizeof(aName), "%s", g_Config.m_ClShowsocial ? m_pClient->m_aClients[ID].m_aName : ""); float w = TextRender()->TextWidth(0, 8.0f, aName, -1, -1.0f) + RenderTools()->GetClientIdRectSize(8.0f); CTextCursor Cursor; float x = min(Whole-w-1.0f, Whole-ScoreWidthMax-ImageSize-2*Split); float y = StartY+(t+1)*20.0f-3.0f; TextRender()->SetCursor(&Cursor, x, y, 8.0f, TEXTFLAG_RENDER); RenderTools()->DrawClientID(TextRender(), &Cursor, ID); TextRender()->TextEx(&Cursor, aName, -1); // draw tee of the flag holder CTeeRenderInfo Info = m_pClient->m_aClients[ID].m_RenderInfo; Info.m_Size = 18.0f; RenderTools()->RenderTee(CAnimState::GetIdle(), &Info, EMOTE_NORMAL, vec2(1,0), vec2(Whole-ScoreWidthMax-Info.m_Size/2-Split, StartY+1.0f+Info.m_Size/2+t*20)); } StartY += 8.0f; } } } else { int Local = -1; int aPos[2] = { 1, 2 }; CGameClient::CPlayerInfoItem aPlayerInfo[2] = {{0}}; int i = 0; for(int t = 0; t < 2 && i < MAX_CLIENTS && m_pClient->m_Snap.m_aInfoByScore[i].m_pPlayerInfo; ++i) { if(m_pClient->m_aClients[m_pClient->m_Snap.m_aInfoByScore[i].m_ClientID].m_Team != TEAM_SPECTATORS) { aPlayerInfo[t] = m_pClient->m_Snap.m_aInfoByScore[i]; if(aPlayerInfo[t].m_ClientID == m_pClient->m_LocalClientID) Local = t; ++t; } } // search local player info if not a spectator, nor within top2 scores if(Local == -1 && m_pClient->m_aClients[m_pClient->m_LocalClientID].m_Team != TEAM_SPECTATORS) { for(; i < MAX_CLIENTS && m_pClient->m_Snap.m_aInfoByScore[i].m_pPlayerInfo; ++i) { if(m_pClient->m_aClients[m_pClient->m_Snap.m_aInfoByScore[i].m_ClientID].m_Team != TEAM_SPECTATORS) ++aPos[1]; if(m_pClient->m_Snap.m_aInfoByScore[i].m_ClientID == m_pClient->m_LocalClientID) { aPlayerInfo[1] = m_pClient->m_Snap.m_aInfoByScore[i]; Local = 1; break; } } } char aScore[2][32]; for(int t = 0; t < 2; ++t) { if(aPlayerInfo[t].m_pPlayerInfo) str_format(aScore[t], sizeof(aScore)/2, "%d", aPlayerInfo[t].m_pPlayerInfo->m_Score); else aScore[t][0] = 0; } float aScoreWidth[2] = {TextRender()->TextWidth(0, 14.0f, aScore[0], -1, -1.0f), TextRender()->TextWidth(0, 14.0f, aScore[1], -1, -1.0f)}; float ScoreWidthMax = max(max(aScoreWidth[0], aScoreWidth[1]), TextRender()->TextWidth(0, 14.0f, "10", -1, -1.0f)); float Split = 3.0f, ImageSize = 16.0f, PosSize = 16.0f; // todo: add core hud for LMS for(int t = 0; t < 2; t++) { // draw box CUIRect Rect = {Whole-ScoreWidthMax-ImageSize-2*Split-PosSize, StartY+t*20, ScoreWidthMax+ImageSize+2*Split+PosSize, 18.0f}; Graphics()->BlendNormal(); RenderTools()->DrawUIRect(&Rect, t == Local ? vec4(1.0f, 1.0f, 1.0f, 0.25f) : vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_L, 5.0f); // draw score TextRender()->Text(0, Whole-ScoreWidthMax+(ScoreWidthMax-aScoreWidth[t])/2-Split, StartY+t*20, 14.0f, aScore[t], -1.0f); if(aPlayerInfo[t].m_pPlayerInfo) { // draw name int ID = aPlayerInfo[t].m_ClientID; char aName[64]; str_format(aName, sizeof(aName), "%s", g_Config.m_ClShowsocial ? m_pClient->m_aClients[ID].m_aName : ""); float w = TextRender()->TextWidth(0, 8.0f, aName, -1, -1.0f) + RenderTools()->GetClientIdRectSize(8.0f); CTextCursor Cursor; float x = min(Whole-w-1.0f, Whole-ScoreWidthMax-ImageSize-2*Split-PosSize); float y = StartY+(t+1)*20.0f-3.0f; TextRender()->SetCursor(&Cursor, x, y, 8.0f, TEXTFLAG_RENDER); RenderTools()->DrawClientID(TextRender(), &Cursor, ID); TextRender()->TextEx(&Cursor, aName, -1); // draw tee CTeeRenderInfo Info = m_pClient->m_aClients[ID].m_RenderInfo; Info.m_Size = 18.0f; RenderTools()->RenderTee(CAnimState::GetIdle(), &Info, EMOTE_NORMAL, vec2(1,0), vec2(Whole-ScoreWidthMax-Info.m_Size/2-Split, StartY+1.0f+Info.m_Size/2+t*20)); } // draw position char aBuf[32]; str_format(aBuf, sizeof(aBuf), "%d.", aPos[t]); TextRender()->Text(0, Whole-ScoreWidthMax-ImageSize-Split-PosSize, StartY+2.0f+t*20, 10.0f, aBuf, -1.0f); StartY += 8.0f; } } } }
boost::statechart::result PlayingGame::react(const ResetToIntroMenu& msg) { if (TRACE_EXECUTION) DebugLogger() << "(HumanClientFSM) PlayingGame.ResetToIntroMenu"; Client().GetClientUI()->GetMessageWnd()->HandleGameStatusUpdate(UserString("RETURN_TO_INTRO") + "\n"); return transit<IntroMenu>(); }
void CHud::RenderWarmupTimer() { // render warmup timer if(m_pClient->m_Snap.m_pGameData->m_GameStateFlags&GAMESTATEFLAG_WARMUP) { char aBuf[256]; float FontSize = 20.0f; float w = 0.0f; const char *pText = Localize("Warmup"); if(m_WarmupHideTick == 0 || (time_get() - m_WarmupHideTick) / time_freq() < 10) { w = TextRender()->TextWidth(0, FontSize, pText, -1, -1.0f); TextRender()->Text(0, 150*Graphics()->ScreenAspect()+-w/2, 50, FontSize, pText, -1.0f); } else { TextRender()->TextColor(1, 1, 0.5f, 1); TextRender()->Text(0x0, 10, 45, 8, pText, -1.0f); } FontSize = 16.0f; if(m_pClient->m_Snap.m_pGameData->m_GameStateEndTick == 0) { if(m_pClient->m_Snap.m_NotReadyCount == 1) { str_format(aBuf, sizeof(aBuf), Localize("%d player not ready"), m_pClient->m_Snap.m_NotReadyCount); RenderReadyUpNotification(); } else if(m_pClient->m_Snap.m_NotReadyCount > 1) { str_format(aBuf, sizeof(aBuf), Localize("%d players not ready"), m_pClient->m_Snap.m_NotReadyCount); RenderReadyUpNotification(); } else { str_format(aBuf, sizeof(aBuf), Localize("wait for more players")); if(m_WarmupHideTick == 0) m_WarmupHideTick = time_get(); } } else { float Seconds = static_cast<float>(m_pClient->m_Snap.m_pGameData->m_GameStateEndTick-Client()->GameTick())/SERVER_TICK_SPEED; if(Seconds < 5) str_format(aBuf, sizeof(aBuf), "%.1f", Seconds); else str_format(aBuf, sizeof(aBuf), "%d", round_to_int(Seconds)); } if(m_WarmupHideTick == 0 || (time_get() - m_WarmupHideTick) / time_freq() < 10) { w = TextRender()->TextWidth(0, FontSize, aBuf, -1, -1.0f); TextRender()->Text(0, 150*Graphics()->ScreenAspect()+-w/2, 75, FontSize, aBuf, -1.0f); } else { TextRender()->Text(0x0, 10, 54, 6, aBuf, -1.0f); TextRender()->TextColor(1, 1, 1, 1); } } else if((m_pClient->m_Snap.m_pGameData->m_GameStateEndTick == 0 && m_pClient->m_Snap.m_NotReadyCount > 0) || m_pClient->m_Snap.m_pGameData->m_GameStateEndTick != 0) m_WarmupHideTick = 0; }
//////////////////////////////////////////////////////////// // WaitingForTurnData //////////////////////////////////////////////////////////// WaitingForTurnData::WaitingForTurnData(my_context ctx) : Base(ctx) { if (TRACE_EXECUTION) DebugLogger() << "(HumanClientFSM) WaitingForTurnData"; Client().GetClientUI()->GetMapWnd()->EnableOrderIssuing(false); }
void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker) { Client()->RecordGameMessage(true); // special messages if(MsgId == NETMSGTYPE_SV_TUNEPARAMS && Client()->State() != IClient::STATE_DEMOPLAYBACK) { Client()->RecordGameMessage(false); // unpack the new tuning CTuningParams NewTuning; int *pParams = (int *)&NewTuning; for(unsigned i = 0; i < sizeof(CTuningParams)/sizeof(int); i++) pParams[i] = pUnpacker->GetInt(); // check for unpacking errors if(pUnpacker->Error()) return; m_ServerMode = SERVERMODE_PURE; // apply new tuning m_Tuning = NewTuning; return; } else if(MsgId == NETMSGTYPE_SV_VOTEOPTIONLISTADD) { int NumOptions = pUnpacker->GetInt(); for(int i = 0; i < NumOptions; i++) { const char *pDescription = pUnpacker->GetString(CUnpacker::SANITIZE_CC); if(pUnpacker->Error()) return; m_pVoting->AddOption(pDescription); } } else if(MsgId == NETMSGTYPE_SV_GAMEMSG) { int GameMsgID = pUnpacker->GetInt(); int aParaI[3]; int NumParaI = 0; // get paras switch(gs_GameMsgList[GameMsgID].m_ParaType) { case PARA_III: aParaI[NumParaI++] = pUnpacker->GetInt(); case PARA_II: aParaI[NumParaI++] = pUnpacker->GetInt(); case PARA_I: aParaI[NumParaI++] = pUnpacker->GetInt(); } // check for unpacking errors if(pUnpacker->Error()) return; // handle special messages static char aBuf[256]; if(gs_GameMsgList[GameMsgID].m_Action == DO_SPECIAL) { switch(GameMsgID) { case GAMEMSG_CTF_DROP: if(m_SuppressEvents) return; m_pSounds->Enqueue(CSounds::CHN_GLOBAL, SOUND_CTF_DROP); break; case GAMEMSG_CTF_RETURN: if(m_SuppressEvents) return; m_pSounds->Enqueue(CSounds::CHN_GLOBAL, SOUND_CTF_RETURN); break; case GAMEMSG_TEAM_BALANCE_VICTIM: str_format(aBuf, sizeof(aBuf), Localize(gs_GameMsgList[GameMsgID].m_pText), GetTeamName(aParaI[0], m_GameInfo.m_GameFlags&GAMEFLAG_TEAMS)); m_pBroadcast->DoBroadcast(aBuf); break; case GAMEMSG_CTF_GRAB: if(m_SuppressEvents) return; if(m_LocalClientID != -1 && (m_aClients[m_LocalClientID].m_Team != aParaI[0] || (m_Snap.m_SpecInfo.m_Active && ((m_Snap.m_SpecInfo.m_SpectatorID != -1 && m_aClients[m_Snap.m_SpecInfo.m_SpectatorID].m_Team != aParaI[0]) || (m_Snap.m_SpecInfo.m_SpecMode == SPEC_FLAGRED && aParaI[0] != TEAM_RED) || (m_Snap.m_SpecInfo.m_SpecMode == SPEC_FLAGBLUE && aParaI[0] != TEAM_BLUE))))) m_pSounds->Enqueue(CSounds::CHN_GLOBAL, SOUND_CTF_GRAB_PL); else m_pSounds->Enqueue(CSounds::CHN_GLOBAL, SOUND_CTF_GRAB_EN); break; case GAMEMSG_CTF_CAPTURE: m_pSounds->Enqueue(CSounds::CHN_GLOBAL, SOUND_CTF_CAPTURE); int ClientID = clamp(aParaI[1], 0, MAX_CLIENTS - 1); if(aParaI[2] <= 60*Client()->GameTickSpeed()) str_format(aBuf, sizeof(aBuf), Localize("The %s flag was captured by '%2d: %s' (%.2f seconds)"), aParaI[0] ? Localize("blue") : Localize("red"), ClientID, g_Config.m_ClShowsocial ? m_aClients[ClientID].m_aName : "", aParaI[2]/(float)Client()->GameTickSpeed()); else str_format(aBuf, sizeof(aBuf), Localize("The %s flag was captured by '%2d: %s'"), aParaI[0] ? Localize("blue") : Localize("red"), ClientID, g_Config.m_ClShowsocial ? m_aClients[ClientID].m_aName : ""); m_pChat->AddLine(-1, 0, aBuf); } return; } // build message const char *pText = ""; if(NumParaI == 0) pText = Localize(gs_GameMsgList[GameMsgID].m_pText); else { if(NumParaI == 1) str_format(aBuf, sizeof(aBuf), Localize(gs_GameMsgList[GameMsgID].m_pText), aParaI[0]); else if(NumParaI == 2) str_format(aBuf, sizeof(aBuf), Localize(gs_GameMsgList[GameMsgID].m_pText), aParaI[0], aParaI[1]); else if(NumParaI == 3) str_format(aBuf, sizeof(aBuf), Localize(gs_GameMsgList[GameMsgID].m_pText), aParaI[0], aParaI[1], aParaI[2]); pText = aBuf; } // handle message switch(gs_GameMsgList[GameMsgID].m_Action) { case DO_CHAT: m_pChat->AddLine(-1, 0, pText); break; case DO_BROADCAST: m_pBroadcast->DoBroadcast(pText); } } void *pRawMsg = m_NetObjHandler.SecureUnpackMsg(MsgId, pUnpacker); if(!pRawMsg) { char aBuf[256]; str_format(aBuf, sizeof(aBuf), "dropped weird message '%s' (%d), failed on '%s'", m_NetObjHandler.GetMsgName(MsgId), MsgId, m_NetObjHandler.FailedMsgOn()); Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client", aBuf); return; } // TODO: this should be done smarter for(int i = 0; i < m_All.m_Num; i++) m_All.m_paComponents[i]->OnMessage(MsgId, pRawMsg); if(MsgId == NETMSGTYPE_SV_CLIENTINFO && Client()->State() != IClient::STATE_DEMOPLAYBACK) { Client()->RecordGameMessage(false); CNetMsg_Sv_ClientInfo *pMsg = (CNetMsg_Sv_ClientInfo *)pRawMsg; if(pMsg->m_Local) { if(m_LocalClientID != -1) { if(g_Config.m_Debug) Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client", "invalid local clientinfo"); return; } m_LocalClientID = pMsg->m_ClientID; } else { if(m_aClients[pMsg->m_ClientID].m_Active) { if(g_Config.m_Debug) Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client", "invalid clientinfo"); return; } if(m_LocalClientID != -1) { DoEnterMessage(pMsg->m_pName, pMsg->m_ClientID, pMsg->m_Team); if(m_pDemoRecorder->IsRecording()) { CNetMsg_De_ClientEnter Msg; Msg.m_pName = pMsg->m_pName; Msg.m_ClientID = pMsg->m_ClientID; Msg.m_Team = pMsg->m_Team; Client()->SendPackMsg(&Msg, MSGFLAG_NOSEND|MSGFLAG_RECORD); } } } m_aClients[pMsg->m_ClientID].m_Active = true; m_aClients[pMsg->m_ClientID].m_Team = pMsg->m_Team; str_copy(m_aClients[pMsg->m_ClientID].m_aName, pMsg->m_pName, sizeof(m_aClients[pMsg->m_ClientID].m_aName)); str_copy(m_aClients[pMsg->m_ClientID].m_aClan, pMsg->m_pClan, sizeof(m_aClients[pMsg->m_ClientID].m_aClan)); m_aClients[pMsg->m_ClientID].m_Country = pMsg->m_Country; for(int i = 0; i < 6; i++) { str_copy(m_aClients[pMsg->m_ClientID].m_aaSkinPartNames[i], pMsg->m_apSkinPartNames[i], 24); m_aClients[pMsg->m_ClientID].m_aUseCustomColors[i] = pMsg->m_aUseCustomColors[i]; m_aClients[pMsg->m_ClientID].m_aSkinPartColors[i] = pMsg->m_aSkinPartColors[i]; } // update friend state m_aClients[pMsg->m_ClientID].m_Friend = Friends()->IsFriend(m_aClients[pMsg->m_ClientID].m_aName, m_aClients[pMsg->m_ClientID].m_aClan, true); m_aClients[pMsg->m_ClientID].UpdateRenderInfo(this, true); m_GameInfo.m_NumPlayers++; // calculate team-balance if(m_aClients[pMsg->m_ClientID].m_Team != TEAM_SPECTATORS) m_GameInfo.m_aTeamSize[m_aClients[pMsg->m_ClientID].m_Team]++; } else if(MsgId == NETMSGTYPE_SV_CLIENTDROP && Client()->State() != IClient::STATE_DEMOPLAYBACK) { Client()->RecordGameMessage(false); CNetMsg_Sv_ClientDrop *pMsg = (CNetMsg_Sv_ClientDrop *)pRawMsg; if(m_LocalClientID == pMsg->m_ClientID || !m_aClients[pMsg->m_ClientID].m_Active) { if(g_Config.m_Debug) Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client", "invalid clientdrop"); return; } DoLeaveMessage(m_aClients[pMsg->m_ClientID].m_aName, pMsg->m_ClientID, pMsg->m_pReason); CNetMsg_De_ClientLeave Msg; Msg.m_pName = m_aClients[pMsg->m_ClientID].m_aName; Msg.m_ClientID = pMsg->m_ClientID; Msg.m_pReason = pMsg->m_pReason; Client()->SendPackMsg(&Msg, MSGFLAG_NOSEND|MSGFLAG_RECORD); m_GameInfo.m_NumPlayers--; // calculate team-balance if(m_aClients[pMsg->m_ClientID].m_Team != TEAM_SPECTATORS) m_GameInfo.m_aTeamSize[m_aClients[pMsg->m_ClientID].m_Team]--; m_aClients[pMsg->m_ClientID].Reset(this); } else if(MsgId == NETMSGTYPE_SV_GAMEINFO && Client()->State() != IClient::STATE_DEMOPLAYBACK) { Client()->RecordGameMessage(false); CNetMsg_Sv_GameInfo *pMsg = (CNetMsg_Sv_GameInfo *)pRawMsg; m_GameInfo.m_GameFlags = pMsg->m_GameFlags; m_GameInfo.m_ScoreLimit = pMsg->m_ScoreLimit; m_GameInfo.m_TimeLimit = pMsg->m_TimeLimit; m_GameInfo.m_MatchNum = pMsg->m_MatchNum; m_GameInfo.m_MatchCurrent = pMsg->m_MatchCurrent; } else if(MsgId == NETMSGTYPE_SV_SERVERSETTINGS && Client()->State() != IClient::STATE_DEMOPLAYBACK) { Client()->RecordGameMessage(false); CNetMsg_Sv_ServerSettings *pMsg = (CNetMsg_Sv_ServerSettings *)pRawMsg; if(!m_ServerSettings.m_TeamLock && pMsg->m_TeamLock) m_pChat->AddLine(-1, 0, Localize("Teams were locked")); else if(m_ServerSettings.m_TeamLock && !pMsg->m_TeamLock) m_pChat->AddLine(-1, 0, Localize("Teams were unlocked")); m_ServerSettings.m_KickVote = pMsg->m_KickVote; m_ServerSettings.m_KickMin = pMsg->m_KickMin; m_ServerSettings.m_SpecVote = pMsg->m_SpecVote; m_ServerSettings.m_TeamLock = pMsg->m_TeamLock; m_ServerSettings.m_TeamBalance = pMsg->m_TeamBalance; m_ServerSettings.m_PlayerSlots = pMsg->m_PlayerSlots; } else if(MsgId == NETMSGTYPE_SV_TEAM) { CNetMsg_Sv_Team *pMsg = (CNetMsg_Sv_Team *)pRawMsg; if(Client()->State() != IClient::STATE_DEMOPLAYBACK) { // calculate team-balance if(m_aClients[pMsg->m_ClientID].m_Team != TEAM_SPECTATORS) m_GameInfo.m_aTeamSize[m_aClients[pMsg->m_ClientID].m_Team]--; m_aClients[pMsg->m_ClientID].m_Team = pMsg->m_Team; if(m_aClients[pMsg->m_ClientID].m_Team != TEAM_SPECTATORS) m_GameInfo.m_aTeamSize[m_aClients[pMsg->m_ClientID].m_Team]++; m_aClients[pMsg->m_ClientID].UpdateRenderInfo(this, false); if(pMsg->m_ClientID == m_LocalClientID) m_TeamCooldownTick = pMsg->m_CooldownTick; } if(pMsg->m_Silent == 0) { DoTeamChangeMessage(m_aClients[pMsg->m_ClientID].m_aName, pMsg->m_ClientID, pMsg->m_Team); } } else if(MsgId == NETMSGTYPE_SV_READYTOENTER) { Client()->EnterGame(); } else if (MsgId == NETMSGTYPE_SV_EMOTICON) { CNetMsg_Sv_Emoticon *pMsg = (CNetMsg_Sv_Emoticon *)pRawMsg; // apply m_aClients[pMsg->m_ClientID].m_Emoticon = pMsg->m_Emoticon; m_aClients[pMsg->m_ClientID].m_EmoticonStart = Client()->GameTick(); } else if(MsgId == NETMSGTYPE_DE_CLIENTENTER && Client()->State() == IClient::STATE_DEMOPLAYBACK) { CNetMsg_De_ClientEnter *pMsg = (CNetMsg_De_ClientEnter *)pRawMsg; DoEnterMessage(pMsg->m_pName, pMsg->m_ClientID, pMsg->m_Team); } else if(MsgId == NETMSGTYPE_DE_CLIENTLEAVE && Client()->State() == IClient::STATE_DEMOPLAYBACK) { CNetMsg_De_ClientLeave *pMsg = (CNetMsg_De_ClientLeave *)pRawMsg; DoLeaveMessage(pMsg->m_pName, pMsg->m_ClientID, pMsg->m_pReason); } }