hostile-takeover/game/creategameform.cpp
2016-01-03 23:19:26 -08:00

460 lines
14 KiB
C++

#include "game/ht.h"
#include "game/creategameform.h"
#include "game/completemanager.h"
#include "game/httppackmanager.h"
#include "game/httppackinfomanager.h"
#include "yajl/wrapper/jsontypes.h"
namespace wi {
const char *GetString(const json::JsonMap *map, const char *key);
CreateGameForm::CreateGameForm(LoginHandler& handler, const PackId *ppackidFind,
Chatter& chatter, GameParams *prams) : handler_(handler),
chatter_(chatter), m_prams(prams), m_pml(NULL),
m_mt(kmtMultiplayerChallenge) {
memset(&m_miidFind, 0, sizeof(m_miidFind));
if (ppackidFind != NULL) {
m_miidFind.packid = *ppackidFind;
}
chatter_.SetChatTitle("Room Chat");
chatter_.SignalOnBlink.connect(this, &CreateGameForm::OnChatBlink);
}
CreateGameForm::~CreateGameForm() {
delete m_pml;
chatter_.SignalOnBlink.disconnect(this);
chatter_.HideChat();
}
bool CreateGameForm::DoForm(LoginHandler& handler, const PackId *ppackidFind,
Chatter& chatter, GameParams *params) {
CreateGameForm *pfrm = (CreateGameForm *)gpmfrmm->LoadForm(gpiniForms,
kidfCreateGameWide, new CreateGameForm(handler, ppackidFind,
chatter, params));
if (pfrm == NULL) {
return false;
}
int idc = kidcCancel;
pfrm->DoModal(&idc);
delete pfrm;
return idc == kidcOk;
}
bool CreateGameForm::DoModal(int *pnResult) {
// Format the lists.
int aidcList[] = { kidcChallengeList, kidcAddOnList };
for (int i = 0; i < ARRAYSIZE(aidcList); i++) {
ListControl *plstc = (ListControl *)GetControlPtr(aidcList[i]);
m_aplstc[i] = plstc;
Rect rc;
plstc->GetRect(&rc);
Font *pfnt = gapfnt[kifntShadow];
int cxComplete = pfnt->GetTextExtent("Complete");
int xTitle = rc.Width() / 2 - cxComplete * 3 / 2;
plstc->SetTabStops(xTitle);
plstc->SetTabFlags(kfLstTabEllipsis);
plstc->SetFlags(plstc->GetFlags() | kfLstcKeepInteriorPositioning);
plstc->Clear();
}
if (m_pml == NULL) {
m_pml = CreateMissionList(NULL, kmltMultiplayer);
}
if (m_pml == NULL) {
return false;
}
// If asked to find a certain mission, find it first to
// see what type it is, and switch the radio button bar to
// that type.
int iPack = -1;
int iMission = -1;
int cLevels = m_pml->GetCount();
for (int nLevel = 0; nLevel < cLevels; nLevel++) {
MissionIdentifier miid;
m_pml->GetMissionIdentifier(nLevel, &miid);
if (memcmp(&miid.packid, &m_miidFind.packid,
sizeof(miid.packid)) == 0) {
if (iPack == -1) {
iPack = nLevel;
}
if (strcmp(miid.szLvlFilename,
m_miidFind.szLvlFilename) == 0) {
iMission = nLevel;
break;
}
}
}
if (iMission == -1) {
iMission = iPack;
}
int iMissionSelect = iMission;
// Init the lists
MissionType mt = InitLists(iMissionSelect);
SwitchToMissionType(mt);
// Game Speed
m_tGameSpeed = gtGameSpeed;
if (m_tGameSpeed < 4)
m_tGameSpeed = 4;
SliderControl *psldr = (SliderControl *)GetControlPtr(kidcGameSpeed);
psldr->SetRange(2, ARRAYSIZE(gatGameSpeeds) - 1 - 3); // bring the extremes in a bit for multiplayer
psldr->SetValue(8);
for (int i = 0; i < ARRAYSIZE(gatGameSpeeds); i++) {
if (gatGameSpeeds[i] == m_tGameSpeed) {
psldr->SetValue(i);
break;
}
}
// Hide this label. If we're finding an Add-On mission, then
// there are add-on missions and this label isn't meant to be visible.
GetControlPtr(kidcAddOnMessage)->Show(false);
UpdateLabels();
gptra->SetCallback(this);
bool fSuccess = ShellForm::DoModal(pnResult);
gptra->SetCallback(NULL);
delete m_pml;
m_pml = NULL;
return fSuccess;
}
void CreateGameForm::OnChatBlink(bool on) {
GetControlPtr(kidcChat)->Show(on);
}
void CreateGameForm::OnConnectionClose() {
Event evt;
memset(&evt, 0, sizeof(evt));
evt.idf = m_idf;
evt.eType = connectionCloseEvent;
gevm.PostEvent(&evt);
}
void CreateGameForm::OnShowMessage(const char *message) {
message_ = message;
Event evt;
memset(&evt, 0, sizeof(evt));
evt.idf = m_idf;
evt.eType = showMessageEvent;
gevm.PostEvent(&evt);
}
bool CreateGameForm::OnFilterEvent(Event *pevt) {
if (pevt->eType == connectionCloseEvent) {
chatter_.HideChat();
HtMessageBox(kfMbWhiteBorder, "Comm Problem", "The server has closed your connection.");
EndForm(kidcCancel);
return true;
}
if (pevt->eType == showMessageEvent) {
chatter_.HideChat();
HtMessageBox(kfMbWhiteBorder, "Server Message", message_.c_str());
message_ = "";
return true;
}
return false;
}
int CreateGameForm::IndexFromMissionType(MissionType mt) {
switch (mt) {
case kmtMultiplayerChallenge:
return 0;
case kmtMultiplayerAddOn:
return 1;
default:
return -1;
}
}
MissionType CreateGameForm::MissionTypeFromIndex(int i) {
switch (i) {
case 0:
return kmtMultiplayerChallenge;
case 1:
return kmtMultiplayerAddOn;
default:
return kmtUnknown;
}
}
void CreateGameForm::SwitchToMissionType(MissionType mt) {
m_mt = mt;
RadioButtonBarControl *prbbc =
(RadioButtonBarControl *)GetControlPtr(kidcCategories);
prbbc->SetSelectionIndex(IndexFromMissionType(mt));
for (int i = 0; i < ARRAYSIZE(m_aplstc); i++) {
bool fShow = false;
if (i == IndexFromMissionType(mt)) {
fShow = true;
}
m_aplstc[i]->Show(fShow);
}
UpdateLabels();
}
MissionType CreateGameForm::InitLists(int iMissionSelect) {
// Fill in the lists, and along the way keep track of useful selection
// indexes.
int ailiFirstIncomplete[kmtUnknown + 1];
memset(ailiFirstIncomplete, 0xff, sizeof(ailiFirstIncomplete));
int iliSelectSpecial = -1;
MissionType mtSelectSpecial = kmtUnknown;
int cMissions = m_pml->GetCount();
for (int i = 0; i < cMissions; i++) {
MissionDescription md;
if (!m_pml->GetMissionDescription(i, &md)) {
continue;
}
if (md.mt != kmtMultiplayerChallenge &&
md.mt != kmtMultiplayerAddOn) {
continue;
}
// Add the item.
const char *pszT;
if (md.cPlayersMin == md.cPlayersMax) {
pszT = base::Format::ToString("%s (%d players)",
md.szLvlTitle, md.cPlayersMin);
} else {
pszT = base::Format::ToString("%s (%d-%d players)",
md.szLvlTitle, md.cPlayersMin, md.cPlayersMax);
}
ListControl *plstc = m_aplstc[IndexFromMissionType(md.mt)];
plstc->Add(pszT, (void *)(pword)i);
// Track the first incomplete, for later selection
if (ailiFirstIncomplete[md.mt] == -1) {
MissionIdentifier miid;
m_pml->GetMissionIdentifier(i, &miid);
if (!gpcptm->IsComplete(&miid)) {
ailiFirstIncomplete[md.mt] = plstc->GetCount() - 1;
}
}
// This is passed in when the form needs to select a certain
// mission when it first shows.
if (i == iMissionSelect) {
iliSelectSpecial = plstc->GetCount() - 1;
mtSelectSpecial = md.mt;
}
}
// The initially selected missions are the first incomplete missions
// for each mission type.
MissionType mtSelect = kmtMultiplayerChallenge;
for (int i = 0; i < ARRAYSIZE(m_aplstc); i++) {
ListControl *plstc = m_aplstc[i];
// Is this the list that is awarded the special selection?
if (i == IndexFromMissionType(mtSelectSpecial)) {
plstc->Select(iliSelectSpecial, true, true);
mtSelect = mtSelectSpecial;
continue;
}
int iliSelect = ailiFirstIncomplete[MissionTypeFromIndex(i)];
if (iliSelect < 0) {
iliSelect = 0;
}
plstc->Select(iliSelect, true, true);
}
return mtSelect;
}
void CreateGameForm::OnControlSelected(word idc) {
switch (idc) {
case kidcPasswordPanel:
DoInputPanelForm(this, kidcPasswordLabel, kidcPassword);
break;
case kidcGameSpeed:
{
SliderControl *psldr = (SliderControl *)GetControlPtr(
kidcGameSpeed);
m_tGameSpeed = gatGameSpeeds[psldr->GetValue()];
UpdateLabels();
}
break;
case kidcChat:
chatter_.ShowChat();
break;
case kidcCancel:
EndForm(idc);
break;
case kidcOk:
// Fill in GameParams
ListControl *plstc = m_aplstc[IndexFromMissionType(m_mt)];
int nLevel = (int)(pword)plstc->GetSelectedItemData();
MissionIdentifier miid;
if (!m_pml->GetMissionIdentifier(nLevel, &miid)) {
HtMessageBox(kfMbWhiteBorder, "Error!",
"First you must select a map to play on.");
return;
}
// Mount the pdb
if (!gppackm->Mount(gpakr, &miid.packid)) {
HtMessageBox(kfMbWhiteBorder, "Error!",
"Cannot load mission pack.");
return;
}
// Remember for later selecting from the list
m_miidFind = miid;
// Read the level info
Level *plvl = new Level();
if (plvl != NULL) {
if (plvl->LoadLevelInfo(miid.szLvlFilename)) {
m_prams->packid = miid.packid;
m_prams->dwVersionSimulation = knVersionSimulation;
m_prams->tGameSpeed = m_tGameSpeed;
strncpyz(m_prams->szLvlFilename, miid.szLvlFilename,
sizeof(m_prams->szLvlFilename));
}
delete plvl;
} else {
HtMessageBox(kfMbWhiteBorder, "Error", "Out of memory!");
idc = kidcCancel;
}
gppackm->Unmount(gpakr, &miid.packid);
// Keep this game speed around for next time
gtGameSpeed = m_tGameSpeed;
ggame.SavePreferences();
EndForm(idc);
break;
}
}
void CreateGameForm::OnControlNotify(word idc, int nNotify) {
if (idc == kidcCategories) {
RadioButtonBarControl *prbbc =
(RadioButtonBarControl *)GetControlPtr(kidcCategories);
int iButtonSelected = prbbc->GetSelectionIndex();
if (iButtonSelected < 0) {
iButtonSelected = 0;
}
MissionType mtNew = MissionTypeFromIndex(iButtonSelected);
if (mtNew == m_mt) {
return;
}
SwitchToMissionType(mtNew);
// If in Add-On category, and there is nothing there, show this
// label, otherwise hide it
bool fShowLabel = false;
ListControl *plstc =
m_aplstc[IndexFromMissionType(kmtMultiplayerAddOn)];
if (m_mt == kmtMultiplayerAddOn) {
if (plstc->GetCount() == 0) {
fShowLabel = true;
}
}
LabelControl *plbl =
(LabelControl *)GetControlPtr(kidcAddOnMessage);
if (fShowLabel) {
plbl->Show(true);
if (m_mt == kmtMultiplayerAddOn) {
plstc->Show(false);
}
} else {
plbl->Show(false);
if (m_mt == kmtMultiplayerAddOn) {
plstc->Show(true);
}
}
}
if (idc == kidcChallengeList || idc == kidcAddOnList) {
UpdateLabels();
}
// Handle button hiding
bool fShow = true;
ListControl *plstc = m_aplstc[IndexFromMissionType(m_mt)];
if (plstc->GetSelectedItemIndex() == -1) {
fShow = false;
}
GetControlPtr(kidcOk)->Show(fShow);
}
void CreateGameForm::UpdateLabels() {
// Update Game Speed label
char szT[80];
GetSpeedMultiplierString(szT, m_tGameSpeed);
LabelControl *plbl = (LabelControl *)GetControlPtr(kidcGameSpeedLabel);
plbl->SetText(szT);
// Update Mission Pack Info label
plbl = (LabelControl *)GetControlPtr(kidcMissionPackInfo);
ListControl *plstc = m_aplstc[IndexFromMissionType(m_mt)];
if (plstc->GetSelectedItemIndex() == -1) {
plbl->SetText("");
return;
}
int i = (int)(pword)plstc->GetSelectedItemData();
MissionIdentifier miid;
if (!m_pml->GetMissionIdentifier(i, &miid)) {
plbl->SetText("");
return;
}
json::JsonMap *map = gppim->GetInfoMap(&miid.packid);
if (map == NULL) {
MissionDescription md;
if (!m_pml->GetMissionDescription(i, &md)) {
plbl->SetText("");
return;
}
const char *s;
if (miid.packid.id == PACKID_MAIN) {
s = base::Format::ToString("%s by Spiffcode, Inc.",
md.szPackName);
} else {
s = md.szPackName;
}
plbl->SetText((char *)s);
return;
}
const char *szAuthor = GetString(map, "a");
const char *szTitle = GetString(map, "t");
const char *s = base::Format::ToString("%s by %s", szTitle, szAuthor);
plbl->SetText((char *)s);
delete map;
}
} // namespace wi