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"
25 // taken from psnet.h and psnet2.h
27 #define DEFAULT_GAME_PORT 4000
28 #elif defined(FS2_DEMO)
29 #define DEFAULT_GAME_PORT 7802
31 #define DEFAULT_GAME_PORT 7808
34 // taken from osregistry.cpp
35 const char *Osreg_company_name = "Volition";
37 const char *Osreg_title = "FreeSpace Demo";
38 #define PROFILE_NAME "FreeSpaceDemo.ini"
39 #elif defined(FS2_DEMO)
40 const char *Osreg_title = "FreeSpace 2 Demo";
41 #define PROFILE_NAME "FreeSpace2Demo.ini"
42 #elif defined(OEM_BUILD)
43 const char *Osreg_title = "FreeSpace 2 OEM";
44 #define PROFILE_NAME "FreeSpace2OEM.ini"
45 #elif defined(MAKE_FS1)
46 const char *Osreg_title = "FreeSpace";
47 #define PROFILE_NAME "FreeSpace.ini"
49 const char *Osreg_title = "FreeSpace 2";
50 #define PROFILE_NAME "FreeSpace2.ini"
54 IMPLEMENT_APP(StandaloneApp)
56 bool StandaloneApp::OnInit()
58 if ( !wxApp::OnInit() ) {
62 std_client = new Standalone(NULL);
65 if ( !std_client->startFreeSpace(argc, argv) ) {
66 throw "Unable to start FreeSpace";
71 if ( !std_client->wsInitialize() ) {
72 throw "Unable to initialize WebSocket";
74 } catch (const char *err) {
75 wxMessageBox(err, "Error!", wxOK|wxICON_ERROR|wxCENTRE|wxSTAY_ON_TOP);
80 std_client->Show(true);
81 SetTopWindow(std_client);
86 StandaloneTimer::StandaloneTimer(Standalone *stand)
91 StandaloneTimer::~StandaloneTimer()
95 void StandaloneTimer::Notify()
100 StandPopup::StandPopup( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxFrame( parent, id, title, pos, size, style )
102 this->SetSizeHints( wxSize( 300,100 ), wxDefaultSize );
105 bSizer2 = new wxBoxSizer( wxVERTICAL );
107 wxFlexGridSizer* fgSizer3;
108 fgSizer3 = new wxFlexGridSizer( 0, 2, 0, 0 );
109 fgSizer3->AddGrowableRow(0, 1);
111 m_Label1 = new wxStaticText( this, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
112 m_Label1->Wrap( -1 );
113 fgSizer3->Add( m_Label1, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
115 m_Label2 = new wxStaticText( this, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
116 m_Label2->Wrap( -1 );
117 fgSizer3->Add( m_Label2, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
120 bSizer2->Add( fgSizer3, 1, wxALL|wxEXPAND, 10 );
123 this->SetSizer( bSizer2 );
125 bSizer2->Fit( this );
127 this->Centre( wxBOTH );
130 StandPopup::~StandPopup()
134 wxBEGIN_EVENT_TABLE(Standalone, wxDialog)
135 EVT_CLOSE(Standalone::OnClose)
136 EVT_BUTTON(ID_B_SHUTDOWN, Standalone::OnShutdown)
137 EVT_BUTTON(ID_B_KICK, Standalone::OnKick)
138 EVT_BUTTON(ID_B_MREFRESH, Standalone::OnMissionRefresh)
139 EVT_BUTTON(ID_B_RESET_ALL, Standalone::OnResetAll)
140 EVT_SLIDER(ID_FPS_SLIDER, Standalone::OnFPSSel)
141 EVT_TEXT_ENTER(ID_T_MSG, Standalone::OnServerMsg)
142 EVT_TEXT_ENTER(ID_T_SERVER_NAME, Standalone::OnServerNameChange)
143 EVT_TEXT_ENTER(ID_T_HOST_PASS, Standalone::OnHostPassChange)
144 EVT_CHOICE(ID_C_P_PLAYERS, Standalone::OnPinfoPlayer)
147 Standalone::Standalone( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style )
149 this->SetSizeHints( wxDefaultSize, wxDefaultSize );
152 fsport = DEFAULT_GAME_PORT;
153 stand_context = NULL;
154 wsi_standalone = NULL;
157 m_timer = new StandaloneTimer(this);
158 m_timer->Start(1000/30);
160 m_popup = new StandPopup(this);
161 m_popup->Show(false);
164 bSizer1 = new wxBoxSizer( wxVERTICAL );
166 wxNotebook* nbook = new wxNotebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
168 createTab_Server(nbook);
169 createTab_Multi(nbook);
170 createTab_Player(nbook);
171 createTab_GodStuff(nbook);
172 createTab_Debug(nbook);
174 bSizer1->Add( nbook, 1, wxEXPAND | wxALL, 5 );
176 wxButton* bshutdown = new wxButton( this, ID_B_SHUTDOWN, wxT("Shutdown"), wxDefaultPosition, wxDefaultSize, 0 );
177 bSizer1->Add( bshutdown, 0, wxALIGN_CENTER|wxALL, 5 );
180 this->SetSizer( bSizer1 );
182 bSizer1->SetSizeHints(this);
184 this->Centre( wxBOTH );
187 Standalone::~Standalone()
192 void Standalone::OnClose( wxCloseEvent& WXUNUSED(event) )
197 void Standalone::OnShutdown( wxCommandEvent& WXUNUSED(event) )
202 void Standalone::Shutdown()
205 std::string msg("shutdown");
208 lws_service(stand_context, 50);
210 lws_context_destroy(stand_context);
213 if ( wxProcess::Exists(fspid) ) {
214 // wait a little bit, and if process still exists then kill it
217 if ( wxProcess::Exists(fspid) ) {
218 wxProcess::Kill(fspid, wxSIGTERM);
225 void Standalone::OnServerNameChange(wxCommandEvent& WXUNUSED(event) )
227 std::string msg("S:name ");
229 msg.append( m_S_ServerName->GetValue().c_str() );
234 void Standalone::OnHostPassChange(wxCommandEvent& WXUNUSED(event) )
236 std::string msg("S:pass ");
238 msg.append( m_S_HostPass->GetValue().c_str() );
243 void Standalone::OnKick( wxCommandEvent& WXUNUSED(event) )
245 std::string msg("S:kick ");
249 if ( !m_S_Connections->PositionToXY(m_S_Connections->GetInsertionPoint(), &col, &row) ) {
253 wxString line = m_S_Connections->GetLineText(row);
255 if ( line.IsEmpty() ) {
259 wxArrayString ipaddr = wxSplit(line, ',');
261 msg.append( ipaddr.Item(0).c_str() );
266 void Standalone::OnMissionRefresh( wxCommandEvent& WXUNUSED(event) )
268 std::string msg("G:mrefresh");
273 void Standalone::OnResetAll( wxCommandEvent& WXUNUSED(event) )
275 std::string msg("reset");
280 void Standalone::OnFPSSel( wxCommandEvent& WXUNUSED(event) )
282 wxString fps = wxString::Format("%d", m_M_sliderFPS->GetValue());
284 m_M_FPS->SetLabel(fps);
286 std::string msg("M:fps ");
292 void Standalone::OnServerMsg( wxCommandEvent& WXUNUSED(event) )
294 if ( m_GS_msg->GetValue().IsEmpty() ) {
298 std::string msg("G:smsg ");
300 msg.append( m_GS_msg->GetValue().c_str() );
302 // strip off return char which GetValue() has
303 size_t pos = msg.find_last_not_of("\r\n");
305 if (pos != std::string::npos) {
314 void Standalone::OnPinfoPlayer(wxCommandEvent& WXUNUSED(event) )
316 int idx = m_P_Players->GetCurrentSelection();
318 if (idx == wxNOT_FOUND) {
322 std::string msg("P:info ");
324 msg.append( m_P_Players->GetString(idx).c_str() );
329 void Standalone::createTab_Server(wxNotebook* parent)
331 wxPanel* panel = new wxPanel( parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
333 wxBoxSizer *panelSizer = new wxBoxSizer( wxVERTICAL );
335 wxBoxSizer* bSizer = new wxBoxSizer( wxVERTICAL );
337 wxFlexGridSizer* fgSizer5 = new wxFlexGridSizer( 0, 2, 0, 0 );
338 fgSizer5->AddGrowableCol(1, 1);
340 wxStaticText* m_staticText6 = new wxStaticText( panel, wxID_ANY, wxT("Server Name"), wxDefaultPosition, wxDefaultSize, 0 );
341 fgSizer5->Add( m_staticText6, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
343 m_S_ServerName = new wxTextCtrl( panel, ID_T_SERVER_NAME, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER );
344 m_S_ServerName->SetMaxLength( 31 );
345 fgSizer5->Add( m_S_ServerName, 0, wxALL|wxEXPAND, 5 );
347 wxStaticText* m_staticText7 = new wxStaticText( panel, wxID_ANY, wxT("Host Password"), wxDefaultPosition, wxDefaultSize, 0 );
348 fgSizer5->Add( m_staticText7, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
350 m_S_HostPass = new wxTextCtrl( panel, ID_T_HOST_PASS, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER );
351 m_S_HostPass->SetMaxLength( 16 );
352 fgSizer5->Add( m_S_HostPass, 0, wxALL|wxEXPAND, 5 );
354 bSizer->Add( fgSizer5, 0, wxEXPAND, 0 );
356 wxStaticLine* m_staticline1 = new wxStaticLine( panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
357 bSizer->Add( m_staticline1, 0, wxEXPAND | wxALL, 5 );
359 wxFlexGridSizer* fgSizer7 = new wxFlexGridSizer( 0, 2, 0, 0 );
360 fgSizer7->SetFlexibleDirection( wxBOTH );
361 fgSizer7->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
363 wxStaticText* m_staticText9 = new wxStaticText( panel, wxID_ANY, wxT("# Connections :"), wxDefaultPosition, wxDefaultSize, 0 );
364 fgSizer7->Add( m_staticText9, 0, wxALL, 5 );
366 m_S_NumConn = new wxStaticText( panel, wxID_ANY, wxT("0"), wxDefaultPosition, wxDefaultSize, 0 );
367 fgSizer7->Add( m_S_NumConn, 0, wxALL, 5 );
369 bSizer->Add( fgSizer7, 0, wxEXPAND, 5 );
371 wxStaticText* m_staticText8 = new wxStaticText( panel, wxID_ANY, wxT("Address and Ping"), wxDefaultPosition, wxDefaultSize, 0 );
372 bSizer->Add( m_staticText8, 0, wxALL, 5 );
374 wxFlexGridSizer* fgSizer3 = new wxFlexGridSizer( 0, 2, 0, 0 );
375 fgSizer3->SetFlexibleDirection( wxBOTH );
376 fgSizer3->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
378 m_S_Connections = new wxTextCtrl( panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 300,300 ), wxTE_MULTILINE|wxTE_READONLY|wxTE_NO_VSCROLL );
379 fgSizer3->Add( m_S_Connections, 0, wxALL|wxEXPAND, 5 );
381 wxBoxSizer* bbSizer = new wxBoxSizer( wxVERTICAL );
383 m_S_btnKick = new wxButton( panel, ID_B_KICK, wxT("Kick"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
384 bbSizer->Add( m_S_btnKick, 1, wxALL, 5 );
386 m_S_btnMRefresh = new wxButton( panel, ID_B_MREFRESH, wxT(" Refresh\nMissions"), wxDefaultPosition, wxDefaultSize, 0 );
387 bbSizer->Add( m_S_btnMRefresh, 2, wxALL, 5 );
389 m_S_btnResetAll = new wxButton( panel, ID_B_RESET_ALL, wxT("Reset All"), wxDefaultPosition, wxDefaultSize, 0 );
390 bbSizer->Add( m_S_btnResetAll, 3, wxALL, 5 );
392 fgSizer3->Add( bbSizer, 1, wxEXPAND, 5 );
394 bSizer->Add( fgSizer3, 0, wxEXPAND, 5 );
396 panelSizer->Add( bSizer, 1, wxALL|wxEXPAND, 5 );
398 panel->SetSizer( panelSizer );
399 panelSizer->Fit( panel );
400 panelSizer->SetSizeHints( panel );
402 parent->AddPage( panel, wxT("Server"), true );
405 void Standalone::createTab_Multi(wxNotebook* parent)
407 wxPanel* panel = new wxPanel( parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
409 wxBoxSizer* panelSizer = new wxBoxSizer(wxVERTICAL);
411 wxBoxSizer* bSizer = new wxBoxSizer(wxVERTICAL);
413 m_M_sliderFPS = new wxSlider( panel, ID_FPS_SLIDER, 30, 15, 60, wxDefaultPosition, wxDefaultSize, wxSL_HORIZONTAL );
414 bSizer->Add( m_M_sliderFPS, 0, wxALL|wxEXPAND, 5 );
416 wxFlexGridSizer* fgSizer8;
417 fgSizer8 = new wxFlexGridSizer( 0, 5, 0, 0 );
418 fgSizer8->AddGrowableCol(2, 1);
420 wxStaticText* m_staticText71 = new wxStaticText( panel, wxID_ANY, wxT("Frame Cap : "), wxDefaultPosition, wxDefaultSize, 0 );
421 m_staticText71->Wrap( -1 );
422 fgSizer8->Add( m_staticText71, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
424 wxPanel* fpsPanel = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
425 wxBoxSizer* fpsSizer = new wxBoxSizer(wxHORIZONTAL);
426 m_M_FPS = new wxStaticText( fpsPanel, wxID_ANY, "30", wxDefaultPosition, wxSize(60, -1), 0 );
428 fpsSizer->Add( m_M_FPS, 0, wxALL, 2 );
429 fpsPanel->SetSizer(fpsSizer);
430 fpsSizer->Fit(fpsPanel);
431 fgSizer8->Add(fpsPanel, 0, wxALL, 3);
434 fgSizer8->Add( 0, 0, 1, wxEXPAND );
436 wxStaticText* m_staticText81 = new wxStaticText( panel, wxID_ANY, wxT("Realized FPS : "), wxDefaultPosition, wxDefaultSize, 0 );
437 m_staticText81->Wrap( -1 );
438 fgSizer8->Add( m_staticText81, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
440 wxPanel*fpscapPanel = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
441 wxBoxSizer* fpscapSizer = new wxBoxSizer(wxHORIZONTAL);
442 m_M_FPSRel = new wxStaticText( fpscapPanel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(60, -1), 0 );
443 m_M_FPSRel->Wrap( -1 );
444 fpscapSizer->Add( m_M_FPSRel, 0, wxALL, 2 );
445 fpscapPanel->SetSizer(fpscapSizer);
446 fpscapSizer->Fit(fpscapPanel);
447 fgSizer8->Add(fpscapPanel, 0, wxALL, 3);
450 bSizer->Add( fgSizer8, 0, wxEXPAND, 5 );
452 wxStaticLine* m_staticline2 = new wxStaticLine( panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
453 bSizer->Add( m_staticline2, 0, wxEXPAND | wxALL, 5 );
456 bSizer->Add( 0, 0, 0, wxALL, 20 );
459 wxFlexGridSizer* fgSizer9;
460 fgSizer9 = new wxFlexGridSizer( 0, 2, 0, 0 );
461 fgSizer9->SetFlexibleDirection( wxBOTH );
462 fgSizer9->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
464 wxStaticText* m_staticText91 = new wxStaticText( panel, wxID_ANY, wxT("Mission Name : "), wxDefaultPosition, wxDefaultSize, 0 );
465 m_staticText91->Wrap( -1 );
466 fgSizer9->Add( m_staticText91, 0, wxALL, 5 );
468 wxPanel* mnPanel = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
469 wxBoxSizer* mnSizer = new wxBoxSizer(wxHORIZONTAL);
470 m_M_MissionName = new wxStaticText( mnPanel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(150, -1), 0 );
471 m_M_MissionName->Wrap( -1 );
472 mnSizer->Add( m_M_MissionName, 0, wxALL, 2 );
473 mnPanel->SetSizer(mnSizer);
474 mnSizer->Fit(mnPanel);
475 fgSizer9->Add(mnPanel, 0, wxALL, 3);
477 wxStaticText* m_staticText101 = new wxStaticText( panel, wxID_ANY, wxT("Mission Time : "), wxDefaultPosition, wxDefaultSize, 0 );
478 m_staticText101->Wrap( -1 );
479 fgSizer9->Add( m_staticText101, 0, wxALL, 5 );
481 wxPanel* mtPanel = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
482 wxBoxSizer* mtSizer = new wxBoxSizer(wxHORIZONTAL);
483 m_M_MissionTime = new wxStaticText( mtPanel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(150, -1), 0 );
484 m_M_MissionTime->Wrap( -1 );
485 mtSizer->Add( m_M_MissionTime, 0, wxALL, 2 );
486 mtPanel->SetSizer(mtSizer);
487 mtSizer->Fit(mtPanel);
488 fgSizer9->Add(mtPanel, 0, wxALL, 3);
491 bSizer->Add( fgSizer9, 0, wxEXPAND, 5 );
494 bSizer->Add( 0, 0, 0, wxALL, 20 );
496 wxBoxSizer* bSizer3 = new wxBoxSizer(wxHORIZONTAL);
498 wxBoxSizer* bSizer4 = new wxBoxSizer(wxVERTICAL);
500 wxStaticText* m_staticText11 = new wxStaticText( panel, wxID_ANY, wxT("Mission Goals"), wxDefaultPosition, wxDefaultSize, 0 );
501 m_staticText11->Wrap( -1 );
502 bSizer4->Add( m_staticText11, 0, wxALL, 5 );
504 m_M_Goals = new wxTreeCtrl( panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTR_HIDE_ROOT|wxTR_NO_BUTTONS );
506 wxImageList *goal_imgs = new wxImageList(16, 16);
508 goal_imgs->Add( wxBitmap(goal_ord_xpm), wxColour(0xff, 0x0, 0xff) );
509 goal_imgs->Add( wxBitmap(goal_none_xpm), wxColour(0xff, 0xff, 0xff) );
510 goal_imgs->Add( wxBitmap(goal_inc_xpm), wxColour(0xff, 0xff, 0xff) );
511 goal_imgs->Add( wxBitmap(goal_com_xpm), wxColour(0xff, 0xff, 0xff) );
512 goal_imgs->Add( wxBitmap(goal_fail_xpm), wxColour(0xff, 0xff, 0xff) );
514 m_M_Goals->AssignImageList(goal_imgs);
516 wxTreeItemId root = m_M_Goals->AddRoot( wxT("Goals") );
518 m_M_GoalItems[0] = m_M_Goals->AppendItem(root, wxT("Primary Objectives"), 0);
519 m_M_GoalItems[1] = m_M_Goals->AppendItem(root, wxT("Secondary Objectives"), 0);
520 m_M_GoalItems[2] = m_M_Goals->AppendItem(root, wxT("Bonus Objectives"), 0);
522 bSizer4->Add( m_M_Goals, 1, wxALL|wxEXPAND, 5 );
524 bSizer3->Add(bSizer4, 1, wxEXPAND);
526 wxBoxSizer* bSizer5 = new wxBoxSizer(wxVERTICAL);
528 wxStaticText* m_staticText12 = new wxStaticText( panel, wxID_ANY, wxT("Netgame Information"), wxDefaultPosition, wxDefaultSize, 0 );
529 m_staticText12->Wrap( -1 );
530 bSizer5->Add( m_staticText12, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5 );
532 wxFlexGridSizer* fgSizer11;
533 fgSizer11 = new wxFlexGridSizer( 0, 2, 0, 15 );
534 fgSizer11->AddGrowableRow(0, 1);
535 fgSizer11->AddGrowableRow(1, 1);
536 fgSizer11->AddGrowableRow(2, 1);
537 fgSizer11->AddGrowableRow(3, 1);
539 wxStaticText* m_staticText13 = new wxStaticText( panel, wxID_ANY, wxT("Max Players"), wxDefaultPosition, wxDefaultSize, 0 );
540 m_staticText13->Wrap( -1 );
541 fgSizer11->Add( m_staticText13, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
543 m_M_ngMaxPlayers = new wxStaticText( panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
544 m_M_ngMaxPlayers->Wrap( -1 );
545 fgSizer11->Add( m_M_ngMaxPlayers, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
547 wxStaticText* m_staticText15 = new wxStaticText( panel, wxID_ANY, wxT("Max Observers"), wxDefaultPosition, wxDefaultSize, 0 );
548 m_staticText15->Wrap( -1 );
549 fgSizer11->Add( m_staticText15, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
551 m_M_ngMaxObservers = new wxStaticText( panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
552 m_M_ngMaxObservers->Wrap( -1 );
553 fgSizer11->Add( m_M_ngMaxObservers, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
555 wxStaticText* m_staticText17 = new wxStaticText( panel, wxID_ANY, wxT("Security"), wxDefaultPosition, wxDefaultSize, 0 );
556 m_staticText17->Wrap( -1 );
557 fgSizer11->Add( m_staticText17, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
559 m_M_ngSecurity = new wxStaticText( panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
560 m_M_ngSecurity->Wrap( -1 );
561 fgSizer11->Add( m_M_ngSecurity, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
563 wxStaticText* m_staticText19 = new wxStaticText( panel, wxID_ANY, wxT("Respawns"), wxDefaultPosition, wxDefaultSize, 0 );
564 m_staticText19->Wrap( -1 );
565 fgSizer11->Add( m_staticText19, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
567 m_M_ngRespawns = new wxStaticText( panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
568 m_M_ngRespawns->Wrap( -1 );
569 fgSizer11->Add( m_M_ngRespawns, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
571 bSizer5->Add( fgSizer11, 1, wxEXPAND );
573 bSizer3->Add(bSizer5, 1, wxEXPAND);
575 bSizer->Add( bSizer3, 1, wxEXPAND, 5 );
577 panelSizer->Add(bSizer, 1, wxALL|wxEXPAND, 5);
579 panel->SetSizer( panelSizer );
580 panelSizer->Fit( panel );
581 panelSizer->SetSizeHints( panel );
583 parent->AddPage( panel, wxT("Multi-Player") );
586 void Standalone::createTab_Player(wxNotebook* parent)
588 wxPanel* panel = new wxPanel( parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
590 wxBoxSizer* panelSizer = new wxBoxSizer( wxVERTICAL );
592 wxBoxSizer* bSizer = new wxBoxSizer( wxVERTICAL );
594 wxBoxSizer* bSizer21;
595 bSizer21 = new wxBoxSizer( wxHORIZONTAL );
597 wxStaticText* m_staticText211 = new wxStaticText( panel, wxID_ANY, wxT("Player"), wxDefaultPosition, wxDefaultSize, 0 );
598 m_staticText211->Wrap( -1 );
599 bSizer21->Add( m_staticText211, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
601 wxArrayString m_choice11Choices;
602 m_P_Players = new wxChoice( panel, ID_C_P_PLAYERS, wxDefaultPosition, wxSize(200, -1), m_choice11Choices, 0 );
603 m_P_Players->SetSelection( wxNOT_FOUND );
604 bSizer21->Add( m_P_Players, 0, wxALL, 5 );
606 bSizer->Add( bSizer21, 0, wxEXPAND );
609 wxStaticLine* m_staticline4 = new wxStaticLine( panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
610 bSizer->Add( m_staticline4, 0, wxEXPAND | wxALL, 5 );
612 wxFlexGridSizer* fgSizer14;
613 fgSizer14 = new wxFlexGridSizer( 0, 2, 0, 0 );
615 wxStaticText* m_staticText26 = new wxStaticText( panel, wxID_ANY, wxT("Ship Type"), wxDefaultPosition, wxDefaultSize, 0 );
616 m_staticText26->Wrap( -1 );
617 fgSizer14->Add( m_staticText26, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
619 wxPanel* stPanel = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
620 wxBoxSizer* stSizer = new wxBoxSizer(wxHORIZONTAL);
621 m_P_ShipType = new wxStaticText( stPanel, wxID_ANY, wxT(""), wxDefaultPosition, wxSize(150, -1), 0 );
622 m_P_ShipType->Wrap( -1 );
623 stSizer->Add(m_P_ShipType, 0, wxALL, 2);
624 stPanel->SetSizer(stSizer);
625 stSizer->Fit(stPanel);
626 fgSizer14->Add( stPanel, 0, wxALL, 5 );
628 wxStaticText* m_staticText28 = new wxStaticText( panel, wxID_ANY, wxT("Avg Ping"), wxDefaultPosition, wxDefaultSize, 0 );
629 m_staticText28->Wrap( -1 );
630 fgSizer14->Add( m_staticText28, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
632 wxPanel* apPanel = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
633 wxBoxSizer* apSizer = new wxBoxSizer(wxHORIZONTAL);
634 m_P_AvgPing = new wxStaticText( apPanel, wxID_ANY, wxT(""), wxDefaultPosition, wxSize(150, -1), 0 );
635 m_P_AvgPing->Wrap( -1 );
636 apSizer->Add(m_P_AvgPing, 0, wxALL, 2);
637 apPanel->SetSizer(apSizer);
638 apSizer->Fit(apPanel);
639 fgSizer14->Add( apPanel, 0, wxALL, 5 );
641 bSizer->Add( fgSizer14, 0, wxEXPAND );
643 bSizer->Add( 0, 0, 0, wxALL, 10);
646 bSizer6 = new wxBoxSizer( wxHORIZONTAL );
652 wxBoxSizer* atsboxSizer = new wxBoxSizer( wxVERTICAL );
654 wxStaticText* atsText = new wxStaticText( panel, wxID_ANY, wxT("All Time Stats") );
655 atsboxSizer->Add( atsText, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 );
657 wxFlexGridSizer* atsgSizer = new wxFlexGridSizer( 0, 2, 0, 0 );
658 atsgSizer->AddGrowableCol(1, 1);
662 wxStaticText* itxt = new wxStaticText( panel, wxID_ANY, wxT("Primary Shots"), wxDefaultPosition, wxDefaultSize, 0 );
664 atsgSizer->Add( itxt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
665 wxPanel* p1 = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
666 wxBoxSizer* p1sizer = new wxBoxSizer( wxHORIZONTAL );
667 m_P_atsPriShots = new wxStaticText( p1, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
668 m_P_atsPriShots->Wrap( -1 );
669 p1sizer->Add( m_P_atsPriShots, 1, wxALL|wxEXPAND, 1);
670 p1->SetSizer( p1sizer );
672 atsgSizer->Add( p1, 0, wxALL|wxEXPAND, 1 );
677 wxStaticText* itxt = new wxStaticText( panel, wxID_ANY, wxT("Primary Hits"), wxDefaultPosition, wxDefaultSize, 0 );
679 atsgSizer->Add( itxt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
680 wxPanel* p1 = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
681 wxBoxSizer* p1sizer = new wxBoxSizer( wxHORIZONTAL );
682 m_P_atsPriHits = new wxStaticText( p1, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
683 m_P_atsPriHits->Wrap( -1 );
684 p1sizer->Add( m_P_atsPriHits, 0, wxALL|wxEXPAND, 1);
685 p1->SetSizer( p1sizer );
687 atsgSizer->Add( p1, 0, wxALL|wxEXPAND, 1 );
692 wxStaticText* itxt = new wxStaticText( panel, wxID_ANY, wxT("Primary BH Hits"), wxDefaultPosition, wxDefaultSize, 0 );
694 atsgSizer->Add( itxt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
695 wxPanel* p1 = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
696 wxBoxSizer* p1sizer = new wxBoxSizer( wxHORIZONTAL );
697 m_P_atsPriBHHits = new wxStaticText( p1, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
698 m_P_atsPriBHHits->Wrap( -1 );
699 p1sizer->Add( m_P_atsPriBHHits, 0, wxALL|wxEXPAND, 1);
700 p1->SetSizer( p1sizer );
702 atsgSizer->Add( p1, 0, wxALL|wxEXPAND, 1 );
707 wxStaticText* itxt = new wxStaticText( panel, wxID_ANY, wxT("Primary Hit %"), wxDefaultPosition, wxDefaultSize, 0 );
709 atsgSizer->Add( itxt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
710 wxPanel* p1 = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
711 wxBoxSizer* p1sizer = new wxBoxSizer( wxHORIZONTAL );
712 m_P_atsPriHitPer = new wxStaticText( p1, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
713 m_P_atsPriHitPer->Wrap( -1 );
714 p1sizer->Add( m_P_atsPriHitPer, 0, wxALL|wxEXPAND, 1);
715 p1->SetSizer( p1sizer );
717 atsgSizer->Add( p1, 0, wxALL|wxEXPAND, 1 );
722 wxStaticText* itxt = new wxStaticText( panel, wxID_ANY, wxT("Primary BH Hit %"), wxDefaultPosition, wxDefaultSize, 0 );
724 atsgSizer->Add( itxt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
725 wxPanel* p1 = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
726 wxBoxSizer* p1sizer = new wxBoxSizer( wxHORIZONTAL );
727 m_P_atsPriBHHitPer = new wxStaticText( p1, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
728 m_P_atsPriBHHitPer->Wrap( -1 );
729 p1sizer->Add( m_P_atsPriBHHitPer, 0, wxALL|wxEXPAND, 1);
730 p1->SetSizer( p1sizer );
732 atsgSizer->Add( p1, 0, wxALL|wxEXPAND, 1 );
737 wxStaticText* itxt = new wxStaticText( panel, wxID_ANY, wxT("Secondary Shots"), wxDefaultPosition, wxDefaultSize, 0 );
739 atsgSizer->Add( itxt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
740 wxPanel* p1 = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
741 wxBoxSizer* p1sizer = new wxBoxSizer( wxHORIZONTAL );
742 m_P_atsSecShots = new wxStaticText( p1, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
743 m_P_atsSecShots->Wrap( -1 );
744 p1sizer->Add( m_P_atsSecShots, 0, wxALL|wxEXPAND, 1);
745 p1->SetSizer( p1sizer );
747 atsgSizer->Add( p1, 0, wxALL|wxEXPAND, 1 );
752 wxStaticText* itxt = new wxStaticText( panel, wxID_ANY, wxT("Secondary Hits"), wxDefaultPosition, wxDefaultSize, 0 );
754 atsgSizer->Add( itxt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
755 wxPanel* p1 = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
756 wxBoxSizer* p1sizer = new wxBoxSizer( wxHORIZONTAL );
757 m_P_atsSecHits = new wxStaticText( p1, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
758 m_P_atsSecHits->Wrap( -1 );
759 p1sizer->Add( m_P_atsSecHits, 0, wxALL|wxEXPAND, 1);
760 p1->SetSizer( p1sizer );
762 atsgSizer->Add( p1, 0, wxALL|wxEXPAND, 1 );
767 wxStaticText* itxt = new wxStaticText( panel, wxID_ANY, wxT("Secondary BH Hits"), wxDefaultPosition, wxDefaultSize, 0 );
769 atsgSizer->Add( itxt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
770 wxPanel* p1 = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
771 wxBoxSizer* p1sizer = new wxBoxSizer( wxHORIZONTAL );
772 m_P_atsSecBHHits = new wxStaticText( p1, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
773 m_P_atsSecBHHits->Wrap( -1 );
774 p1sizer->Add( m_P_atsSecBHHits, 0, wxALL|wxEXPAND, 1);
775 p1->SetSizer( p1sizer );
777 atsgSizer->Add( p1, 0, wxALL|wxEXPAND, 1 );
782 wxStaticText* itxt = new wxStaticText( panel, wxID_ANY, wxT("Secondary Hit %"), wxDefaultPosition, wxDefaultSize, 0 );
784 atsgSizer->Add( itxt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
785 wxPanel* p1 = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
786 wxBoxSizer* p1sizer = new wxBoxSizer( wxHORIZONTAL );
787 m_P_atsSecHitPer = new wxStaticText( p1, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
788 m_P_atsSecHitPer->Wrap( -1 );
789 p1sizer->Add( m_P_atsSecHitPer, 0, wxALL|wxEXPAND, 1);
790 p1->SetSizer( p1sizer );
792 atsgSizer->Add( p1, 0, wxALL|wxEXPAND, 1 );
795 // secondary BH hit %
797 wxStaticText* itxt = new wxStaticText( panel, wxID_ANY, wxT("Secondary BH Hit %"), wxDefaultPosition, wxDefaultSize, 0 );
799 atsgSizer->Add( itxt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
800 wxPanel* p1 = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
801 wxBoxSizer* p1sizer = new wxBoxSizer( wxHORIZONTAL );
802 m_P_atsSecBHHitPer = new wxStaticText( p1, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
803 m_P_atsSecBHHitPer->Wrap( -1 );
804 p1sizer->Add( m_P_atsSecBHHitPer, 0, wxALL|wxEXPAND, 1);
805 p1->SetSizer( p1sizer );
807 atsgSizer->Add( p1, 0, wxALL|wxEXPAND, 1 );
812 wxStaticText* itxt = new wxStaticText( panel, wxID_ANY, wxT("Assists"), wxDefaultPosition, wxDefaultSize, 0 );
814 atsgSizer->Add( itxt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
815 wxPanel* p1 = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
816 wxBoxSizer* p1sizer = new wxBoxSizer( wxHORIZONTAL );
817 m_P_atsAssists = new wxStaticText( p1, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
818 m_P_atsAssists->Wrap( -1 );
819 p1sizer->Add( m_P_atsAssists, 0, wxALL|wxEXPAND, 1);
820 p1->SetSizer( p1sizer );
822 atsgSizer->Add( p1, 0, wxALL|wxEXPAND, 1 );
825 atsboxSizer->Add( atsgSizer, 1, wxEXPAND );
827 bSizer6->Add( atsboxSizer, 1, wxEXPAND, 5 );
829 wxStaticLine* m_staticline3 = new wxStaticLine( panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL );
830 bSizer6->Add( m_staticline3, 0, wxEXPAND | wxALL, 5 );
836 wxBoxSizer* msboxSizer = new wxBoxSizer( wxVERTICAL );
838 wxStaticText* msText = new wxStaticText( panel, wxID_ANY, wxT("Mission Stats") );
839 msboxSizer->Add( msText, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 );
841 wxFlexGridSizer* msgSizer = new wxFlexGridSizer( 0, 2, 0, 0 );
842 msgSizer->AddGrowableCol(1, 1);
846 wxStaticText* itxt = new wxStaticText( panel, wxID_ANY, wxT("Primary Shots"), wxDefaultPosition, wxDefaultSize, 0 );
848 msgSizer->Add( itxt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
849 wxPanel* p1 = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
850 wxBoxSizer* p1sizer = new wxBoxSizer( wxHORIZONTAL );
851 m_P_msPriShots = new wxStaticText( p1, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
852 m_P_msPriShots->Wrap( -1 );
853 p1sizer->Add( m_P_msPriShots, 1, wxALL|wxEXPAND, 1);
854 p1->SetSizer( p1sizer );
856 msgSizer->Add( p1, 0, wxALL|wxEXPAND, 1 );
861 wxStaticText* itxt = new wxStaticText( panel, wxID_ANY, wxT("Primary Hits"), wxDefaultPosition, wxDefaultSize, 0 );
863 msgSizer->Add( itxt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
864 wxPanel* p1 = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
865 wxBoxSizer* p1sizer = new wxBoxSizer( wxHORIZONTAL );
866 m_P_msPriHits = new wxStaticText( p1, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
867 m_P_msPriHits->Wrap( -1 );
868 p1sizer->Add( m_P_msPriHits, 0, wxALL|wxEXPAND, 1);
869 p1->SetSizer( p1sizer );
871 msgSizer->Add( p1, 0, wxALL|wxEXPAND, 1 );
876 wxStaticText* itxt = new wxStaticText( panel, wxID_ANY, wxT("Primary BH Hits"), wxDefaultPosition, wxDefaultSize, 0 );
878 msgSizer->Add( itxt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
879 wxPanel* p1 = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
880 wxBoxSizer* p1sizer = new wxBoxSizer( wxHORIZONTAL );
881 m_P_msPriBHHits = new wxStaticText( p1, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
882 m_P_msPriBHHits->Wrap( -1 );
883 p1sizer->Add( m_P_msPriBHHits, 0, wxALL|wxEXPAND, 1);
884 p1->SetSizer( p1sizer );
886 msgSizer->Add( p1, 0, wxALL|wxEXPAND, 1 );
891 wxStaticText* itxt = new wxStaticText( panel, wxID_ANY, wxT("Primary Hit %"), wxDefaultPosition, wxDefaultSize, 0 );
893 msgSizer->Add( itxt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
894 wxPanel* p1 = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
895 wxBoxSizer* p1sizer = new wxBoxSizer( wxHORIZONTAL );
896 m_P_msPriHitPer = new wxStaticText( p1, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
897 m_P_msPriHitPer->Wrap( -1 );
898 p1sizer->Add( m_P_msPriHitPer, 0, wxALL|wxEXPAND, 1);
899 p1->SetSizer( p1sizer );
901 msgSizer->Add( p1, 0, wxALL|wxEXPAND, 1 );
906 wxStaticText* itxt = new wxStaticText( panel, wxID_ANY, wxT("Primary BH Hit %"), wxDefaultPosition, wxDefaultSize, 0 );
908 msgSizer->Add( itxt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
909 wxPanel* p1 = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
910 wxBoxSizer* p1sizer = new wxBoxSizer( wxHORIZONTAL );
911 m_P_msPriBHHitPer = new wxStaticText( p1, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
912 m_P_msPriBHHitPer->Wrap( -1 );
913 p1sizer->Add( m_P_msPriBHHitPer, 0, wxALL|wxEXPAND, 1);
914 p1->SetSizer( p1sizer );
916 msgSizer->Add( p1, 0, wxALL|wxEXPAND, 1 );
921 wxStaticText* itxt = new wxStaticText( panel, wxID_ANY, wxT("Secondary Shots"), wxDefaultPosition, wxDefaultSize, 0 );
923 msgSizer->Add( itxt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
924 wxPanel* p1 = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
925 wxBoxSizer* p1sizer = new wxBoxSizer( wxHORIZONTAL );
926 m_P_msSecShots = new wxStaticText( p1, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
927 m_P_msSecShots->Wrap( -1 );
928 p1sizer->Add( m_P_msSecShots, 0, wxALL|wxEXPAND, 1);
929 p1->SetSizer( p1sizer );
931 msgSizer->Add( p1, 0, wxALL|wxEXPAND, 1 );
936 wxStaticText* itxt = new wxStaticText( panel, wxID_ANY, wxT("Secondary Hits"), wxDefaultPosition, wxDefaultSize, 0 );
938 msgSizer->Add( itxt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
939 wxPanel* p1 = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
940 wxBoxSizer* p1sizer = new wxBoxSizer( wxHORIZONTAL );
941 m_P_msSecHits = new wxStaticText( p1, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
942 m_P_msSecHits->Wrap( -1 );
943 p1sizer->Add( m_P_msSecHits, 0, wxALL|wxEXPAND, 1);
944 p1->SetSizer( p1sizer );
946 msgSizer->Add( p1, 0, wxALL|wxEXPAND, 1 );
951 wxStaticText* itxt = new wxStaticText( panel, wxID_ANY, wxT("Secondary BH Hits"), wxDefaultPosition, wxDefaultSize, 0 );
953 msgSizer->Add( itxt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
954 wxPanel* p1 = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
955 wxBoxSizer* p1sizer = new wxBoxSizer( wxHORIZONTAL );
956 m_P_msSecBHHits = new wxStaticText( p1, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
957 m_P_msSecBHHits->Wrap( -1 );
958 p1sizer->Add( m_P_msSecBHHits, 0, wxALL|wxEXPAND, 1);
959 p1->SetSizer( p1sizer );
961 msgSizer->Add( p1, 0, wxALL|wxEXPAND, 1 );
966 wxStaticText* itxt = new wxStaticText( panel, wxID_ANY, wxT("Secondary Hit %"), wxDefaultPosition, wxDefaultSize, 0 );
968 msgSizer->Add( itxt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
969 wxPanel* p1 = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
970 wxBoxSizer* p1sizer = new wxBoxSizer( wxHORIZONTAL );
971 m_P_msSecHitPer = new wxStaticText( p1, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
972 m_P_msSecHitPer->Wrap( -1 );
973 p1sizer->Add( m_P_msSecHitPer, 0, wxALL|wxEXPAND, 1);
974 p1->SetSizer( p1sizer );
976 msgSizer->Add( p1, 0, wxALL|wxEXPAND, 1 );
979 // secondary BH hit %
981 wxStaticText* itxt = new wxStaticText( panel, wxID_ANY, wxT("Secondary BH Hit %"), wxDefaultPosition, wxDefaultSize, 0 );
983 msgSizer->Add( itxt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
984 wxPanel* p1 = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
985 wxBoxSizer* p1sizer = new wxBoxSizer( wxHORIZONTAL );
986 m_P_msSecBHHitPer = new wxStaticText( p1, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
987 m_P_msSecBHHitPer->Wrap( -1 );
988 p1sizer->Add( m_P_msSecBHHitPer, 0, wxALL|wxEXPAND, 1);
989 p1->SetSizer( p1sizer );
991 msgSizer->Add( p1, 0, wxALL|wxEXPAND, 1 );
996 wxStaticText* itxt = new wxStaticText( panel, wxID_ANY, wxT("Assists"), wxDefaultPosition, wxDefaultSize, 0 );
998 msgSizer->Add( itxt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
999 wxPanel* p1 = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
1000 wxBoxSizer* p1sizer = new wxBoxSizer( wxHORIZONTAL );
1001 m_P_msAssists = new wxStaticText( p1, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
1002 m_P_msAssists->Wrap( -1 );
1003 p1sizer->Add( m_P_msAssists, 0, wxALL|wxEXPAND, 1);
1004 p1->SetSizer( p1sizer );
1006 msgSizer->Add( p1, 0, wxALL|wxEXPAND, 1 );
1009 msboxSizer->Add( msgSizer, 1, wxEXPAND );
1011 bSizer6->Add( msboxSizer, 1, wxEXPAND );
1013 bSizer->Add( bSizer6, 1, wxEXPAND );
1015 panelSizer->Add( bSizer, 1, wxALL|wxEXPAND, 5 );
1017 panel->SetSizer( panelSizer );
1018 panelSizer->Fit( panel );
1019 panelSizer->SetSizeHints(panel);
1021 parent->AddPage( panel, wxT("Player Info") );
1024 void Standalone::createTab_GodStuff(wxNotebook* parent)
1026 wxPanel* panel = new wxPanel( parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
1028 wxBoxSizer* panelSizer = new wxBoxSizer( wxVERTICAL );
1030 wxBoxSizer* bSizer = new wxBoxSizer( wxVERTICAL );
1032 wxBoxSizer* bSizer2 = new wxBoxSizer( wxHORIZONTAL );
1034 wxStaticText* m_staticText21 = new wxStaticText( panel, wxID_ANY, wxT("Player"), wxDefaultPosition, wxDefaultSize, 0 );
1035 bSizer2->Add( m_staticText21, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
1037 wxArrayString m_choice1Choices;
1038 m_GS_Players = new wxChoice( panel, wxID_ANY, wxDefaultPosition, wxSize(200, -1), m_choice1Choices, 0 );
1039 m_GS_Players->SetSelection( wxNOT_FOUND );
1040 bSizer2->Add( m_GS_Players, 0, wxALL|wxEXPAND, 5 );
1042 bSizer->Add( bSizer2, 0, wxEXPAND, 5 );
1044 bSizer->Add( 0, 0, 0, wxALL, 10 );
1046 wxStaticText* m_staticText22 = new wxStaticText( panel, wxID_ANY, wxT("Server Message"), wxDefaultPosition, wxDefaultSize, 0 );
1047 bSizer->Add( m_staticText22, 0, wxALL, 5 );
1049 m_GS_msg = new wxTextCtrl( panel, ID_T_MSG, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER );
1050 m_GS_msg->SetMaxLength(150);
1051 bSizer->Add( m_GS_msg, 0, wxALL|wxEXPAND, 5 );
1053 bSizer->Add( 0, 0, 0, wxALL, 5 );
1055 m_GS_Messages = new wxTextCtrl( panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY );
1056 bSizer->Add( m_GS_Messages, 1, wxALL|wxEXPAND, 5 );
1058 panelSizer->Add( bSizer, 1, wxALL|wxEXPAND, 5 );
1060 panel->SetSizer( panelSizer );
1061 panelSizer->Fit( panel );
1062 panelSizer->SetSizeHints( panel );
1064 parent->AddPage( panel, wxT("God Stuff") );
1067 void Standalone::createTab_Debug(wxNotebook* parent)
1069 wxPanel* panel = new wxPanel( parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
1071 wxBoxSizer* bSizer = new wxBoxSizer( wxVERTICAL );
1073 wxBoxSizer* hbSizer = new wxBoxSizer( wxHORIZONTAL );
1075 wxStaticText* m_staticText1 = new wxStaticText( panel, wxID_ANY, wxT("Standalone State :"), wxDefaultPosition, wxDefaultSize, 0 );
1076 hbSizer->Add( m_staticText1, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
1078 wxPanel* p1 = new wxPanel( panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER );
1080 wxBoxSizer* p1Sizer = new wxBoxSizer( wxHORIZONTAL );
1082 m_D_State = new wxStaticText( p1, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
1083 p1Sizer->Add( m_D_State, 1, wxALL|wxEXPAND, 2);
1085 p1->SetSizer( p1Sizer );
1088 hbSizer->Add( p1, 1, wxALL|wxEXPAND, 5 );
1090 bSizer->Add( hbSizer, 0, wxALL|wxEXPAND, 5 );
1092 panel->SetSizer( bSizer );
1095 bSizer->Fit( panel );
1097 parent->AddPage( panel, wxT("Debug") );
1100 bool Standalone::startFreeSpace(int argc, wxCmdLineArgsArray &argv)
1102 wxString epath = wxFileName(wxStandardPaths::Get().GetExecutablePath()).GetPath(true);
1103 bool cmd_port = false;
1105 epath.Append( wxT("fs") );
1108 epath.Append( wxT("2") );
1111 #if defined(FS1_DEMO) || defined(FS2_DEMO)
1112 epath.Append( wxT("demo") );
1116 epath.Append( wxT(".exe") );
1119 epath.Append( wxT(" -standalone") );
1121 for (int i = 1; i < argc; i++) {
1122 wxString arg( argv[i] );
1124 // check if -port argument and set var
1125 if ( arg.IsSameAs( wxT("-port"), false) && (argc > i+1) ) {
1126 fsport = wxAtoi(argv[i+1]);
1130 epath.Append( wxT(" ") );
1134 // if port isn't specified on cmdline, check ini file for "ForcePort" value
1136 char *u_path = SDL_GetPrefPath(Osreg_company_name, Osreg_title);
1139 wxFileName ini_name(u_path, PROFILE_NAME);
1140 wxTextFile fs_ini( ini_name.GetFullPath() );
1142 if ( fs_ini.Open() ) {
1145 for (line = fs_ini.GetLastLine(); fs_ini.GetCurrentLine() > 0; line = fs_ini.GetPrevLine()) {
1146 wxArrayString chk = wxSplit(line, '=');
1148 if (chk.GetCount() == 2) {
1149 if (chk.Item(0) == "ForcePort") {
1150 int port = wxAtoi( chk.Item(1) );
1168 // test if socket is in use (in case exising instance is running on same port)
1169 wxDatagramSocket *sock;
1173 addr.Service( (unsigned short)fsport );
1175 sock = new wxDatagramSocket(addr);
1177 bool isok = sock->IsOk();
1182 throw "Unable to start FreeSpace\n\nAn instance is already running";
1185 // start game executable
1186 fspid = wxExecute(epath, wxEXEC_ASYNC | wxEXEC_MAKE_GROUP_LEADER | wxEXEC_HIDE_CONSOLE);
1191 void Standalone::ResetAll()
1193 m_popup->Show(false);
1195 m_S_ServerName->Clear();
1196 m_S_HostPass->Clear();
1197 m_S_NumConn->SetLabel( wxT("0") );
1198 m_S_Connections->Clear();
1200 m_M_sliderFPS->SetValue(30);
1201 m_M_FPS->SetLabel("30");
1202 m_M_FPSRel->SetLabel( wxT("0.0") );
1203 m_M_MissionName->SetLabel("");
1204 m_M_MissionTime->SetLabel("");
1205 m_M_ngMaxPlayers->SetLabel("");
1206 m_M_ngMaxObservers->SetLabel("");
1207 m_M_ngSecurity->SetLabel("");
1208 m_M_ngRespawns->SetLabel("");
1210 for (int idx = 0; idx < 3; idx++) {
1211 m_M_Goals->DeleteChildren( m_M_GoalItems[idx] );
1214 m_P_Players->Clear();
1215 m_P_ShipType->SetLabel("");
1216 m_P_AvgPing->SetLabel("");
1217 m_P_atsPriShots->SetLabel("");
1218 m_P_atsPriHits->SetLabel("");
1219 m_P_atsPriBHHits->SetLabel("");
1220 m_P_atsPriHitPer->SetLabel("");
1221 m_P_atsPriBHHitPer->SetLabel("");
1222 m_P_atsSecShots->SetLabel("");
1223 m_P_atsSecHits->SetLabel("");
1224 m_P_atsSecBHHits->SetLabel("");
1225 m_P_atsSecHitPer->SetLabel("");
1226 m_P_atsSecBHHitPer->SetLabel("");
1227 m_P_atsAssists->SetLabel("");
1228 m_P_msPriShots->SetLabel("");
1229 m_P_msPriHits->SetLabel("");
1230 m_P_msPriBHHits->SetLabel("");
1231 m_P_msPriHitPer->SetLabel("");
1232 m_P_msPriBHHitPer->SetLabel("");
1233 m_P_msSecShots->SetLabel("");
1234 m_P_msSecHits->SetLabel("");
1235 m_P_msSecBHHits->SetLabel("");
1236 m_P_msSecHitPer->SetLabel("");
1237 m_P_msSecBHHitPer->SetLabel("");
1238 m_P_msAssists->SetLabel("");
1240 m_GS_Players->Clear();
1242 m_GS_Messages->Clear();
1244 m_D_State->SetLabel("");
1247 static int callback_standalone_client(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len)
1249 #define MAX_BUF_SIZE 1050
1250 unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + MAX_BUF_SIZE + LWS_SEND_BUFFER_POST_PADDING];
1251 unsigned char *p = &buf[LWS_SEND_BUFFER_PRE_PADDING];
1256 case LWS_CALLBACK_CLIENT_ESTABLISHED:
1257 lws_callback_on_writable(wsi);
1260 case LWS_CALLBACK_CLOSED:
1261 wxGetApp().Client().wsDisconnect();
1264 case LWS_CALLBACK_CLIENT_RECEIVE:
1265 wxGetApp().Client().wsMessage( (const char *)in, len );
1268 case LWS_CALLBACK_CLIENT_WRITEABLE: {
1269 while ( !wxGetApp().Client().wsGetSendBuffer().empty() ) {
1270 std::string msg = wxGetApp().Client().wsGetSendBuffer().front();
1272 size = wxStrlcpy((char *)p, msg.c_str(), MAX_BUF_SIZE);
1274 rval = lws_write(wsi, p, size, LWS_WRITE_TEXT);
1277 lwsl_err("ERROR sending buffer!\n");
1281 wxGetApp().Client().wsGetSendBuffer().pop_front();
1283 if ( lws_send_pipe_choked(wsi) ) {
1284 lws_callback_on_writable(wsi);
1293 case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
1294 wxGetApp().Client().wsDisconnect();
1304 static struct lws_protocols protocols[] = {
1307 callback_standalone_client,
1311 { NULL, NULL, 0, 0 }
1314 bool Standalone::wsInitialize()
1316 struct lws_context_creation_info info;
1318 memset(&info, 0, sizeof(info));
1319 memset(&ccinfo, 0, sizeof(ccinfo));
1321 info.port = CONTEXT_PORT_NO_LISTEN;
1322 info.protocols = protocols;
1326 stand_context = lws_create_context(&info);
1328 if (stand_context == NULL) {
1332 ccinfo.context = stand_context;
1333 ccinfo.address = "127.0.0.1";
1334 ccinfo.port = fsport;
1336 ccinfo.host = ccinfo.address;
1337 ccinfo.origin = ccinfo.address;
1338 ccinfo.ietf_version_or_minus_one = -1;
1339 ccinfo.protocol = protocols[0].name;
1341 // async call, actual connection to occur later
1342 wsi_standalone = lws_client_connect_via_info(&ccinfo);
1344 lws_service(stand_context, 0);
1349 void Standalone::wsDoFrame()
1351 if ( !stand_context ) {
1355 // if connection is lost attempt reconnect every 2 seconds
1356 if ( !wsi_standalone && !(++m_rate_limit % 60) ) {
1357 // restart game process if it terminated
1358 if ( !wxProcess::Exists(fspid) ) {
1359 wxCmdLineArgsArray empty;
1362 startFreeSpace(0, empty);
1363 } catch (const char *err) {
1364 wxMessageBox(err, "Error!", wxOK|wxICON_ERROR|wxCENTRE|wxSTAY_ON_TOP);
1372 wsi_standalone = lws_client_connect_via_info(&ccinfo);
1376 lws_service(stand_context, 0);
1379 void Standalone::wsDisconnect()
1381 wsi_standalone = NULL;
1384 void Standalone::wsMessage(const char *msg, size_t len)
1386 if (msg == NULL || len < 5) {
1390 if ( !wxStrcmp(msg, "reset") ) {
1395 if ( !wxStrncmp(msg, "popup ", 6) ) {
1397 m_popup->Show(false);
1399 wxArrayString popmsg = wxSplit(msg+6, ';');
1401 m_popup->SetTitle( popmsg.Item(0) );
1402 m_popup->SetLabel1( popmsg.Item(1) );
1403 m_popup->SetLabel2( popmsg.Item(2) );
1405 m_popup->CenterOnParent();
1406 m_popup->Show(true);
1412 char mtype = msg[0];
1416 } else if (mtype == 'D') {
1417 m_D_State->SetLabel(msg+2);
1420 else if (mtype == 'S') {
1421 wxString cmd(msg+2, 4);
1423 if (cmd == "name") {
1424 m_S_ServerName->SetValue(msg+7);
1425 } else if (cmd == "pass") {
1426 m_S_HostPass->SetValue(msg+7);
1427 } else if (cmd == "conn") {
1428 wxArrayString conns = wxSplit(msg+7, ';');
1430 size_t n_conn = conns.size();
1432 m_S_NumConn->SetLabel( wxString::Format("%u", (unsigned int)n_conn) );
1434 m_S_Connections->Clear();
1436 for (size_t idx = 0; idx < n_conn; idx++) {
1437 wxArrayString m_conn = wxSplit(conns.Item(idx), ',');
1439 m_P_Players->Append( m_conn.Item(0) );
1440 m_GS_Players->Append( m_conn.Item(0) );
1442 m_S_Connections->AppendText( m_conn.Item(1) + wxT(", \n") );
1444 } else if (cmd == "ping") {
1445 wxArrayString ping_list = wxSplit(msg+7, ',');
1447 size_t n_pings = ping_list.size();
1449 size_t offset_pos = 0;
1450 long col = 0, row = 0;
1452 m_S_Connections->PositionToXY(m_S_Connections->GetInsertionPoint(), &col, &row);
1454 for (size_t idx = 0; idx < n_pings; idx++) {
1455 size_t from_pos = m_S_Connections->GetValue().find(", ", offset_pos);
1457 if (from_pos == wxString::npos) {
1463 size_t to_pos = m_S_Connections->GetValue().find_first_of("\n", from_pos);
1465 m_S_Connections->Replace(from_pos, to_pos, ping_list.Item(idx));
1467 offset_pos = to_pos;
1470 // move intersion point to start of original line (avoids accidental kick)
1471 m_S_Connections->SetInsertionPoint( m_S_Connections->XYToPosition(0, row) );
1475 else if (mtype == 'M') {
1476 wxString cmd(msg+2, 4);
1478 if (cmd == "name") {
1479 m_M_MissionName->SetLabel(msg+7);
1480 } else if (cmd == "time") {
1481 m_M_MissionTime->SetLabel(msg+7);
1482 } else if (cmd == "info") {
1483 wxArrayString ng_info = wxSplit(msg+7, ',');
1485 m_M_ngMaxPlayers->SetLabel( ng_info.Item(0) );
1486 m_M_ngMaxObservers->SetLabel( ng_info.Item(1) );
1487 m_M_ngSecurity->SetLabel( ng_info.Item(2) );
1488 m_M_ngRespawns->SetLabel( ng_info.Item(3) );
1489 } else if (cmd == "rfps") {
1490 m_M_FPSRel->SetLabel(msg+7);
1491 } else if (cmd == "goal") {
1492 wxArrayString objectives = wxSplit(msg+7, ';');
1494 size_t n_objectives = objectives.size();
1495 wxASSERT(n_objectives == 3);
1497 for (size_t idx = 0; idx < n_objectives; idx++) {
1498 wxArrayString goals = wxSplit( objectives.Item(idx), ',' );
1500 size_t n_goals = goals.size();
1502 m_M_Goals->DeleteChildren(m_M_GoalItems[idx]);
1504 for (size_t j = 0; j < n_goals; j++) {
1505 char status = goals.Item(j).GetChar(0);
1506 wxString goal = goals.Item(j).substr(2);
1511 if (goal == "none") {
1532 m_M_Goals->AppendItem(m_M_GoalItems[idx], goal, img);
1536 m_M_Goals->ExpandAll();
1540 else if (mtype == 'P') {
1541 wxString cmd(msg+2, 4);
1543 if (cmd == "info") {
1544 wxArrayString pinfo = wxSplit(msg+7, ';');
1545 wxArrayString stats;
1547 m_P_ShipType->SetLabel( pinfo.Item(0) );
1548 m_P_AvgPing->SetLabel( pinfo.Item(1) );
1550 stats = wxSplit(pinfo.Item(2), ',');
1552 m_P_atsPriShots->SetLabel( stats.Item(0) );
1553 m_P_atsPriHits->SetLabel( stats.Item(1) );
1554 m_P_atsPriBHHits->SetLabel( stats.Item(2) );
1555 m_P_atsPriHitPer->SetLabel( stats.Item(3) );
1556 m_P_atsPriBHHitPer->SetLabel( stats.Item(4) );
1557 m_P_atsSecShots->SetLabel( stats.Item(5) );
1558 m_P_atsSecHits->SetLabel( stats.Item(6) );
1559 m_P_atsSecBHHits->SetLabel( stats.Item(7) );
1560 m_P_atsSecHitPer->SetLabel( stats.Item(8) );
1561 m_P_atsSecBHHitPer->SetLabel( stats.Item(9) );
1562 m_P_atsAssists->SetLabel( stats.Item(10) );
1564 stats = wxSplit(pinfo.Item(3), ',');
1566 m_P_msPriShots->SetLabel( stats.Item(0) );
1567 m_P_msPriHits->SetLabel( stats.Item(1) );
1568 m_P_msPriBHHits->SetLabel( stats.Item(2) );
1569 m_P_msPriHitPer->SetLabel( stats.Item(3) );
1570 m_P_msPriBHHitPer->SetLabel( stats.Item(4) );
1571 m_P_msSecShots->SetLabel( stats.Item(5) );
1572 m_P_msSecHits->SetLabel( stats.Item(6) );
1573 m_P_msSecBHHits->SetLabel( stats.Item(7) );
1574 m_P_msSecHitPer->SetLabel( stats.Item(8) );
1575 m_P_msSecBHHitPer->SetLabel( stats.Item(9) );
1576 m_P_msAssists->SetLabel( stats.Item(10) );
1580 else if (mtype == 'G') {
1581 wxString cmd(msg+2, 4);
1583 if (cmd == "mesg") {
1584 m_GS_Messages->AppendText(msg+7);
1589 void Standalone::wsSend(std::string &msg)
1591 send_buf.push_back(msg);
1593 if (wsi_standalone) {
1594 lws_callback_on_writable(wsi_standalone);