2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
4 * All source code herein is the property of Volition, Inc. You may not sell
5 * or otherwise commercially exploit the source or things you created based on the
10 #include "stand_gui.h"
11 #include "osregistry.h"
13 #include "wx/statline.h"
14 #include "wx/filename.h"
15 #include "wx/stdpaths.h"
17 #include "wx/msgdlg.h"
18 #include "wx/process.h"
19 #include "wx/textfile.h"
20 #include "wx/socket.h"
21 #include "wx/cmdline.h"
22 #include "wx/access.h"
27 // taken from psnet.h and psnet2.h
29 #define DEFAULT_GAME_PORT 4000
30 #elif defined(FS2_DEMO)
31 #define DEFAULT_GAME_PORT 7802
33 #define DEFAULT_GAME_PORT 7808
36 // taken from osregistry.cpp
37 const char *Osreg_company_name = "Volition";
39 const char *Osreg_app_name = "FreeSpaceDemo";
40 #define PROFILE_NAME "FreeSpaceDemo.ini"
41 #elif defined(FS2_DEMO)
42 const char *Osreg_app_name = "FreeSpace2Demo";
43 #define PROFILE_NAME "FreeSpace2Demo.ini"
44 #elif defined(OEM_BUILD)
45 const char *Osreg_app_name = "FreeSpace2OEM";
46 #define PROFILE_NAME "FreeSpace2OEM.ini"
47 #elif defined(MAKE_FS1)
48 const char *Osreg_app_name = "FreeSpace";
49 #define PROFILE_NAME "FreeSpace.ini"
51 const char *Osreg_app_name = "FreeSpace2";
52 #define PROFILE_NAME "FreeSpace2.ini"
56 IMPLEMENT_APP(StandaloneApp)
58 bool StandaloneApp::OnInit()
60 if ( !wxApp::OnInit() ) {
64 std_client = new Standalone(NULL);
67 if ( !std_client->startFreeSpace(argc, argv) ) {
68 throw "Unable to start FreeSpace";
73 if ( !std_client->wsInitialize() ) {
74 throw "Unable to initialize WebSocket";
76 } catch (const char *err) {
77 wxMessageBox(err, "Error!", wxOK|wxICON_ERROR|wxCENTRE|wxSTAY_ON_TOP);
80 } catch (const bool retval) {
86 std_client->Show(true);
87 SetTopWindow(std_client);
92 void StandaloneApp::OnInitCmdLine(wxCmdLineParser& parser)
94 parser.SetCmdLine( wxT("") );
97 bool StandaloneApp::OnCmdLineParsed(wxCmdLineParser& WXUNUSED(parser))
102 StandaloneTimer::StandaloneTimer(Standalone *stand)
107 StandaloneTimer::~StandaloneTimer()
111 void StandaloneTimer::Notify()
113 m_stand->wsDoFrame();
116 StandPopup::StandPopup( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxFrame( parent, id, title, pos, size, style )
118 this->SetSizeHints( wxSize( 300,100 ), wxDefaultSize );
121 bSizer2 = new wxBoxSizer( wxVERTICAL );
123 wxFlexGridSizer* fgSizer3;
124 fgSizer3 = new wxFlexGridSizer( 0, 2, 0, 0 );
125 fgSizer3->AddGrowableRow(0, 1);
127 m_Label1 = new wxStaticText( this, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
128 m_Label1->Wrap( -1 );
129 fgSizer3->Add( m_Label1, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
131 m_Label2 = new wxStaticText( this, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
132 m_Label2->Wrap( -1 );
133 fgSizer3->Add( m_Label2, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
136 bSizer2->Add( fgSizer3, 1, wxALL|wxEXPAND, 10 );
139 this->SetSizer( bSizer2 );
141 bSizer2->Fit( this );
143 this->Centre( wxBOTH );
146 StandPopup::~StandPopup()
150 wxBEGIN_EVENT_TABLE(Standalone, wxDialog)
151 EVT_CLOSE(Standalone::OnClose)
152 EVT_BUTTON(ID_B_SHUTDOWN, Standalone::OnShutdown)
153 EVT_BUTTON(ID_B_KICK, Standalone::OnKick)
154 EVT_BUTTON(ID_B_MREFRESH, Standalone::OnMissionRefresh)
155 EVT_BUTTON(ID_B_RESET_ALL, Standalone::OnResetAll)
156 EVT_SLIDER(ID_FPS_SLIDER, Standalone::OnFPSSel)
157 EVT_TEXT_ENTER(ID_T_MSG, Standalone::OnServerMsg)
158 EVT_TEXT_ENTER(ID_T_SERVER_NAME, Standalone::OnServerNameChange)
159 EVT_TEXT_ENTER(ID_T_HOST_PASS, Standalone::OnHostPassChange)
160 EVT_CHOICE(ID_C_P_PLAYERS, Standalone::OnPinfoPlayer)
163 Standalone::Standalone( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style )
165 this->SetSizeHints( wxDefaultSize, wxDefaultSize );
168 fsport = DEFAULT_GAME_PORT;
169 stand_context = NULL;
170 wsi_standalone = NULL;
173 m_timer = new StandaloneTimer(this);
174 m_timer->Start(1000/30);
176 m_popup = new StandPopup(this);
177 m_popup->Show(false);
180 bSizer1 = new wxBoxSizer( wxVERTICAL );
182 wxNotebook* nbook = new wxNotebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
184 createTab_Server(nbook);
185 createTab_Multi(nbook);
186 createTab_Player(nbook);
187 createTab_GodStuff(nbook);
188 createTab_Debug(nbook);
190 bSizer1->Add( nbook, 1, wxEXPAND | wxALL, 5 );
192 wxButton* bshutdown = new wxButton( this, ID_B_SHUTDOWN, wxT("Shutdown"), wxDefaultPosition, wxDefaultSize, 0 );
193 bSizer1->Add( bshutdown, 0, wxALIGN_CENTER|wxALL, 5 );
196 this->SetSizer( bSizer1 );
198 bSizer1->SetSizeHints(this);
200 this->Centre( wxBOTH );
203 Standalone::~Standalone()
208 void Standalone::OnClose( wxCloseEvent& WXUNUSED(event) )
213 void Standalone::OnShutdown( wxCommandEvent& WXUNUSED(event) )
218 void Standalone::Shutdown()
223 std::string msg("shutdown");
226 lws_service(stand_context, 50);
228 lws_context_destroy(stand_context);
231 if ( wxProcess::Exists(fspid) ) {
232 // wait a little bit, and if process still exists then kill it
235 if ( wxProcess::Exists(fspid) ) {
236 wxProcess::Kill(fspid, wxSIGTERM);
243 void Standalone::OnServerNameChange(wxCommandEvent& WXUNUSED(event) )
245 std::string msg("S:name ");
247 msg.append( m_S_ServerName->GetValue().c_str() );
252 void Standalone::OnHostPassChange(wxCommandEvent& WXUNUSED(event) )
254 std::string msg("S:pass ");
256 msg.append( m_S_HostPass->GetValue().c_str() );
261 void Standalone::OnKick( wxCommandEvent& WXUNUSED(event) )
263 std::string msg("S:kick ");
267 if ( !m_S_Connections->PositionToXY(m_S_Connections->GetInsertionPoint(), &col, &row) ) {
271 wxString line = m_S_Connections->GetLineText(row);
273 if ( line.IsEmpty() ) {
277 wxArrayString ipaddr = wxSplit(line, ',');
279 msg.append( ipaddr.Item(0).c_str() );
284 void Standalone::OnMissionRefresh( wxCommandEvent& WXUNUSED(event) )
286 std::string msg("G:mrefresh");
291 void Standalone::OnResetAll( wxCommandEvent& WXUNUSED(event) )
293 std::string msg("reset");
298 void Standalone::OnFPSSel( wxCommandEvent& WXUNUSED(event) )
300 wxString fps = wxString::Format("%d", m_M_sliderFPS->GetValue());
302 m_M_FPS->SetLabel(fps);
304 std::string msg("M:fps ");
310 void Standalone::OnServerMsg( wxCommandEvent& WXUNUSED(event) )
312 if ( m_GS_msg->GetValue().IsEmpty() ) {
316 std::string msg("G:smsg ");
318 msg.append( m_GS_msg->GetValue().c_str() );
320 // strip off return char which GetValue() has
321 size_t pos = msg.find_last_not_of("\r\n");
323 if (pos != std::string::npos) {
332 void Standalone::OnPinfoPlayer(wxCommandEvent& WXUNUSED(event) )
334 int idx = m_P_Players->GetCurrentSelection();
336 if (idx == wxNOT_FOUND) {
340 std::string msg("P:info ");
342 msg.append( m_P_Players->GetString(idx).c_str() );
347 void Standalone::createTab_Server(wxNotebook* parent)
349 wxPanel* panel = new wxPanel( parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
351 wxBoxSizer *panelSizer = new wxBoxSizer( wxVERTICAL );
353 wxBoxSizer* bSizer = new wxBoxSizer( wxVERTICAL );
355 wxFlexGridSizer* fgSizer5 = new wxFlexGridSizer( 0, 2, 0, 0 );
356 fgSizer5->AddGrowableCol(1, 1);
358 wxStaticText* m_staticText6 = new wxStaticText( panel, wxID_ANY, wxT("Server Name"), wxDefaultPosition, wxDefaultSize, 0 );
359 fgSizer5->Add( m_staticText6, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
361 m_S_ServerName = new wxTextCtrl( panel, ID_T_SERVER_NAME, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER );
362 m_S_ServerName->SetMaxLength( 31 );
363 fgSizer5->Add( m_S_ServerName, 0, wxALL|wxEXPAND, 5 );
365 wxStaticText* m_staticText7 = new wxStaticText( panel, wxID_ANY, wxT("Host Password"), wxDefaultPosition, wxDefaultSize, 0 );
366 fgSizer5->Add( m_staticText7, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
368 m_S_HostPass = new wxTextCtrl( panel, ID_T_HOST_PASS, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER );
369 m_S_HostPass->SetMaxLength( 16 );
370 fgSizer5->Add( m_S_HostPass, 0, wxALL|wxEXPAND, 5 );
372 bSizer->Add( fgSizer5, 0, wxEXPAND, 0 );
374 wxStaticLine* m_staticline1 = new wxStaticLine( panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
375 bSizer->Add( m_staticline1, 0, wxEXPAND | wxALL, 5 );
377 wxFlexGridSizer* fgSizer7 = new wxFlexGridSizer( 0, 2, 0, 0 );
378 fgSizer7->SetFlexibleDirection( wxBOTH );
379 fgSizer7->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
381 wxStaticText* m_staticText9 = new wxStaticText( panel, wxID_ANY, wxT("# Connections :"), wxDefaultPosition, wxDefaultSize, 0 );
382 fgSizer7->Add( m_staticText9, 0, wxALL, 5 );
384 m_S_NumConn = new wxStaticText( panel, wxID_ANY, wxT("0"), wxDefaultPosition, wxDefaultSize, 0 );
385 fgSizer7->Add( m_S_NumConn, 0, wxALL, 5 );
387 bSizer->Add( fgSizer7, 0, wxEXPAND, 5 );
389 wxStaticText* m_staticText8 = new wxStaticText( panel, wxID_ANY, wxT("Address and Ping"), wxDefaultPosition, wxDefaultSize, 0 );
390 bSizer->Add( m_staticText8, 0, wxALL, 5 );
392 wxFlexGridSizer* fgSizer3 = new wxFlexGridSizer( 0, 2, 0, 0 );
393 fgSizer3->SetFlexibleDirection( wxBOTH );
394 fgSizer3->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
396 m_S_Connections = new wxTextCtrl( panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 300,300 ), wxTE_MULTILINE|wxTE_READONLY|wxTE_NO_VSCROLL );
397 fgSizer3->Add( m_S_Connections, 0, wxALL|wxEXPAND, 5 );
399 wxBoxSizer* bbSizer = new wxBoxSizer( wxVERTICAL );
401 m_S_btnKick = new wxButton( panel, ID_B_KICK, wxT("Kick"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
402 bbSizer->Add( m_S_btnKick, 1, wxALL, 5 );
404 m_S_btnMRefresh = new wxButton( panel, ID_B_MREFRESH, wxT(" Refresh\nMissions"), wxDefaultPosition, wxDefaultSize, 0 );
405 bbSizer->Add( m_S_btnMRefresh, 2, wxALL, 5 );
407 m_S_btnResetAll = new wxButton( panel, ID_B_RESET_ALL, wxT("Reset All"), wxDefaultPosition, wxDefaultSize, 0 );
408 bbSizer->Add( m_S_btnResetAll, 3, wxALL, 5 );
410 fgSizer3->Add( bbSizer, 1, wxEXPAND, 5 );
412 bSizer->Add( fgSizer3, 0, wxEXPAND, 5 );
414 panelSizer->Add( bSizer, 1, wxALL|wxEXPAND, 5 );
416 panel->SetSizer( panelSizer );
417 panelSizer->Fit( panel );
418 panelSizer->SetSizeHints( panel );
420 parent->AddPage( panel, wxT("Server"), true );
423 void Standalone::createTab_Multi(wxNotebook* parent)
425 wxPanel* panel = new wxPanel( parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
427 wxBoxSizer* panelSizer = new wxBoxSizer(wxVERTICAL);
429 wxBoxSizer* bSizer = new wxBoxSizer(wxVERTICAL);
431 m_M_sliderFPS = new wxSlider( panel, ID_FPS_SLIDER, 60, 10, 120, wxDefaultPosition, wxDefaultSize, wxSL_HORIZONTAL );
432 bSizer->Add( m_M_sliderFPS, 0, wxALL|wxEXPAND, 5 );
434 wxFlexGridSizer* fgSizer8;
435 fgSizer8 = new wxFlexGridSizer( 0, 5, 0, 0 );
436 fgSizer8->AddGrowableCol(2, 1);
438 wxStaticText* m_staticText71 = new wxStaticText( panel, wxID_ANY, wxT("Frame Cap : "), wxDefaultPosition, wxDefaultSize, 0 );
439 m_staticText71->Wrap( -1 );
440 fgSizer8->Add( m_staticText71, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
442 wxPanel* fpsPanel = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
443 wxBoxSizer* fpsSizer = new wxBoxSizer(wxHORIZONTAL);
444 m_M_FPS = new wxStaticText( fpsPanel, wxID_ANY, "60", wxDefaultPosition, wxSize(60, -1), 0 );
446 fpsSizer->Add( m_M_FPS, 0, wxALL, 2 );
447 fpsPanel->SetSizer(fpsSizer);
448 fpsSizer->Fit(fpsPanel);
449 fgSizer8->Add(fpsPanel, 0, wxALL, 3);
452 fgSizer8->Add( 0, 0, 1, wxEXPAND );
454 wxStaticText* m_staticText81 = new wxStaticText( panel, wxID_ANY, wxT("Realized FPS : "), wxDefaultPosition, wxDefaultSize, 0 );
455 m_staticText81->Wrap( -1 );
456 fgSizer8->Add( m_staticText81, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
458 wxPanel*fpscapPanel = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
459 wxBoxSizer* fpscapSizer = new wxBoxSizer(wxHORIZONTAL);
460 m_M_FPSRel = new wxStaticText( fpscapPanel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(60, -1), 0 );
461 m_M_FPSRel->Wrap( -1 );
462 fpscapSizer->Add( m_M_FPSRel, 0, wxALL, 2 );
463 fpscapPanel->SetSizer(fpscapSizer);
464 fpscapSizer->Fit(fpscapPanel);
465 fgSizer8->Add(fpscapPanel, 0, wxALL, 3);
468 bSizer->Add( fgSizer8, 0, wxEXPAND, 5 );
470 wxStaticLine* m_staticline2 = new wxStaticLine( panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
471 bSizer->Add( m_staticline2, 0, wxEXPAND | wxALL, 5 );
474 bSizer->Add( 0, 0, 0, wxALL, 20 );
477 wxFlexGridSizer* fgSizer9;
478 fgSizer9 = new wxFlexGridSizer( 0, 2, 0, 0 );
479 fgSizer9->SetFlexibleDirection( wxBOTH );
480 fgSizer9->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
482 wxStaticText* m_staticText91 = new wxStaticText( panel, wxID_ANY, wxT("Mission Name : "), wxDefaultPosition, wxDefaultSize, 0 );
483 m_staticText91->Wrap( -1 );
484 fgSizer9->Add( m_staticText91, 0, wxALL, 5 );
486 wxPanel* mnPanel = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
487 wxBoxSizer* mnSizer = new wxBoxSizer(wxHORIZONTAL);
488 m_M_MissionName = new wxStaticText( mnPanel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(150, -1), 0 );
489 m_M_MissionName->Wrap( -1 );
490 mnSizer->Add( m_M_MissionName, 0, wxALL, 2 );
491 mnPanel->SetSizer(mnSizer);
492 mnSizer->Fit(mnPanel);
493 fgSizer9->Add(mnPanel, 0, wxALL, 3);
495 wxStaticText* m_staticText101 = new wxStaticText( panel, wxID_ANY, wxT("Mission Time : "), wxDefaultPosition, wxDefaultSize, 0 );
496 m_staticText101->Wrap( -1 );
497 fgSizer9->Add( m_staticText101, 0, wxALL, 5 );
499 wxPanel* mtPanel = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
500 wxBoxSizer* mtSizer = new wxBoxSizer(wxHORIZONTAL);
501 m_M_MissionTime = new wxStaticText( mtPanel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(150, -1), 0 );
502 m_M_MissionTime->Wrap( -1 );
503 mtSizer->Add( m_M_MissionTime, 0, wxALL, 2 );
504 mtPanel->SetSizer(mtSizer);
505 mtSizer->Fit(mtPanel);
506 fgSizer9->Add(mtPanel, 0, wxALL, 3);
509 bSizer->Add( fgSizer9, 0, wxEXPAND, 5 );
512 bSizer->Add( 0, 0, 0, wxALL, 20 );
514 wxBoxSizer* bSizer3 = new wxBoxSizer(wxHORIZONTAL);
516 wxBoxSizer* bSizer4 = new wxBoxSizer(wxVERTICAL);
518 wxStaticText* m_staticText11 = new wxStaticText( panel, wxID_ANY, wxT("Mission Goals"), wxDefaultPosition, wxDefaultSize, 0 );
519 m_staticText11->Wrap( -1 );
520 bSizer4->Add( m_staticText11, 0, wxALL, 5 );
522 m_M_Goals = new wxTreeCtrl( panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTR_HIDE_ROOT|wxTR_NO_BUTTONS );
524 wxImageList *goal_imgs = new wxImageList(16, 16);
526 goal_imgs->Add( wxBitmap(goal_ord_xpm), wxColour(0xff, 0x0, 0xff) );
527 goal_imgs->Add( wxBitmap(goal_none_xpm), wxColour(0xff, 0xff, 0xff) );
528 goal_imgs->Add( wxBitmap(goal_inc_xpm), wxColour(0xff, 0xff, 0xff) );
529 goal_imgs->Add( wxBitmap(goal_com_xpm), wxColour(0xff, 0xff, 0xff) );
530 goal_imgs->Add( wxBitmap(goal_fail_xpm), wxColour(0xff, 0xff, 0xff) );
532 m_M_Goals->AssignImageList(goal_imgs);
534 wxTreeItemId root = m_M_Goals->AddRoot( wxT("Goals") );
536 m_M_GoalItems[0] = m_M_Goals->AppendItem(root, wxT("Primary Objectives"), 0);
537 m_M_GoalItems[1] = m_M_Goals->AppendItem(root, wxT("Secondary Objectives"), 0);
538 m_M_GoalItems[2] = m_M_Goals->AppendItem(root, wxT("Bonus Objectives"), 0);
540 bSizer4->Add( m_M_Goals, 1, wxALL|wxEXPAND, 5 );
542 bSizer3->Add(bSizer4, 1, wxEXPAND);
544 wxBoxSizer* bSizer5 = new wxBoxSizer(wxVERTICAL);
546 wxStaticText* m_staticText12 = new wxStaticText( panel, wxID_ANY, wxT("Netgame Information"), wxDefaultPosition, wxDefaultSize, 0 );
547 m_staticText12->Wrap( -1 );
548 bSizer5->Add( m_staticText12, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5 );
550 wxFlexGridSizer* fgSizer11;
551 fgSizer11 = new wxFlexGridSizer( 0, 2, 0, 15 );
552 fgSizer11->AddGrowableRow(0, 1);
553 fgSizer11->AddGrowableRow(1, 1);
554 fgSizer11->AddGrowableRow(2, 1);
555 fgSizer11->AddGrowableRow(3, 1);
557 wxStaticText* m_staticText13 = new wxStaticText( panel, wxID_ANY, wxT("Max Players"), wxDefaultPosition, wxDefaultSize, 0 );
558 m_staticText13->Wrap( -1 );
559 fgSizer11->Add( m_staticText13, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
561 m_M_ngMaxPlayers = new wxStaticText( panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
562 m_M_ngMaxPlayers->Wrap( -1 );
563 fgSizer11->Add( m_M_ngMaxPlayers, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
565 wxStaticText* m_staticText15 = new wxStaticText( panel, wxID_ANY, wxT("Max Observers"), wxDefaultPosition, wxDefaultSize, 0 );
566 m_staticText15->Wrap( -1 );
567 fgSizer11->Add( m_staticText15, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
569 m_M_ngMaxObservers = new wxStaticText( panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
570 m_M_ngMaxObservers->Wrap( -1 );
571 fgSizer11->Add( m_M_ngMaxObservers, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
573 wxStaticText* m_staticText17 = new wxStaticText( panel, wxID_ANY, wxT("Security"), wxDefaultPosition, wxDefaultSize, 0 );
574 m_staticText17->Wrap( -1 );
575 fgSizer11->Add( m_staticText17, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
577 m_M_ngSecurity = new wxStaticText( panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
578 m_M_ngSecurity->Wrap( -1 );
579 fgSizer11->Add( m_M_ngSecurity, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
581 wxStaticText* m_staticText19 = new wxStaticText( panel, wxID_ANY, wxT("Respawns"), wxDefaultPosition, wxDefaultSize, 0 );
582 m_staticText19->Wrap( -1 );
583 fgSizer11->Add( m_staticText19, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
585 m_M_ngRespawns = new wxStaticText( panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
586 m_M_ngRespawns->Wrap( -1 );
587 fgSizer11->Add( m_M_ngRespawns, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
589 bSizer5->Add( fgSizer11, 1, wxEXPAND );
591 bSizer3->Add(bSizer5, 1, wxEXPAND);
593 bSizer->Add( bSizer3, 1, wxEXPAND, 5 );
595 panelSizer->Add(bSizer, 1, wxALL|wxEXPAND, 5);
597 panel->SetSizer( panelSizer );
598 panelSizer->Fit( panel );
599 panelSizer->SetSizeHints( panel );
601 parent->AddPage( panel, wxT("Multi-Player") );
604 void Standalone::createTab_Player(wxNotebook* parent)
606 wxPanel* panel = new wxPanel( parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
608 wxBoxSizer* panelSizer = new wxBoxSizer( wxVERTICAL );
610 wxBoxSizer* bSizer = new wxBoxSizer( wxVERTICAL );
612 wxBoxSizer* bSizer21;
613 bSizer21 = new wxBoxSizer( wxHORIZONTAL );
615 wxStaticText* m_staticText211 = new wxStaticText( panel, wxID_ANY, wxT("Player"), wxDefaultPosition, wxDefaultSize, 0 );
616 m_staticText211->Wrap( -1 );
617 bSizer21->Add( m_staticText211, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
619 wxArrayString m_choice11Choices;
620 m_P_Players = new wxChoice( panel, ID_C_P_PLAYERS, wxDefaultPosition, wxSize(200, -1), m_choice11Choices, 0 );
621 m_P_Players->SetSelection( wxNOT_FOUND );
622 bSizer21->Add( m_P_Players, 0, wxALL, 5 );
624 bSizer->Add( bSizer21, 0, wxEXPAND );
627 wxStaticLine* m_staticline4 = new wxStaticLine( panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
628 bSizer->Add( m_staticline4, 0, wxEXPAND | wxALL, 5 );
630 wxFlexGridSizer* fgSizer14;
631 fgSizer14 = new wxFlexGridSizer( 0, 2, 0, 0 );
633 wxStaticText* m_staticText26 = new wxStaticText( panel, wxID_ANY, wxT("Ship Type"), wxDefaultPosition, wxDefaultSize, 0 );
634 m_staticText26->Wrap( -1 );
635 fgSizer14->Add( m_staticText26, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
637 wxPanel* stPanel = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
638 wxBoxSizer* stSizer = new wxBoxSizer(wxHORIZONTAL);
639 m_P_ShipType = new wxStaticText( stPanel, wxID_ANY, wxT(""), wxDefaultPosition, wxSize(150, -1), 0 );
640 m_P_ShipType->Wrap( -1 );
641 stSizer->Add(m_P_ShipType, 0, wxALL, 2);
642 stPanel->SetSizer(stSizer);
643 stSizer->Fit(stPanel);
644 fgSizer14->Add( stPanel, 0, wxALL, 5 );
646 wxStaticText* m_staticText28 = new wxStaticText( panel, wxID_ANY, wxT("Avg Ping"), wxDefaultPosition, wxDefaultSize, 0 );
647 m_staticText28->Wrap( -1 );
648 fgSizer14->Add( m_staticText28, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
650 wxPanel* apPanel = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
651 wxBoxSizer* apSizer = new wxBoxSizer(wxHORIZONTAL);
652 m_P_AvgPing = new wxStaticText( apPanel, wxID_ANY, wxT(""), wxDefaultPosition, wxSize(150, -1), 0 );
653 m_P_AvgPing->Wrap( -1 );
654 apSizer->Add(m_P_AvgPing, 0, wxALL, 2);
655 apPanel->SetSizer(apSizer);
656 apSizer->Fit(apPanel);
657 fgSizer14->Add( apPanel, 0, wxALL, 5 );
659 bSizer->Add( fgSizer14, 0, wxEXPAND );
661 bSizer->Add( 0, 0, 0, wxALL, 10);
664 bSizer6 = new wxBoxSizer( wxHORIZONTAL );
670 wxBoxSizer* atsboxSizer = new wxBoxSizer( wxVERTICAL );
672 wxStaticText* atsText = new wxStaticText( panel, wxID_ANY, wxT("All Time Stats") );
673 atsboxSizer->Add( atsText, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 );
675 wxFlexGridSizer* atsgSizer = new wxFlexGridSizer( 0, 2, 0, 0 );
676 atsgSizer->AddGrowableCol(1, 1);
680 wxStaticText* itxt = new wxStaticText( panel, wxID_ANY, wxT("Primary Shots"), wxDefaultPosition, wxDefaultSize, 0 );
682 atsgSizer->Add( itxt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
683 wxPanel* p1 = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
684 wxBoxSizer* p1sizer = new wxBoxSizer( wxHORIZONTAL );
685 m_P_atsPriShots = new wxStaticText( p1, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
686 m_P_atsPriShots->Wrap( -1 );
687 p1sizer->Add( m_P_atsPriShots, 1, wxALL|wxEXPAND, 1);
688 p1->SetSizer( p1sizer );
690 atsgSizer->Add( p1, 0, wxALL|wxEXPAND, 1 );
695 wxStaticText* itxt = new wxStaticText( panel, wxID_ANY, wxT("Primary Hits"), wxDefaultPosition, wxDefaultSize, 0 );
697 atsgSizer->Add( itxt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
698 wxPanel* p1 = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
699 wxBoxSizer* p1sizer = new wxBoxSizer( wxHORIZONTAL );
700 m_P_atsPriHits = new wxStaticText( p1, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
701 m_P_atsPriHits->Wrap( -1 );
702 p1sizer->Add( m_P_atsPriHits, 0, wxALL|wxEXPAND, 1);
703 p1->SetSizer( p1sizer );
705 atsgSizer->Add( p1, 0, wxALL|wxEXPAND, 1 );
710 wxStaticText* itxt = new wxStaticText( panel, wxID_ANY, wxT("Primary BH Hits"), wxDefaultPosition, wxDefaultSize, 0 );
712 atsgSizer->Add( itxt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
713 wxPanel* p1 = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
714 wxBoxSizer* p1sizer = new wxBoxSizer( wxHORIZONTAL );
715 m_P_atsPriBHHits = new wxStaticText( p1, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
716 m_P_atsPriBHHits->Wrap( -1 );
717 p1sizer->Add( m_P_atsPriBHHits, 0, wxALL|wxEXPAND, 1);
718 p1->SetSizer( p1sizer );
720 atsgSizer->Add( p1, 0, wxALL|wxEXPAND, 1 );
725 wxStaticText* itxt = new wxStaticText( panel, wxID_ANY, wxT("Primary Hit %"), wxDefaultPosition, wxDefaultSize, 0 );
727 atsgSizer->Add( itxt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
728 wxPanel* p1 = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
729 wxBoxSizer* p1sizer = new wxBoxSizer( wxHORIZONTAL );
730 m_P_atsPriHitPer = new wxStaticText( p1, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
731 m_P_atsPriHitPer->Wrap( -1 );
732 p1sizer->Add( m_P_atsPriHitPer, 0, wxALL|wxEXPAND, 1);
733 p1->SetSizer( p1sizer );
735 atsgSizer->Add( p1, 0, wxALL|wxEXPAND, 1 );
740 wxStaticText* itxt = new wxStaticText( panel, wxID_ANY, wxT("Primary BH Hit %"), wxDefaultPosition, wxDefaultSize, 0 );
742 atsgSizer->Add( itxt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
743 wxPanel* p1 = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
744 wxBoxSizer* p1sizer = new wxBoxSizer( wxHORIZONTAL );
745 m_P_atsPriBHHitPer = new wxStaticText( p1, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
746 m_P_atsPriBHHitPer->Wrap( -1 );
747 p1sizer->Add( m_P_atsPriBHHitPer, 0, wxALL|wxEXPAND, 1);
748 p1->SetSizer( p1sizer );
750 atsgSizer->Add( p1, 0, wxALL|wxEXPAND, 1 );
755 wxStaticText* itxt = new wxStaticText( panel, wxID_ANY, wxT("Secondary Shots"), wxDefaultPosition, wxDefaultSize, 0 );
757 atsgSizer->Add( itxt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
758 wxPanel* p1 = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
759 wxBoxSizer* p1sizer = new wxBoxSizer( wxHORIZONTAL );
760 m_P_atsSecShots = new wxStaticText( p1, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
761 m_P_atsSecShots->Wrap( -1 );
762 p1sizer->Add( m_P_atsSecShots, 0, wxALL|wxEXPAND, 1);
763 p1->SetSizer( p1sizer );
765 atsgSizer->Add( p1, 0, wxALL|wxEXPAND, 1 );
770 wxStaticText* itxt = new wxStaticText( panel, wxID_ANY, wxT("Secondary Hits"), wxDefaultPosition, wxDefaultSize, 0 );
772 atsgSizer->Add( itxt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
773 wxPanel* p1 = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
774 wxBoxSizer* p1sizer = new wxBoxSizer( wxHORIZONTAL );
775 m_P_atsSecHits = new wxStaticText( p1, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
776 m_P_atsSecHits->Wrap( -1 );
777 p1sizer->Add( m_P_atsSecHits, 0, wxALL|wxEXPAND, 1);
778 p1->SetSizer( p1sizer );
780 atsgSizer->Add( p1, 0, wxALL|wxEXPAND, 1 );
785 wxStaticText* itxt = new wxStaticText( panel, wxID_ANY, wxT("Secondary BH Hits"), wxDefaultPosition, wxDefaultSize, 0 );
787 atsgSizer->Add( itxt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
788 wxPanel* p1 = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
789 wxBoxSizer* p1sizer = new wxBoxSizer( wxHORIZONTAL );
790 m_P_atsSecBHHits = new wxStaticText( p1, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
791 m_P_atsSecBHHits->Wrap( -1 );
792 p1sizer->Add( m_P_atsSecBHHits, 0, wxALL|wxEXPAND, 1);
793 p1->SetSizer( p1sizer );
795 atsgSizer->Add( p1, 0, wxALL|wxEXPAND, 1 );
800 wxStaticText* itxt = new wxStaticText( panel, wxID_ANY, wxT("Secondary Hit %"), wxDefaultPosition, wxDefaultSize, 0 );
802 atsgSizer->Add( itxt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
803 wxPanel* p1 = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
804 wxBoxSizer* p1sizer = new wxBoxSizer( wxHORIZONTAL );
805 m_P_atsSecHitPer = new wxStaticText( p1, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
806 m_P_atsSecHitPer->Wrap( -1 );
807 p1sizer->Add( m_P_atsSecHitPer, 0, wxALL|wxEXPAND, 1);
808 p1->SetSizer( p1sizer );
810 atsgSizer->Add( p1, 0, wxALL|wxEXPAND, 1 );
813 // secondary BH hit %
815 wxStaticText* itxt = new wxStaticText( panel, wxID_ANY, wxT("Secondary BH Hit %"), wxDefaultPosition, wxDefaultSize, 0 );
817 atsgSizer->Add( itxt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
818 wxPanel* p1 = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
819 wxBoxSizer* p1sizer = new wxBoxSizer( wxHORIZONTAL );
820 m_P_atsSecBHHitPer = new wxStaticText( p1, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
821 m_P_atsSecBHHitPer->Wrap( -1 );
822 p1sizer->Add( m_P_atsSecBHHitPer, 0, wxALL|wxEXPAND, 1);
823 p1->SetSizer( p1sizer );
825 atsgSizer->Add( p1, 0, wxALL|wxEXPAND, 1 );
830 wxStaticText* itxt = new wxStaticText( panel, wxID_ANY, wxT("Assists"), wxDefaultPosition, wxDefaultSize, 0 );
832 atsgSizer->Add( itxt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
833 wxPanel* p1 = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
834 wxBoxSizer* p1sizer = new wxBoxSizer( wxHORIZONTAL );
835 m_P_atsAssists = new wxStaticText( p1, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
836 m_P_atsAssists->Wrap( -1 );
837 p1sizer->Add( m_P_atsAssists, 0, wxALL|wxEXPAND, 1);
838 p1->SetSizer( p1sizer );
840 atsgSizer->Add( p1, 0, wxALL|wxEXPAND, 1 );
843 atsboxSizer->Add( atsgSizer, 1, wxEXPAND );
845 bSizer6->Add( atsboxSizer, 1, wxEXPAND, 5 );
847 wxStaticLine* m_staticline3 = new wxStaticLine( panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL );
848 bSizer6->Add( m_staticline3, 0, wxEXPAND | wxALL, 5 );
854 wxBoxSizer* msboxSizer = new wxBoxSizer( wxVERTICAL );
856 wxStaticText* msText = new wxStaticText( panel, wxID_ANY, wxT("Mission Stats") );
857 msboxSizer->Add( msText, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 );
859 wxFlexGridSizer* msgSizer = new wxFlexGridSizer( 0, 2, 0, 0 );
860 msgSizer->AddGrowableCol(1, 1);
864 wxStaticText* itxt = new wxStaticText( panel, wxID_ANY, wxT("Primary Shots"), wxDefaultPosition, wxDefaultSize, 0 );
866 msgSizer->Add( itxt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
867 wxPanel* p1 = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
868 wxBoxSizer* p1sizer = new wxBoxSizer( wxHORIZONTAL );
869 m_P_msPriShots = new wxStaticText( p1, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
870 m_P_msPriShots->Wrap( -1 );
871 p1sizer->Add( m_P_msPriShots, 1, wxALL|wxEXPAND, 1);
872 p1->SetSizer( p1sizer );
874 msgSizer->Add( p1, 0, wxALL|wxEXPAND, 1 );
879 wxStaticText* itxt = new wxStaticText( panel, wxID_ANY, wxT("Primary Hits"), wxDefaultPosition, wxDefaultSize, 0 );
881 msgSizer->Add( itxt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
882 wxPanel* p1 = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
883 wxBoxSizer* p1sizer = new wxBoxSizer( wxHORIZONTAL );
884 m_P_msPriHits = new wxStaticText( p1, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
885 m_P_msPriHits->Wrap( -1 );
886 p1sizer->Add( m_P_msPriHits, 0, wxALL|wxEXPAND, 1);
887 p1->SetSizer( p1sizer );
889 msgSizer->Add( p1, 0, wxALL|wxEXPAND, 1 );
894 wxStaticText* itxt = new wxStaticText( panel, wxID_ANY, wxT("Primary BH Hits"), wxDefaultPosition, wxDefaultSize, 0 );
896 msgSizer->Add( itxt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
897 wxPanel* p1 = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
898 wxBoxSizer* p1sizer = new wxBoxSizer( wxHORIZONTAL );
899 m_P_msPriBHHits = new wxStaticText( p1, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
900 m_P_msPriBHHits->Wrap( -1 );
901 p1sizer->Add( m_P_msPriBHHits, 0, wxALL|wxEXPAND, 1);
902 p1->SetSizer( p1sizer );
904 msgSizer->Add( p1, 0, wxALL|wxEXPAND, 1 );
909 wxStaticText* itxt = new wxStaticText( panel, wxID_ANY, wxT("Primary Hit %"), wxDefaultPosition, wxDefaultSize, 0 );
911 msgSizer->Add( itxt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
912 wxPanel* p1 = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
913 wxBoxSizer* p1sizer = new wxBoxSizer( wxHORIZONTAL );
914 m_P_msPriHitPer = new wxStaticText( p1, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
915 m_P_msPriHitPer->Wrap( -1 );
916 p1sizer->Add( m_P_msPriHitPer, 0, wxALL|wxEXPAND, 1);
917 p1->SetSizer( p1sizer );
919 msgSizer->Add( p1, 0, wxALL|wxEXPAND, 1 );
924 wxStaticText* itxt = new wxStaticText( panel, wxID_ANY, wxT("Primary BH Hit %"), wxDefaultPosition, wxDefaultSize, 0 );
926 msgSizer->Add( itxt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
927 wxPanel* p1 = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
928 wxBoxSizer* p1sizer = new wxBoxSizer( wxHORIZONTAL );
929 m_P_msPriBHHitPer = new wxStaticText( p1, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
930 m_P_msPriBHHitPer->Wrap( -1 );
931 p1sizer->Add( m_P_msPriBHHitPer, 0, wxALL|wxEXPAND, 1);
932 p1->SetSizer( p1sizer );
934 msgSizer->Add( p1, 0, wxALL|wxEXPAND, 1 );
939 wxStaticText* itxt = new wxStaticText( panel, wxID_ANY, wxT("Secondary Shots"), wxDefaultPosition, wxDefaultSize, 0 );
941 msgSizer->Add( itxt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
942 wxPanel* p1 = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
943 wxBoxSizer* p1sizer = new wxBoxSizer( wxHORIZONTAL );
944 m_P_msSecShots = new wxStaticText( p1, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
945 m_P_msSecShots->Wrap( -1 );
946 p1sizer->Add( m_P_msSecShots, 0, wxALL|wxEXPAND, 1);
947 p1->SetSizer( p1sizer );
949 msgSizer->Add( p1, 0, wxALL|wxEXPAND, 1 );
954 wxStaticText* itxt = new wxStaticText( panel, wxID_ANY, wxT("Secondary Hits"), wxDefaultPosition, wxDefaultSize, 0 );
956 msgSizer->Add( itxt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
957 wxPanel* p1 = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
958 wxBoxSizer* p1sizer = new wxBoxSizer( wxHORIZONTAL );
959 m_P_msSecHits = new wxStaticText( p1, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
960 m_P_msSecHits->Wrap( -1 );
961 p1sizer->Add( m_P_msSecHits, 0, wxALL|wxEXPAND, 1);
962 p1->SetSizer( p1sizer );
964 msgSizer->Add( p1, 0, wxALL|wxEXPAND, 1 );
969 wxStaticText* itxt = new wxStaticText( panel, wxID_ANY, wxT("Secondary BH Hits"), wxDefaultPosition, wxDefaultSize, 0 );
971 msgSizer->Add( itxt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
972 wxPanel* p1 = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
973 wxBoxSizer* p1sizer = new wxBoxSizer( wxHORIZONTAL );
974 m_P_msSecBHHits = new wxStaticText( p1, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
975 m_P_msSecBHHits->Wrap( -1 );
976 p1sizer->Add( m_P_msSecBHHits, 0, wxALL|wxEXPAND, 1);
977 p1->SetSizer( p1sizer );
979 msgSizer->Add( p1, 0, wxALL|wxEXPAND, 1 );
984 wxStaticText* itxt = new wxStaticText( panel, wxID_ANY, wxT("Secondary Hit %"), wxDefaultPosition, wxDefaultSize, 0 );
986 msgSizer->Add( itxt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
987 wxPanel* p1 = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
988 wxBoxSizer* p1sizer = new wxBoxSizer( wxHORIZONTAL );
989 m_P_msSecHitPer = new wxStaticText( p1, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
990 m_P_msSecHitPer->Wrap( -1 );
991 p1sizer->Add( m_P_msSecHitPer, 0, wxALL|wxEXPAND, 1);
992 p1->SetSizer( p1sizer );
994 msgSizer->Add( p1, 0, wxALL|wxEXPAND, 1 );
997 // secondary BH hit %
999 wxStaticText* itxt = new wxStaticText( panel, wxID_ANY, wxT("Secondary BH Hit %"), wxDefaultPosition, wxDefaultSize, 0 );
1001 msgSizer->Add( itxt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
1002 wxPanel* p1 = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
1003 wxBoxSizer* p1sizer = new wxBoxSizer( wxHORIZONTAL );
1004 m_P_msSecBHHitPer = new wxStaticText( p1, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
1005 m_P_msSecBHHitPer->Wrap( -1 );
1006 p1sizer->Add( m_P_msSecBHHitPer, 0, wxALL|wxEXPAND, 1);
1007 p1->SetSizer( p1sizer );
1009 msgSizer->Add( p1, 0, wxALL|wxEXPAND, 1 );
1014 wxStaticText* itxt = new wxStaticText( panel, wxID_ANY, wxT("Assists"), wxDefaultPosition, wxDefaultSize, 0 );
1016 msgSizer->Add( itxt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
1017 wxPanel* p1 = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
1018 wxBoxSizer* p1sizer = new wxBoxSizer( wxHORIZONTAL );
1019 m_P_msAssists = new wxStaticText( p1, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
1020 m_P_msAssists->Wrap( -1 );
1021 p1sizer->Add( m_P_msAssists, 0, wxALL|wxEXPAND, 1);
1022 p1->SetSizer( p1sizer );
1024 msgSizer->Add( p1, 0, wxALL|wxEXPAND, 1 );
1027 msboxSizer->Add( msgSizer, 1, wxEXPAND );
1029 bSizer6->Add( msboxSizer, 1, wxEXPAND );
1031 bSizer->Add( bSizer6, 1, wxEXPAND );
1033 panelSizer->Add( bSizer, 1, wxALL|wxEXPAND, 5 );
1035 panel->SetSizer( panelSizer );
1036 panelSizer->Fit( panel );
1037 panelSizer->SetSizeHints(panel);
1039 parent->AddPage( panel, wxT("Player Info") );
1042 void Standalone::createTab_GodStuff(wxNotebook* parent)
1044 wxPanel* panel = new wxPanel( parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
1046 wxBoxSizer* panelSizer = new wxBoxSizer( wxVERTICAL );
1048 wxBoxSizer* bSizer = new wxBoxSizer( wxVERTICAL );
1050 wxBoxSizer* bSizer2 = new wxBoxSizer( wxHORIZONTAL );
1052 wxStaticText* m_staticText21 = new wxStaticText( panel, wxID_ANY, wxT("Player"), wxDefaultPosition, wxDefaultSize, 0 );
1053 bSizer2->Add( m_staticText21, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
1055 wxArrayString m_choice1Choices;
1056 m_GS_Players = new wxChoice( panel, wxID_ANY, wxDefaultPosition, wxSize(200, -1), m_choice1Choices, 0 );
1057 m_GS_Players->SetSelection( wxNOT_FOUND );
1058 bSizer2->Add( m_GS_Players, 0, wxALL|wxEXPAND, 5 );
1060 bSizer->Add( bSizer2, 0, wxEXPAND, 5 );
1062 bSizer->Add( 0, 0, 0, wxALL, 10 );
1064 wxStaticText* m_staticText22 = new wxStaticText( panel, wxID_ANY, wxT("Server Message"), wxDefaultPosition, wxDefaultSize, 0 );
1065 bSizer->Add( m_staticText22, 0, wxALL, 5 );
1067 m_GS_msg = new wxTextCtrl( panel, ID_T_MSG, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER );
1068 m_GS_msg->SetMaxLength(150);
1069 bSizer->Add( m_GS_msg, 0, wxALL|wxEXPAND, 5 );
1071 bSizer->Add( 0, 0, 0, wxALL, 5 );
1073 m_GS_Messages = new wxTextCtrl( panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY );
1074 bSizer->Add( m_GS_Messages, 1, wxALL|wxEXPAND, 5 );
1076 panelSizer->Add( bSizer, 1, wxALL|wxEXPAND, 5 );
1078 panel->SetSizer( panelSizer );
1079 panelSizer->Fit( panel );
1080 panelSizer->SetSizeHints( panel );
1082 parent->AddPage( panel, wxT("God Stuff") );
1085 void Standalone::createTab_Debug(wxNotebook* parent)
1087 wxPanel* panel = new wxPanel( parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
1089 wxBoxSizer* bSizer = new wxBoxSizer( wxVERTICAL );
1091 wxBoxSizer* hbSizer = new wxBoxSizer( wxHORIZONTAL );
1093 wxStaticText* m_staticText1 = new wxStaticText( panel, wxID_ANY, wxT("Standalone State :"), wxDefaultPosition, wxDefaultSize, 0 );
1094 hbSizer->Add( m_staticText1, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
1096 wxPanel* p1 = new wxPanel( panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER );
1098 wxBoxSizer* p1Sizer = new wxBoxSizer( wxHORIZONTAL );
1100 m_D_State = new wxStaticText( p1, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
1101 p1Sizer->Add( m_D_State, 1, wxALL|wxEXPAND, 2);
1103 p1->SetSizer( p1Sizer );
1106 hbSizer->Add( p1, 1, wxALL|wxEXPAND, 5 );
1108 bSizer->Add( hbSizer, 0, wxALL|wxEXPAND, 5 );
1110 panel->SetSizer( bSizer );
1113 bSizer->Fit( panel );
1115 parent->AddPage( panel, wxT("Debug") );
1118 bool Standalone::startFreeSpace(int argc, wxCmdLineArgsArray &argv)
1120 wxString epath = wxFileName(wxStandardPaths::Get().GetExecutablePath()).GetPath(true);
1121 bool cmd_port = false;
1122 bool shutdown_cmd = false;
1124 epath.Append( wxT("fs") );
1127 epath.Append( wxT("2") );
1130 #if defined(FS1_DEMO) || defined(FS2_DEMO)
1131 epath.Append( wxT("demo") );
1135 epath.Append( wxT(".exe") );
1138 epath.Append( wxT(" -standalone") );
1140 for (int i = 1; i < argc; i++) {
1141 wxString arg( argv[i] );
1143 // check if -port argument and set var
1144 if ( (argc > i+1) && (arg.Contains( wxT("-port") ) || arg.IsSameAs( wxT("-o") )) ) {
1145 fsport = wxAtoi(argv[i+1]);
1149 // if we have help or version options, exit after game exec
1150 if ( arg.Contains( wxT("-help") ) || arg.Contains( wxT("-version") )
1151 || arg.IsSameAs( wxT("-h") ) || arg.IsSameAs( wxT("-v") ) ) {
1152 shutdown_cmd = true;
1155 epath.Append( wxT(" ") );
1159 // if port isn't specified on cmdline, check ini file for "ForcePort" value
1161 char *u_path = SDL_GetPrefPath(Osreg_company_name, Osreg_app_name);
1164 wxFileName ini_name(u_path, PROFILE_NAME);
1165 wxTextFile fs_ini( ini_name.GetFullPath() );
1167 if ( fs_ini.Open() ) {
1170 for (line = fs_ini.GetLastLine(); fs_ini.GetCurrentLine() > 0; line = fs_ini.GetPrevLine()) {
1171 wxArrayString chk = wxSplit(line, '=');
1173 if (chk.GetCount() == 2) {
1174 if (chk.Item(0) == "ForcePort") {
1175 int port = wxAtoi( chk.Item(1) );
1193 // test if socket is in use (in case exising instance is running on same port)
1194 wxDatagramSocket *sock;
1198 addr.Service( (unsigned short)fsport );
1200 sock = new wxDatagramSocket(addr);
1202 bool isok = sock->IsOk();
1207 throw "Unable to start FreeSpace\n\nAn instance is already running";
1210 // start game executable
1211 fspid = wxExecute(epath, wxEXEC_ASYNC | wxEXEC_MAKE_GROUP_LEADER | wxEXEC_HIDE_CONSOLE);
1213 // throw shutdown if we should exit (such as help or version cmdline options)
1221 void Standalone::ResetAll()
1223 m_popup->Show(false);
1225 m_S_ServerName->Clear();
1226 m_S_HostPass->Clear();
1227 m_S_NumConn->SetLabel( wxT("0") );
1228 m_S_Connections->Clear();
1230 m_M_sliderFPS->SetValue(60);
1231 m_M_FPS->SetLabel("60");
1232 m_M_FPSRel->SetLabel( wxT("0.0") );
1233 m_M_MissionName->SetLabel("");
1234 m_M_MissionTime->SetLabel("");
1235 m_M_ngMaxPlayers->SetLabel("");
1236 m_M_ngMaxObservers->SetLabel("");
1237 m_M_ngSecurity->SetLabel("");
1238 m_M_ngRespawns->SetLabel("");
1240 for (int idx = 0; idx < 3; idx++) {
1241 m_M_Goals->DeleteChildren( m_M_GoalItems[idx] );
1244 m_P_Players->Clear();
1245 m_P_ShipType->SetLabel("");
1246 m_P_AvgPing->SetLabel("");
1247 m_P_atsPriShots->SetLabel("");
1248 m_P_atsPriHits->SetLabel("");
1249 m_P_atsPriBHHits->SetLabel("");
1250 m_P_atsPriHitPer->SetLabel("");
1251 m_P_atsPriBHHitPer->SetLabel("");
1252 m_P_atsSecShots->SetLabel("");
1253 m_P_atsSecHits->SetLabel("");
1254 m_P_atsSecBHHits->SetLabel("");
1255 m_P_atsSecHitPer->SetLabel("");
1256 m_P_atsSecBHHitPer->SetLabel("");
1257 m_P_atsAssists->SetLabel("");
1258 m_P_msPriShots->SetLabel("");
1259 m_P_msPriHits->SetLabel("");
1260 m_P_msPriBHHits->SetLabel("");
1261 m_P_msPriHitPer->SetLabel("");
1262 m_P_msPriBHHitPer->SetLabel("");
1263 m_P_msSecShots->SetLabel("");
1264 m_P_msSecHits->SetLabel("");
1265 m_P_msSecBHHits->SetLabel("");
1266 m_P_msSecHitPer->SetLabel("");
1267 m_P_msSecBHHitPer->SetLabel("");
1268 m_P_msAssists->SetLabel("");
1270 m_GS_Players->Clear();
1272 m_GS_Messages->Clear();
1274 m_D_State->SetLabel("");
1277 static int callback_standalone_client(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len)
1279 #define MAX_BUF_SIZE 1050
1280 unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + MAX_BUF_SIZE + LWS_SEND_BUFFER_POST_PADDING];
1281 unsigned char *p = &buf[LWS_SEND_BUFFER_PRE_PADDING];
1286 case LWS_CALLBACK_CLIENT_ESTABLISHED:
1287 lws_callback_on_writable(wsi);
1290 case LWS_CALLBACK_CLOSED:
1291 wxGetApp().Client().wsDisconnect();
1294 case LWS_CALLBACK_CLIENT_RECEIVE:
1295 wxGetApp().Client().wsMessage( (const char *)in, len );
1298 case LWS_CALLBACK_CLIENT_WRITEABLE: {
1299 while ( !wxGetApp().Client().wsGetSendBuffer().empty() ) {
1300 std::string msg = wxGetApp().Client().wsGetSendBuffer().front();
1302 size = wxStrlcpy((char *)p, msg.c_str(), MAX_BUF_SIZE);
1304 rval = lws_write(wsi, p, size, LWS_WRITE_TEXT);
1307 lwsl_err("ERROR sending buffer!\n");
1311 wxGetApp().Client().wsGetSendBuffer().pop_front();
1313 if ( lws_send_pipe_choked(wsi) ) {
1314 lws_callback_on_writable(wsi);
1323 case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
1324 wxGetApp().Client().wsDisconnect();
1334 static struct lws_protocols protocols[] = {
1337 callback_standalone_client,
1341 { NULL, NULL, 0, 0 }
1344 bool Standalone::wsInitialize()
1346 struct lws_context_creation_info info;
1348 memset(&info, 0, sizeof(info));
1349 memset(&ccinfo, 0, sizeof(ccinfo));
1351 info.port = CONTEXT_PORT_NO_LISTEN;
1352 info.protocols = protocols;
1356 stand_context = lws_create_context(&info);
1358 if (stand_context == NULL) {
1362 ccinfo.context = stand_context;
1363 ccinfo.address = "127.0.0.1";
1364 ccinfo.port = fsport;
1366 ccinfo.host = ccinfo.address;
1367 ccinfo.origin = ccinfo.address;
1368 ccinfo.ietf_version_or_minus_one = -1;
1369 ccinfo.protocol = protocols[0].name;
1371 // async call, actual connection to occur later
1372 wsi_standalone = lws_client_connect_via_info(&ccinfo);
1374 lws_service(stand_context, 0);
1379 void Standalone::wsDoFrame()
1381 if ( !stand_context ) {
1385 // if connection is lost attempt reconnect every 2 seconds
1386 if ( !wsi_standalone && !(++m_rate_limit % 60) ) {
1387 // restart game process if it terminated
1388 if ( !wxProcess::Exists(fspid) ) {
1390 startFreeSpace(wxGetApp().argc, wxGetApp().argv);
1391 } catch (const char *err) {
1392 wxMessageBox(err, "Error!", wxOK|wxICON_ERROR|wxCENTRE|wxSTAY_ON_TOP);
1395 } catch (const bool) { }
1400 wsi_standalone = lws_client_connect_via_info(&ccinfo);
1404 lws_service(stand_context, 0);
1407 void Standalone::wsDisconnect()
1409 wsi_standalone = NULL;
1412 void Standalone::wsMessage(const char *msg, size_t len)
1414 if (msg == NULL || len < 5) {
1418 if ( !wxStrcmp(msg, "reset") ) {
1423 if ( !wxStrncmp(msg, "popup ", 6) ) {
1425 m_popup->Show(false);
1427 wxArrayString popmsg = wxSplit(msg+6, ';');
1429 m_popup->SetTitle( popmsg.Item(0) );
1430 m_popup->SetLabel1( popmsg.Item(1) );
1431 m_popup->SetLabel2( popmsg.Item(2) );
1433 m_popup->Layout(); // layout required to deal with label size changes
1434 m_popup->CenterOnParent();
1435 m_popup->Show(true);
1441 char mtype = msg[0];
1445 } else if (mtype == 'D') {
1446 m_D_State->SetLabel(msg+2);
1449 else if (mtype == 'S') {
1450 wxString cmd(msg+2, 4);
1452 if (cmd == "name") {
1453 m_S_ServerName->SetValue(msg+7);
1454 } else if (cmd == "pass") {
1455 m_S_HostPass->SetValue(msg+7);
1456 } else if (cmd == "conn") {
1457 wxArrayString conns = wxSplit(msg+7, ';');
1459 size_t n_conn = conns.size();
1461 m_S_NumConn->SetLabel( wxString::Format("%u", (unsigned int)n_conn) );
1463 m_S_Connections->Clear();
1465 for (size_t idx = 0; idx < n_conn; idx++) {
1466 wxArrayString m_conn = wxSplit(conns.Item(idx), ',');
1468 m_P_Players->Append( m_conn.Item(0) );
1469 m_GS_Players->Append( m_conn.Item(0) );
1471 m_S_Connections->AppendText( m_conn.Item(1) + wxT(", \n") );
1473 } else if (cmd == "ping") {
1474 wxArrayString ping_list = wxSplit(msg+7, ',');
1476 size_t n_pings = ping_list.size();
1478 size_t offset_pos = 0;
1479 long col = 0, row = 0;
1481 m_S_Connections->PositionToXY(m_S_Connections->GetInsertionPoint(), &col, &row);
1483 for (size_t idx = 0; idx < n_pings; idx++) {
1484 size_t from_pos = m_S_Connections->GetValue().find(", ", offset_pos);
1486 if (from_pos == wxString::npos) {
1492 size_t to_pos = m_S_Connections->GetValue().find_first_of("\n", from_pos);
1494 m_S_Connections->Replace(from_pos, to_pos, ping_list.Item(idx));
1496 offset_pos = to_pos;
1499 // move intersion point to start of original line (avoids accidental kick)
1500 m_S_Connections->SetInsertionPoint( m_S_Connections->XYToPosition(0, row) );
1504 else if (mtype == 'M') {
1505 wxString cmd(msg+2, 4);
1507 if (cmd == "name") {
1508 m_M_MissionName->SetLabel(msg+7);
1509 } else if (cmd == "time") {
1510 m_M_MissionTime->SetLabel(msg+7);
1511 } else if (cmd == "info") {
1512 wxArrayString ng_info = wxSplit(msg+7, ',');
1514 m_M_ngMaxPlayers->SetLabel( ng_info.Item(0) );
1515 m_M_ngMaxObservers->SetLabel( ng_info.Item(1) );
1516 m_M_ngSecurity->SetLabel( ng_info.Item(2) );
1517 m_M_ngRespawns->SetLabel( ng_info.Item(3) );
1518 } else if (cmd == "rfps") {
1519 m_M_FPSRel->SetLabel(msg+7);
1520 } else if (cmd == "goal") {
1521 wxArrayString objectives = wxSplit(msg+7, ';');
1523 size_t n_objectives = objectives.size();
1524 wxASSERT(n_objectives == 3);
1526 for (size_t idx = 0; idx < n_objectives; idx++) {
1527 wxArrayString goals = wxSplit( objectives.Item(idx), ',' );
1529 size_t n_goals = goals.size();
1531 m_M_Goals->DeleteChildren(m_M_GoalItems[idx]);
1533 for (size_t j = 0; j < n_goals; j++) {
1534 char status = goals.Item(j).GetChar(0);
1535 wxString goal = goals.Item(j).substr(2);
1540 if (goal == "none") {
1561 m_M_Goals->AppendItem(m_M_GoalItems[idx], goal, img);
1565 m_M_Goals->ExpandAll();
1569 else if (mtype == 'P') {
1570 wxString cmd(msg+2, 4);
1572 if (cmd == "info") {
1573 wxArrayString pinfo = wxSplit(msg+7, ';');
1574 wxArrayString stats;
1576 m_P_ShipType->SetLabel( pinfo.Item(0) );
1577 m_P_AvgPing->SetLabel( pinfo.Item(1) );
1579 stats = wxSplit(pinfo.Item(2), ',');
1581 m_P_atsPriShots->SetLabel( stats.Item(0) );
1582 m_P_atsPriHits->SetLabel( stats.Item(1) );
1583 m_P_atsPriBHHits->SetLabel( stats.Item(2) );
1584 m_P_atsPriHitPer->SetLabel( stats.Item(3) );
1585 m_P_atsPriBHHitPer->SetLabel( stats.Item(4) );
1586 m_P_atsSecShots->SetLabel( stats.Item(5) );
1587 m_P_atsSecHits->SetLabel( stats.Item(6) );
1588 m_P_atsSecBHHits->SetLabel( stats.Item(7) );
1589 m_P_atsSecHitPer->SetLabel( stats.Item(8) );
1590 m_P_atsSecBHHitPer->SetLabel( stats.Item(9) );
1591 m_P_atsAssists->SetLabel( stats.Item(10) );
1593 stats = wxSplit(pinfo.Item(3), ',');
1595 m_P_msPriShots->SetLabel( stats.Item(0) );
1596 m_P_msPriHits->SetLabel( stats.Item(1) );
1597 m_P_msPriBHHits->SetLabel( stats.Item(2) );
1598 m_P_msPriHitPer->SetLabel( stats.Item(3) );
1599 m_P_msPriBHHitPer->SetLabel( stats.Item(4) );
1600 m_P_msSecShots->SetLabel( stats.Item(5) );
1601 m_P_msSecHits->SetLabel( stats.Item(6) );
1602 m_P_msSecBHHits->SetLabel( stats.Item(7) );
1603 m_P_msSecHitPer->SetLabel( stats.Item(8) );
1604 m_P_msSecBHHitPer->SetLabel( stats.Item(9) );
1605 m_P_msAssists->SetLabel( stats.Item(10) );
1609 else if (mtype == 'G') {
1610 wxString cmd(msg+2, 4);
1612 if (cmd == "mesg") {
1613 m_GS_Messages->AppendText(msg+7);
1618 void Standalone::wsSend(std::string &msg)
1620 send_buf.push_back(msg);
1622 if (wsi_standalone) {
1623 lws_callback_on_writable(wsi_standalone);