// vim: set ts=4 sw=4 tw=99 noet: // // AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). // Copyright (C) The AMX Mod X Development Team. // // This software is licensed under the GNU General Public License, version 3 or higher. // Additional exceptions apply. For full license details, see LICENSE.txt or visit: // https://alliedmods.net/amxmodx-license #include "stdafx.h" #include "WinCSX.h" #include #include "commctrl.h" #include int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { // TODO: Place code here. MSG msg; HACCEL hAccelTable; // Initialize global strings LoadString(hInstance, IDS_APP_TITLE, g_szTitle, MAX_LOADSTRING); LoadString(hInstance, IDC_WINCSX, g_szWindowClass, MAX_LOADSTRING); MyRegisterClass(hInstance); // Perform application initialization: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } InitCommonControls(); hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_WINCSX); // Show the dialog box now. DialogBox(hInst, (LPCTSTR)IDD_WINCSXBOX, g_hWnd, (DLGPROC)WinCSXBox); // Main message loop: while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return (int) msg.wParam; } // // FUNCTION: MyRegisterClass() // // PURPOSE: Registers the window class. // // COMMENTS: // // This function and its usage are only necessary if you want this code // to be compatible with Win32 systems prior to the 'RegisterClassEx' // function that was added to Windows 95. It is important to call this function // so that the application will get 'well formed' small icons associated // with it. // ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = 0; // CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = (WNDPROC)WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_WINCSX); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = (LPCTSTR)IDC_WINCSX; wcex.lpszClassName = g_szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL); return RegisterClassEx(&wcex); } // // FUNCTION: InitInstance(HANDLE, int) // // PURPOSE: Saves instance handle and creates main window // // COMMENTS: // // In this function, we save the instance handle in a global variable and // create and display the main program window. // BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { hInst = hInstance; // Store instance handle in our global variable g_hWnd = CreateWindow(g_szWindowClass, g_szTitle, WS_DLGFRAME, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, NULL, NULL, hInstance, NULL); // WS_OVERLAPPED WS_MINIMIZE if (!g_hWnd) { MessageBox(g_hWnd, "Failed to create main window!", "A caption", MB_OK); return FALSE; } ShowWindow(g_hWnd, SW_SHOWMINNOACTIVE); // nCmdShow SW_SHOWNORMAL were rubbish. SW_SHOWMINNOACTIVE looks ok. UpdateWindow(g_hWnd); return TRUE; } bool LoadRankFromFile(HWND hDlg) { if ( !g_rank.begin() ) { if (!g_rank.loadRank(STATS_FILENAME)) { MessageBox(hDlg, "File load failed! Make sure you have csstats.dat in the same directory as this executable. Exiting...", "Where IS that file of yours?", MB_OK); PostQuitMessage(0); return false; } } return true; } // // FUNCTION: WndProc(HWND, unsigned, WORD, LONG) // // PURPOSE: Processes messages for the main window. // // WM_COMMAND - process the application menu // WM_PAINT - Paint the main window // WM_DESTROY - post a quit message and return // // LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { //int wmId, wmEvent; PAINTSTRUCT ps; HDC hdc; switch (message) { case WM_PAINT: hdc = BeginPaint(hWnd, &ps); // TODO: Add any drawing code here... EndPaint(hWnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } void UpdateListBox(HWND hDlg) { HWND listbox = GetDlgItem(hDlg, IDC_LIST); // Clear first if there's anything in here already SendMessage(listbox, LB_RESETCONTENT, NULL, NULL); if (g_rank.front() == NULL) { MessageBox(hDlg, "The stats file is empty", "Emptiness...", MB_OK); return; } // This part copies the occurring authids into the lefthand listbox. int index = 10, len = 0; char tempbuffer[1024]; for (RankSystem::iterator b = g_rank.front(); b; --b) { //if ((*b).getPosition() < 1) // umm... naaah! //continue; ke::SafeSprintf(tempbuffer, sizeof(tempbuffer)-1, "%s", (*b).getName()); SendMessage( // returns LRESULT in lResult listbox, // handle to destination control LB_ADDSTRING, // message ID 0, // = (WPARAM) () wParam; (LPARAM) tempbuffer // = (LPARAM) () lParam; ); } } LRESULT InitWinCSXBox(HWND hDlg) { // Load the stats if (!LoadRankFromFile(hDlg)) return TRUE; UpdateListBox(hDlg); return TRUE; } void ClearStatsfields(HWND hDlg) { SetDlgItemText(hDlg, IDC_EDIT_POSITION, ""); SetDlgItemText(hDlg, IDC_EDIT_NAME, ""); SetDlgItemText(hDlg, IDC_EDIT_AUTHID, ""); SetDlgItemText(hDlg, IDC_EDIT_FRAGS, ""); SetDlgItemText(hDlg, IDC_EDIT_DEATHS, ""); SetDlgItemText(hDlg, IDC_EDIT_HS, ""); SetDlgItemText(hDlg, IDC_EDIT_TKS, ""); SetDlgItemText(hDlg, IDC_EDIT_SHOTS, ""); SetDlgItemText(hDlg, IDC_EDIT_HITS, ""); SetDlgItemText(hDlg, IDC_EDIT_DAMAGE, ""); SetDlgItemText(hDlg, IDC_EDIT_PLANTS, ""); SetDlgItemText(hDlg, IDC_EDIT_EXPLOSIONS, ""); SetDlgItemText(hDlg, IDC_EDIT_DEFUSIONS, ""); SetDlgItemText(hDlg, IDC_EDIT_DEFUSED, ""); } void ListboxItemSelected(HWND hDlg) { HWND hwndList = GetDlgItem(hDlg, IDC_LIST); // Get the handle of the listbox LRESULT nItem = SendMessage(hwndList, LB_GETCURSEL, 0, 0); // Get the item # that's selected. First item is prolly 0... if (nItem == LB_ERR) { // Error, reset the form items... //MessageBox(hDlg, "Error: Couldn't find the selected record in the listbox!", "Oh fiddlesticks!", MB_OK); ClearStatsfields(hDlg); return; } // Retrieve complete stats record of this position. Position in listbox should be same as rank in our records! RankSystem::RankStats* stats = g_rank.findEntryInRankByPos((int)nItem + 1); if (stats == NULL) { char msg[] = "Error: Couldn't find the record by position! (nItem = %d)"; sprintf(msg, msg, nItem); MessageBox(hDlg, msg, "Oh fiddlesticks!", MB_OK); ClearStatsfields(hDlg); return; } // Copy data into form SetDlgItemInt(hDlg, IDC_EDIT_POSITION, stats->getPosition(), 0); SetDlgItemText(hDlg, IDC_EDIT_NAME, stats->getName()); SetDlgItemText(hDlg, IDC_EDIT_AUTHID, stats->getUnique()); SetDlgItemInt(hDlg, IDC_EDIT_FRAGS, stats->kills, 0); SetDlgItemInt(hDlg, IDC_EDIT_DEATHS, stats->deaths, 0); SetDlgItemInt(hDlg, IDC_EDIT_HS, stats->hs, 0); SetDlgItemInt(hDlg, IDC_EDIT_TKS, stats->tks, 0); SetDlgItemInt(hDlg, IDC_EDIT_SHOTS, stats->shots, 0); SetDlgItemInt(hDlg, IDC_EDIT_HITS, stats->hits, 0); SetDlgItemInt(hDlg, IDC_EDIT_DAMAGE, stats->damage, 0); SetDlgItemInt(hDlg, IDC_EDIT_PLANTS, stats->bPlants, 0); SetDlgItemInt(hDlg, IDC_EDIT_EXPLOSIONS, stats->bExplosions, 0); SetDlgItemInt(hDlg, IDC_EDIT_DEFUSIONS, stats->bDefusions, 0); SetDlgItemInt(hDlg, IDC_EDIT_DEFUSED, stats->bDefused, 0); } void SaveChanges(HWND hDlg) { BOOL success; int position = GetDlgItemInt(hDlg, IDC_EDIT_POSITION, &success, false); if (!success) goto BadEnd; char authid[32]; // "primary key" GetDlgItemText(hDlg, IDC_EDIT_AUTHID, authid, sizeof(authid)); RankSystem::RankStats* entry = g_rank.findEntryInRankByUnique(authid); if (!entry) { char buffer[256]; sprintf(buffer, "Authid %s not found!", authid); MessageBox(hDlg, buffer, "Update failed", MB_OK); return; } char name[32]; GetDlgItemText(hDlg, IDC_EDIT_NAME, name, sizeof(name)); int frags = GetDlgItemInt(hDlg, IDC_EDIT_FRAGS, &success, false); if (!success) goto BadEnd; int deaths = GetDlgItemInt(hDlg, IDC_EDIT_DEATHS, &success, false); if (!success) goto BadEnd; int hs = GetDlgItemInt(hDlg, IDC_EDIT_HS, &success, false); if (!success) goto BadEnd; int tks = GetDlgItemInt(hDlg, IDC_EDIT_TKS, &success, false); if (!success) goto BadEnd; int shots = GetDlgItemInt(hDlg, IDC_EDIT_SHOTS, &success, false); if (!success) goto BadEnd; int hits = GetDlgItemInt(hDlg, IDC_EDIT_HITS, &success, false); if (!success) goto BadEnd; int damage = GetDlgItemInt(hDlg, IDC_EDIT_DAMAGE, &success, false); if (!success) goto BadEnd; int plants = GetDlgItemInt(hDlg, IDC_EDIT_PLANTS, &success, false); if (!success) goto BadEnd; int explosions = GetDlgItemInt(hDlg, IDC_EDIT_EXPLOSIONS, &success, false); if (!success) goto BadEnd; int defusions = GetDlgItemInt(hDlg, IDC_EDIT_DEFUSIONS, &success, false); if (!success) goto BadEnd; int defused = GetDlgItemInt(hDlg, IDC_EDIT_DEFUSED, &success, false); if (!success) goto BadEnd; // Update stats in memory entry->setName(name); entry->kills = frags; entry->deaths = deaths; entry->hs = hs; entry->tks = tks; entry->shots = shots; entry->hits = hits; entry->damage = damage; entry->bPlants = plants; entry->bExplosions = explosions; entry->bDefusions = defusions; entry->bDefused = defused; int newPosition = entry->updatePosition(NULL); // Updates rank (prolly just calculates "frags - deaths" and moves up/down in rank) g_rank.saveRank(STATS_FILENAME); // Save changes to file // Now update our listbox UpdateListBox(hDlg); char buffer[256]; ke::SafeSprintf(buffer, sizeof(buffer)-1, "New rank of %s: %d", name, newPosition); MessageBox(hDlg, buffer, "Update succeeded", MB_OK); // In the listbox, we need to reselect the item we just updated. Use the new name. HWND listbox = GetDlgItem(hDlg, IDC_LIST); if (SendMessage(listbox, LB_SELECTSTRING, newPosition - 1, (LPARAM)name) == LB_ERR) MessageBox(hDlg, "Error selecting item!", "Oh fiddlesticks!", MB_OK); else { // Update ListboxItemSelected(hDlg); } return; BadEnd: MessageBox(hDlg, "Update failed", "Oh fiddlesticks!", MB_OK); } void ClearStats(HWND hDlg) { if (MessageBox(hDlg, "Are you sure? If you continue the whole csstats.dat will be wiped out!", "Omg!", MB_OKCANCEL | MB_DEFBUTTON2 | MB_ICONWARNING) != IDOK) return; g_rank.clear(); g_rank.saveRank(STATS_FILENAME); // Now update our listbox UpdateListBox(hDlg); // Update ListboxItemSelected(hDlg); } void DeleteRecord(HWND hDlg) { if (MessageBox(hDlg, "Are you sure?", "Omg!", MB_OKCANCEL | MB_DEFBUTTON2 | MB_ICONWARNING) != IDOK) return; BOOL success; int position = GetDlgItemInt(hDlg, IDC_EDIT_POSITION, &success, false); if (!success) goto BadEnd; char authid[32]; // "primary key" GetDlgItemText(hDlg, IDC_EDIT_AUTHID, authid, sizeof(authid)); RankSystem::RankStats* entry = g_rank.findEntryInRankByUnique(authid); if (!entry) { char buffer[256]; sprintf(buffer, "Authid %s not found!", authid); MessageBox(hDlg, buffer, "Update failed", MB_OK); return; } // Mark this record to delete it. entry->MarkToDelete(); // Save ranks from memory to disk. g_rank.saveRank(STATS_FILENAME); // Save changes to file // Clear memory. g_rank.clear(); // Reload from disk into memory. LoadRankFromFile(hDlg); // Update list box. UpdateListBox(hDlg); MessageBox(hDlg, "Deleted record", "Delete succeeded", MB_OK); return; BadEnd: MessageBox(hDlg, "Delete failed", "Oh fiddlesticks!", MB_OK); return; } // Message handler for WinCSXBox. LRESULT CALLBACK WinCSXBox(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_INITDIALOG: return InitWinCSXBox(hDlg); // load all data from file and fill the listbox with the shit case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: case IDCANCEL: EndDialog(hDlg, LOWORD(wParam)); PostQuitMessage(0); return TRUE; case IDC_LIST: switch (HIWORD(wParam)) { case LBN_SELCHANGE: // Omg omg, a line in linebox was selected. ListboxItemSelected(hDlg); return TRUE; } break; case IDC_ABOUT: DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hDlg, (DLGPROC)AboutBox); break; case IDC_BUTTON_SAVECHANGES: SaveChanges(hDlg); break; case IDC_BUTTON_CLEARSTATS: ClearStats(hDlg); break; case IDC_BUTTON_DELETE: DeleteRecord(hDlg); //DialogBox(hInst, (LPCTSTR)IDD_DELETEBOX, hDlg, (DLGPROC)DeleteBox); break; } break; } return FALSE; } // Message handler for AboutBox. LRESULT CALLBACK AboutBox(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: case IDCANCEL: EndDialog(hDlg, LOWORD(wParam)); return TRUE; } break; } return FALSE; }