mirror of
https://github.com/ZDoom/qzdoom-gpl.git
synced 2025-04-11 19:01:00 +00:00
Merge branch 'master' of https://github.com/coelckers/gzdoom
This commit is contained in:
commit
56790c7590
63 changed files with 3672 additions and 3609 deletions
|
@ -38,6 +38,7 @@ conversation
|
|||
page
|
||||
{
|
||||
drop = <string>;
|
||||
userstring = <string>; New field which can be used to pass data to custom conversation menu classes.
|
||||
ifitem
|
||||
{
|
||||
item = <string>;
|
||||
|
@ -63,10 +64,6 @@ either refuse loading dialogues with the 'ZDoom' namespace or if it does not
|
|||
outright abort on incompatible namespaces fail with a type mismatch error on
|
||||
one of the specified propeties.
|
||||
|
||||
In addition ZDoom defines one new field in the top level of a conversation block:
|
||||
|
||||
id = <integer>; Assigns a conversation ID for use in Thing_SetConversation or in UDMF's 'conversation' actor property.
|
||||
|
||||
ZDoom-format dialogues need to start with the line:
|
||||
|
||||
namespace = "ZDoom";
|
||||
|
@ -86,6 +83,7 @@ conversation // Starts a dialog.
|
|||
// the standard conversation ID ('actor' property) is used instead
|
||||
// for this purpose but since 'ZDoom' namespace requires the actor
|
||||
// to be a class name it needs a separate field for this.
|
||||
class = <string>; //Override the default conversation menu class for this conversation.
|
||||
|
||||
page
|
||||
{
|
||||
|
|
|
@ -679,15 +679,12 @@ set( FASTMATH_PCH_SOURCES
|
|||
intermission/intermission.cpp
|
||||
intermission/intermission_parse.cpp
|
||||
menu/joystickmenu.cpp
|
||||
menu/listmenu.cpp
|
||||
menu/loadsavemenu.cpp
|
||||
menu/menu.cpp
|
||||
menu/menudef.cpp
|
||||
menu/menuinput.cpp
|
||||
menu/messagebox.cpp
|
||||
menu/optionmenu.cpp
|
||||
menu/playermenu.cpp
|
||||
menu/readthis.cpp
|
||||
menu/videomenu.cpp
|
||||
timidity/common.cpp
|
||||
timidity/instrum.cpp
|
||||
|
|
|
@ -207,7 +207,7 @@ DEFINE_ACTION_FUNCTION(_CVar, SetInt)
|
|||
{
|
||||
// Only menus are allowed to change CVARs.
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FBaseCVar);
|
||||
if (!(self->GetFlags() & CVAR_MOD) && DMenu::CurrentMenu == nullptr) return 0;
|
||||
if (!(self->GetFlags() & CVAR_MOD) && CurrentMenu == nullptr) return 0;
|
||||
PARAM_INT(val);
|
||||
UCVarValue v;
|
||||
v.Int = val;
|
||||
|
@ -219,7 +219,7 @@ DEFINE_ACTION_FUNCTION(_CVar, SetFloat)
|
|||
{
|
||||
// Only menus are allowed to change CVARs.
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FBaseCVar);
|
||||
if (!(self->GetFlags() & CVAR_MOD) && DMenu::CurrentMenu == nullptr) return 0;
|
||||
if (!(self->GetFlags() & CVAR_MOD) && CurrentMenu == nullptr) return 0;
|
||||
PARAM_FLOAT(val);
|
||||
UCVarValue v;
|
||||
v.Float = (float)val;
|
||||
|
@ -231,7 +231,7 @@ DEFINE_ACTION_FUNCTION(_CVar, SetString)
|
|||
{
|
||||
// Only menus are allowed to change CVARs.
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FBaseCVar);
|
||||
if (!(self->GetFlags() & CVAR_MOD) && DMenu::CurrentMenu == nullptr) return 0;
|
||||
if (!(self->GetFlags() & CVAR_MOD) && CurrentMenu == nullptr) return 0;
|
||||
PARAM_STRING(val);
|
||||
UCVarValue v;
|
||||
v.String = val.GetChars();
|
||||
|
|
|
@ -666,7 +666,7 @@ void C_DoCommand (const char *cmd, int keynum)
|
|||
// This is only accessible to the special menu item to run CCMDs.
|
||||
DEFINE_ACTION_FUNCTION(DOptionMenuItemCommand, DoCommand)
|
||||
{
|
||||
if (DMenu::CurrentMenu == nullptr) return 0;
|
||||
if (CurrentMenu == nullptr) return 0;
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_STRING(cmd);
|
||||
C_DoCommand(cmd);
|
||||
|
|
|
@ -95,23 +95,6 @@ char *copystring (const char *s)
|
|||
return b;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// ncopystring
|
||||
//
|
||||
// If the string has no content, returns NULL. Otherwise, returns a copy.
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
char *ncopystring (const char *string)
|
||||
{
|
||||
if (string == NULL || string[0] == 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return copystring (string);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ReplaceString
|
||||
|
|
|
@ -38,7 +38,6 @@ int ParseHex(const char *str, FScriptPosition *sc = nullptr);
|
|||
bool IsNum (const char *str); // [RH] added
|
||||
|
||||
char *copystring(const char *s);
|
||||
char *ncopystring(const char *s);
|
||||
void ReplaceString (char **ptr, const char *str);
|
||||
|
||||
bool CheckWildcards (const char *pattern, const char *text);
|
||||
|
|
|
@ -74,7 +74,7 @@ EXTERN_CVAR (Int, autosavecount)
|
|||
#define SIMULATEERRORS 0
|
||||
|
||||
extern BYTE *demo_p; // [RH] Special "ticcmds" get recorded in demos
|
||||
extern char savedescription[SAVESTRINGSIZE];
|
||||
extern FString savedescription;
|
||||
extern FString savegamefile;
|
||||
|
||||
extern short consistancy[MAXPLAYERS][BACKUPTICS];
|
||||
|
@ -2419,8 +2419,7 @@ void Net_DoCommand (int type, BYTE **stream, int player)
|
|||
savegamefile = s;
|
||||
delete[] s;
|
||||
s = ReadString (stream);
|
||||
memset (savedescription, 0, sizeof(savedescription));
|
||||
strncpy (savedescription, s, sizeof(savedescription));
|
||||
savedescription = s;
|
||||
if (player != consoleplayer)
|
||||
{
|
||||
// Paths sent over the network will be valid for the system that sent
|
||||
|
|
|
@ -729,7 +729,7 @@ void D_WriteUserInfoStrings (int pnum, BYTE **stream, bool compact)
|
|||
break;
|
||||
|
||||
case NAME_Skin:
|
||||
*stream += sprintf(*((char **)stream), "\\%s", D_EscapeUserInfo(skins[info->GetSkin()].name).GetChars());
|
||||
*stream += sprintf(*((char **)stream), "\\%s", D_EscapeUserInfo(Skins[info->GetSkin()].Name).GetChars());
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -828,7 +828,7 @@ void D_ReadUserInfoStrings (int pnum, BYTE **stream, bool update)
|
|||
players[pnum].mo->state->sprite ==
|
||||
GetDefaultByType (players[pnum].cls)->SpawnState->sprite)
|
||||
{ // Only change the sprite if the player is using a standard one
|
||||
players[pnum].mo->sprite = skins[info->GetSkin()].sprite;
|
||||
players[pnum].mo->sprite = Skins[info->GetSkin()].sprite;
|
||||
}
|
||||
}
|
||||
// Rebuild translation in case the new skin uses a different range
|
||||
|
@ -898,7 +898,7 @@ void WriteUserInfo(FSerializer &arc, userinfo_t &info)
|
|||
switch (pair->Key.GetIndex())
|
||||
{
|
||||
case NAME_Skin:
|
||||
string = skins[info.GetSkin()].name;
|
||||
string = Skins[info.GetSkin()].Name;
|
||||
break;
|
||||
|
||||
case NAME_PlayerClass:
|
||||
|
@ -986,7 +986,7 @@ CCMD (playerinfo)
|
|||
// Print special info
|
||||
Printf("%20s: %s\n", "Name", ui->GetName());
|
||||
Printf("%20s: %s (%d)\n", "Team", ui->GetTeam() == TEAM_NONE ? "None" : Teams[ui->GetTeam()].GetName(), ui->GetTeam());
|
||||
Printf("%20s: %s (%d)\n", "Skin", skins[ui->GetSkin()].name, ui->GetSkin());
|
||||
Printf("%20s: %s (%d)\n", "Skin", Skins[ui->GetSkin()].Name.GetChars(), ui->GetSkin());
|
||||
Printf("%20s: %s (%d)\n", "Gender", GenderNames[ui->GetGender()], ui->GetGender());
|
||||
Printf("%20s: %s (%d)\n", "PlayerClass",
|
||||
ui->GetPlayerClassNum() == -1 ? "Random" : ui->GetPlayerClassType()->DisplayName.GetChars(),
|
||||
|
|
|
@ -298,6 +298,11 @@ struct userinfo_t : TMap<FName,FBaseCVar *>
|
|||
return aim;
|
||||
}
|
||||
}
|
||||
// Same but unfiltered.
|
||||
double GetAutoaim() const
|
||||
{
|
||||
return *static_cast<FFloatCVar *>(*CheckKey(NAME_Autoaim));
|
||||
}
|
||||
const char *GetName() const
|
||||
{
|
||||
return *static_cast<FStringCVar *>(*CheckKey(NAME_Name));
|
||||
|
|
|
@ -227,7 +227,7 @@ int mousex;
|
|||
int mousey;
|
||||
|
||||
FString savegamefile;
|
||||
char savedescription[SAVESTRINGSIZE];
|
||||
FString savedescription;
|
||||
|
||||
// [RH] Name of screenshot file to generate (usually NULL)
|
||||
FString shotfile;
|
||||
|
@ -1082,7 +1082,7 @@ void G_Ticker ()
|
|||
G_DoSaveGame (true, savegamefile, savedescription);
|
||||
gameaction = ga_nothing;
|
||||
savegamefile = "";
|
||||
savedescription[0] = '\0';
|
||||
savedescription = "";
|
||||
break;
|
||||
case ga_autosave:
|
||||
G_DoAutoSave ();
|
||||
|
@ -1696,7 +1696,7 @@ static void G_QueueBody (AActor *body)
|
|||
{
|
||||
// Apply skin's scale to actor's scale, it will be lost otherwise
|
||||
const AActor *const defaultActor = body->GetDefault();
|
||||
const FPlayerSkin &skin = skins[skinidx];
|
||||
const FPlayerSkin &skin = Skins[skinidx];
|
||||
|
||||
body->Scale.X *= skin.Scale.X / defaultActor->Scale.X;
|
||||
body->Scale.Y *= skin.Scale.Y / defaultActor->Scale.Y;
|
||||
|
@ -2069,8 +2069,7 @@ void G_SaveGame (const char *filename, const char *description)
|
|||
else
|
||||
{
|
||||
savegamefile = filename;
|
||||
strncpy (savedescription, description, sizeof(savedescription)-1);
|
||||
savedescription[sizeof(savedescription)-1] = '\0';
|
||||
savedescription = description;
|
||||
sendsave = true;
|
||||
}
|
||||
}
|
||||
|
@ -2120,7 +2119,7 @@ extern void P_CalcHeight (player_t *);
|
|||
|
||||
void G_DoAutoSave ()
|
||||
{
|
||||
char description[SAVESTRINGSIZE];
|
||||
FString description;
|
||||
FString file;
|
||||
// Keep up to four autosaves at a time
|
||||
UCVarValue num;
|
||||
|
@ -2148,10 +2147,7 @@ void G_DoAutoSave ()
|
|||
}
|
||||
|
||||
readableTime = myasctime ();
|
||||
strcpy (description, "Autosave ");
|
||||
strncpy (description+9, readableTime+4, 12);
|
||||
description[9+12] = 0;
|
||||
|
||||
description.Format("Autosave %.12s", readableTime + 4);
|
||||
G_DoSaveGame (false, file, description);
|
||||
}
|
||||
|
||||
|
@ -2311,7 +2307,7 @@ void G_DoSaveGame (bool okForQuicksave, FString filename, const char *descriptio
|
|||
|
||||
WriteZip(filename, savegame_filenames, savegame_content);
|
||||
|
||||
savegameManager.NotifyNewSave (filename.GetChars(), description, okForQuicksave);
|
||||
savegameManager.NotifyNewSave (filename, description, okForQuicksave);
|
||||
|
||||
// delete the JSON buffers we created just above. Everything else will
|
||||
// either still be needed or taken care of automatically.
|
||||
|
|
|
@ -1461,6 +1461,7 @@ void G_InitLevelLocals ()
|
|||
level.LevelName = level.info->LookupLevelName();
|
||||
level.NextMap = info->NextMap;
|
||||
level.NextSecretMap = info->NextSecretMap;
|
||||
level.F1Pic = info->F1Pic;
|
||||
|
||||
compatflags.Callback();
|
||||
compatflags2.Callback();
|
||||
|
@ -1909,6 +1910,7 @@ DEFINE_FIELD(FLevelLocals, LevelName)
|
|||
DEFINE_FIELD(FLevelLocals, MapName)
|
||||
DEFINE_FIELD(FLevelLocals, NextMap)
|
||||
DEFINE_FIELD(FLevelLocals, NextSecretMap)
|
||||
DEFINE_FIELD(FLevelLocals, F1Pic)
|
||||
DEFINE_FIELD(FLevelLocals, maptype)
|
||||
DEFINE_FIELD(FLevelLocals, Music)
|
||||
DEFINE_FIELD(FLevelLocals, musicorder)
|
||||
|
@ -1934,6 +1936,7 @@ DEFINE_FIELD_BIT(FLevelLocals, flags2, polygrind, LEVEL2_POLYGRIND)
|
|||
DEFINE_FIELD_BIT(FLevelLocals, flags2, nomonsters, LEVEL2_NOMONSTERS)
|
||||
DEFINE_FIELD_BIT(FLevelLocals, flags2, frozen, LEVEL2_FROZEN)
|
||||
DEFINE_FIELD_BIT(FLevelLocals, flags2, infinite_flight, LEVEL2_INFINITE_FLIGHT)
|
||||
DEFINE_FIELD_BIT(FLevelLocals, flags2, no_dlg_freeze, LEVEL2_CONV_SINGLE_UNFREEZE)
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
|
|
@ -25,6 +25,7 @@ struct FLevelLocals
|
|||
FString MapName; // the lump name (E1M1, MAP01, etc)
|
||||
FString NextMap; // go here when using the regular exit
|
||||
FString NextSecretMap; // map to go to when used secret exit
|
||||
FString F1Pic;
|
||||
EMapType maptype;
|
||||
|
||||
TStaticArray<vertex_t> vertexes;
|
||||
|
|
|
@ -1970,6 +1970,7 @@ static void ClearMapinfo()
|
|||
DefaultSkill = -1;
|
||||
DeinitIntermissions();
|
||||
level.info = NULL;
|
||||
level.F1Pic = "";
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -298,7 +298,7 @@ bool P_UndoPlayerMorph (player_t *activator, player_t *player, int unmorphflag,
|
|||
// If a custom skin was in use, then reload it
|
||||
// or else the base skin for the player class.
|
||||
if ((unsigned int)player->userinfo.GetSkin() >= PlayerClasses.Size () &&
|
||||
(size_t)player->userinfo.GetSkin() < numskins)
|
||||
(unsigned)player->userinfo.GetSkin() < Skins.Size())
|
||||
{
|
||||
|
||||
skinindex = player->userinfo.GetSkin();
|
||||
|
|
|
@ -489,7 +489,7 @@ FTexture *FMugShot::GetFace(player_t *player, const char *default_face, int accu
|
|||
if (CurrentState != NULL)
|
||||
{
|
||||
int skin = player->userinfo.GetSkin();
|
||||
const char *skin_face = (stateflags & FMugShot::CUSTOM) ? nullptr : (player->morphTics ? ((APlayerPawn*)GetDefaultByType(player->MorphedPlayerClass))->Face.GetChars() : skins[skin].face);
|
||||
const char *skin_face = (stateflags & FMugShot::CUSTOM) ? nullptr : (player->morphTics ? ((APlayerPawn*)GetDefaultByType(player->MorphedPlayerClass))->Face.GetChars() : Skins[skin].Face.GetChars());
|
||||
return CurrentState->GetCurrentFrameTexture(default_face, skin_face, level, angle);
|
||||
}
|
||||
return NULL;
|
||||
|
|
|
@ -50,6 +50,8 @@ DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, Armor2Percent)
|
|||
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, ArmorIcon1)
|
||||
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, ArmorIcon2)
|
||||
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, gametype)
|
||||
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, norandomplayerclass)
|
||||
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, infoPages)
|
||||
|
||||
|
||||
const char *GameNames[17] =
|
||||
|
@ -360,6 +362,7 @@ void FMapInfoParser::ParseGameInfo()
|
|||
GAMEINFOKEY_INT(TextScreenX, "textscreenx")
|
||||
GAMEINFOKEY_INT(TextScreenY, "textscreeny")
|
||||
GAMEINFOKEY_STRING(DefaultEndSequence, "defaultendsequence")
|
||||
GAMEINFOKEY_STRING(DefaultConversationMenuClass, "defaultconversationmenuclass")
|
||||
GAMEINFOKEY_FONT(mStatscreenMapNameFont, "statscreen_mapnamefont")
|
||||
GAMEINFOKEY_FONT(mStatscreenFinishedFont, "statscreen_finishedfont")
|
||||
GAMEINFOKEY_FONT(mStatscreenEnteringFont, "statscreen_enteringfont")
|
||||
|
|
1
src/gi.h
1
src/gi.h
|
@ -172,6 +172,7 @@ struct gameinfo_t
|
|||
double gibfactor;
|
||||
int TextScreenX;
|
||||
int TextScreenY;
|
||||
FName DefaultConversationMenuClass;
|
||||
FName DefaultEndSequence;
|
||||
FString mMapArrow, mCheatMapArrow;
|
||||
FString mEasyKey, mCheatKey;
|
||||
|
|
|
@ -593,7 +593,7 @@ void DIntermissionScreenCast::Drawer ()
|
|||
if (!(mDefaults->flags4 & MF4_NOSKIN) &&
|
||||
mDefaults->SpawnState != NULL && caststate->sprite == mDefaults->SpawnState->sprite &&
|
||||
mClass->IsDescendantOf(RUNTIME_CLASS(APlayerPawn)) &&
|
||||
skins != NULL)
|
||||
Skins.Size() > 0)
|
||||
{
|
||||
// Only use the skin sprite if this class has not been removed from the
|
||||
// PlayerClasses list.
|
||||
|
@ -601,7 +601,7 @@ void DIntermissionScreenCast::Drawer ()
|
|||
{
|
||||
if (PlayerClasses[i].Type == mClass)
|
||||
{
|
||||
FPlayerSkin *skin = &skins[players[consoleplayer].userinfo.GetSkin()];
|
||||
FPlayerSkin *skin = &Skins[players[consoleplayer].userinfo.GetSkin()];
|
||||
castsprite = skin->sprite;
|
||||
|
||||
if (!(mDefaults->flags4 & MF4_NOSKIN))
|
||||
|
|
|
@ -186,12 +186,12 @@ void UpdateJoystickMenu(IJoystickConfig *selected)
|
|||
{
|
||||
opt->mSelectedItem = opt->mItems.Size() - 1;
|
||||
}
|
||||
opt->CalcIndent();
|
||||
//opt->CalcIndent();
|
||||
|
||||
// If the joystick config menu is open, close it if the device it's open for is gone.
|
||||
if (DMenu::CurrentMenu != nullptr && (DMenu::CurrentMenu->IsKindOf("JoystickConfigMenu")))
|
||||
if (CurrentMenu != nullptr && (CurrentMenu->IsKindOf("JoystickConfigMenu")))
|
||||
{
|
||||
auto p = DMenu::CurrentMenu->PointerVar<IJoystickConfig>("mJoy");
|
||||
auto p = CurrentMenu->PointerVar<IJoystickConfig>("mJoy");
|
||||
if (p != nullptr)
|
||||
{
|
||||
unsigned i;
|
||||
|
@ -204,7 +204,7 @@ void UpdateJoystickMenu(IJoystickConfig *selected)
|
|||
}
|
||||
if (i == Joysticks.Size())
|
||||
{
|
||||
DMenu::CurrentMenu->Close();
|
||||
CurrentMenu->Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,281 +0,0 @@
|
|||
/*
|
||||
** listmenu.cpp
|
||||
** A simple menu consisting of a list of items
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2010 Christoph Oelckers
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
#include "v_video.h"
|
||||
#include "v_font.h"
|
||||
#include "cmdlib.h"
|
||||
#include "gstrings.h"
|
||||
#include "g_level.h"
|
||||
#include "gi.h"
|
||||
#include "d_gui.h"
|
||||
#include "d_event.h"
|
||||
#include "menu/menu.h"
|
||||
|
||||
IMPLEMENT_CLASS(DListMenu, false, false)
|
||||
|
||||
IMPLEMENT_POINTERS_START(DListMenu)
|
||||
IMPLEMENT_POINTER(mFocusControl)
|
||||
IMPLEMENT_POINTERS_END
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
DListMenu::DListMenu(DMenu *parent, DListMenuDescriptor *desc)
|
||||
: DMenu(parent)
|
||||
{
|
||||
mDesc = NULL;
|
||||
if (desc != NULL) Init(parent, desc);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DListMenu::Init(DMenu *parent, DListMenuDescriptor *desc)
|
||||
{
|
||||
mParentMenu = parent;
|
||||
GC::WriteBarrier(this, parent);
|
||||
mDesc = desc;
|
||||
if (desc->mCenter)
|
||||
{
|
||||
int center = 160;
|
||||
for(unsigned i=0;i<mDesc->mItems.Size(); i++)
|
||||
{
|
||||
int xpos = mDesc->mItems[i]->GetX();
|
||||
int width = mDesc->mItems[i]->GetWidth();
|
||||
int curx = mDesc->mSelectOfsX;
|
||||
|
||||
if (width > 0 && mDesc->mItems[i]->Selectable())
|
||||
{
|
||||
int left = 160 - (width - curx) / 2 - curx;
|
||||
if (left < center) center = left;
|
||||
}
|
||||
}
|
||||
for(unsigned i=0;i<mDesc->mItems.Size(); i++)
|
||||
{
|
||||
int width = mDesc->mItems[i]->GetWidth();
|
||||
|
||||
if (width > 0)
|
||||
{
|
||||
mDesc->mItems[i]->SetX(center);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
DMenuItemBase *DListMenu::GetItem(FName name)
|
||||
{
|
||||
for(unsigned i=0;i<mDesc->mItems.Size(); i++)
|
||||
{
|
||||
FName nm = mDesc->mItems[i]->GetAction(NULL);
|
||||
if (nm == name) return mDesc->mItems[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DListMenu::Responder (event_t *ev)
|
||||
{
|
||||
if (ev->type == EV_GUI_Event)
|
||||
{
|
||||
if (ev->subtype == EV_GUI_KeyDown)
|
||||
{
|
||||
int ch = tolower (ev->data1);
|
||||
|
||||
for(unsigned i = mDesc->mSelectedItem + 1; i < mDesc->mItems.Size(); i++)
|
||||
{
|
||||
if (mDesc->mItems[i]->CheckHotkey(ch))
|
||||
{
|
||||
mDesc->mSelectedItem = i;
|
||||
S_Sound(CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for(int i = 0; i < mDesc->mSelectedItem; i++)
|
||||
{
|
||||
if (mDesc->mItems[i]->CheckHotkey(ch))
|
||||
{
|
||||
mDesc->mSelectedItem = i;
|
||||
S_Sound(CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Super::Responder(ev);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DListMenu::MenuEvent (int mkey, bool fromcontroller)
|
||||
{
|
||||
int oldSelect = mDesc->mSelectedItem;
|
||||
int startedAt = mDesc->mSelectedItem;
|
||||
if (startedAt < 0) startedAt = 0;
|
||||
|
||||
switch (mkey)
|
||||
{
|
||||
case MKEY_Up:
|
||||
do
|
||||
{
|
||||
if (--mDesc->mSelectedItem < 0) mDesc->mSelectedItem = mDesc->mItems.Size()-1;
|
||||
}
|
||||
while (!mDesc->mItems[mDesc->mSelectedItem]->Selectable() && mDesc->mSelectedItem != startedAt);
|
||||
if (mDesc->mSelectedItem == startedAt) mDesc->mSelectedItem = oldSelect;
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
|
||||
return true;
|
||||
|
||||
case MKEY_Down:
|
||||
do
|
||||
{
|
||||
if (++mDesc->mSelectedItem >= (int)mDesc->mItems.Size()) mDesc->mSelectedItem = 0;
|
||||
}
|
||||
while (!mDesc->mItems[mDesc->mSelectedItem]->Selectable() && mDesc->mSelectedItem != startedAt);
|
||||
if (mDesc->mSelectedItem == startedAt) mDesc->mSelectedItem = oldSelect;
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
|
||||
return true;
|
||||
|
||||
case MKEY_Enter:
|
||||
if (mDesc->mSelectedItem >= 0 && mDesc->mItems[mDesc->mSelectedItem]->Activate())
|
||||
{
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/choose", snd_menuvolume, ATTN_NONE);
|
||||
}
|
||||
return true;
|
||||
|
||||
default:
|
||||
return Super::MenuEvent(mkey, fromcontroller);
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DListMenu::MouseEvent(int type, int x, int y)
|
||||
{
|
||||
int sel = -1;
|
||||
|
||||
// convert x/y from screen to virtual coordinates, according to CleanX/Yfac use in DrawTexture
|
||||
x = ((x - (screen->GetWidth() / 2)) / CleanXfac) + 160;
|
||||
y = ((y - (screen->GetHeight() / 2)) / CleanYfac) + 100;
|
||||
|
||||
if (mFocusControl != NULL)
|
||||
{
|
||||
mFocusControl->MouseEvent(type, x, y);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((mDesc->mWLeft <= 0 || x > mDesc->mWLeft) &&
|
||||
(mDesc->mWRight <= 0 || x < mDesc->mWRight))
|
||||
{
|
||||
for(unsigned i=0;i<mDesc->mItems.Size(); i++)
|
||||
{
|
||||
if (mDesc->mItems[i]->CheckCoordinate(x, y))
|
||||
{
|
||||
if ((int)i != mDesc->mSelectedItem)
|
||||
{
|
||||
//S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
|
||||
}
|
||||
mDesc->mSelectedItem = i;
|
||||
mDesc->mItems[i]->MouseEvent(type, x, y);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mDesc->mSelectedItem = -1;
|
||||
return Super::MouseEvent(type, x, y);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DListMenu::Ticker ()
|
||||
{
|
||||
Super::Ticker();
|
||||
for(unsigned i=0;i<mDesc->mItems.Size(); i++)
|
||||
{
|
||||
mDesc->mItems[i]->Ticker();
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DListMenu::Drawer ()
|
||||
{
|
||||
for(unsigned i=0;i<mDesc->mItems.Size(); i++)
|
||||
{
|
||||
if (mDesc->mItems[i]->mEnabled) mDesc->mItems[i]->Drawer(mDesc->mSelectedItem == (int)i);
|
||||
}
|
||||
if (mDesc->mSelectedItem >= 0 && mDesc->mSelectedItem < (int)mDesc->mItems.Size())
|
||||
mDesc->mItems[mDesc->mSelectedItem]->DrawSelector(mDesc->mSelectOfsX, mDesc->mSelectOfsY, mDesc->mSelector);
|
||||
Super::Drawer();
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// base class for menu items
|
||||
//
|
||||
//=============================================================================
|
||||
IMPLEMENT_CLASS(DMenuItemBase, false, false)
|
File diff suppressed because it is too large
Load diff
|
@ -63,24 +63,23 @@
|
|||
CVAR (Float, mouse_sensitivity, 1.f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CVAR (Bool, show_messages, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CVAR (Bool, show_obituaries, true, CVAR_ARCHIVE)
|
||||
CVAR(Bool, m_showinputgrid, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
|
||||
|
||||
CVAR (Float, snd_menuvolume, 0.6f, CVAR_ARCHIVE)
|
||||
CVAR(Int, m_use_mouse, 2, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CVAR(Int, m_show_backbutton, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
|
||||
DMenu *DMenu::CurrentMenu;
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DMenu, GetCurrentMenu)
|
||||
{
|
||||
ACTION_RETURN_OBJECT(DMenu::CurrentMenu);
|
||||
ACTION_RETURN_OBJECT(CurrentMenu);
|
||||
}
|
||||
|
||||
int DMenu::MenuTime;
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DMenu, MenuTime)
|
||||
{
|
||||
ACTION_RETURN_INT(DMenu::MenuTime);
|
||||
ACTION_RETURN_INT(MenuTime);
|
||||
}
|
||||
|
||||
FGameStartup GameStartupInfo;
|
||||
|
@ -92,6 +91,8 @@ bool MenuButtonOrigin[NUM_MKEYS];
|
|||
int BackbuttonTime;
|
||||
float BackbuttonAlpha;
|
||||
static bool MenuEnabled = true;
|
||||
DMenu *CurrentMenu;
|
||||
int MenuTime;
|
||||
|
||||
void M_InitVideoModes();
|
||||
extern PClass *DefaultListMenuClass;
|
||||
|
@ -140,7 +141,7 @@ void M_MarkMenus()
|
|||
{
|
||||
GC::Mark(pair->Value);
|
||||
}
|
||||
GC::Mark(DMenu::CurrentMenu);
|
||||
GC::Mark(CurrentMenu);
|
||||
}
|
||||
//============================================================================
|
||||
//
|
||||
|
@ -159,6 +160,7 @@ DMenu::DMenu(DMenu *parent)
|
|||
mParentMenu = parent;
|
||||
mMouseCapture = false;
|
||||
mBackbuttonSelected = false;
|
||||
DontDim = false;
|
||||
GC::WriteBarrier(this, parent);
|
||||
}
|
||||
|
||||
|
@ -237,7 +239,7 @@ bool DMenu::MenuEvent (int mkey, bool fromcontroller)
|
|||
{
|
||||
Close();
|
||||
S_Sound (CHAN_VOICE | CHAN_UI,
|
||||
DMenu::CurrentMenu != nullptr? "menu/backup" : "menu/clear", snd_menuvolume, ATTN_NONE);
|
||||
CurrentMenu != nullptr? "menu/backup" : "menu/clear", snd_menuvolume, ATTN_NONE);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -272,13 +274,13 @@ bool DMenu::CallMenuEvent(int mkey, bool fromcontroller)
|
|||
|
||||
void DMenu::Close ()
|
||||
{
|
||||
if (DMenu::CurrentMenu == nullptr) return; // double closing can happen in the save menu.
|
||||
assert(DMenu::CurrentMenu == this);
|
||||
DMenu::CurrentMenu = mParentMenu;
|
||||
if (CurrentMenu == nullptr) return; // double closing can happen in the save menu.
|
||||
assert(CurrentMenu == this);
|
||||
CurrentMenu = mParentMenu;
|
||||
Destroy();
|
||||
if (DMenu::CurrentMenu != nullptr)
|
||||
if (CurrentMenu != nullptr)
|
||||
{
|
||||
GC::WriteBarrier(DMenu::CurrentMenu);
|
||||
GC::WriteBarrier(CurrentMenu);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -401,7 +403,7 @@ void DMenu::CallTicker()
|
|||
|
||||
void DMenu::Drawer ()
|
||||
{
|
||||
if (this == DMenu::CurrentMenu && BackbuttonAlpha > 0 && m_show_backbutton >= 0 && m_use_mouse)
|
||||
if (this == CurrentMenu && BackbuttonAlpha > 0 && m_show_backbutton >= 0 && m_use_mouse)
|
||||
{
|
||||
FTexture *tex = TexMan(gameinfo.mBackButton);
|
||||
int w = tex->GetScaledWidth() * CleanXfac;
|
||||
|
@ -444,26 +446,6 @@ DEFINE_ACTION_FUNCTION(DMenu, Close)
|
|||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DMenu, GetItem)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DMenu);
|
||||
PARAM_NAME(name);
|
||||
ACTION_RETURN_OBJECT(self->GetItem(name));
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DOptionMenuDescriptor, GetItem)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DOptionMenuDescriptor);
|
||||
PARAM_NAME(name);
|
||||
ACTION_RETURN_OBJECT(self->GetItem(name));
|
||||
}
|
||||
|
||||
|
||||
bool DMenu::DimAllowed()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DMenu::TranslateKeyboardEvents()
|
||||
{
|
||||
IFVIRTUAL(DMenu, TranslateKeyboardEvents)
|
||||
|
@ -486,7 +468,7 @@ bool DMenu::TranslateKeyboardEvents()
|
|||
void M_StartControlPanel (bool makeSound)
|
||||
{
|
||||
// intro might call this repeatedly
|
||||
if (DMenu::CurrentMenu != nullptr)
|
||||
if (CurrentMenu != nullptr)
|
||||
return;
|
||||
|
||||
ResetButtonStates ();
|
||||
|
@ -518,9 +500,9 @@ void M_StartControlPanel (bool makeSound)
|
|||
void M_ActivateMenu(DMenu *menu)
|
||||
{
|
||||
if (menuactive == MENU_Off) menuactive = MENU_On;
|
||||
if (DMenu::CurrentMenu != nullptr) DMenu::CurrentMenu->ReleaseCapture();
|
||||
DMenu::CurrentMenu = menu;
|
||||
GC::WriteBarrier(DMenu::CurrentMenu);
|
||||
if (CurrentMenu != nullptr) CurrentMenu->ReleaseCapture();
|
||||
CurrentMenu = menu;
|
||||
GC::WriteBarrier(CurrentMenu);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DMenu, ActivateMenu)
|
||||
|
@ -602,6 +584,11 @@ void M_SetMenu(FName menu, int param)
|
|||
M_InitVideoModes();
|
||||
break;
|
||||
|
||||
case NAME_Quitmenu:
|
||||
// The separate menu class no longer exists but the name still needs support for existing mods.
|
||||
C_DoCommand("menu_quit");
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// End of special checks
|
||||
|
@ -629,8 +616,12 @@ void M_SetMenu(FName menu, int param)
|
|||
if (cls == nullptr) cls = DefaultListMenuClass;
|
||||
if (cls == nullptr) cls = PClass::FindClass("ListMenu");
|
||||
|
||||
DListMenu *newmenu = (DListMenu *)cls->CreateNew();
|
||||
newmenu->Init(DMenu::CurrentMenu, ld);
|
||||
DMenu *newmenu = (DMenu *)cls->CreateNew();
|
||||
IFVIRTUALPTRNAME(newmenu, "ListMenu", Init)
|
||||
{
|
||||
VMValue params[3] = { newmenu, CurrentMenu, ld };
|
||||
GlobalVMStack.Call(func, params, 3, nullptr, 0);
|
||||
}
|
||||
M_ActivateMenu(newmenu);
|
||||
}
|
||||
}
|
||||
|
@ -644,7 +635,7 @@ void M_SetMenu(FName menu, int param)
|
|||
DMenu *newmenu = (DMenu*)cls->CreateNew();
|
||||
IFVIRTUALPTRNAME(newmenu, "OptionMenu", Init)
|
||||
{
|
||||
VMValue params[3] = { newmenu, DMenu::CurrentMenu, ld };
|
||||
VMValue params[3] = { newmenu, CurrentMenu, ld };
|
||||
GlobalVMStack.Call(func, params, 3, nullptr, 0);
|
||||
}
|
||||
M_ActivateMenu(newmenu);
|
||||
|
@ -659,7 +650,7 @@ void M_SetMenu(FName menu, int param)
|
|||
if (menuclass->IsDescendantOf(RUNTIME_CLASS(DMenu)))
|
||||
{
|
||||
DMenu *newmenu = (DMenu*)menuclass->CreateNew();
|
||||
newmenu->mParentMenu = DMenu::CurrentMenu;
|
||||
newmenu->mParentMenu = CurrentMenu;
|
||||
M_ActivateMenu(newmenu);
|
||||
return;
|
||||
}
|
||||
|
@ -695,7 +686,7 @@ bool M_Responder (event_t *ev)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (DMenu::CurrentMenu != nullptr && menuactive != MENU_Off)
|
||||
if (CurrentMenu != nullptr && menuactive != MENU_Off)
|
||||
{
|
||||
// There are a few input sources we are interested in:
|
||||
//
|
||||
|
@ -730,9 +721,9 @@ bool M_Responder (event_t *ev)
|
|||
}
|
||||
|
||||
// pass everything else on to the current menu
|
||||
return DMenu::CurrentMenu->CallResponder(ev);
|
||||
return CurrentMenu->CallResponder(ev);
|
||||
}
|
||||
else if (DMenu::CurrentMenu->TranslateKeyboardEvents())
|
||||
else if (CurrentMenu->TranslateKeyboardEvents())
|
||||
{
|
||||
ch = ev->data1;
|
||||
keyup = ev->subtype == EV_GUI_KeyUp;
|
||||
|
@ -751,7 +742,7 @@ bool M_Responder (event_t *ev)
|
|||
default:
|
||||
if (!keyup)
|
||||
{
|
||||
return DMenu::CurrentMenu->CallResponder(ev);
|
||||
return CurrentMenu->CallResponder(ev);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -834,11 +825,11 @@ bool M_Responder (event_t *ev)
|
|||
{
|
||||
MenuButtonTickers[mkey] = KEY_REPEAT_DELAY;
|
||||
}
|
||||
DMenu::CurrentMenu->CallMenuEvent(mkey, fromcontroller);
|
||||
CurrentMenu->CallMenuEvent(mkey, fromcontroller);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return DMenu::CurrentMenu->CallResponder(ev) || !keyup;
|
||||
return CurrentMenu->CallResponder(ev) || !keyup;
|
||||
}
|
||||
else if (MenuEnabled)
|
||||
{
|
||||
|
@ -879,10 +870,10 @@ bool M_Responder (event_t *ev)
|
|||
|
||||
void M_Ticker (void)
|
||||
{
|
||||
DMenu::MenuTime++;
|
||||
if (DMenu::CurrentMenu != nullptr && menuactive != MENU_Off)
|
||||
MenuTime++;
|
||||
if (CurrentMenu != nullptr && menuactive != MENU_Off)
|
||||
{
|
||||
DMenu::CurrentMenu->CallTicker();
|
||||
CurrentMenu->CallTicker();
|
||||
|
||||
for (int i = 0; i < NUM_MKEYS; ++i)
|
||||
{
|
||||
|
@ -891,7 +882,7 @@ void M_Ticker (void)
|
|||
if (MenuButtonTickers[i] > 0 && --MenuButtonTickers[i] <= 0)
|
||||
{
|
||||
MenuButtonTickers[i] = KEY_REPEAT_RATE;
|
||||
DMenu::CurrentMenu->CallMenuEvent(i, MenuButtonOrigin[i]);
|
||||
CurrentMenu->CallMenuEvent(i, MenuButtonOrigin[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -931,14 +922,14 @@ void M_Drawer (void)
|
|||
}
|
||||
|
||||
|
||||
if (DMenu::CurrentMenu != nullptr && menuactive != MENU_Off)
|
||||
if (CurrentMenu != nullptr && menuactive != MENU_Off)
|
||||
{
|
||||
if (DMenu::CurrentMenu->DimAllowed())
|
||||
if (!CurrentMenu->DontDim)
|
||||
{
|
||||
screen->Dim(fade);
|
||||
V_SetBorderNeedRefresh();
|
||||
}
|
||||
DMenu::CurrentMenu->CallDrawer();
|
||||
CurrentMenu->CallDrawer();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -951,10 +942,10 @@ void M_Drawer (void)
|
|||
void M_ClearMenus ()
|
||||
{
|
||||
M_DemoNoPlay = false;
|
||||
if (DMenu::CurrentMenu != nullptr)
|
||||
if (CurrentMenu != nullptr)
|
||||
{
|
||||
DMenu::CurrentMenu->Destroy();
|
||||
DMenu::CurrentMenu = nullptr;
|
||||
CurrentMenu->Destroy();
|
||||
CurrentMenu = nullptr;
|
||||
}
|
||||
V_SetBorderNeedRefresh();
|
||||
menuactive = MENU_Off;
|
||||
|
@ -1192,11 +1183,11 @@ CCMD(reset2saved)
|
|||
// This really should be in the script but we can't do scripted CCMDs yet.
|
||||
CCMD(undocolorpic)
|
||||
{
|
||||
if (DMenu::CurrentMenu != NULL)
|
||||
if (CurrentMenu != NULL)
|
||||
{
|
||||
IFVIRTUALPTR(DMenu::CurrentMenu, DMenu, ResetColor)
|
||||
IFVIRTUALPTR(CurrentMenu, DMenu, ResetColor)
|
||||
{
|
||||
VMValue params[] = { (DObject*)DMenu::CurrentMenu };
|
||||
VMValue params[] = { (DObject*)CurrentMenu };
|
||||
GlobalVMStack.Call(func, params, countof(params), nullptr, 0, nullptr);
|
||||
}
|
||||
}
|
||||
|
@ -1206,6 +1197,9 @@ CCMD(undocolorpic)
|
|||
|
||||
|
||||
DEFINE_FIELD(DMenu, mParentMenu)
|
||||
DEFINE_FIELD(DMenu, mMouseCapture);
|
||||
DEFINE_FIELD(DMenu, mBackbuttonSelected);
|
||||
DEFINE_FIELD(DMenu, DontDim);
|
||||
|
||||
DEFINE_FIELD(DMenuDescriptor, mMenuName)
|
||||
DEFINE_FIELD(DMenuDescriptor, mNetgameMessage)
|
||||
|
@ -1216,9 +1210,6 @@ DEFINE_FIELD(DMenuItemBase, mYpos)
|
|||
DEFINE_FIELD(DMenuItemBase, mAction)
|
||||
DEFINE_FIELD(DMenuItemBase, mEnabled)
|
||||
|
||||
DEFINE_FIELD(DListMenu, mDesc)
|
||||
DEFINE_FIELD(DListMenu, mFocusControl)
|
||||
|
||||
DEFINE_FIELD(DListMenuDescriptor, mItems)
|
||||
DEFINE_FIELD(DListMenuDescriptor, mSelectedItem)
|
||||
DEFINE_FIELD(DListMenuDescriptor, mSelectOfsX)
|
||||
|
@ -1318,50 +1309,6 @@ DMenuItemBase * CreateListMenuItemText(int x, int y, int height, int hotkey, con
|
|||
return (DMenuItemBase*)p;
|
||||
}
|
||||
|
||||
bool DMenuItemBase::CheckCoordinate(int x, int y)
|
||||
{
|
||||
IFVIRTUAL(DMenuItemBase, CheckCoordinate)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this, x, y };
|
||||
int retval;
|
||||
VMReturn ret(&retval);
|
||||
GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr);
|
||||
return !!retval;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DMenuItemBase::Ticker()
|
||||
{
|
||||
IFVIRTUAL(DMenuItemBase, Ticker)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this };
|
||||
GlobalVMStack.Call(func, params, countof(params), nullptr, 0, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void DMenuItemBase::Drawer(bool selected)
|
||||
{
|
||||
IFVIRTUAL(DMenuItemBase, Drawer)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this, selected };
|
||||
GlobalVMStack.Call(func, params, countof(params), nullptr, 0, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
bool DMenuItemBase::Selectable()
|
||||
{
|
||||
IFVIRTUAL(DMenuItemBase, Selectable)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this };
|
||||
int retval;
|
||||
VMReturn ret(&retval);
|
||||
GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr);
|
||||
return !!retval;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DMenuItemBase::Activate()
|
||||
{
|
||||
IFVIRTUAL(DMenuItemBase, Activate)
|
||||
|
@ -1374,18 +1321,6 @@ bool DMenuItemBase::Activate()
|
|||
}
|
||||
return false;
|
||||
}
|
||||
FName DMenuItemBase::GetAction(int *pparam)
|
||||
{
|
||||
IFVIRTUAL(DMenuItemBase, GetAction)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this };
|
||||
int retval[2];
|
||||
VMReturn ret[2]; ret[0].IntAt(&retval[0]); ret[1].IntAt(&retval[1]);
|
||||
GlobalVMStack.Call(func, params, countof(params), ret, 2, nullptr);
|
||||
return ENamedName(retval[0]);
|
||||
}
|
||||
return NAME_None;
|
||||
}
|
||||
|
||||
bool DMenuItemBase::SetString(int i, const char *s)
|
||||
{
|
||||
|
@ -1443,112 +1378,4 @@ bool DMenuItemBase::GetValue(int i, int *pvalue)
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
void DMenuItemBase::Enable(bool on)
|
||||
{
|
||||
IFVIRTUAL(DMenuItemBase, Enable)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this, on };
|
||||
GlobalVMStack.Call(func, params, countof(params), nullptr, 0, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
bool DMenuItemBase::MenuEvent(int mkey, bool fromcontroller)
|
||||
{
|
||||
IFVIRTUAL(DMenuItemBase, MenuEvent)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this, mkey, fromcontroller };
|
||||
int retval;
|
||||
VMReturn ret(&retval);
|
||||
GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr);
|
||||
return !!retval;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DMenuItemBase::MouseEvent(int type, int x, int y)
|
||||
{
|
||||
IFVIRTUAL(DMenuItemBase, MouseEvent)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this, type, x, y };
|
||||
int retval;
|
||||
VMReturn ret(&retval);
|
||||
GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr);
|
||||
return !!retval;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DMenuItemBase::CheckHotkey(int c)
|
||||
{
|
||||
IFVIRTUAL(DMenuItemBase, CheckHotkey)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this, c };
|
||||
int retval;
|
||||
VMReturn ret(&retval);
|
||||
GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr);
|
||||
return !!retval;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int DMenuItemBase::GetWidth()
|
||||
{
|
||||
IFVIRTUAL(DMenuItemBase, GetWidth)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this };
|
||||
int retval;
|
||||
VMReturn ret(&retval);
|
||||
GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr);
|
||||
return retval;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int DMenuItemBase::GetIndent()
|
||||
{
|
||||
IFVIRTUAL(DMenuItemBase, GetIndent)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this };
|
||||
int retval;
|
||||
VMReturn ret(&retval);
|
||||
GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr);
|
||||
return retval;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int DMenuItemBase::Draw(DOptionMenuDescriptor *desc, int y, int indent, bool selected)
|
||||
{
|
||||
IFVIRTUAL(DMenuItemBase, Draw)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this, desc, y, indent, selected };
|
||||
int retval;
|
||||
VMReturn ret(&retval);
|
||||
GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr);
|
||||
return retval;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DMenuItemBase::DrawSelector(int xofs, int yofs, FTextureID tex)
|
||||
{
|
||||
if (tex.isNull())
|
||||
{
|
||||
if ((DMenu::MenuTime % 8) < 6)
|
||||
{
|
||||
screen->DrawText(ConFont, OptionSettings.mFontColorSelection,
|
||||
(mXpos + xofs - 160) * CleanXfac + screen->GetWidth() / 2,
|
||||
(mYpos + yofs - 100) * CleanYfac + screen->GetHeight() / 2,
|
||||
"\xd",
|
||||
DTA_CellX, 8 * CleanXfac,
|
||||
DTA_CellY, 8 * CleanYfac,
|
||||
TAG_DONE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
screen->DrawTexture(TexMan(tex), mXpos + xofs, mYpos + yofs, DTA_Clean, true, TAG_DONE);
|
||||
}
|
||||
}
|
||||
|
||||
IMPLEMENT_CLASS(DMenuItemBase, false, false)
|
||||
|
|
149
src/menu/menu.h
149
src/menu/menu.h
|
@ -58,46 +58,58 @@ extern FGameStartup GameStartupInfo;
|
|||
|
||||
struct FSaveGameNode
|
||||
{
|
||||
char Title[SAVESTRINGSIZE];
|
||||
FString SaveTitle;
|
||||
FString Filename;
|
||||
bool bOldVersion;
|
||||
bool bMissingWads;
|
||||
bool bNoDelete;
|
||||
|
||||
FSaveGameNode() { bNoDelete = false; }
|
||||
bool bOldVersion = false;
|
||||
bool bMissingWads = false;
|
||||
bool bNoDelete = false;
|
||||
};
|
||||
|
||||
struct SavegameManager
|
||||
struct FSavegameManager
|
||||
{
|
||||
private:
|
||||
TArray<FSaveGameNode*> SaveGames;
|
||||
FSaveGameNode NewSaveNode;
|
||||
int LastSaved = -1;
|
||||
int LastAccessed = -1;
|
||||
int WindowSize = 0;
|
||||
FSaveGameNode *quickSaveSlot = nullptr;
|
||||
|
||||
FileReader *currentSavePic = nullptr;
|
||||
TArray<char> SavePicData;
|
||||
|
||||
FTexture *SavePic = nullptr;
|
||||
FBrokenLines *SaveComment = nullptr;
|
||||
|
||||
void ClearSaveGames();
|
||||
public:
|
||||
int WindowSize = 0;
|
||||
FSaveGameNode *quickSaveSlot = nullptr;
|
||||
~FSavegameManager();
|
||||
|
||||
private:
|
||||
int InsertSaveNode(FSaveGameNode *node);
|
||||
int RemoveSaveSlot(int index);
|
||||
public:
|
||||
void NotifyNewSave(const FString &file, const FString &title, bool okForQuicksave);
|
||||
void ClearSaveGames();
|
||||
|
||||
void ReadSaveStrings();
|
||||
void NotifyNewSave(const char *file, const char *title, bool okForQuicksave);
|
||||
void UnloadSaveData();
|
||||
|
||||
int RemoveSaveSlot(int index);
|
||||
void LoadSavegame(int Selected);
|
||||
void DoSave(int Selected, const char *savegamestring);
|
||||
void DeleteEntry(int Selected);
|
||||
void ExtractSaveData(int index);
|
||||
void UnloadSaveData();
|
||||
unsigned ExtractSaveData(int index);
|
||||
void ClearSaveStuff();
|
||||
bool DrawSavePic(int x, int y, int w, int h);
|
||||
void DrawSaveComment(FFont *font, int cr, int x, int y, int scalefactor);
|
||||
void SetFileInfo(int Selected);
|
||||
unsigned SavegameCount();
|
||||
FSaveGameNode *GetSavegame(int i);
|
||||
void InsertNewSaveNode();
|
||||
bool RemoveNewSaveNode();
|
||||
|
||||
};
|
||||
|
||||
extern SavegameManager savegameManager;
|
||||
extern FSavegameManager savegameManager;
|
||||
class DMenu;
|
||||
extern DMenu *CurrentMenu;
|
||||
extern int MenuTime;
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
|
@ -241,9 +253,7 @@ class DMenu : public DObject
|
|||
DECLARE_CLASS (DMenu, DObject)
|
||||
HAS_OBJECT_POINTERS
|
||||
|
||||
protected:
|
||||
bool mMouseCapture;
|
||||
bool mBackbuttonSelected;
|
||||
|
||||
|
||||
public:
|
||||
enum
|
||||
|
@ -258,17 +268,16 @@ public:
|
|||
BACKBUTTON_TIME = 4*TICRATE
|
||||
};
|
||||
|
||||
static DMenu *CurrentMenu;
|
||||
static int MenuTime;
|
||||
|
||||
TObjPtr<DMenu> mParentMenu;
|
||||
bool mMouseCapture;
|
||||
bool mBackbuttonSelected;
|
||||
bool DontDim;
|
||||
|
||||
DMenu(DMenu *parent = NULL);
|
||||
virtual bool Responder (event_t *ev);
|
||||
virtual bool MenuEvent (int mkey, bool fromcontroller);
|
||||
virtual void Ticker ();
|
||||
virtual void Drawer ();
|
||||
virtual bool DimAllowed ();
|
||||
bool TranslateKeyboardEvents();
|
||||
virtual void Close();
|
||||
virtual bool MouseEvent(int type, int x, int y);
|
||||
|
@ -277,8 +286,6 @@ public:
|
|||
virtual bool CheckFocus(DMenuItemBase *fc) { return false; }
|
||||
virtual void ReleaseFocus() {}
|
||||
|
||||
virtual DMenuItemBase *GetItem(FName name) { return nullptr; }
|
||||
|
||||
bool CallResponder(event_t *ev);
|
||||
bool CallMenuEvent(int mkey, bool fromcontroller);
|
||||
bool CallMouseEvent(int type, int x, int y);
|
||||
|
@ -308,70 +315,15 @@ public:
|
|||
FNameNoInit mAction;
|
||||
bool mEnabled;
|
||||
|
||||
bool CheckCoordinate(int x, int y);
|
||||
void Ticker();
|
||||
void Drawer(bool selected);
|
||||
bool Selectable();
|
||||
bool Activate();
|
||||
FName GetAction(int *pparam);
|
||||
bool SetString(int i, const char *s);
|
||||
bool GetString(int i, char *s, int len);
|
||||
bool SetValue(int i, int value);
|
||||
bool GetValue(int i, int *pvalue);
|
||||
void Enable(bool on);
|
||||
bool MenuEvent (int mkey, bool fromcontroller);
|
||||
bool MouseEvent(int type, int x, int y);
|
||||
bool CheckHotkey(int c);
|
||||
int GetWidth();
|
||||
int GetIndent();
|
||||
int Draw(DOptionMenuDescriptor *desc, int y, int indent, bool selected);
|
||||
void OffsetPositionY(int ydelta) { mYpos += ydelta; }
|
||||
int GetY() { return mYpos; }
|
||||
int GetX() { return mXpos; }
|
||||
void SetX(int x) { mXpos = x; }
|
||||
|
||||
void DrawSelector(int xofs, int yofs, FTextureID tex);
|
||||
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// list menu class runs a menu described by a DListMenuDescriptor
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class DListMenu : public DMenu
|
||||
{
|
||||
DECLARE_CLASS(DListMenu, DMenu)
|
||||
HAS_OBJECT_POINTERS;
|
||||
public:
|
||||
|
||||
DListMenuDescriptor *mDesc;
|
||||
DMenuItemBase *mFocusControl;
|
||||
|
||||
DListMenu(DMenu *parent = NULL, DListMenuDescriptor *desc = NULL);
|
||||
virtual void Init(DMenu *parent = NULL, DListMenuDescriptor *desc = NULL);
|
||||
DMenuItemBase *GetItem(FName name);
|
||||
bool Responder (event_t *ev);
|
||||
bool MenuEvent (int mkey, bool fromcontroller);
|
||||
bool MouseEvent(int type, int x, int y);
|
||||
void Ticker ();
|
||||
void Drawer ();
|
||||
void SetFocus(DMenuItemBase *fc)
|
||||
{
|
||||
mFocusControl = fc;
|
||||
}
|
||||
bool CheckFocus(DMenuItemBase *fc)
|
||||
{
|
||||
return mFocusControl == fc;
|
||||
}
|
||||
void ReleaseFocus()
|
||||
{
|
||||
mFocusControl = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
|
@ -396,41 +348,10 @@ extern FOptionMap OptionValues;
|
|||
|
||||
//=============================================================================
|
||||
//
|
||||
// Input some text
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class DTextEnterMenu : public DMenu
|
||||
{
|
||||
DECLARE_ABSTRACT_CLASS(DTextEnterMenu, DMenu)
|
||||
|
||||
public:
|
||||
FString mEnterString;
|
||||
unsigned int mEnterSize;
|
||||
unsigned int mEnterPos;
|
||||
int mSizeMode; // 1: size is length in chars. 2: also check string width
|
||||
bool mInputGridOkay;
|
||||
|
||||
int InputGridX;
|
||||
int InputGridY;
|
||||
|
||||
// [TP]
|
||||
bool AllowColors;
|
||||
|
||||
|
||||
// [TP] Added allowcolors
|
||||
DTextEnterMenu(DMenu *parent, const char *textbuffer, int maxlen, int sizemode, bool showgrid, bool allowcolors = false);
|
||||
|
||||
void Drawer ();
|
||||
bool MenuEvent (int mkey, bool fromcontroller);
|
||||
bool Responder(event_t *ev);
|
||||
bool MouseEvent(int type, int x, int y);
|
||||
FString GetText();
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
struct event_t;
|
||||
void M_EnableMenu (bool on) ;
|
||||
bool M_Responder (event_t *ev);
|
||||
|
|
|
@ -147,7 +147,7 @@ static void DeinitMenus()
|
|||
}
|
||||
MenuDescriptors.Clear();
|
||||
OptionValues.Clear();
|
||||
DMenu::CurrentMenu = nullptr;
|
||||
CurrentMenu = nullptr;
|
||||
savegameManager.ClearSaveGames();
|
||||
}
|
||||
|
||||
|
@ -290,7 +290,7 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc)
|
|||
{
|
||||
sc.MustGetString();
|
||||
PClass *cls = PClass::FindClass(sc.String);
|
||||
if (cls == nullptr || !cls->IsDescendantOf(RUNTIME_CLASS(DListMenu)))
|
||||
if (cls == nullptr || !cls->IsDescendantOf("ListMenu"))
|
||||
{
|
||||
sc.ScriptError("Unknown menu class '%s'", sc.String);
|
||||
}
|
||||
|
@ -864,7 +864,6 @@ static void ParseOptionMenu(FScanner &sc)
|
|||
|
||||
ParseOptionMenuBody(sc, desc);
|
||||
ReplaceMenu(sc, desc);
|
||||
if (desc->mIndent == 0) desc->CalcIndent();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1336,7 +1335,7 @@ void M_StartupSkillMenu(FGameStartup *gs)
|
|||
// Delete previous contents
|
||||
for(unsigned i=0; i<ld->mItems.Size(); i++)
|
||||
{
|
||||
FName n = ld->mItems[i]->GetAction(nullptr);
|
||||
FName n = ld->mItems[i]->mAction;
|
||||
if (n == NAME_Startgame || n == NAME_StartgameConfirm)
|
||||
{
|
||||
ld->mItems.Resize(i);
|
||||
|
|
|
@ -1,396 +0,0 @@
|
|||
/*
|
||||
** menuinput.cpp
|
||||
** The string input code
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2001-2010 Randy Heit
|
||||
** Copyright 2010 Christoph Oelckers
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
#include "menu/menu.h"
|
||||
#include "v_video.h"
|
||||
#include "c_cvars.h"
|
||||
#include "d_event.h"
|
||||
#include "d_gui.h"
|
||||
#include "v_font.h"
|
||||
#include "v_palette.h"
|
||||
#include "cmdlib.h"
|
||||
// [TP] New #includes
|
||||
#include "v_text.h"
|
||||
|
||||
IMPLEMENT_CLASS(DTextEnterMenu, true, false)
|
||||
|
||||
#define INPUTGRID_WIDTH 13
|
||||
#define INPUTGRID_HEIGHT 5
|
||||
|
||||
// Heretic and Hexen do not, by default, come with glyphs for all of these
|
||||
// characters. Oh well. Doom and Strife do.
|
||||
static const char InputGridChars[INPUTGRID_WIDTH * INPUTGRID_HEIGHT] =
|
||||
"ABCDEFGHIJKLM"
|
||||
"NOPQRSTUVWXYZ"
|
||||
"0123456789+-="
|
||||
".,!?@'\":;[]()"
|
||||
"<>^#$%&*/_ \b";
|
||||
|
||||
|
||||
CVAR(Bool, m_showinputgrid, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
|
||||
DEFINE_FIELD(DTextEnterMenu, mInputGridOkay)
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
// [TP] Added allowcolors
|
||||
DTextEnterMenu::DTextEnterMenu(DMenu *parent, const char *textbuffer, int maxlen, int sizemode, bool showgrid, bool allowcolors)
|
||||
: DMenu(parent)
|
||||
{
|
||||
mEnterString = textbuffer;
|
||||
mEnterSize = maxlen < 0 ? UINT_MAX : unsigned(maxlen);
|
||||
mSizeMode = sizemode;
|
||||
mInputGridOkay = showgrid || m_showinputgrid;
|
||||
if (mEnterString.IsNotEmpty())
|
||||
{
|
||||
InputGridX = INPUTGRID_WIDTH - 1;
|
||||
InputGridY = INPUTGRID_HEIGHT - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we are naming a new save, don't start the cursor on "end".
|
||||
InputGridX = 0;
|
||||
InputGridY = 0;
|
||||
}
|
||||
AllowColors = allowcolors; // [TP]
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
FString DTextEnterMenu::GetText()
|
||||
{
|
||||
return mEnterString;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DTextEnterMenu::Responder(event_t *ev)
|
||||
{
|
||||
if (ev->type == EV_GUI_Event)
|
||||
{
|
||||
// Save game and player name string input
|
||||
if (ev->subtype == EV_GUI_Char)
|
||||
{
|
||||
mInputGridOkay = false;
|
||||
if (mEnterString.Len() < mEnterSize &&
|
||||
(mSizeMode == 2/*entering player name*/ || (size_t)SmallFont->StringWidth(mEnterString) < (mEnterSize-1)*8))
|
||||
{
|
||||
mEnterString.AppendFormat("%c", (char)ev->data1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
char ch = (char)ev->data1;
|
||||
if ((ev->subtype == EV_GUI_KeyDown || ev->subtype == EV_GUI_KeyRepeat) && ch == '\b')
|
||||
{
|
||||
if (mEnterString.IsNotEmpty())
|
||||
{
|
||||
mEnterString.Truncate(mEnterString.Len() - 1);
|
||||
}
|
||||
}
|
||||
else if (ev->subtype == EV_GUI_KeyDown)
|
||||
{
|
||||
if (ch == GK_ESCAPE)
|
||||
{
|
||||
DMenu *parent = mParentMenu;
|
||||
Close();
|
||||
parent->CallMenuEvent(MKEY_Abort, false);
|
||||
return true;
|
||||
}
|
||||
else if (ch == '\r')
|
||||
{
|
||||
if (mEnterString.IsNotEmpty())
|
||||
{
|
||||
// [TP] If we allow color codes, colorize the string now.
|
||||
if (AllowColors)
|
||||
mEnterString = strbin1(mEnterString);
|
||||
|
||||
DMenu *parent = mParentMenu;
|
||||
parent->CallMenuEvent(MKEY_Input, false);
|
||||
Close();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ev->subtype == EV_GUI_KeyDown || ev->subtype == EV_GUI_KeyRepeat)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return Super::Responder(ev);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DTextEnterMenu::MouseEvent(int type, int x, int y)
|
||||
{
|
||||
const int cell_width = 18 * CleanXfac;
|
||||
const int cell_height = 12 * CleanYfac;
|
||||
const int screen_y = screen->GetHeight() - INPUTGRID_HEIGHT * cell_height;
|
||||
const int screen_x = (screen->GetWidth() - INPUTGRID_WIDTH * cell_width) / 2;
|
||||
|
||||
if (x >= screen_x && x < screen_x + INPUTGRID_WIDTH * cell_width && y >= screen_y)
|
||||
{
|
||||
InputGridX = (x - screen_x) / cell_width;
|
||||
InputGridY = (y - screen_y) / cell_height;
|
||||
if (type == DMenu::MOUSE_Release)
|
||||
{
|
||||
if (CallMenuEvent(MKEY_Enter, true))
|
||||
{
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/choose", snd_menuvolume, ATTN_NONE);
|
||||
if (m_use_mouse == 2) InputGridX = InputGridY = -1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
InputGridX = InputGridY = -1;
|
||||
}
|
||||
return Super::MouseEvent(type, x, y);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DTextEnterMenu::MenuEvent (int key, bool fromcontroller)
|
||||
{
|
||||
if (key == MKEY_Back)
|
||||
{
|
||||
mParentMenu->CallMenuEvent(MKEY_Abort, false);
|
||||
return Super::MenuEvent(key, fromcontroller);
|
||||
}
|
||||
if (fromcontroller)
|
||||
{
|
||||
mInputGridOkay = true;
|
||||
}
|
||||
|
||||
if (mInputGridOkay)
|
||||
{
|
||||
int ch;
|
||||
|
||||
if (InputGridX == -1 || InputGridY == -1)
|
||||
{
|
||||
InputGridX = InputGridY = 0;
|
||||
}
|
||||
switch (key)
|
||||
{
|
||||
case MKEY_Down:
|
||||
InputGridY = (InputGridY + 1) % INPUTGRID_HEIGHT;
|
||||
return true;
|
||||
|
||||
case MKEY_Up:
|
||||
InputGridY = (InputGridY + INPUTGRID_HEIGHT - 1) % INPUTGRID_HEIGHT;
|
||||
return true;
|
||||
|
||||
case MKEY_Right:
|
||||
InputGridX = (InputGridX + 1) % INPUTGRID_WIDTH;
|
||||
return true;
|
||||
|
||||
case MKEY_Left:
|
||||
InputGridX = (InputGridX + INPUTGRID_WIDTH - 1) % INPUTGRID_WIDTH;
|
||||
return true;
|
||||
|
||||
case MKEY_Clear:
|
||||
if (mEnterString.IsNotEmpty())
|
||||
{
|
||||
mEnterString.Truncate(mEnterString.Len() - 1);
|
||||
}
|
||||
return true;
|
||||
|
||||
case MKEY_Enter:
|
||||
assert(unsigned(InputGridX) < INPUTGRID_WIDTH && unsigned(InputGridY) < INPUTGRID_HEIGHT);
|
||||
if (mInputGridOkay)
|
||||
{
|
||||
ch = InputGridChars[InputGridX + InputGridY * INPUTGRID_WIDTH];
|
||||
if (ch == 0) // end
|
||||
{
|
||||
if (mEnterString.IsNotEmpty())
|
||||
{
|
||||
DMenu *parent = mParentMenu;
|
||||
Close();
|
||||
parent->CallMenuEvent(MKEY_Input, false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (ch == '\b') // bs
|
||||
{
|
||||
if (mEnterString.IsNotEmpty())
|
||||
{
|
||||
mEnterString.Truncate(mEnterString.Len() - 1);
|
||||
}
|
||||
}
|
||||
else if (mEnterString.Len() < mEnterSize &&
|
||||
(mSizeMode == 2/*entering player name*/ || (size_t)SmallFont->StringWidth(mEnterString) < (mEnterSize-1)*8))
|
||||
{
|
||||
mEnterString += char(ch);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
default:
|
||||
break; // Keep GCC quiet
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DTextEnterMenu::Drawer ()
|
||||
{
|
||||
mParentMenu->CallDrawer();
|
||||
if (mInputGridOkay)
|
||||
{
|
||||
const int cell_width = 18 * CleanXfac;
|
||||
const int cell_height = 12 * CleanYfac;
|
||||
const int top_padding = cell_height / 2 - SmallFont->GetHeight() * CleanYfac / 2;
|
||||
|
||||
// Darken the background behind the character grid.
|
||||
// Unless we frame it with a border, I think it looks better to extend the
|
||||
// background across the full width of the screen.
|
||||
screen->Dim(0, 0.8f,
|
||||
0 /*screen->GetWidth()/2 - 13 * cell_width / 2*/,
|
||||
screen->GetHeight() - INPUTGRID_HEIGHT * cell_height,
|
||||
screen->GetWidth() /*13 * cell_width*/,
|
||||
INPUTGRID_HEIGHT * cell_height);
|
||||
|
||||
if (InputGridX >= 0 && InputGridY >= 0)
|
||||
{
|
||||
// Highlight the background behind the selected character.
|
||||
screen->Dim(MAKERGB(255,248,220), 0.6f,
|
||||
InputGridX * cell_width - INPUTGRID_WIDTH * cell_width / 2 + screen->GetWidth() / 2,
|
||||
InputGridY * cell_height - INPUTGRID_HEIGHT * cell_height + screen->GetHeight(),
|
||||
cell_width, cell_height);
|
||||
}
|
||||
|
||||
for (int y = 0; y < INPUTGRID_HEIGHT; ++y)
|
||||
{
|
||||
const int yy = y * cell_height - INPUTGRID_HEIGHT * cell_height + screen->GetHeight();
|
||||
for (int x = 0; x < INPUTGRID_WIDTH; ++x)
|
||||
{
|
||||
int width;
|
||||
const int xx = x * cell_width - INPUTGRID_WIDTH * cell_width / 2 + screen->GetWidth() / 2;
|
||||
const int ch = InputGridChars[y * INPUTGRID_WIDTH + x];
|
||||
FTexture *pic = SmallFont->GetChar(ch, &width);
|
||||
EColorRange color;
|
||||
|
||||
// The highlighted character is yellow; the rest are dark gray.
|
||||
color = (x == InputGridX && y == InputGridY) ? CR_YELLOW : CR_DARKGRAY;
|
||||
|
||||
if (pic != NULL)
|
||||
{
|
||||
// Draw a normal character.
|
||||
screen->DrawChar(SmallFont, color, xx + cell_width/2 - width*CleanXfac/2, yy + top_padding, ch, DTA_CleanNoMove, true, TAG_DONE);
|
||||
}
|
||||
else if (ch == ' ')
|
||||
{
|
||||
FRemapTable *remap = SmallFont->GetColorTranslation(color);
|
||||
// Draw the space as a box outline. We also draw it 50% wider than it really is.
|
||||
const int x1 = xx + cell_width/2 - width * CleanXfac * 3 / 4;
|
||||
const int x2 = x1 + width * 3 * CleanXfac / 2;
|
||||
const int y1 = yy + top_padding;
|
||||
const int y2 = y1 + SmallFont->GetHeight() * CleanYfac;
|
||||
const int palentry = remap->Remap[remap->NumEntries * 2 / 3];
|
||||
const uint32 palcolor = remap->Palette[remap->NumEntries * 2 / 3];
|
||||
screen->Clear(x1, y1, x2, y1+CleanYfac, palentry, palcolor); // top
|
||||
screen->Clear(x1, y2, x2, y2+CleanYfac, palentry, palcolor); // bottom
|
||||
screen->Clear(x1, y1+CleanYfac, x1+CleanXfac, y2, palentry, palcolor); // left
|
||||
screen->Clear(x2-CleanXfac, y1+CleanYfac, x2, y2, palentry, palcolor); // right
|
||||
}
|
||||
else if (ch == '\b' || ch == 0)
|
||||
{
|
||||
// Draw the backspace and end "characters".
|
||||
const char *const str = ch == '\b' ? "BS" : "ED";
|
||||
screen->DrawText(SmallFont, color,
|
||||
xx + cell_width/2 - SmallFont->StringWidth(str)*CleanXfac/2,
|
||||
yy + top_padding, str, DTA_CleanNoMove, true, TAG_DONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Super::Drawer();
|
||||
}
|
||||
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DTextEnterMenu, Open)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_OBJECT(parent, DMenu);
|
||||
PARAM_STRING(text);
|
||||
PARAM_INT(maxlen);
|
||||
PARAM_INT(sizemode);
|
||||
PARAM_BOOL(fromcontroller);
|
||||
auto m = new DTextEnterMenu(parent, text.GetChars(), maxlen, sizemode, fromcontroller, false);
|
||||
M_ActivateMenu(m);
|
||||
ACTION_RETURN_OBJECT(m);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DTextEnterMenu, GetText)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DTextEnterMenu);
|
||||
ACTION_RETURN_STRING(self->GetText());
|
||||
}
|
|
@ -46,52 +46,15 @@
|
|||
#include "c_dispatch.h"
|
||||
#include "g_game.h"
|
||||
|
||||
|
||||
EXTERN_CVAR (Bool, saveloadconfirmation) // [mxd]
|
||||
|
||||
class DMessageBoxMenu : public DMenu
|
||||
typedef void(*hfunc)();
|
||||
DEFINE_ACTION_FUNCTION(DMessageBoxMenu, CallHandler)
|
||||
{
|
||||
DECLARE_CLASS(DMessageBoxMenu, DMenu)
|
||||
|
||||
FBrokenLines *mMessage;
|
||||
int mMessageMode;
|
||||
int messageSelection;
|
||||
int mMouseLeft, mMouseRight, mMouseY;
|
||||
FName mAction;
|
||||
|
||||
public:
|
||||
|
||||
DMessageBoxMenu(DMenu *parent = NULL, const char *message = NULL, int messagemode = 0, bool playsound = false, FName action = NAME_None);
|
||||
void OnDestroy() override;
|
||||
void Init(DMenu *parent, const char *message, int messagemode, bool playsound = false);
|
||||
void Drawer();
|
||||
bool Responder(event_t *ev);
|
||||
bool MenuEvent(int mkey, bool fromcontroller);
|
||||
bool MouseEvent(int type, int x, int y);
|
||||
void CloseSound();
|
||||
virtual void HandleResult(bool res);
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS(DMessageBoxMenu, false, false)
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
DMessageBoxMenu::DMessageBoxMenu(DMenu *parent, const char *message, int messagemode, bool playsound, FName action)
|
||||
: DMenu(parent)
|
||||
{
|
||||
mAction = action;
|
||||
messageSelection = 0;
|
||||
mMouseLeft = 140;
|
||||
mMouseY = INT_MIN;
|
||||
int mr1 = 170 + SmallFont->StringWidth(GStrings["TXT_YES"]);
|
||||
int mr2 = 170 + SmallFont->StringWidth(GStrings["TXT_NO"]);
|
||||
mMouseRight = MAX(mr1, mr2);
|
||||
|
||||
Init(parent, message, messagemode, playsound);
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_POINTERTYPE(Handler, hfunc);
|
||||
Handler();
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
@ -100,325 +63,15 @@ DMessageBoxMenu::DMessageBoxMenu(DMenu *parent, const char *message, int message
|
|||
//
|
||||
//=============================================================================
|
||||
|
||||
void DMessageBoxMenu::Init(DMenu *parent, const char *message, int messagemode, bool playsound)
|
||||
DMenu *CreateMessageBoxMenu(DMenu *parent, const char *message, int messagemode, bool playsound, FName action = NAME_None, hfunc handler = nullptr)
|
||||
{
|
||||
mParentMenu = parent;
|
||||
if (message != NULL)
|
||||
{
|
||||
if (*message == '$') message = GStrings(message+1);
|
||||
mMessage = V_BreakLines(SmallFont, 300, message);
|
||||
}
|
||||
else mMessage = NULL;
|
||||
mMessageMode = messagemode;
|
||||
if (playsound)
|
||||
{
|
||||
S_StopSound (CHAN_VOICE);
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/prompt", snd_menuvolume, ATTN_NONE);
|
||||
}
|
||||
}
|
||||
auto c = PClass::FindClass("MessageBoxMenu");
|
||||
auto p = c->CreateNew();
|
||||
VMValue params[] = { p, parent, FString(message), messagemode, playsound, action.GetIndex(), reinterpret_cast<void*>(handler) };
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DMessageBoxMenu::OnDestroy()
|
||||
{
|
||||
if (mMessage != NULL) V_FreeBrokenLines(mMessage);
|
||||
mMessage = NULL;
|
||||
Super::OnDestroy();
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DMessageBoxMenu::CloseSound()
|
||||
{
|
||||
S_Sound (CHAN_VOICE | CHAN_UI,
|
||||
DMenu::CurrentMenu != NULL? "menu/backup" : "menu/dismiss", snd_menuvolume, ATTN_NONE);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DMessageBoxMenu::HandleResult(bool res)
|
||||
{
|
||||
if (mParentMenu != NULL)
|
||||
{
|
||||
if (mMessageMode == 0)
|
||||
{
|
||||
if (mAction == NAME_None)
|
||||
{
|
||||
mParentMenu->CallMenuEvent(res? MKEY_MBYes : MKEY_MBNo, false);
|
||||
Close();
|
||||
}
|
||||
else
|
||||
{
|
||||
Close();
|
||||
if (res) M_SetMenu(mAction, -1);
|
||||
}
|
||||
CloseSound();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DMessageBoxMenu::Drawer ()
|
||||
{
|
||||
int i, y;
|
||||
PalEntry fade = 0;
|
||||
|
||||
int fontheight = SmallFont->GetHeight();
|
||||
//V_SetBorderNeedRefresh();
|
||||
//ST_SetNeedRefresh();
|
||||
|
||||
y = 100;
|
||||
|
||||
if (mMessage != NULL)
|
||||
{
|
||||
for (i = 0; mMessage[i].Width >= 0; i++)
|
||||
y -= SmallFont->GetHeight () / 2;
|
||||
|
||||
for (i = 0; mMessage[i].Width >= 0; i++)
|
||||
{
|
||||
screen->DrawText (SmallFont, CR_UNTRANSLATED, 160 - mMessage[i].Width/2, y, mMessage[i].Text,
|
||||
DTA_Clean, true, TAG_DONE);
|
||||
y += fontheight;
|
||||
}
|
||||
}
|
||||
|
||||
if (mMessageMode == 0)
|
||||
{
|
||||
y += fontheight;
|
||||
mMouseY = y;
|
||||
screen->DrawText(SmallFont,
|
||||
messageSelection == 0? OptionSettings.mFontColorSelection : OptionSettings.mFontColor,
|
||||
160, y, GStrings["TXT_YES"], DTA_Clean, true, TAG_DONE);
|
||||
screen->DrawText(SmallFont,
|
||||
messageSelection == 1? OptionSettings.mFontColorSelection : OptionSettings.mFontColor,
|
||||
160, y + fontheight + 1, GStrings["TXT_NO"], DTA_Clean, true, TAG_DONE);
|
||||
|
||||
if (messageSelection >= 0)
|
||||
{
|
||||
if ((DMenu::MenuTime%8) < 6)
|
||||
{
|
||||
screen->DrawText(ConFont, OptionSettings.mFontColorSelection,
|
||||
(150 - 160) * CleanXfac + screen->GetWidth() / 2,
|
||||
(y + (fontheight + 1) * messageSelection - 100 + fontheight/2 - 5) * CleanYfac + screen->GetHeight() / 2,
|
||||
"\xd",
|
||||
DTA_CellX, 8 * CleanXfac,
|
||||
DTA_CellY, 8 * CleanYfac,
|
||||
TAG_DONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DMessageBoxMenu::Responder(event_t *ev)
|
||||
{
|
||||
if (ev->type == EV_GUI_Event && ev->subtype == EV_GUI_KeyDown)
|
||||
{
|
||||
if (mMessageMode == 0)
|
||||
{
|
||||
int ch = tolower(ev->data1);
|
||||
if (ch == 'n' || ch == ' ')
|
||||
{
|
||||
HandleResult(false);
|
||||
return true;
|
||||
}
|
||||
else if (ch == 'y')
|
||||
{
|
||||
HandleResult(true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Close();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else if (ev->type == EV_KeyDown)
|
||||
{
|
||||
Close();
|
||||
return true;
|
||||
}
|
||||
return Super::Responder(ev);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DMessageBoxMenu::MenuEvent(int mkey, bool fromcontroller)
|
||||
{
|
||||
if (mMessageMode == 0)
|
||||
{
|
||||
if (mkey == MKEY_Up || mkey == MKEY_Down)
|
||||
{
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
|
||||
messageSelection = !messageSelection;
|
||||
return true;
|
||||
}
|
||||
else if (mkey == MKEY_Enter)
|
||||
{
|
||||
// 0 is yes, 1 is no
|
||||
HandleResult(!messageSelection);
|
||||
return true;
|
||||
}
|
||||
else if (mkey == MKEY_Back)
|
||||
{
|
||||
HandleResult(false);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Close();
|
||||
CloseSound();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DMessageBoxMenu::MouseEvent(int type, int x, int y)
|
||||
{
|
||||
if (mMessageMode == 1)
|
||||
{
|
||||
if (type == MOUSE_Click)
|
||||
{
|
||||
return MenuEvent(MKEY_Enter, true);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
int sel = -1;
|
||||
int fh = SmallFont->GetHeight() + 1;
|
||||
|
||||
// convert x/y from screen to virtual coordinates, according to CleanX/Yfac use in DrawTexture
|
||||
x = ((x - (screen->GetWidth() / 2)) / CleanXfac) + 160;
|
||||
y = ((y - (screen->GetHeight() / 2)) / CleanYfac) + 100;
|
||||
|
||||
if (x >= mMouseLeft && x <= mMouseRight && y >= mMouseY && y < mMouseY + 2 * fh)
|
||||
{
|
||||
sel = y >= mMouseY + fh;
|
||||
}
|
||||
if (sel != -1 && sel != messageSelection)
|
||||
{
|
||||
//S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
|
||||
}
|
||||
messageSelection = sel;
|
||||
if (type == MOUSE_Release)
|
||||
{
|
||||
return MenuEvent(MKEY_Enter, true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class DQuitMenu : public DMessageBoxMenu
|
||||
{
|
||||
DECLARE_CLASS(DQuitMenu, DMessageBoxMenu)
|
||||
|
||||
public:
|
||||
|
||||
DQuitMenu(bool playsound = false);
|
||||
virtual void HandleResult(bool res);
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS(DQuitMenu, false, false)
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
DQuitMenu::DQuitMenu(bool playsound)
|
||||
{
|
||||
int messageindex = gametic % gameinfo.quitmessages.Size();
|
||||
FString EndString;
|
||||
const char *msg = gameinfo.quitmessages[messageindex];
|
||||
if (msg[0] == '$')
|
||||
{
|
||||
if (msg[1] == '*')
|
||||
{
|
||||
EndString = GStrings(msg+2);
|
||||
}
|
||||
else
|
||||
{
|
||||
EndString.Format("%s\n\n%s", GStrings(msg+1), GStrings("DOSY"));
|
||||
}
|
||||
}
|
||||
else EndString = gameinfo.quitmessages[messageindex];
|
||||
|
||||
Init(NULL, EndString, 0, playsound);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DQuitMenu::HandleResult(bool res)
|
||||
{
|
||||
if (res)
|
||||
{
|
||||
if (!netgame)
|
||||
{
|
||||
if (gameinfo.quitSound.IsNotEmpty())
|
||||
{
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, gameinfo.quitSound, snd_menuvolume, ATTN_NONE);
|
||||
I_WaitVBL (105);
|
||||
}
|
||||
}
|
||||
ST_Endoom();
|
||||
}
|
||||
else
|
||||
{
|
||||
Close();
|
||||
CloseSound();
|
||||
}
|
||||
auto f = dyn_cast<PFunction>(c->Symbols.FindSymbol("Init", false));
|
||||
GlobalVMStack.Call(f->Variants[0].Implementation, params, countof(params), nullptr, 0);
|
||||
return (DMenu*)p;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
@ -430,70 +83,42 @@ void DQuitMenu::HandleResult(bool res)
|
|||
CCMD (menu_quit)
|
||||
{ // F10
|
||||
M_StartControlPanel (true);
|
||||
DMenu *newmenu = new DQuitMenu(false);
|
||||
newmenu->mParentMenu = DMenu::CurrentMenu;
|
||||
|
||||
int messageindex = gametic % gameinfo.quitmessages.Size();
|
||||
FString EndString;
|
||||
const char *msg = gameinfo.quitmessages[messageindex];
|
||||
if (msg[0] == '$')
|
||||
{
|
||||
if (msg[1] == '*')
|
||||
{
|
||||
EndString = GStrings(msg + 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
EndString.Format("%s\n\n%s", GStrings(msg + 1), GStrings("DOSY"));
|
||||
}
|
||||
}
|
||||
else EndString = gameinfo.quitmessages[messageindex];
|
||||
|
||||
DMenu *newmenu = CreateMessageBoxMenu(CurrentMenu, EndString, 0, false, NAME_None, []()
|
||||
{
|
||||
if (!netgame)
|
||||
{
|
||||
if (gameinfo.quitSound.IsNotEmpty())
|
||||
{
|
||||
S_Sound(CHAN_VOICE | CHAN_UI, gameinfo.quitSound, snd_menuvolume, ATTN_NONE);
|
||||
I_WaitVBL(105);
|
||||
}
|
||||
}
|
||||
ST_Endoom();
|
||||
});
|
||||
|
||||
|
||||
M_ActivateMenu(newmenu);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class DEndGameMenu : public DMessageBoxMenu
|
||||
{
|
||||
DECLARE_CLASS(DEndGameMenu, DMessageBoxMenu)
|
||||
|
||||
public:
|
||||
|
||||
DEndGameMenu(bool playsound = false);
|
||||
virtual void HandleResult(bool res);
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS(DEndGameMenu, false, false)
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
DEndGameMenu::DEndGameMenu(bool playsound)
|
||||
{
|
||||
Init(NULL, GStrings(netgame ? "NETEND" : "ENDGAME"), 0, playsound);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DEndGameMenu::HandleResult(bool res)
|
||||
{
|
||||
if (res)
|
||||
{
|
||||
M_ClearMenus ();
|
||||
if (!netgame)
|
||||
{
|
||||
D_StartTitle ();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Close();
|
||||
CloseSound();
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
|
@ -510,67 +135,18 @@ CCMD (menu_endgame)
|
|||
|
||||
//M_StartControlPanel (true);
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/activate", snd_menuvolume, ATTN_NONE);
|
||||
DMenu *newmenu = new DEndGameMenu(false);
|
||||
newmenu->mParentMenu = DMenu::CurrentMenu;
|
||||
M_ActivateMenu(newmenu);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class DQuickSaveMenu : public DMessageBoxMenu
|
||||
{
|
||||
DECLARE_CLASS(DQuickSaveMenu, DMessageBoxMenu)
|
||||
|
||||
public:
|
||||
|
||||
DQuickSaveMenu(bool playsound = false);
|
||||
virtual void HandleResult(bool res);
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS(DQuickSaveMenu, false, false)
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
DQuickSaveMenu::DQuickSaveMenu(bool playsound)
|
||||
{
|
||||
FString tempstring;
|
||||
|
||||
tempstring.Format(GStrings("QSPROMPT"), savegameManager.quickSaveSlot->Title);
|
||||
Init(NULL, tempstring, 0, playsound);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DQuickSaveMenu::HandleResult(bool res)
|
||||
{
|
||||
if (res)
|
||||
FString tempstring = GStrings(netgame ? "NETEND" : "ENDGAME");
|
||||
DMenu *newmenu = CreateMessageBoxMenu(CurrentMenu, tempstring, 0, false, NAME_None, []()
|
||||
{
|
||||
G_SaveGame (savegameManager.quickSaveSlot->Filename.GetChars(), savegameManager.quickSaveSlot->Title);
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/dismiss", snd_menuvolume, ATTN_NONE);
|
||||
M_ClearMenus();
|
||||
}
|
||||
else
|
||||
{
|
||||
Close();
|
||||
CloseSound();
|
||||
}
|
||||
if (!netgame)
|
||||
{
|
||||
D_StartTitle();
|
||||
}
|
||||
});
|
||||
|
||||
M_ActivateMenu(newmenu);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
@ -601,72 +177,23 @@ CCMD (quicksave)
|
|||
// [mxd]. Just save the game, no questions asked.
|
||||
if (!saveloadconfirmation)
|
||||
{
|
||||
G_SaveGame(savegameManager.quickSaveSlot->Filename.GetChars(), savegameManager.quickSaveSlot->Title);
|
||||
G_SaveGame(savegameManager.quickSaveSlot->Filename.GetChars(), savegameManager.quickSaveSlot->SaveTitle.GetChars());
|
||||
return;
|
||||
}
|
||||
|
||||
S_Sound(CHAN_VOICE | CHAN_UI, "menu/activate", snd_menuvolume, ATTN_NONE);
|
||||
DMenu *newmenu = new DQuickSaveMenu(false);
|
||||
newmenu->mParentMenu = DMenu::CurrentMenu;
|
||||
M_ActivateMenu(newmenu);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class DQuickLoadMenu : public DMessageBoxMenu
|
||||
{
|
||||
DECLARE_CLASS(DQuickLoadMenu, DMessageBoxMenu)
|
||||
|
||||
public:
|
||||
|
||||
DQuickLoadMenu(bool playsound = false);
|
||||
virtual void HandleResult(bool res);
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS(DQuickLoadMenu, false, false)
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
DQuickLoadMenu::DQuickLoadMenu(bool playsound)
|
||||
{
|
||||
FString tempstring;
|
||||
tempstring.Format(GStrings("QSPROMPT"), savegameManager.quickSaveSlot->SaveTitle.GetChars());
|
||||
|
||||
tempstring.Format(GStrings("QLPROMPT"), savegameManager.quickSaveSlot->Title);
|
||||
Init(NULL, tempstring, 0, playsound);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DQuickLoadMenu::HandleResult(bool res)
|
||||
{
|
||||
if (res)
|
||||
DMenu *newmenu = CreateMessageBoxMenu(CurrentMenu, tempstring, 0, false, NAME_None, []()
|
||||
{
|
||||
G_LoadGame (savegameManager.quickSaveSlot->Filename.GetChars());
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/dismiss", snd_menuvolume, ATTN_NONE);
|
||||
G_SaveGame(savegameManager.quickSaveSlot->Filename.GetChars(), savegameManager.quickSaveSlot->SaveTitle.GetChars());
|
||||
S_Sound(CHAN_VOICE | CHAN_UI, "menu/dismiss", snd_menuvolume, ATTN_NONE);
|
||||
M_ClearMenus();
|
||||
}
|
||||
else
|
||||
{
|
||||
Close();
|
||||
CloseSound();
|
||||
}
|
||||
});
|
||||
|
||||
M_ActivateMenu(newmenu);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
@ -699,10 +226,17 @@ CCMD (quickload)
|
|||
G_LoadGame(savegameManager.quickSaveSlot->Filename.GetChars());
|
||||
return;
|
||||
}
|
||||
FString tempstring;
|
||||
tempstring.Format(GStrings("QLPROMPT"), savegameManager.quickSaveSlot->SaveTitle.GetChars());
|
||||
|
||||
M_StartControlPanel(true);
|
||||
DMenu *newmenu = new DQuickLoadMenu(false);
|
||||
newmenu->mParentMenu = DMenu::CurrentMenu;
|
||||
|
||||
DMenu *newmenu = CreateMessageBoxMenu(CurrentMenu, tempstring, 0, false, NAME_None, []()
|
||||
{
|
||||
G_LoadGame(savegameManager.quickSaveSlot->Filename.GetChars());
|
||||
S_Sound(CHAN_VOICE | CHAN_UI, "menu/dismiss", snd_menuvolume, ATTN_NONE);
|
||||
M_ClearMenus();
|
||||
});
|
||||
M_ActivateMenu(newmenu);
|
||||
}
|
||||
|
||||
|
@ -714,13 +248,13 @@ CCMD (quickload)
|
|||
|
||||
void M_StartMessage(const char *message, int messagemode, FName action)
|
||||
{
|
||||
if (DMenu::CurrentMenu == NULL)
|
||||
if (CurrentMenu == NULL)
|
||||
{
|
||||
// only play a sound if no menu was active before
|
||||
M_StartControlPanel(menuactive == MENU_Off);
|
||||
}
|
||||
DMenu *newmenu = new DMessageBoxMenu(DMenu::CurrentMenu, message, messagemode, false, action);
|
||||
newmenu->mParentMenu = DMenu::CurrentMenu;
|
||||
DMenu *newmenu = CreateMessageBoxMenu(CurrentMenu, message, messagemode, false, action);
|
||||
newmenu->mParentMenu = CurrentMenu;
|
||||
M_ActivateMenu(newmenu);
|
||||
}
|
||||
|
||||
|
@ -732,4 +266,4 @@ DEFINE_ACTION_FUNCTION(DMenu, StartMessage)
|
|||
PARAM_NAME_DEF(action);
|
||||
M_StartMessage(msg, mode, action);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,32 +49,6 @@
|
|||
#include "menu/menu.h"
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DOptionMenuDescriptor::CalcIndent()
|
||||
{
|
||||
// calculate the menu indent
|
||||
int widest = 0, thiswidth;
|
||||
|
||||
for (unsigned i = 0; i < mItems.Size(); i++)
|
||||
{
|
||||
thiswidth = mItems[i]->GetIndent();
|
||||
if (thiswidth > widest) widest = thiswidth;
|
||||
}
|
||||
mIndent = widest + 4;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DOptionMenuDescriptor, CalcIndent)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DOptionMenuDescriptor);
|
||||
self->CalcIndent();
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
|
@ -85,7 +59,7 @@ DMenuItemBase *DOptionMenuDescriptor::GetItem(FName name)
|
|||
{
|
||||
for(unsigned i=0;i<mItems.Size(); i++)
|
||||
{
|
||||
FName nm = mItems[i]->GetAction(NULL);
|
||||
FName nm = mItems[i]->mAction;
|
||||
if (nm == name) return mItems[i];
|
||||
}
|
||||
return NULL;
|
||||
|
|
|
@ -48,12 +48,10 @@
|
|||
#include "r_data/r_translate.h"
|
||||
#include "v_text.h"
|
||||
|
||||
EXTERN_CVAR (String, playerclass)
|
||||
EXTERN_CVAR (String, name)
|
||||
EXTERN_CVAR (Int, team)
|
||||
EXTERN_CVAR (Float, autoaim)
|
||||
EXTERN_CVAR(Int, team)
|
||||
EXTERN_CVAR(Float, autoaim)
|
||||
EXTERN_CVAR(Bool, neverswitchonpickup)
|
||||
EXTERN_CVAR (Bool, cl_run)
|
||||
EXTERN_CVAR(Bool, cl_run)
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
|
@ -61,365 +59,42 @@ EXTERN_CVAR (Bool, cl_run)
|
|||
//
|
||||
//=============================================================================
|
||||
|
||||
class DPlayerMenu : public DListMenu
|
||||
DEFINE_ACTION_FUNCTION(DPlayerMenu, ColorChanged)
|
||||
{
|
||||
DECLARE_CLASS(DPlayerMenu, DListMenu)
|
||||
|
||||
int PlayerClassIndex;
|
||||
FPlayerClass *PlayerClass;
|
||||
TArray<int> PlayerColorSets;
|
||||
TArray<int> PlayerSkins;
|
||||
int mRotation;
|
||||
|
||||
void PickPlayerClass ();
|
||||
void UpdateColorsets();
|
||||
void UpdateSkins();
|
||||
void UpdateTranslation();
|
||||
void SendNewColor (int red, int green, int blue);
|
||||
|
||||
void PlayerNameChanged(DMenuItemBase *li);
|
||||
void ColorSetChanged (DMenuItemBase *li);
|
||||
void ClassChanged (DMenuItemBase *li);
|
||||
void AutoaimChanged (DMenuItemBase *li);
|
||||
void SkinChanged (DMenuItemBase *li);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
DPlayerMenu() {}
|
||||
void Init(DMenu *parent, DListMenuDescriptor *desc);
|
||||
bool Responder (event_t *ev);
|
||||
bool MenuEvent (int mkey, bool fromcontroller);
|
||||
bool MouseEvent(int type, int x, int y);
|
||||
void Ticker ();
|
||||
void Drawer ();
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS(DPlayerMenu, false, false)
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
enum EPDFlags
|
||||
{
|
||||
ListMenuItemPlayerDisplay_PDF_ROTATION = 0x10001,
|
||||
ListMenuItemPlayerDisplay_PDF_SKIN = 0x10002,
|
||||
ListMenuItemPlayerDisplay_PDF_CLASS = 0x10003,
|
||||
ListMenuItemPlayerDisplay_PDF_MODE = 0x10004,
|
||||
ListMenuItemPlayerDisplay_PDF_TRANSLATE = 0x10005,
|
||||
};
|
||||
|
||||
void DPlayerMenu::Init(DMenu *parent, DListMenuDescriptor *desc)
|
||||
{
|
||||
DMenuItemBase *li;
|
||||
|
||||
Super::Init(parent, desc);
|
||||
PickPlayerClass();
|
||||
mRotation = 0;
|
||||
|
||||
li = GetItem(NAME_Playerdisplay);
|
||||
if (li != NULL)
|
||||
PARAM_SELF_PROLOGUE(DMenu);
|
||||
PARAM_INT(r);
|
||||
PARAM_INT(g);
|
||||
PARAM_INT(b);
|
||||
// only allow if the menu is active to prevent abuse.
|
||||
if (self == CurrentMenu)
|
||||
{
|
||||
li->SetValue(ListMenuItemPlayerDisplay_PDF_ROTATION, 0);
|
||||
li->SetValue(ListMenuItemPlayerDisplay_PDF_MODE, 1);
|
||||
li->SetValue(ListMenuItemPlayerDisplay_PDF_TRANSLATE, 1);
|
||||
li->SetValue(ListMenuItemPlayerDisplay_PDF_CLASS, players[consoleplayer].userinfo.GetPlayerClassNum());
|
||||
if (PlayerClass != NULL && !(GetDefaultByType (PlayerClass->Type)->flags4 & MF4_NOSKIN) &&
|
||||
players[consoleplayer].userinfo.GetPlayerClassNum() != -1)
|
||||
{
|
||||
li->SetValue(ListMenuItemPlayerDisplay_PDF_SKIN, players[consoleplayer].userinfo.GetSkin());
|
||||
}
|
||||
char command[24];
|
||||
players[consoleplayer].userinfo.ColorChanged(MAKERGB(r, g, b));
|
||||
mysnprintf(command, countof(command), "color \"%02x %02x %02x\"", r, g, b);
|
||||
C_DoCommand(command);
|
||||
}
|
||||
|
||||
li = GetItem(NAME_Playerbox);
|
||||
if (li != NULL)
|
||||
{
|
||||
li->SetString(0, name);
|
||||
}
|
||||
|
||||
li = GetItem(NAME_Team);
|
||||
if (li != NULL)
|
||||
{
|
||||
li->SetString(0, "None");
|
||||
for(unsigned i=0;i<Teams.Size(); i++)
|
||||
{
|
||||
li->SetString(i+1, Teams[i].GetName());
|
||||
}
|
||||
li->SetValue(0, team == TEAM_NONE? 0 : team + 1);
|
||||
}
|
||||
|
||||
int mycolorset = players[consoleplayer].userinfo.GetColorSet();
|
||||
int color = players[consoleplayer].userinfo.GetColor();
|
||||
|
||||
UpdateColorsets();
|
||||
|
||||
li = GetItem(NAME_Red);
|
||||
if (li != NULL)
|
||||
{
|
||||
li->Enable(mycolorset == -1);
|
||||
li->SetValue(0, RPART(color));
|
||||
}
|
||||
|
||||
li = GetItem(NAME_Green);
|
||||
if (li != NULL)
|
||||
{
|
||||
li->Enable(mycolorset == -1);
|
||||
li->SetValue(0, GPART(color));
|
||||
}
|
||||
|
||||
li = GetItem(NAME_Blue);
|
||||
if (li != NULL)
|
||||
{
|
||||
li->Enable(mycolorset == -1);
|
||||
li->SetValue(0, BPART(color));
|
||||
}
|
||||
|
||||
li = GetItem(NAME_Class);
|
||||
if (li != NULL)
|
||||
{
|
||||
if (PlayerClasses.Size() == 1)
|
||||
{
|
||||
li->SetString(0, GetPrintableDisplayName(PlayerClasses[0].Type));
|
||||
li->SetValue(0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// [XA] Remove the "Random" option if the relevant gameinfo flag is set.
|
||||
if(!gameinfo.norandomplayerclass)
|
||||
li->SetString(0, "Random");
|
||||
for(unsigned i=0; i< PlayerClasses.Size(); i++)
|
||||
{
|
||||
const char *cls = GetPrintableDisplayName(PlayerClasses[i].Type);
|
||||
li->SetString(gameinfo.norandomplayerclass ? i : i+1, cls);
|
||||
}
|
||||
int pclass = players[consoleplayer].userinfo.GetPlayerClassNum();
|
||||
li->SetValue(0, gameinfo.norandomplayerclass && pclass >= 0 ? pclass : pclass + 1);
|
||||
}
|
||||
}
|
||||
|
||||
UpdateSkins();
|
||||
|
||||
li = GetItem(NAME_Gender);
|
||||
if (li != NULL)
|
||||
{
|
||||
li->SetValue(0, players[consoleplayer].userinfo.GetGender());
|
||||
}
|
||||
|
||||
li = GetItem(NAME_Autoaim);
|
||||
if (li != NULL)
|
||||
{
|
||||
li->SetValue(0, (int)autoaim);
|
||||
}
|
||||
|
||||
li = GetItem(NAME_Switch);
|
||||
if (li != NULL)
|
||||
{
|
||||
li->SetValue(0, neverswitchonpickup);
|
||||
}
|
||||
|
||||
li = GetItem(NAME_AlwaysRun);
|
||||
if (li != NULL)
|
||||
{
|
||||
li->SetValue(0, cl_run);
|
||||
}
|
||||
|
||||
if (mDesc->mSelectedItem < 0) mDesc->mSelectedItem = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
// access to the player config is done natively, so that broader access
|
||||
// functions do not need to be exported.
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DPlayerMenu::Responder (event_t *ev)
|
||||
DEFINE_ACTION_FUNCTION(DPlayerMenu, PlayerNameChanged)
|
||||
{
|
||||
if (ev->type == EV_GUI_Event && ev->subtype == EV_GUI_Char && ev->data1 == ' ')
|
||||
PARAM_SELF_PROLOGUE(DMenu);
|
||||
PARAM_STRING(s);
|
||||
const char *pp = s;
|
||||
FString command("name \"");
|
||||
|
||||
if (self == CurrentMenu)
|
||||
{
|
||||
// turn the player sprite around
|
||||
mRotation = 8 - mRotation;
|
||||
DMenuItemBase *li = GetItem(NAME_Playerdisplay);
|
||||
if (li != NULL)
|
||||
{
|
||||
li->SetValue(ListMenuItemPlayerDisplay_PDF_ROTATION, mRotation);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return Super::Responder(ev);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DPlayerMenu::UpdateTranslation()
|
||||
{
|
||||
int PlayerColor = players[consoleplayer].userinfo.GetColor();
|
||||
int PlayerSkin = players[consoleplayer].userinfo.GetSkin();
|
||||
int PlayerColorset = players[consoleplayer].userinfo.GetColorSet();
|
||||
|
||||
if (PlayerClass != NULL)
|
||||
{
|
||||
PlayerSkin = R_FindSkin (skins[PlayerSkin].name, int(PlayerClass - &PlayerClasses[0]));
|
||||
R_GetPlayerTranslation(PlayerColor, GetColorSet(PlayerClass->Type, PlayerColorset),
|
||||
&skins[PlayerSkin], translationtables[TRANSLATION_Players][MAXPLAYERS]);
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DPlayerMenu::PickPlayerClass()
|
||||
{
|
||||
|
||||
/*
|
||||
// What's the point of this? Aren't we supposed to edit the
|
||||
// userinfo?
|
||||
if (players[consoleplayer].mo != NULL)
|
||||
{
|
||||
PlayerClassIndex = players[consoleplayer].CurrentPlayerClass;
|
||||
}
|
||||
else
|
||||
*/
|
||||
{
|
||||
int pclass = 0;
|
||||
// [GRB] Pick a class from player class list
|
||||
if (PlayerClasses.Size () > 1)
|
||||
{
|
||||
pclass = players[consoleplayer].userinfo.GetPlayerClassNum();
|
||||
|
||||
if (pclass < 0)
|
||||
{
|
||||
pclass = (MenuTime>>7) % PlayerClasses.Size ();
|
||||
}
|
||||
}
|
||||
PlayerClassIndex = pclass;
|
||||
}
|
||||
PlayerClass = &PlayerClasses[PlayerClassIndex];
|
||||
UpdateTranslation();
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DPlayerMenu::SendNewColor (int red, int green, int blue)
|
||||
{
|
||||
char command[24];
|
||||
|
||||
players[consoleplayer].userinfo.ColorChanged(MAKERGB(red,green,blue));
|
||||
mysnprintf (command, countof(command), "color \"%02x %02x %02x\"", red, green, blue);
|
||||
C_DoCommand (command);
|
||||
UpdateTranslation();
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DPlayerMenu::UpdateColorsets()
|
||||
{
|
||||
DMenuItemBase *li = GetItem(NAME_Color);
|
||||
if (li != NULL)
|
||||
{
|
||||
int sel = 0;
|
||||
EnumColorSets(PlayerClass->Type, &PlayerColorSets);
|
||||
li->SetString(0, "Custom");
|
||||
for(unsigned i=0;i<PlayerColorSets.Size(); i++)
|
||||
{
|
||||
FPlayerColorSet *colorset = GetColorSet(PlayerClass->Type, PlayerColorSets[i]);
|
||||
li->SetString(i+1, colorset->Name);
|
||||
}
|
||||
int mycolorset = players[consoleplayer].userinfo.GetColorSet();
|
||||
if (mycolorset != -1)
|
||||
{
|
||||
for(unsigned i=0;i<PlayerColorSets.Size(); i++)
|
||||
{
|
||||
if (PlayerColorSets[i] == mycolorset)
|
||||
{
|
||||
sel = i+1;
|
||||
}
|
||||
}
|
||||
}
|
||||
li->SetValue(0, sel);
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DPlayerMenu::UpdateSkins()
|
||||
{
|
||||
int sel = 0;
|
||||
int skin;
|
||||
DMenuItemBase *li = GetItem(NAME_Skin);
|
||||
if (li != NULL)
|
||||
{
|
||||
if (GetDefaultByType (PlayerClass->Type)->flags4 & MF4_NOSKIN ||
|
||||
players[consoleplayer].userinfo.GetPlayerClassNum() == -1)
|
||||
{
|
||||
li->SetString(0, "Base");
|
||||
li->SetValue(0, 0);
|
||||
skin = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
PlayerSkins.Clear();
|
||||
for(int i=0;i<(int)numskins; i++)
|
||||
{
|
||||
if (PlayerClass->CheckSkin(i))
|
||||
{
|
||||
int j = PlayerSkins.Push(i);
|
||||
li->SetString(j, skins[i].name);
|
||||
if (players[consoleplayer].userinfo.GetSkin() == i)
|
||||
{
|
||||
sel = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
li->SetValue(0, sel);
|
||||
skin = PlayerSkins[sel];
|
||||
}
|
||||
li = GetItem(NAME_Playerdisplay);
|
||||
if (li != NULL)
|
||||
{
|
||||
li->SetValue(ListMenuItemPlayerDisplay_PDF_SKIN, skin);
|
||||
}
|
||||
}
|
||||
UpdateTranslation();
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DPlayerMenu::PlayerNameChanged(DMenuItemBase *li)
|
||||
{
|
||||
char pp[MAXPLAYERNAME+1];
|
||||
const char *p;
|
||||
if (li->GetString(0, pp, MAXPLAYERNAME))
|
||||
{
|
||||
FString command("name \"");
|
||||
|
||||
// Escape any backslashes or quotation marks before sending the name to the console.
|
||||
for (p = pp; *p != '\0'; ++p)
|
||||
for (auto p = pp; *p != '\0'; ++p)
|
||||
{
|
||||
if (*p == '"' || *p == '\\')
|
||||
{
|
||||
|
@ -428,41 +103,9 @@ void DPlayerMenu::PlayerNameChanged(DMenuItemBase *li)
|
|||
command << *p;
|
||||
}
|
||||
command << '"';
|
||||
C_DoCommand (command);
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DPlayerMenu::ColorSetChanged (DMenuItemBase *li)
|
||||
{
|
||||
int sel;
|
||||
|
||||
if (li->GetValue(0, &sel))
|
||||
{
|
||||
int mycolorset = -1;
|
||||
|
||||
if (sel > 0) mycolorset = PlayerColorSets[sel-1];
|
||||
|
||||
DMenuItemBase *red = GetItem(NAME_Red);
|
||||
DMenuItemBase *green = GetItem(NAME_Green);
|
||||
DMenuItemBase *blue = GetItem(NAME_Blue);
|
||||
|
||||
// disable the sliders if a valid colorset is selected
|
||||
if (red != NULL) red->Enable(mycolorset == -1);
|
||||
if (green != NULL) green->Enable(mycolorset == -1);
|
||||
if (blue != NULL) blue->Enable(mycolorset == -1);
|
||||
|
||||
char command[24];
|
||||
players[consoleplayer].userinfo.ColorSetChanged(mycolorset);
|
||||
mysnprintf(command, countof(command), "colorset %d", mycolorset);
|
||||
C_DoCommand(command);
|
||||
UpdateTranslation();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
@ -471,32 +114,18 @@ void DPlayerMenu::ColorSetChanged (DMenuItemBase *li)
|
|||
//
|
||||
//=============================================================================
|
||||
|
||||
void DPlayerMenu::ClassChanged (DMenuItemBase *li)
|
||||
DEFINE_ACTION_FUNCTION(DPlayerMenu, ColorSetChanged)
|
||||
{
|
||||
if (PlayerClasses.Size () == 1)
|
||||
PARAM_SELF_PROLOGUE(DMenu);
|
||||
PARAM_INT(sel);
|
||||
if (self == CurrentMenu)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int sel;
|
||||
|
||||
if (li->GetValue(0, &sel))
|
||||
{
|
||||
players[consoleplayer].userinfo.PlayerClassNumChanged(gameinfo.norandomplayerclass ? sel : sel-1);
|
||||
PickPlayerClass();
|
||||
|
||||
cvar_set ("playerclass", sel == 0 && !gameinfo.norandomplayerclass ? "Random" : GetPrintableDisplayName(PlayerClass->Type).GetChars());
|
||||
|
||||
UpdateSkins();
|
||||
UpdateColorsets();
|
||||
UpdateTranslation();
|
||||
|
||||
li = GetItem(NAME_Playerdisplay);
|
||||
if (li != NULL)
|
||||
{
|
||||
li->SetValue(ListMenuItemPlayerDisplay_PDF_CLASS, players[consoleplayer].userinfo.GetPlayerClassNum());
|
||||
}
|
||||
players[consoleplayer].userinfo.ColorSetChanged(sel);
|
||||
char command[24];
|
||||
mysnprintf(command, countof(command), "colorset %d", sel);
|
||||
C_DoCommand(command);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
@ -505,29 +134,36 @@ void DPlayerMenu::ClassChanged (DMenuItemBase *li)
|
|||
//
|
||||
//=============================================================================
|
||||
|
||||
void DPlayerMenu::SkinChanged (DMenuItemBase *li)
|
||||
DEFINE_ACTION_FUNCTION(DPlayerMenu, ClassChanged)
|
||||
{
|
||||
if (GetDefaultByType (PlayerClass->Type)->flags4 & MF4_NOSKIN ||
|
||||
players[consoleplayer].userinfo.GetPlayerClassNum() == -1)
|
||||
PARAM_SELF_PROLOGUE(DMenu);
|
||||
PARAM_INT(sel);
|
||||
PARAM_POINTER(cls, FPlayerClass);
|
||||
if (self == CurrentMenu)
|
||||
{
|
||||
return;
|
||||
players[consoleplayer].userinfo.PlayerClassNumChanged(gameinfo.norandomplayerclass ? sel : sel - 1);
|
||||
cvar_set("playerclass", sel == 0 && !gameinfo.norandomplayerclass ? "Random" : GetPrintableDisplayName(cls->Type).GetChars());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sel;
|
||||
|
||||
if (li->GetValue(0, &sel))
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DPlayerMenu, SkinChanged)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DMenu);
|
||||
PARAM_INT(sel);
|
||||
if (self == CurrentMenu)
|
||||
{
|
||||
sel = PlayerSkins[sel];
|
||||
players[consoleplayer].userinfo.SkinNumChanged(sel);
|
||||
UpdateTranslation();
|
||||
cvar_set ("skin", skins[sel].name);
|
||||
|
||||
li = GetItem(NAME_Playerdisplay);
|
||||
if (li != NULL)
|
||||
{
|
||||
li->SetValue(ListMenuItemPlayerDisplay_PDF_SKIN, sel);
|
||||
}
|
||||
cvar_set("skin", Skins[sel].Name);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
@ -536,14 +172,16 @@ void DPlayerMenu::SkinChanged (DMenuItemBase *li)
|
|||
//
|
||||
//=============================================================================
|
||||
|
||||
void DPlayerMenu::AutoaimChanged (DMenuItemBase *li)
|
||||
DEFINE_ACTION_FUNCTION(DPlayerMenu, AutoaimChanged)
|
||||
{
|
||||
int sel;
|
||||
|
||||
if (li->GetValue(0, &sel))
|
||||
PARAM_SELF_PROLOGUE(DMenu);
|
||||
PARAM_FLOAT(val);
|
||||
// only allow if the menu is active to prevent abuse.
|
||||
if (self == CurrentMenu)
|
||||
{
|
||||
autoaim = (float)sel;
|
||||
autoaim = float(val);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
@ -552,145 +190,34 @@ void DPlayerMenu::AutoaimChanged (DMenuItemBase *li)
|
|||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DPlayerMenu::MenuEvent (int mkey, bool fromcontroller)
|
||||
DEFINE_ACTION_FUNCTION(DPlayerMenu, TeamChanged)
|
||||
{
|
||||
int v;
|
||||
if (mDesc->mSelectedItem >= 0)
|
||||
PARAM_SELF_PROLOGUE(DMenu);
|
||||
PARAM_INT(val);
|
||||
// only allow if the menu is active to prevent abuse.
|
||||
if (self == CurrentMenu)
|
||||
{
|
||||
DMenuItemBase *li = mDesc->mItems[mDesc->mSelectedItem];
|
||||
if (li->MenuEvent(mkey, fromcontroller))
|
||||
{
|
||||
FName current = li->GetAction(NULL);
|
||||
switch(current)
|
||||
{
|
||||
// item specific handling comes here
|
||||
|
||||
case NAME_Playerbox:
|
||||
if (mkey == MKEY_Input)
|
||||
{
|
||||
PlayerNameChanged(li);
|
||||
}
|
||||
break;
|
||||
|
||||
case NAME_Team:
|
||||
if (li->GetValue(0, &v))
|
||||
{
|
||||
team = v==0? TEAM_NONE : v-1;
|
||||
}
|
||||
break;
|
||||
|
||||
case NAME_Color:
|
||||
ColorSetChanged(li);
|
||||
break;
|
||||
|
||||
case NAME_Red:
|
||||
if (li->GetValue(0, &v))
|
||||
{
|
||||
uint32 color = players[consoleplayer].userinfo.GetColor();
|
||||
SendNewColor (v, GPART(color), BPART(color));
|
||||
}
|
||||
break;
|
||||
|
||||
case NAME_Green:
|
||||
if (li->GetValue(0, &v))
|
||||
{
|
||||
uint32 color = players[consoleplayer].userinfo.GetColor();
|
||||
SendNewColor (RPART(color), v, BPART(color));
|
||||
}
|
||||
break;
|
||||
|
||||
case NAME_Blue:
|
||||
if (li->GetValue(0, &v))
|
||||
{
|
||||
uint32 color = players[consoleplayer].userinfo.GetColor();
|
||||
SendNewColor (RPART(color), GPART(color), v);
|
||||
}
|
||||
break;
|
||||
|
||||
case NAME_Class:
|
||||
ClassChanged(li);
|
||||
break;
|
||||
|
||||
case NAME_Skin:
|
||||
SkinChanged(li);
|
||||
break;
|
||||
|
||||
case NAME_Gender:
|
||||
if (li->GetValue(0, &v))
|
||||
{
|
||||
cvar_set ("gender", v==0? "male" : v==1? "female" : "other");
|
||||
}
|
||||
break;
|
||||
|
||||
case NAME_Autoaim:
|
||||
AutoaimChanged(li);
|
||||
break;
|
||||
|
||||
case NAME_Switch:
|
||||
if (li->GetValue(0, &v))
|
||||
{
|
||||
neverswitchonpickup = !!v;
|
||||
}
|
||||
break;
|
||||
|
||||
case NAME_AlwaysRun:
|
||||
if (li->GetValue(0, &v))
|
||||
{
|
||||
cl_run = !!v;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
team = val == 0 ? TEAM_NONE : val - 1;
|
||||
}
|
||||
return Super::MenuEvent(mkey, fromcontroller);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DPlayerMenu::MouseEvent(int type, int x, int y)
|
||||
DEFINE_ACTION_FUNCTION(DPlayerMenu, GenderChanged)
|
||||
{
|
||||
int v;
|
||||
DMenuItemBase *li = mFocusControl;
|
||||
bool res = Super::MouseEvent(type, x, y);
|
||||
if (li == NULL) li = mFocusControl;
|
||||
if (li != NULL)
|
||||
PARAM_SELF_PROLOGUE(DMenu);
|
||||
PARAM_INT(v);
|
||||
// only allow if the menu is active to prevent abuse.
|
||||
if (self == CurrentMenu)
|
||||
{
|
||||
// Check if the colors have changed
|
||||
FName current = li->GetAction(NULL);
|
||||
switch(current)
|
||||
{
|
||||
case NAME_Red:
|
||||
if (li->GetValue(0, &v))
|
||||
{
|
||||
uint32 color = players[consoleplayer].userinfo.GetColor();
|
||||
SendNewColor (v, GPART(color), BPART(color));
|
||||
}
|
||||
break;
|
||||
|
||||
case NAME_Green:
|
||||
if (li->GetValue(0, &v))
|
||||
{
|
||||
uint32 color = players[consoleplayer].userinfo.GetColor();
|
||||
SendNewColor (RPART(color), v, BPART(color));
|
||||
}
|
||||
break;
|
||||
|
||||
case NAME_Blue:
|
||||
if (li->GetValue(0, &v))
|
||||
{
|
||||
uint32 color = players[consoleplayer].userinfo.GetColor();
|
||||
SendNewColor (RPART(color), GPART(color), v);
|
||||
}
|
||||
break;
|
||||
case NAME_Autoaim:
|
||||
AutoaimChanged(li);
|
||||
break;
|
||||
}
|
||||
cvar_set("gender", v == 0 ? "male" : v == 1 ? "female" : "other");
|
||||
}
|
||||
return res;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
@ -699,10 +226,16 @@ bool DPlayerMenu::MouseEvent(int type, int x, int y)
|
|||
//
|
||||
//=============================================================================
|
||||
|
||||
void DPlayerMenu::Ticker ()
|
||||
DEFINE_ACTION_FUNCTION(DPlayerMenu, SwitchOnPickupChanged)
|
||||
{
|
||||
|
||||
Super::Ticker();
|
||||
PARAM_SELF_PROLOGUE(DMenu);
|
||||
PARAM_INT(v);
|
||||
// only allow if the menu is active to prevent abuse.
|
||||
if (self == CurrentMenu)
|
||||
{
|
||||
neverswitchonpickup = !!v;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
@ -711,20 +244,14 @@ void DPlayerMenu::Ticker ()
|
|||
//
|
||||
//=============================================================================
|
||||
|
||||
void DPlayerMenu::Drawer ()
|
||||
DEFINE_ACTION_FUNCTION(DPlayerMenu, AlwaysRunChanged)
|
||||
{
|
||||
|
||||
Super::Drawer();
|
||||
|
||||
const char *str = "PRESS " TEXTCOLOR_WHITE "SPACE";
|
||||
screen->DrawText (SmallFont, CR_GOLD, 320 - 32 - 32 -
|
||||
SmallFont->StringWidth (str)/2,
|
||||
50 + 48 + 70, str,
|
||||
DTA_Clean, true, TAG_DONE);
|
||||
str = mRotation ? "TO SEE FRONT" : "TO SEE BACK";
|
||||
screen->DrawText (SmallFont, CR_GOLD, 320 - 32 - 32 -
|
||||
SmallFont->StringWidth (str)/2,
|
||||
50 + 48 + 70 + SmallFont->GetHeight (), str,
|
||||
DTA_Clean, true, TAG_DONE);
|
||||
|
||||
PARAM_SELF_PROLOGUE(DMenu);
|
||||
PARAM_INT(v);
|
||||
// only allow if the menu is active to prevent abuse.
|
||||
if (self == CurrentMenu)
|
||||
{
|
||||
cl_run = !!v;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,149 +0,0 @@
|
|||
/*
|
||||
** readthis.cpp
|
||||
** Help screens
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2001-2010 Randy Heit
|
||||
** Copyright 2010 Christoph Oelckers
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
#include "menu/menu.h"
|
||||
#include "v_video.h"
|
||||
#include "g_level.h"
|
||||
#include "gi.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "textures/textures.h"
|
||||
|
||||
class DReadThisMenu : public DMenu
|
||||
{
|
||||
DECLARE_CLASS(DReadThisMenu, DMenu)
|
||||
int mScreen;
|
||||
int mInfoTic;
|
||||
|
||||
public:
|
||||
|
||||
DReadThisMenu(DMenu *parent = NULL);
|
||||
void Drawer();
|
||||
bool MenuEvent(int mkey, bool fromcontroller);
|
||||
bool DimAllowed () { return false; }
|
||||
bool MouseEvent(int type, int x, int y);
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS(DReadThisMenu, false, false)
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Read This Menus
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
DReadThisMenu::DReadThisMenu(DMenu *parent)
|
||||
: DMenu(parent)
|
||||
{
|
||||
mScreen = 1;
|
||||
mInfoTic = gametic;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void DReadThisMenu::Drawer()
|
||||
{
|
||||
FTexture *tex = NULL, *prevpic = NULL;
|
||||
double alpha;
|
||||
|
||||
// Did the mapper choose a custom help page via MAPINFO?
|
||||
if ((level.info != NULL) && level.info->F1Pic.Len() != 0)
|
||||
{
|
||||
tex = TexMan.FindTexture(level.info->F1Pic);
|
||||
mScreen = 1;
|
||||
}
|
||||
|
||||
if (tex == NULL)
|
||||
{
|
||||
tex = TexMan[gameinfo.infoPages[mScreen-1].GetChars()];
|
||||
}
|
||||
|
||||
if (mScreen > 1)
|
||||
{
|
||||
prevpic = TexMan[gameinfo.infoPages[mScreen-2].GetChars()];
|
||||
}
|
||||
|
||||
screen->Dim(0, 1.0, 0,0, SCREENWIDTH, SCREENHEIGHT);
|
||||
alpha = MIN((gametic - mInfoTic) * (3. / TICRATE), 1.);
|
||||
if (alpha < 1. && prevpic != NULL)
|
||||
{
|
||||
screen->DrawTexture (prevpic, 0, 0, DTA_Fullscreen, true, TAG_DONE);
|
||||
}
|
||||
screen->DrawTexture (tex, 0, 0, DTA_Fullscreen, true, DTA_Alpha, alpha, TAG_DONE);
|
||||
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DReadThisMenu::MenuEvent(int mkey, bool fromcontroller)
|
||||
{
|
||||
if (mkey == MKEY_Enter)
|
||||
{
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/choose", snd_menuvolume, ATTN_NONE);
|
||||
mScreen++;
|
||||
mInfoTic = gametic;
|
||||
if ((level.info != NULL && level.info->F1Pic.Len() != 0) || mScreen > int(gameinfo.infoPages.Size()))
|
||||
{
|
||||
Close();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else return Super::MenuEvent(mkey, fromcontroller);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool DReadThisMenu::MouseEvent(int type, int x, int y)
|
||||
{
|
||||
if (type == MOUSE_Click)
|
||||
{
|
||||
return MenuEvent(MKEY_Enter, true);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -653,6 +653,7 @@ xx(Link)
|
|||
xx(Goodbye)
|
||||
xx(Require)
|
||||
xx(Exclude)
|
||||
xx(Userstring)
|
||||
|
||||
// Special menus
|
||||
xx(Mainmenu)
|
||||
|
|
|
@ -3919,7 +3919,7 @@ DEFINE_ACTION_FUNCTION(AActor, PlayerSkinCheck)
|
|||
PARAM_SELF_PROLOGUE(AActor);
|
||||
|
||||
ACTION_RETURN_BOOL(self->player != NULL &&
|
||||
skins[self->player->userinfo.GetSkin()].othergame);
|
||||
Skins[self->player->userinfo.GetSkin()].othergame);
|
||||
}
|
||||
|
||||
// [KS] *** Start of my modifications ***
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
#include "p_local.h"
|
||||
#include "menu/menu.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "virtual.h"
|
||||
|
||||
// The conversations as they exist inside a SCRIPTxx lump.
|
||||
struct Response
|
||||
|
@ -112,7 +113,7 @@ static FDialogueMap ClassRoots;
|
|||
static int ConversationMenuY;
|
||||
|
||||
static int ConversationPauseTic;
|
||||
static bool ShowGold;
|
||||
static int StaticLastReply;
|
||||
|
||||
static bool LoadScriptFile(int lumpnum, FileReader *lump, int numnodes, bool include, int type);
|
||||
static FStrifeDialogueNode *ReadRetailNode (FileReader *lump, DWORD &prevSpeakerType);
|
||||
|
@ -124,9 +125,6 @@ static void TerminalResponse (const char *str);
|
|||
|
||||
static FStrifeDialogueNode *PrevNode;
|
||||
|
||||
#define NUM_RANDOM_LINES 10
|
||||
#define NUM_RANDOM_GOODBYES 3
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// GetStrifeType
|
||||
|
@ -347,11 +345,11 @@ static FStrifeDialogueNode *ReadRetailNode (FileReader *lump, DWORD &prevSpeaker
|
|||
}
|
||||
|
||||
// Convert the rest of the data to our own internal format.
|
||||
node->Dialogue = ncopystring (speech.Dialogue);
|
||||
node->Dialogue = speech.Dialogue;
|
||||
|
||||
// The speaker's portrait, if any.
|
||||
speech.Dialogue[0] = 0; //speech.Backdrop[8] = 0;
|
||||
node->Backdrop = TexMan.CheckForTexture (speech.Backdrop, FTexture::TEX_MiscPatch);
|
||||
node->Backdrop = speech.Backdrop;
|
||||
|
||||
// The speaker's voice for this node, if any.
|
||||
speech.Backdrop[0] = 0; //speech.Sound[8] = 0;
|
||||
|
@ -360,7 +358,7 @@ static FStrifeDialogueNode *ReadRetailNode (FileReader *lump, DWORD &prevSpeaker
|
|||
|
||||
// The speaker's name, if any.
|
||||
speech.Sound[0] = 0; //speech.Name[16] = 0;
|
||||
node->SpeakerName = ncopystring(speech.Name);
|
||||
node->SpeakerName = speech.Name;
|
||||
|
||||
// The item the speaker should drop when killed.
|
||||
node->DropType = dyn_cast<PClassActor>(GetStrifeType(speech.DropType));
|
||||
|
@ -422,10 +420,10 @@ static FStrifeDialogueNode *ReadTeaserNode (FileReader *lump, DWORD &prevSpeaker
|
|||
}
|
||||
|
||||
// Convert the rest of the data to our own internal format.
|
||||
node->Dialogue = ncopystring (speech.Dialogue);
|
||||
node->Dialogue = speech.Dialogue;
|
||||
|
||||
// The Teaser version doesn't have portraits.
|
||||
node->Backdrop.SetInvalid();
|
||||
node->Backdrop = "";
|
||||
|
||||
// The speaker's voice for this node, if any.
|
||||
if (speech.VoiceNumber != 0)
|
||||
|
@ -440,7 +438,7 @@ static FStrifeDialogueNode *ReadTeaserNode (FileReader *lump, DWORD &prevSpeaker
|
|||
|
||||
// The speaker's name, if any.
|
||||
speech.Dialogue[0] = 0; //speech.Name[16] = 0;
|
||||
node->SpeakerName = ncopystring (speech.Name);
|
||||
node->SpeakerName = speech.Name;
|
||||
|
||||
// The item the speaker should drop when killed.
|
||||
node->DropType = dyn_cast<PClassActor>(GetStrifeType (speech.DropType));
|
||||
|
@ -505,7 +503,7 @@ static void ParseReplies (FStrifeDialogueReply **replyptr, Response *responses)
|
|||
|
||||
// The message to record in the log for this reply.
|
||||
reply->LogNumber = rsp->Log;
|
||||
reply->LogString = NULL;
|
||||
reply->LogString = "";
|
||||
|
||||
// The item to receive when this reply is used.
|
||||
reply->GiveType = dyn_cast<PClassActor>(GetStrifeType (rsp->GiveType));
|
||||
|
@ -520,31 +518,32 @@ static void ParseReplies (FStrifeDialogueReply **replyptr, Response *responses)
|
|||
reply->ItemCheck[k].Item = inv;
|
||||
reply->ItemCheck[k].Amount = rsp->Count[k];
|
||||
}
|
||||
reply->PrintAmount = reply->ItemCheck[0].Amount;
|
||||
reply->ItemCheckRequire.Clear();
|
||||
reply->ItemCheckExclude.Clear();
|
||||
|
||||
// If the first item check has a positive amount required, then
|
||||
// add that to the reply string. Otherwise, use the reply as-is.
|
||||
reply->Reply = copystring (rsp->Reply);
|
||||
reply->Reply = rsp->Reply;
|
||||
reply->NeedsGold = (rsp->Count[0] > 0);
|
||||
|
||||
// QuickYes messages are shown when you meet the item checks.
|
||||
// QuickNo messages are shown when you don't.
|
||||
if (rsp->Yes[0] == '_' && rsp->Yes[1] == 0)
|
||||
{
|
||||
reply->QuickYes = NULL;
|
||||
reply->QuickYes = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
reply->QuickYes = ncopystring (rsp->Yes);
|
||||
reply->QuickYes = rsp->Yes;
|
||||
}
|
||||
if (reply->ItemCheck[0].Item != 0)
|
||||
{
|
||||
reply->QuickNo = ncopystring (rsp->No);
|
||||
reply->QuickNo = rsp->No;
|
||||
}
|
||||
else
|
||||
{
|
||||
reply->QuickNo = NULL;
|
||||
reply->QuickNo = "";
|
||||
}
|
||||
reply->Next = *replyptr;
|
||||
*replyptr = reply;
|
||||
|
@ -560,9 +559,6 @@ static void ParseReplies (FStrifeDialogueReply **replyptr, Response *responses)
|
|||
|
||||
FStrifeDialogueNode::~FStrifeDialogueNode ()
|
||||
{
|
||||
if (SpeakerName != NULL) delete[] SpeakerName;
|
||||
if (Dialogue != NULL) delete[] Dialogue;
|
||||
if (Goodbye != nullptr) delete[] Goodbye;
|
||||
FStrifeDialogueReply *tokill = Children;
|
||||
while (tokill != NULL)
|
||||
{
|
||||
|
@ -580,9 +576,6 @@ FStrifeDialogueNode::~FStrifeDialogueNode ()
|
|||
|
||||
FStrifeDialogueReply::~FStrifeDialogueReply ()
|
||||
{
|
||||
if (Reply != NULL) delete[] Reply;
|
||||
if (QuickYes != NULL) delete[] QuickYes;
|
||||
if (QuickNo != NULL) delete[] QuickNo;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
@ -672,7 +665,7 @@ CUSTOM_CVAR(Float, dlg_musicvolume, 1.0f, CVAR_ARCHIVE)
|
|||
|
||||
static bool ShouldSkipReply(FStrifeDialogueReply *reply, player_t *player)
|
||||
{
|
||||
if (reply->Reply == nullptr)
|
||||
if (reply->Reply.IsEmpty())
|
||||
return true;
|
||||
|
||||
int i;
|
||||
|
@ -694,428 +687,60 @@ static bool ShouldSkipReply(FStrifeDialogueReply *reply, player_t *player)
|
|||
return false;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// The conversation menu
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
class DConversationMenu : public DMenu
|
||||
DEFINE_ACTION_FUNCTION(FStrifeDialogueReply, ShouldSkipReply)
|
||||
{
|
||||
DECLARE_CLASS(DConversationMenu, DMenu)
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FStrifeDialogueReply);
|
||||
PARAM_POINTER(player, player_t);
|
||||
ACTION_RETURN_BOOL(ShouldSkipReply(self, player));
|
||||
}
|
||||
|
||||
FString mSpeaker;
|
||||
FBrokenLines *mDialogueLines;
|
||||
TArray<FString> mResponseLines;
|
||||
TArray<unsigned int> mResponses;
|
||||
bool mShowGold;
|
||||
FStrifeDialogueNode *mCurNode;
|
||||
int mYpos;
|
||||
player_t *mPlayer;
|
||||
DEFINE_ACTION_FUNCTION(DConversationMenu, SendConversationReply)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_INT(node);
|
||||
PARAM_INT(reply);
|
||||
switch (node)
|
||||
{
|
||||
case -1:
|
||||
Net_WriteByte(DEM_CONVNULL);
|
||||
break;
|
||||
|
||||
case -2:
|
||||
Net_WriteByte(DEM_CONVCLOSE);
|
||||
break;
|
||||
|
||||
default:
|
||||
Net_WriteByte(DEM_CONVREPLY);
|
||||
Net_WriteWord(node);
|
||||
Net_WriteByte(reply);
|
||||
break;
|
||||
}
|
||||
StaticLastReply = reply;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Needed for the conversion process.
|
||||
class DBrokenLines : public DObject
|
||||
{
|
||||
DECLARE_ABSTRACT_CLASS(DBrokenLines, DObject)
|
||||
|
||||
public:
|
||||
static int mSelection;
|
||||
FBrokenLines *mBroken;
|
||||
unsigned int mCount;
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
DConversationMenu(FStrifeDialogueNode *CurNode, player_t *player)
|
||||
DBrokenLines(FBrokenLines *broken, unsigned int count)
|
||||
{
|
||||
mCurNode = CurNode;
|
||||
mPlayer = player;
|
||||
mDialogueLines = NULL;
|
||||
mShowGold = false;
|
||||
|
||||
// Format the speaker's message.
|
||||
const char * toSay = CurNode->Dialogue;
|
||||
if (strncmp (toSay, "RANDOM_", 7) == 0)
|
||||
{
|
||||
FString dlgtext;
|
||||
|
||||
dlgtext.Format("TXT_%s_%02d", toSay, 1+(pr_randomspeech() % NUM_RANDOM_LINES));
|
||||
toSay = GStrings[dlgtext];
|
||||
if (toSay == NULL)
|
||||
{
|
||||
toSay = GStrings["TXT_GOAWAY"]; // Ok, it's lame - but it doesn't look like an error to the player. ;)
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// handle string table replacement
|
||||
if (toSay[0] == '$')
|
||||
{
|
||||
toSay = GStrings(toSay + 1);
|
||||
}
|
||||
}
|
||||
if (toSay == NULL)
|
||||
{
|
||||
toSay = ".";
|
||||
}
|
||||
mDialogueLines = V_BreakLines (SmallFont, screen->GetWidth()/CleanXfac - 24*2, toSay);
|
||||
|
||||
FStrifeDialogueReply *reply;
|
||||
int i,j;
|
||||
for (reply = CurNode->Children, i = 1; reply != NULL; reply = reply->Next)
|
||||
{
|
||||
if (ShouldSkipReply(reply, mPlayer))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
mShowGold |= reply->NeedsGold;
|
||||
|
||||
const char *ReplyText = reply->Reply;
|
||||
if (ReplyText[0] == '$')
|
||||
{
|
||||
ReplyText = GStrings(ReplyText + 1);
|
||||
}
|
||||
FString ReplyString = ReplyText;
|
||||
if (reply->NeedsGold) ReplyString.AppendFormat(" for %u", reply->ItemCheck[0].Amount);
|
||||
|
||||
FBrokenLines *ReplyLines = V_BreakLines (SmallFont, 320-50-10, ReplyString);
|
||||
|
||||
mResponses.Push(mResponseLines.Size());
|
||||
for (j = 0; ReplyLines[j].Width >= 0; ++j)
|
||||
{
|
||||
mResponseLines.Push(ReplyLines[j].Text);
|
||||
}
|
||||
++i;
|
||||
V_FreeBrokenLines (ReplyLines);
|
||||
}
|
||||
const char *goodbyestr = CurNode->Goodbye;
|
||||
if (goodbyestr == nullptr)
|
||||
{
|
||||
char goodbye[25];
|
||||
mysnprintf(goodbye, countof(goodbye), "TXT_RANDOMGOODBYE_%d", 1 + (pr_randomspeech() % NUM_RANDOM_GOODBYES));
|
||||
goodbyestr = GStrings[goodbye];
|
||||
}
|
||||
else if (strncmp(goodbyestr, "RANDOM_", 7) == 0)
|
||||
{
|
||||
FString byetext;
|
||||
|
||||
byetext.Format("TXT_%s_%02d", goodbyestr, 1 + (pr_randomspeech() % NUM_RANDOM_LINES));
|
||||
goodbyestr = GStrings[byetext];
|
||||
}
|
||||
else if (goodbyestr[0] == '$')
|
||||
{
|
||||
goodbyestr = GStrings(goodbyestr + 1);
|
||||
}
|
||||
if (goodbyestr == nullptr) goodbyestr = "Bye.";
|
||||
mResponses.Push(mResponseLines.Size());
|
||||
mResponseLines.Push(FString(goodbyestr));
|
||||
|
||||
// Determine where the top of the reply list should be positioned.
|
||||
i = OptionSettings.mLinespacing;
|
||||
mYpos = MIN<int> (140, 192 - mResponseLines.Size() * i);
|
||||
for (i = 0; mDialogueLines[i].Width >= 0; ++i)
|
||||
{ }
|
||||
i = 44 + i * 10;
|
||||
if (mYpos - 100 < i - screen->GetHeight() / CleanYfac / 2)
|
||||
{
|
||||
mYpos = i - screen->GetHeight() / CleanYfac / 2 + 100;
|
||||
}
|
||||
ConversationMenuY = mYpos;
|
||||
//ConversationMenu.indent = 50;
|
||||
|
||||
// Because replies can be selectively hidden mResponses.Size() won't be consistent.
|
||||
// So make sure mSelection doesn't exceed mResponses.Size(). [FishyClockwork]
|
||||
if (mSelection >= (int)mResponses.Size())
|
||||
{
|
||||
mSelection = mResponses.Size() - 1;
|
||||
}
|
||||
mBroken = broken;
|
||||
mCount = count;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void OnDestroy() override
|
||||
{
|
||||
V_FreeBrokenLines(mDialogueLines);
|
||||
mDialogueLines = NULL;
|
||||
I_SetMusicVolume (1.f);
|
||||
Super::OnDestroy();
|
||||
V_FreeBrokenLines(mBroken);
|
||||
}
|
||||
|
||||
bool DimAllowed()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool MenuEvent(int mkey, bool fromcontroller)
|
||||
{
|
||||
if (demoplayback)
|
||||
{ // During demo playback, don't let the user do anything besides close this menu.
|
||||
if (mkey == MKEY_Back)
|
||||
{
|
||||
Close();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (mkey == MKEY_Up)
|
||||
{
|
||||
if (--mSelection < 0) mSelection = mResponses.Size() - 1;
|
||||
return true;
|
||||
}
|
||||
else if (mkey == MKEY_Down)
|
||||
{
|
||||
if (++mSelection >= (int)mResponses.Size()) mSelection = 0;
|
||||
return true;
|
||||
}
|
||||
else if (mkey == MKEY_Back)
|
||||
{
|
||||
Net_WriteByte (DEM_CONVNULL);
|
||||
Close();
|
||||
return true;
|
||||
}
|
||||
else if (mkey == MKEY_Enter)
|
||||
{
|
||||
if ((unsigned)mSelection >= mResponses.Size())
|
||||
{
|
||||
Net_WriteByte(DEM_CONVCLOSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert((unsigned)mCurNode->ThisNodeNum < StrifeDialogues.Size());
|
||||
assert(StrifeDialogues[mCurNode->ThisNodeNum] == mCurNode);
|
||||
|
||||
// This is needed because mSelection represents the replies currently being displayed which will
|
||||
// not match up with what's supposed to be selected if there are any hidden/skipped replies. [FishyClockwork]
|
||||
FStrifeDialogueReply *reply = mCurNode->Children;
|
||||
int replynum = mSelection;
|
||||
for (int i = 0; i <= mSelection && reply != nullptr; reply = reply->Next)
|
||||
{
|
||||
if (ShouldSkipReply(reply, mPlayer))
|
||||
replynum++;
|
||||
else
|
||||
i++;
|
||||
}
|
||||
// Send dialogue and reply numbers across the wire.
|
||||
Net_WriteByte(DEM_CONVREPLY);
|
||||
Net_WriteWord(mCurNode->ThisNodeNum);
|
||||
Net_WriteByte(replynum);
|
||||
}
|
||||
Close();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool MouseEvent(int type, int x, int y)
|
||||
{
|
||||
int sel = -1;
|
||||
int fh = OptionSettings.mLinespacing;
|
||||
|
||||
// convert x/y from screen to virtual coordinates, according to CleanX/Yfac use in DrawTexture
|
||||
x = ((x - (screen->GetWidth() / 2)) / CleanXfac) + 160;
|
||||
y = ((y - (screen->GetHeight() / 2)) / CleanYfac) + 100;
|
||||
|
||||
if (x >= 24 && x <= 320-24 && y >= mYpos && y < mYpos + fh * (int)mResponseLines.Size())
|
||||
{
|
||||
sel = (y - mYpos) / fh;
|
||||
for(unsigned i=0;i<mResponses.Size(); i++)
|
||||
{
|
||||
if ((int)mResponses[i] > sel)
|
||||
{
|
||||
sel = i-1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sel != -1 && sel != mSelection)
|
||||
{
|
||||
//S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
|
||||
}
|
||||
mSelection = sel;
|
||||
if (type == MOUSE_Release)
|
||||
{
|
||||
return MenuEvent(MKEY_Enter, true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool Responder(event_t *ev)
|
||||
{
|
||||
if (demoplayback)
|
||||
{ // No interaction during demo playback
|
||||
return false;
|
||||
}
|
||||
if (ev->type == EV_GUI_Event && ev->subtype == EV_GUI_Char && ev->data1 >= '0' && ev->data1 <= '9')
|
||||
{ // Activate an item of type numberedmore (dialogue only)
|
||||
mSelection = ev->data1 == '0' ? 9 : ev->data1 - '1';
|
||||
return MenuEvent(MKEY_Enter, false);
|
||||
}
|
||||
return Super::Responder(ev);
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// DrawConversationMenu
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
void Drawer()
|
||||
{
|
||||
const char *speakerName;
|
||||
int x, y, linesize;
|
||||
int width, fontheight;
|
||||
|
||||
player_t *cp = &players[consoleplayer];
|
||||
|
||||
assert (mDialogueLines != NULL);
|
||||
assert (mCurNode != NULL);
|
||||
|
||||
FStrifeDialogueNode *CurNode = mCurNode;
|
||||
|
||||
if (CurNode == NULL)
|
||||
{
|
||||
Close ();
|
||||
return;
|
||||
}
|
||||
|
||||
// [CW] Freeze the game depending on MAPINFO options.
|
||||
if (ConversationPauseTic < gametic && !multiplayer && !(level.flags2 & LEVEL2_CONV_SINGLE_UNFREEZE))
|
||||
{
|
||||
menuactive = MENU_On;
|
||||
}
|
||||
|
||||
if (CurNode->Backdrop.isValid())
|
||||
{
|
||||
screen->DrawTexture (TexMan(CurNode->Backdrop), 0, 0, DTA_320x200, true, TAG_DONE);
|
||||
}
|
||||
x = 16 * screen->GetWidth() / 320;
|
||||
y = 16 * screen->GetHeight() / 200;
|
||||
linesize = 10 * CleanYfac;
|
||||
|
||||
// Who is talking to you?
|
||||
if (CurNode->SpeakerName != NULL)
|
||||
{
|
||||
speakerName = CurNode->SpeakerName;
|
||||
if (speakerName[0] == '$') speakerName = GStrings(speakerName+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
speakerName = cp->ConversationNPC->GetTag("Person");
|
||||
}
|
||||
|
||||
// Dim the screen behind the dialogue (but only if there is no backdrop).
|
||||
if (!CurNode->Backdrop.isValid())
|
||||
{
|
||||
int i;
|
||||
for (i = 0; mDialogueLines[i].Width >= 0; ++i)
|
||||
{ }
|
||||
screen->Dim (0, 0.45f, 14 * screen->GetWidth() / 320, 13 * screen->GetHeight() / 200,
|
||||
308 * screen->GetWidth() / 320 - 14 * screen->GetWidth () / 320,
|
||||
speakerName == NULL ? linesize * i + 6 * CleanYfac
|
||||
: linesize * i + 6 * CleanYfac + linesize * 3/2);
|
||||
}
|
||||
|
||||
// Dim the screen behind the PC's choices.
|
||||
|
||||
screen->Dim (0, 0.45f, (24-160) * CleanXfac + screen->GetWidth()/2,
|
||||
(mYpos - 2 - 100) * CleanYfac + screen->GetHeight()/2,
|
||||
272 * CleanXfac,
|
||||
MIN<int>(mResponseLines.Size() * OptionSettings.mLinespacing + 4, 200 - mYpos) * CleanYfac);
|
||||
|
||||
if (speakerName != NULL)
|
||||
{
|
||||
screen->DrawText (SmallFont, CR_WHITE, x, y, speakerName,
|
||||
DTA_CleanNoMove, true, TAG_DONE);
|
||||
y += linesize * 3 / 2;
|
||||
}
|
||||
x = 24 * screen->GetWidth() / 320;
|
||||
for (int i = 0; mDialogueLines[i].Width >= 0; ++i)
|
||||
{
|
||||
screen->DrawText (SmallFont, CR_UNTRANSLATED, x, y, mDialogueLines[i].Text,
|
||||
DTA_CleanNoMove, true, TAG_DONE);
|
||||
y += linesize;
|
||||
}
|
||||
|
||||
if (ShowGold)
|
||||
{
|
||||
auto cointype = PClass::FindActor("Coin");
|
||||
if (cointype)
|
||||
{
|
||||
AInventory *coin = cp->ConversationPC->FindInventory(cointype);
|
||||
char goldstr[32];
|
||||
|
||||
mysnprintf(goldstr, countof(goldstr), "%d", coin != NULL ? coin->Amount : 0);
|
||||
screen->DrawText(SmallFont, CR_GRAY, 21, 191, goldstr, DTA_320x200, true,
|
||||
DTA_FillColor, 0, DTA_Alpha, HR_SHADOW, TAG_DONE);
|
||||
screen->DrawTexture(TexMan(((AInventory *)GetDefaultByType(cointype))->Icon),
|
||||
3, 190, DTA_320x200, true,
|
||||
DTA_FillColor, 0, DTA_Alpha, HR_SHADOW, TAG_DONE);
|
||||
screen->DrawText(SmallFont, CR_GRAY, 20, 190, goldstr, DTA_320x200, true, TAG_DONE);
|
||||
screen->DrawTexture(TexMan(((AInventory *)GetDefaultByType(cointype))->Icon),
|
||||
2, 189, DTA_320x200, true, TAG_DONE);
|
||||
}
|
||||
}
|
||||
|
||||
y = mYpos;
|
||||
fontheight = OptionSettings.mLinespacing;
|
||||
|
||||
int response = 0;
|
||||
for (unsigned i = 0; i < mResponseLines.Size(); i++, y += fontheight)
|
||||
{
|
||||
width = SmallFont->StringWidth(mResponseLines[i]);
|
||||
x = 64;
|
||||
|
||||
screen->DrawText (SmallFont, CR_GREEN, x, y, mResponseLines[i], DTA_Clean, true, TAG_DONE);
|
||||
|
||||
if (i == mResponses[response])
|
||||
{
|
||||
char tbuf[16];
|
||||
|
||||
response++;
|
||||
mysnprintf (tbuf, countof(tbuf), "%d.", response);
|
||||
x = 50 - SmallFont->StringWidth (tbuf);
|
||||
screen->DrawText (SmallFont, CR_GREY, x, y, tbuf, DTA_Clean, true, TAG_DONE);
|
||||
|
||||
if (response == mSelection+1)
|
||||
{
|
||||
int color = ((DMenu::MenuTime%8) < 4) || DMenu::CurrentMenu != this ? CR_RED:CR_GREY;
|
||||
|
||||
x = (50 + 3 - 160) * CleanXfac + screen->GetWidth() / 2;
|
||||
int yy = (y + fontheight/2 - 5 - 100) * CleanYfac + screen->GetHeight() / 2;
|
||||
screen->DrawText (ConFont, color, x, yy, "\xd",
|
||||
DTA_CellX, 8 * CleanXfac,
|
||||
DTA_CellY, 8 * CleanYfac,
|
||||
TAG_DONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS(DConversationMenu, true, false)
|
||||
int DConversationMenu::mSelection; // needs to be preserved if the same dialogue is restarted
|
||||
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// P_FreeStrifeConversations
|
||||
|
@ -1135,9 +760,9 @@ void P_FreeStrifeConversations ()
|
|||
ClassRoots.Clear();
|
||||
|
||||
PrevNode = NULL;
|
||||
if (DMenu::CurrentMenu != NULL && DMenu::CurrentMenu->IsKindOf(RUNTIME_CLASS(DConversationMenu)))
|
||||
if (CurrentMenu != NULL && CurrentMenu->IsKindOf("ConversationMenu"))
|
||||
{
|
||||
DMenu::CurrentMenu->Close();
|
||||
CurrentMenu->Close();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1233,19 +858,31 @@ void P_StartConversation (AActor *npc, AActor *pc, bool facetalker, bool saveang
|
|||
S_Sound (npc, CHAN_VOICE|CHAN_NOPAUSE, CurNode->SpeakerVoice, 1, ATTN_NORM);
|
||||
}
|
||||
|
||||
DConversationMenu *cmenu = new DConversationMenu(CurNode, pc->player);
|
||||
// Create the menu. This may be a user-defined class so check if it is good to use.
|
||||
FName cls = CurNode->MenuClassName;
|
||||
if (cls == NAME_None) cls = gameinfo.DefaultConversationMenuClass;
|
||||
if (cls == NAME_None) cls = "ConversationMenu";
|
||||
auto mcls = PClass::FindClass(cls);
|
||||
if (mcls == nullptr || !mcls->IsDescendantOf("ConversationMenu")) mcls = PClass::FindClass("ConversationMenu");
|
||||
assert(mcls);
|
||||
|
||||
auto cmenu = mcls->CreateNew();
|
||||
IFVIRTUALPTRNAME(cmenu, "ConversationMenu", Init)
|
||||
{
|
||||
VMValue params[] = { cmenu, CurNode, pc->player, StaticLastReply };
|
||||
VMReturn ret(&ConversationMenuY);
|
||||
GlobalVMStack.Call(func, params, countof(params), &ret, 1);
|
||||
}
|
||||
|
||||
if (CurNode != PrevNode)
|
||||
{ // Only reset the selection if showing a different menu.
|
||||
DConversationMenu::mSelection = 0;
|
||||
StaticLastReply = 0;
|
||||
PrevNode = CurNode;
|
||||
}
|
||||
|
||||
// And open the menu
|
||||
M_StartControlPanel (false);
|
||||
M_ActivateMenu(cmenu);
|
||||
ConversationPauseTic = gametic + 20;
|
||||
M_ActivateMenu((DMenu*)cmenu);
|
||||
menuactive = MENU_OnNoPause;
|
||||
}
|
||||
}
|
||||
|
@ -1315,7 +952,7 @@ static void HandleReply(player_t *player, bool isconsole, int nodenum, int reply
|
|||
if (!CheckStrifeItem(player, reply->ItemCheck[i].Item, reply->ItemCheck[i].Amount))
|
||||
{
|
||||
// No, you don't. Say so and let the NPC animate negatively.
|
||||
if (reply->QuickNo && isconsole)
|
||||
if (reply->QuickNo.IsNotEmpty() && isconsole)
|
||||
{
|
||||
TerminalResponse(reply->QuickNo);
|
||||
}
|
||||
|
@ -1396,7 +1033,7 @@ static void HandleReply(player_t *player, bool isconsole, int nodenum, int reply
|
|||
}
|
||||
|
||||
// Update the quest log, if needed.
|
||||
if (reply->LogString != NULL)
|
||||
if (reply->LogString.IsNotEmpty())
|
||||
{
|
||||
const char *log = reply->LogString;
|
||||
if (log[0] == '$')
|
||||
|
@ -1482,10 +1119,9 @@ void P_ConversationCommand (int netcode, int pnum, BYTE **stream)
|
|||
|
||||
// The conversation menus are normally closed by the menu code, but that
|
||||
// doesn't happen during demo playback, so we need to do it here.
|
||||
if (demoplayback && DMenu::CurrentMenu != NULL &&
|
||||
DMenu::CurrentMenu->IsKindOf(RUNTIME_CLASS(DConversationMenu)))
|
||||
if (demoplayback && CurrentMenu != NULL && CurrentMenu->IsKindOf("ConversationMenu"))
|
||||
{
|
||||
DMenu::CurrentMenu->Close();
|
||||
CurrentMenu->Close();
|
||||
}
|
||||
if (netcode == DEM_CONVREPLY)
|
||||
{
|
||||
|
@ -1549,3 +1185,28 @@ static void TerminalResponse (const char *str)
|
|||
}
|
||||
}
|
||||
|
||||
DEFINE_FIELD(FStrifeDialogueNode, DropType);
|
||||
DEFINE_FIELD(FStrifeDialogueNode, ThisNodeNum);
|
||||
DEFINE_FIELD(FStrifeDialogueNode, ItemCheckNode);
|
||||
DEFINE_FIELD(FStrifeDialogueNode, SpeakerType);
|
||||
DEFINE_FIELD(FStrifeDialogueNode, SpeakerName);
|
||||
DEFINE_FIELD(FStrifeDialogueNode, SpeakerVoice);
|
||||
DEFINE_FIELD(FStrifeDialogueNode, Backdrop);
|
||||
DEFINE_FIELD(FStrifeDialogueNode, Dialogue);
|
||||
DEFINE_FIELD(FStrifeDialogueNode, Goodbye);
|
||||
DEFINE_FIELD(FStrifeDialogueNode, Children);
|
||||
DEFINE_FIELD(FStrifeDialogueNode, MenuClassName);
|
||||
DEFINE_FIELD(FStrifeDialogueNode, UserData);
|
||||
|
||||
DEFINE_FIELD(FStrifeDialogueReply, Next);
|
||||
DEFINE_FIELD(FStrifeDialogueReply, GiveType);
|
||||
DEFINE_FIELD(FStrifeDialogueReply, ActionSpecial);
|
||||
DEFINE_FIELD(FStrifeDialogueReply, Args);
|
||||
DEFINE_FIELD(FStrifeDialogueReply, PrintAmount);
|
||||
DEFINE_FIELD(FStrifeDialogueReply, Reply);
|
||||
DEFINE_FIELD(FStrifeDialogueReply, QuickYes);
|
||||
DEFINE_FIELD(FStrifeDialogueReply, QuickNo);
|
||||
DEFINE_FIELD(FStrifeDialogueReply, LogString);
|
||||
DEFINE_FIELD(FStrifeDialogueReply, NextNode);
|
||||
DEFINE_FIELD(FStrifeDialogueReply, LogNumber);
|
||||
DEFINE_FIELD(FStrifeDialogueReply, NeedsGold);
|
||||
|
|
|
@ -26,13 +26,15 @@ struct FStrifeDialogueNode
|
|||
int ItemCheckNode; // index into StrifeDialogues
|
||||
|
||||
PClassActor *SpeakerType;
|
||||
char *SpeakerName;
|
||||
FString SpeakerName;
|
||||
FSoundID SpeakerVoice;
|
||||
FTextureID Backdrop;
|
||||
char *Dialogue;
|
||||
char *Goodbye = nullptr; // must init to null for binary scripts to work as intended
|
||||
FString Backdrop;
|
||||
FString Dialogue;
|
||||
FString Goodbye; // must init to null for binary scripts to work as intended
|
||||
|
||||
FStrifeDialogueReply *Children;
|
||||
FName MenuClassName;
|
||||
FString UserData;
|
||||
};
|
||||
|
||||
// FStrifeDialogueReply holds responses the player can give to the NPC
|
||||
|
@ -44,15 +46,16 @@ struct FStrifeDialogueReply
|
|||
PClassActor *GiveType;
|
||||
int ActionSpecial;
|
||||
int Args[5];
|
||||
int PrintAmount;
|
||||
TArray<FStrifeDialogueItemCheck> ItemCheck;
|
||||
TArray<FStrifeDialogueItemCheck> ItemCheckRequire;
|
||||
TArray<FStrifeDialogueItemCheck> ItemCheckExclude;
|
||||
char *Reply;
|
||||
char *QuickYes;
|
||||
FString Reply;
|
||||
FString QuickYes;
|
||||
FString QuickNo;
|
||||
FString LogString;
|
||||
int NextNode; // index into StrifeDialogues
|
||||
int LogNumber;
|
||||
char *LogString;
|
||||
char *QuickNo;
|
||||
bool NeedsGold;
|
||||
};
|
||||
|
||||
|
|
|
@ -523,7 +523,7 @@ void AActor::PostSerialize()
|
|||
!(flags4 & MF4_NOSKIN) &&
|
||||
state->sprite == GetDefaultByType(player->cls)->SpawnState->sprite)
|
||||
{ // Give player back the skin
|
||||
sprite = skins[player->userinfo.GetSkin()].sprite;
|
||||
sprite = Skins[player->userinfo.GetSkin()].sprite;
|
||||
}
|
||||
if (Speed == 0)
|
||||
{
|
||||
|
@ -667,9 +667,9 @@ bool AActor::SetState (FState *newstate, bool nofunction)
|
|||
// for Dehacked, I would move sprite changing out of the states
|
||||
// altogether, since actors rarely change their sprites after
|
||||
// spawning.
|
||||
if (player != NULL && skins != NULL)
|
||||
if (player != NULL && Skins.Size() > 0)
|
||||
{
|
||||
sprite = skins[player->userinfo.GetSkin()].sprite;
|
||||
sprite = Skins[player->userinfo.GetSkin()].sprite;
|
||||
}
|
||||
else if (newsprite != prevsprite)
|
||||
{
|
||||
|
@ -5399,7 +5399,7 @@ APlayerPawn *P_SpawnPlayer (FPlayerStart *mthing, int playernum, int flags)
|
|||
}
|
||||
|
||||
// [GRB] Reset skin
|
||||
p->userinfo.SkinNumChanged(R_FindSkin (skins[p->userinfo.GetSkin()].name, p->CurrentPlayerClass));
|
||||
p->userinfo.SkinNumChanged(R_FindSkin (Skins[p->userinfo.GetSkin()].Name, p->CurrentPlayerClass));
|
||||
|
||||
if (!(mobj->flags2 & MF2_DONTTRANSLATE))
|
||||
{
|
||||
|
@ -5417,7 +5417,7 @@ APlayerPawn *P_SpawnPlayer (FPlayerStart *mthing, int playernum, int flags)
|
|||
// [RH] Set player sprite based on skin
|
||||
if (!(mobj->flags4 & MF4_NOSKIN))
|
||||
{
|
||||
mobj->sprite = skins[p->userinfo.GetSkin()].sprite;
|
||||
mobj->sprite = Skins[p->userinfo.GetSkin()].sprite;
|
||||
}
|
||||
|
||||
p->DesiredFOV = p->FOV = 90.f;
|
||||
|
|
|
@ -837,7 +837,7 @@ void CopyPlayer(player_t *dst, player_t *src, const char *name)
|
|||
}
|
||||
|
||||
// Validate the skin
|
||||
dst->userinfo.SkinNumChanged(R_FindSkin(skins[dst->userinfo.GetSkin()].name, dst->CurrentPlayerClass));
|
||||
dst->userinfo.SkinNumChanged(R_FindSkin(Skins[dst->userinfo.GetSkin()].Name, dst->CurrentPlayerClass));
|
||||
|
||||
// Make sure the player pawn points to the proper player struct.
|
||||
if (dst->mo != nullptr)
|
||||
|
|
|
@ -4204,7 +4204,6 @@ static void P_Shutdown ()
|
|||
{
|
||||
// [ZZ] delete global event handlers
|
||||
E_Shutdown(false);
|
||||
R_DeinitSpriteData ();
|
||||
P_DeinitKeyMessages ();
|
||||
P_FreeLevelData ();
|
||||
P_FreeExtraLevelData ();
|
||||
|
|
|
@ -74,9 +74,9 @@ DEFINE_ACTION_FUNCTION(FState, GetSpriteTexture)
|
|||
}
|
||||
else
|
||||
{
|
||||
sprframe = &SpriteFrames[sprites[skins[skin].sprite].spriteframes + self->GetFrame()];
|
||||
scalex = skins[skin].Scale.X;
|
||||
scaley = skins[skin].Scale.Y;
|
||||
sprframe = &SpriteFrames[sprites[Skins[skin].sprite].spriteframes + self->GetFrame()];
|
||||
scalex = Skins[skin].Scale.X;
|
||||
scaley = Skins[skin].Scale.Y;
|
||||
}
|
||||
if (numret > 0) ret[0].SetInt(sprframe->Texture[rotation].GetIndex());
|
||||
if (numret > 1) ret[1].SetInt(!!(sprframe->Flip & (1 << rotation)));
|
||||
|
|
|
@ -232,20 +232,21 @@ class USDFParser : public UDMFParserBase
|
|||
// Todo: Finalize
|
||||
if (reply->ItemCheck.Size() > 0)
|
||||
{
|
||||
if (reply->ItemCheck[0].Amount <= 0) reply->NeedsGold = false;
|
||||
reply->PrintAmount = reply->ItemCheck[0].Amount;
|
||||
if (reply->PrintAmount <= 0) reply->NeedsGold = false;
|
||||
}
|
||||
|
||||
reply->Reply = ncopystring(ReplyString);
|
||||
reply->QuickYes = ncopystring(QuickYes);
|
||||
reply->Reply = ReplyString;
|
||||
reply->QuickYes = QuickYes;
|
||||
if (reply->ItemCheck.Size() > 0 && reply->ItemCheck[0].Item != NULL)
|
||||
{
|
||||
reply->QuickNo = ncopystring(QuickNo);
|
||||
reply->QuickNo = QuickNo;
|
||||
}
|
||||
else
|
||||
{
|
||||
reply->QuickNo = NULL;
|
||||
reply->QuickNo = "";
|
||||
}
|
||||
reply->LogString = ncopystring(LogString);
|
||||
reply->LogString = LogString;
|
||||
if(!closeDialog) reply->NextNode *= -1;
|
||||
return true;
|
||||
}
|
||||
|
@ -315,7 +316,14 @@ class USDFParser : public UDMFParserBase
|
|||
break;
|
||||
|
||||
case NAME_Panel:
|
||||
node->Backdrop = TexMan.CheckForTexture (CheckString(key), FTexture::TEX_MiscPatch);
|
||||
node->Backdrop = CheckString(key);
|
||||
break;
|
||||
|
||||
case NAME_Userstring:
|
||||
if (namespace_bits == Zd)
|
||||
{
|
||||
node->UserData = CheckString(key);
|
||||
}
|
||||
break;
|
||||
|
||||
case NAME_Voice:
|
||||
|
@ -373,9 +381,9 @@ class USDFParser : public UDMFParserBase
|
|||
}
|
||||
}
|
||||
}
|
||||
node->SpeakerName = ncopystring(SpeakerName);
|
||||
node->Dialogue = ncopystring(Dialogue);
|
||||
node->Goodbye = ncopystring(Goodbye);
|
||||
node->SpeakerName = SpeakerName;
|
||||
node->Dialogue = Dialogue;
|
||||
node->Goodbye = Goodbye;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -390,6 +398,7 @@ class USDFParser : public UDMFParserBase
|
|||
{
|
||||
PClassActor *type = NULL;
|
||||
int dlgid = -1;
|
||||
FName clsid;
|
||||
unsigned int startpos = StrifeDialogues.Size();
|
||||
|
||||
while (!sc.CheckToken('}'))
|
||||
|
@ -414,6 +423,13 @@ class USDFParser : public UDMFParserBase
|
|||
dlgid = CheckInt(key);
|
||||
}
|
||||
break;
|
||||
|
||||
case NAME_Class:
|
||||
if (namespace_bits == Zd)
|
||||
{
|
||||
clsid = CheckString(key);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -439,6 +455,7 @@ class USDFParser : public UDMFParserBase
|
|||
for(;startpos < StrifeDialogues.Size(); startpos++)
|
||||
{
|
||||
StrifeDialogues[startpos]->SpeakerType = type;
|
||||
StrifeDialogues[startpos]->MenuClassName = clsid;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -164,6 +164,13 @@ FString GetPrintableDisplayName(PClassActor *cls)
|
|||
return cls->DisplayName;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(APlayerPawn, GetPrintableDisplayName)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_CLASS(type, AActor);
|
||||
ACTION_RETURN_STRING(type->DisplayName);
|
||||
}
|
||||
|
||||
bool ValidatePlayerClass(PClassActor *ti, const char *name)
|
||||
{
|
||||
if (ti == NULL)
|
||||
|
@ -578,6 +585,14 @@ void EnumColorSets(PClassActor *cls, TArray<int> *out)
|
|||
qsort(&(*out)[0], out->Size(), sizeof(int), intcmp);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(FPlayerClass, EnumColorSets)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FPlayerClass);
|
||||
PARAM_POINTER(out, TArray<int>);
|
||||
EnumColorSets(self->Type, out);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
|
@ -597,6 +612,14 @@ FPlayerColorSet *GetColorSet(PClassActor *cls, int setnum)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(FPlayerClass, GetColorSetName)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FPlayerClass);
|
||||
PARAM_INT(setnum);
|
||||
auto p = GetColorSet(self->Type, setnum);
|
||||
ACTION_RETURN_INT(p ? p->Name.GetIndex() : 0);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
|
@ -655,6 +678,49 @@ DEFINE_ACTION_FUNCTION(_PlayerInfo, GetNeverSwitch)
|
|||
ACTION_RETURN_BOOL(self->userinfo.GetNeverSwitch());
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_PlayerInfo, GetColor)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(player_t);
|
||||
ACTION_RETURN_INT(self->userinfo.GetColor());
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_PlayerInfo, GetColorSet)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(player_t);
|
||||
ACTION_RETURN_INT(self->userinfo.GetColorSet());
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_PlayerInfo, GetPlayerClassNum)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(player_t);
|
||||
ACTION_RETURN_INT(self->userinfo.GetPlayerClassNum());
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_PlayerInfo, GetSkin)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(player_t);
|
||||
ACTION_RETURN_INT(self->userinfo.GetSkin());
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_PlayerInfo, GetGender)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(player_t);
|
||||
ACTION_RETURN_INT(self->userinfo.GetGender());
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_PlayerInfo, GetAutoaim)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(player_t);
|
||||
ACTION_RETURN_FLOAT(self->userinfo.GetAutoaim());
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_PlayerInfo, GetTeam)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(player_t);
|
||||
ACTION_RETURN_INT(self->userinfo.GetTeam());
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// APlayerPawn
|
||||
|
@ -1228,9 +1294,9 @@ const char *APlayerPawn::GetSoundClass() const
|
|||
if (player != NULL &&
|
||||
(player->mo == NULL || !(player->mo->flags4 &MF4_NOSKIN)) &&
|
||||
(unsigned int)player->userinfo.GetSkin() >= PlayerClasses.Size () &&
|
||||
(size_t)player->userinfo.GetSkin() < numskins)
|
||||
(unsigned)player->userinfo.GetSkin() < Skins.Size())
|
||||
{
|
||||
return skins[player->userinfo.GetSkin()].name;
|
||||
return Skins[player->userinfo.GetSkin()].Name.GetChars();
|
||||
}
|
||||
|
||||
return SoundClass != NAME_None? SoundClass.GetChars() : "player";
|
||||
|
@ -1782,8 +1848,8 @@ void P_CheckPlayerSprite(AActor *actor, int &spritenum, DVector2 &scale)
|
|||
{
|
||||
// Convert from default scale to skin scale.
|
||||
DVector2 defscale = actor->GetDefault()->Scale;
|
||||
scale.X *= skins[player->userinfo.GetSkin()].Scale.X / defscale.X;
|
||||
scale.Y *= skins[player->userinfo.GetSkin()].Scale.Y / defscale.Y;
|
||||
scale.X *= Skins[player->userinfo.GetSkin()].Scale.X / defscale.X;
|
||||
scale.Y *= Skins[player->userinfo.GetSkin()].Scale.Y / defscale.Y;
|
||||
}
|
||||
|
||||
// Set the crouch sprite?
|
||||
|
@ -1794,10 +1860,10 @@ void P_CheckPlayerSprite(AActor *actor, int &spritenum, DVector2 &scale)
|
|||
crouchspriteno = player->mo->crouchsprite;
|
||||
}
|
||||
else if (!(actor->flags4 & MF4_NOSKIN) &&
|
||||
(spritenum == skins[player->userinfo.GetSkin()].sprite ||
|
||||
spritenum == skins[player->userinfo.GetSkin()].crouchsprite))
|
||||
(spritenum == Skins[player->userinfo.GetSkin()].sprite ||
|
||||
spritenum == Skins[player->userinfo.GetSkin()].crouchsprite))
|
||||
{
|
||||
crouchspriteno = skins[player->userinfo.GetSkin()].crouchsprite;
|
||||
crouchspriteno = Skins[player->userinfo.GetSkin()].crouchsprite;
|
||||
}
|
||||
else
|
||||
{ // no sprite -> squash the existing one
|
||||
|
|
|
@ -1171,7 +1171,7 @@ void R_BuildPlayerTranslation (int player)
|
|||
D_GetPlayerColor (player, &h, &s, &v, &colorset);
|
||||
|
||||
R_CreatePlayerTranslation (h, s, v, colorset,
|
||||
&skins[players[player].userinfo.GetSkin()],
|
||||
&Skins[players[player].userinfo.GetSkin()],
|
||||
translationtables[TRANSLATION_Players][player],
|
||||
translationtables[TRANSLATION_PlayersExtra][player],
|
||||
translationtables[TRANSLATION_RainPillar][player]
|
||||
|
@ -1218,9 +1218,9 @@ DEFINE_ACTION_FUNCTION(_Translation, SetPlayerTranslation)
|
|||
|
||||
if (cls != nullptr)
|
||||
{
|
||||
PlayerSkin = R_FindSkin(skins[PlayerSkin].name, int(cls - &PlayerClasses[0]));
|
||||
PlayerSkin = R_FindSkin(Skins[PlayerSkin].Name, int(cls - &PlayerClasses[0]));
|
||||
R_GetPlayerTranslation(PlayerColor, GetColorSet(cls->Type, PlayerColorset),
|
||||
&skins[PlayerSkin], translationtables[tgroup][tnum]);
|
||||
&Skins[PlayerSkin], translationtables[tgroup][tnum]);
|
||||
}
|
||||
ACTION_RETURN_BOOL(true);
|
||||
}
|
||||
|
|
|
@ -30,8 +30,7 @@ struct spriteframewithrotate : public spriteframe_t
|
|||
|
||||
|
||||
// [RH] skin globals
|
||||
FPlayerSkin *skins;
|
||||
size_t numskins;
|
||||
TArray<FPlayerSkin> Skins;
|
||||
BYTE OtherGameSkinRemap[256];
|
||||
PalEntry OtherGameSkinPalette[256];
|
||||
|
||||
|
@ -512,7 +511,7 @@ void R_InitSkins (void)
|
|||
int sndlumps[NUMSKINSOUNDS];
|
||||
char key[65];
|
||||
DWORD intname, crouchname;
|
||||
size_t i;
|
||||
unsigned i;
|
||||
int j, k, base;
|
||||
int lastlump;
|
||||
int aliasid;
|
||||
|
@ -538,7 +537,7 @@ void R_InitSkins (void)
|
|||
i++;
|
||||
for (j = 0; j < NUMSKINSOUNDS; j++)
|
||||
sndlumps[j] = -1;
|
||||
skins[i].namespc = Wads.GetLumpNamespace (base);
|
||||
Skins[i].namespc = Wads.GetLumpNamespace (base);
|
||||
|
||||
FScanner sc(base);
|
||||
intname = 0;
|
||||
|
@ -560,14 +559,13 @@ void R_InitSkins (void)
|
|||
sc.GetString ();
|
||||
if (0 == stricmp (key, "name"))
|
||||
{
|
||||
strncpy (skins[i].name, sc.String, 16);
|
||||
for (j = 0; (size_t)j < i; j++)
|
||||
Skins[i].Name = sc.String;
|
||||
for (j = 0; (unsigned)j < i; j++)
|
||||
{
|
||||
if (stricmp (skins[i].name, skins[j].name) == 0)
|
||||
if (Skins[i].Name.CompareNoCase(Skins[j].Name) == 0)
|
||||
{
|
||||
mysnprintf (skins[i].name, countof(skins[i].name), "skin%d", (int)i);
|
||||
Printf (PRINT_BOLD, "Skin %s duplicated as %s\n",
|
||||
skins[j].name, skins[i].name);
|
||||
Skins[i].Name.Format("skin%u", i);
|
||||
Printf (PRINT_BOLD, "Skin %s duplicated as %s\n", Skins[j].Name.GetChars(), Skins[i].Name.GetChars());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -586,18 +584,16 @@ void R_InitSkins (void)
|
|||
}
|
||||
else if (0 == stricmp (key, "face"))
|
||||
{
|
||||
for (j = 2; j >= 0; j--)
|
||||
skins[i].face[j] = toupper (sc.String[j]);
|
||||
skins[i].face[3] = '\0';
|
||||
Skins[i].Face = FString(sc.String, 3);
|
||||
}
|
||||
else if (0 == stricmp (key, "gender"))
|
||||
{
|
||||
skins[i].gender = D_GenderToInt (sc.String);
|
||||
Skins[i].gender = D_GenderToInt (sc.String);
|
||||
}
|
||||
else if (0 == stricmp (key, "scale"))
|
||||
{
|
||||
skins[i].Scale.X = clamp(atof (sc.String), 1./65536, 256.);
|
||||
skins[i].Scale.Y = skins[i].Scale.X;
|
||||
Skins[i].Scale.X = clamp(atof (sc.String), 1./65536, 256.);
|
||||
Skins[i].Scale.Y = Skins[i].Scale.X;
|
||||
}
|
||||
else if (0 == stricmp (key, "game"))
|
||||
{
|
||||
|
@ -615,7 +611,7 @@ void R_InitSkins (void)
|
|||
if (gameinfo.gametype & GAME_DoomChex)
|
||||
{
|
||||
transtype = PClass::FindActor(NAME_HereticPlayer);
|
||||
skins[i].othergame = true;
|
||||
Skins[i].othergame = true;
|
||||
}
|
||||
else if (gameinfo.gametype != GAME_Heretic)
|
||||
{
|
||||
|
@ -634,7 +630,7 @@ void R_InitSkins (void)
|
|||
if (gameinfo.gametype == GAME_Heretic)
|
||||
{
|
||||
transtype = PClass::FindActor(NAME_DoomPlayer);
|
||||
skins[i].othergame = true;
|
||||
Skins[i].othergame = true;
|
||||
}
|
||||
else if (!(gameinfo.gametype & GAME_DoomChex))
|
||||
{
|
||||
|
@ -659,7 +655,7 @@ void R_InitSkins (void)
|
|||
}
|
||||
else if (key[0] == '*')
|
||||
{ // Player sound replacment (ZDoom extension)
|
||||
int lump = Wads.CheckNumForName (sc.String, skins[i].namespc);
|
||||
int lump = Wads.CheckNumForName (sc.String, Skins[i].namespc);
|
||||
if (lump == -1)
|
||||
{
|
||||
lump = Wads.CheckNumForFullName (sc.String, true, ns_sounds);
|
||||
|
@ -668,11 +664,11 @@ void R_InitSkins (void)
|
|||
{
|
||||
if (stricmp (key, "*pain") == 0)
|
||||
{ // Replace all pain sounds in one go
|
||||
aliasid = S_AddPlayerSound (skins[i].name, skins[i].gender,
|
||||
aliasid = S_AddPlayerSound (Skins[i].Name, Skins[i].gender,
|
||||
playersoundrefs[0], lump, true);
|
||||
for (int l = 3; l > 0; --l)
|
||||
{
|
||||
S_AddPlayerSoundExisting (skins[i].name, skins[i].gender,
|
||||
S_AddPlayerSoundExisting (Skins[i].Name, Skins[i].gender,
|
||||
playersoundrefs[l], aliasid, true);
|
||||
}
|
||||
}
|
||||
|
@ -681,7 +677,7 @@ void R_InitSkins (void)
|
|||
int sndref = S_FindSoundNoHash (key);
|
||||
if (sndref != 0)
|
||||
{
|
||||
S_AddPlayerSound (skins[i].name, skins[i].gender, sndref, lump, true);
|
||||
S_AddPlayerSound (Skins[i].Name, Skins[i].gender, sndref, lump, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -692,7 +688,7 @@ void R_InitSkins (void)
|
|||
{
|
||||
if (stricmp (key, skinsoundnames[j][0]) == 0)
|
||||
{
|
||||
sndlumps[j] = Wads.CheckNumForName (sc.String, skins[i].namespc);
|
||||
sndlumps[j] = Wads.CheckNumForName (sc.String, Skins[i].namespc);
|
||||
if (sndlumps[j] == -1)
|
||||
{ // Replacement not found, try finding it in the global namespace
|
||||
sndlumps[j] = Wads.CheckNumForFullName (sc.String, true, ns_sounds);
|
||||
|
@ -715,7 +711,7 @@ void R_InitSkins (void)
|
|||
{
|
||||
basetype = PClass::FindActor(NAME_HereticPlayer);
|
||||
transtype = PClass::FindActor(NAME_DoomPlayer);
|
||||
skins[i].othergame = true;
|
||||
Skins[i].othergame = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -728,8 +724,8 @@ void R_InitSkins (void)
|
|||
auto transdef = ((APlayerPawn*)GetDefaultByType(transtype));
|
||||
auto basedef = ((APlayerPawn*)GetDefaultByType(basetype));
|
||||
|
||||
skins[i].range0start = transdef->ColorRangeStart;
|
||||
skins[i].range0end = transdef->ColorRangeEnd;
|
||||
Skins[i].range0start = transdef->ColorRangeStart;
|
||||
Skins[i].range0end = transdef->ColorRangeEnd;
|
||||
|
||||
remove = true;
|
||||
for (j = 0; j < (int)PlayerClasses.Size (); j++)
|
||||
|
@ -750,8 +746,8 @@ void R_InitSkins (void)
|
|||
|
||||
if (!remove)
|
||||
{
|
||||
if (skins[i].name[0] == 0)
|
||||
mysnprintf (skins[i].name, countof(skins[i].name), "skin%d", (int)i);
|
||||
if (Skins[i].Name.IsEmpty())
|
||||
Skins[i].Name.Format("skin%u", i);
|
||||
|
||||
// Now collect the sprite frames for this skin. If the sprite name was not
|
||||
// specified, use whatever immediately follows the specifier lump.
|
||||
|
@ -783,7 +779,7 @@ void R_InitSkins (void)
|
|||
}
|
||||
else
|
||||
{
|
||||
skins[i].crouchsprite = -1;
|
||||
Skins[i].crouchsprite = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -806,7 +802,7 @@ void R_InitSkins (void)
|
|||
|
||||
if (spr == 0 && maxframe <= 0)
|
||||
{
|
||||
Printf (PRINT_BOLD, "Skin %s (#%d) has no frames. Removing.\n", skins[i].name, (int)i);
|
||||
Printf (PRINT_BOLD, "Skin %s (#%u) has no frames. Removing.\n", Skins[i].Name.GetChars(), i);
|
||||
remove = true;
|
||||
break;
|
||||
}
|
||||
|
@ -814,16 +810,18 @@ void R_InitSkins (void)
|
|||
Wads.GetLumpName (temp.name, base+1);
|
||||
temp.name[4] = 0;
|
||||
int sprno = (int)sprites.Push (temp);
|
||||
if (spr==0) skins[i].sprite = sprno;
|
||||
else skins[i].crouchsprite = sprno;
|
||||
if (spr==0) Skins[i].sprite = sprno;
|
||||
else Skins[i].crouchsprite = sprno;
|
||||
R_InstallSprite (sprno, sprtemp, maxframe);
|
||||
}
|
||||
}
|
||||
|
||||
if (remove)
|
||||
{
|
||||
if (i < numskins-1)
|
||||
memmove (&skins[i], &skins[i+1], sizeof(skins[0])*(numskins-i-1));
|
||||
if (i < Skins.Size() - 1)
|
||||
{
|
||||
Skins.Delete(i);
|
||||
}
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
|
@ -836,25 +834,25 @@ void R_InitSkins (void)
|
|||
{
|
||||
if (j == 0 || sndlumps[j] != sndlumps[j-1])
|
||||
{
|
||||
aliasid = S_AddPlayerSound (skins[i].name, skins[i].gender,
|
||||
aliasid = S_AddPlayerSound (Skins[i].Name, Skins[i].gender,
|
||||
playersoundrefs[j], sndlumps[j], true);
|
||||
}
|
||||
else
|
||||
{
|
||||
S_AddPlayerSoundExisting (skins[i].name, skins[i].gender,
|
||||
S_AddPlayerSoundExisting (Skins[i].Name, Skins[i].gender,
|
||||
playersoundrefs[j], aliasid, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure face prefix is a full 3 chars
|
||||
if (skins[i].face[1] == 0 || skins[i].face[2] == 0)
|
||||
if (Skins[i].Face.Len() < 3)
|
||||
{
|
||||
skins[i].face[0] = 0;
|
||||
Skins[i].Face = "";
|
||||
}
|
||||
}
|
||||
|
||||
if (numskins > PlayerClasses.Size ())
|
||||
if (Skins.Size() > PlayerClasses.Size ())
|
||||
{ // The sound table may have changed, so rehash it.
|
||||
S_HashSounds ();
|
||||
S_ShrinkPlayerSoundLists ();
|
||||
|
@ -869,9 +867,9 @@ int R_FindSkin (const char *name, int pclass)
|
|||
return pclass;
|
||||
}
|
||||
|
||||
for (unsigned i = PlayerClasses.Size(); i < numskins; i++)
|
||||
for (unsigned i = PlayerClasses.Size(); i < Skins.Size(); i++)
|
||||
{
|
||||
if (strnicmp (skins[i].name, name, 16) == 0)
|
||||
if (Skins[i].Name.CompareNoCase(name) == 0)
|
||||
{
|
||||
if (PlayerClasses[pclass].CheckSkin (i))
|
||||
return i;
|
||||
|
@ -887,8 +885,8 @@ CCMD (skins)
|
|||
{
|
||||
int i;
|
||||
|
||||
for (i = PlayerClasses.Size ()-1; i < (int)numskins; i++)
|
||||
Printf ("% 3d %s\n", i-PlayerClasses.Size ()+1, skins[i].name);
|
||||
for (i = PlayerClasses.Size() - 1; i < (int)Skins.Size(); i++)
|
||||
Printf("% 3d %s\n", i - PlayerClasses.Size() + 1, Skins[i].Name.GetChars());
|
||||
}
|
||||
|
||||
|
||||
|
@ -914,6 +912,7 @@ void R_InitSprites ()
|
|||
{
|
||||
int lump, lastlump;
|
||||
unsigned int i, j;
|
||||
unsigned numskins;
|
||||
|
||||
// [RH] Create a standard translation to map skins between Heretic and Doom
|
||||
if (gameinfo.gametype == GAME_DoomChex)
|
||||
|
@ -934,15 +933,15 @@ void R_InitSprites ()
|
|||
}
|
||||
|
||||
// [RH] Do some preliminary setup
|
||||
if (skins != NULL) delete [] skins;
|
||||
skins = new FPlayerSkin[numskins];
|
||||
memset (skins, 0, sizeof(*skins) * numskins);
|
||||
Skins.Clear();
|
||||
Skins.Resize(numskins);
|
||||
|
||||
for (i = 0; i < numskins; i++)
|
||||
{ // Assume Doom skin by default
|
||||
auto type = ((APlayerPawn*)GetDefaultByType(PlayerClasses[0].Type));
|
||||
skins[i].range0start = type->ColorRangeStart;
|
||||
skins[i].range0end = type->ColorRangeEnd;
|
||||
skins[i].Scale = type->Scale;
|
||||
Skins[i].range0start = type->ColorRangeStart;
|
||||
Skins[i].range0end = type->ColorRangeEnd;
|
||||
Skins[i].Scale = type->Scale;
|
||||
}
|
||||
|
||||
R_InitSpriteDefs ();
|
||||
|
@ -956,33 +955,30 @@ void R_InitSprites ()
|
|||
{
|
||||
auto basetype = ((APlayerPawn*)GetDefaultByType(PlayerClasses[i].Type));
|
||||
|
||||
strcpy (skins[i].name, "Base");
|
||||
Skins[i].Name = "Base";
|
||||
if (basetype->Face == NAME_None)
|
||||
{
|
||||
skins[i].face[0] = 'S';
|
||||
skins[i].face[1] = 'T';
|
||||
skins[i].face[2] = 'F';
|
||||
skins[i].face[3] = '\0';
|
||||
Skins[i].Face = "STF";
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(skins[i].face, basetype->Face);
|
||||
Skins[i].Face = basetype->Face;
|
||||
}
|
||||
skins[i].range0start = basetype->ColorRangeStart;
|
||||
skins[i].range0end = basetype->ColorRangeEnd;
|
||||
skins[i].Scale = basetype->Scale;
|
||||
skins[i].sprite = basetype->SpawnState->sprite;
|
||||
skins[i].namespc = ns_global;
|
||||
Skins[i].range0start = basetype->ColorRangeStart;
|
||||
Skins[i].range0end = basetype->ColorRangeEnd;
|
||||
Skins[i].Scale = basetype->Scale;
|
||||
Skins[i].sprite = basetype->SpawnState->sprite;
|
||||
Skins[i].namespc = ns_global;
|
||||
|
||||
PlayerClasses[i].Skins.Push (i);
|
||||
|
||||
if (memcmp (sprites[skins[i].sprite].name, "PLAY", 4) == 0)
|
||||
if (memcmp (sprites[Skins[i].sprite].name, "PLAY", 4) == 0)
|
||||
{
|
||||
for (j = 0; j < sprites.Size (); j++)
|
||||
{
|
||||
if (memcmp (sprites[j].name, deh.PlayerSprite, 4) == 0)
|
||||
{
|
||||
skins[i].sprite = (int)j;
|
||||
Skins[i].sprite = (int)j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -995,12 +991,14 @@ void R_InitSprites ()
|
|||
gl_InitModels();
|
||||
}
|
||||
|
||||
void R_DeinitSpriteData()
|
||||
{
|
||||
// Free skins
|
||||
if (skins != NULL)
|
||||
{
|
||||
delete[] skins;
|
||||
skins = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
DEFINE_FIELD_NAMED(FPlayerSkin, Name, SkinName);
|
||||
DEFINE_FIELD(FPlayerSkin, Face);
|
||||
DEFINE_FIELD(FPlayerSkin, gender);
|
||||
DEFINE_FIELD(FPlayerSkin, range0start);
|
||||
DEFINE_FIELD(FPlayerSkin, range0end);
|
||||
DEFINE_FIELD(FPlayerSkin, othergame);
|
||||
DEFINE_FIELD(FPlayerSkin, Scale);
|
||||
DEFINE_FIELD(FPlayerSkin, sprite);
|
||||
DEFINE_FIELD(FPlayerSkin, crouchsprite);
|
||||
DEFINE_FIELD(FPlayerSkin, namespc);
|
||||
|
|
|
@ -47,25 +47,23 @@ extern TArray<spriteframe_t> SpriteFrames;
|
|||
class FPlayerSkin
|
||||
{
|
||||
public:
|
||||
char name[17]; // 16 chars + NULL
|
||||
char face[4]; // 3 chars ([MH] + NULL so can use as a C string)
|
||||
BYTE gender; // This skin's gender (not really used)
|
||||
BYTE range0start;
|
||||
BYTE range0end;
|
||||
bool othergame; // [GRB]
|
||||
DVector2 Scale;
|
||||
int sprite;
|
||||
int crouchsprite;
|
||||
int namespc; // namespace for this skin
|
||||
FString Name;
|
||||
FString Face;
|
||||
BYTE gender = 0; // This skin's gender (not really used)
|
||||
BYTE range0start = 0;
|
||||
BYTE range0end = 0;
|
||||
bool othergame = 0; // [GRB]
|
||||
DVector2 Scale = { 1, 1 };
|
||||
int sprite = 0;
|
||||
int crouchsprite = 0;
|
||||
int namespc = 0; // namespace for this skin
|
||||
};
|
||||
|
||||
extern size_t numskins; // [RH]
|
||||
extern FPlayerSkin * skins; // [RH]
|
||||
extern TArray<FPlayerSkin> Skins;
|
||||
|
||||
extern BYTE OtherGameSkinRemap[256];
|
||||
extern PalEntry OtherGameSkinPalette[256];
|
||||
|
||||
void R_InitSprites ();
|
||||
void R_DeinitSpriteData ();
|
||||
|
||||
#endif
|
||||
|
|
|
@ -57,6 +57,8 @@
|
|||
#include "v_video.h"
|
||||
#include "c_bind.h"
|
||||
#include "menu/menu.h"
|
||||
#include "teaminfo.h"
|
||||
#include "r_data/sprites.h"
|
||||
|
||||
static TArray<FPropertyInfo*> properties;
|
||||
static TArray<AFuncDesc> AFTable;
|
||||
|
@ -759,6 +761,14 @@ void InitThingdef()
|
|||
playerclassstruct->Size = sizeof(FPlayerClass);
|
||||
playerclassstruct->Align = alignof(FPlayerClass);
|
||||
|
||||
auto playerskinstruct = NewNativeStruct("PlayerSkin", nullptr);
|
||||
playerskinstruct->Size = sizeof(FPlayerSkin);
|
||||
playerskinstruct->Align = alignof(FPlayerSkin);
|
||||
|
||||
auto teamstruct = NewNativeStruct("Team", nullptr);
|
||||
teamstruct->Size = sizeof(FTeam);
|
||||
teamstruct->Align = alignof(FTeam);
|
||||
|
||||
// set up the lines array in the sector struct. This is a bit messy because the type system is not prepared to handle a pointer to an array of pointers to a native struct even remotely well...
|
||||
// As a result, the size has to be set to something large and arbritrary because it can change between maps. This will need some serious improvement when things get cleaned up.
|
||||
sectorstruct->AddNativeField("lines", NewPointer(NewResizableArray(NewPointer(linestruct, false)), false), myoffsetof(sector_t, Lines), VARF_Native);
|
||||
|
@ -798,6 +808,14 @@ void InitThingdef()
|
|||
PField *plrclsf = new PField("PlayerClasses", plrcls, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&PlayerClasses);
|
||||
Namespaces.GlobalNamespace->Symbols.AddSymbol(plrclsf);
|
||||
|
||||
auto plrskn = NewPointer(NewResizableArray(playerskinstruct), false);
|
||||
PField *plrsknf = new PField("PlayerSkins", plrskn, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&Skins);
|
||||
Namespaces.GlobalNamespace->Symbols.AddSymbol(plrsknf);
|
||||
|
||||
auto teamst = NewPointer(NewResizableArray(teamstruct), false);
|
||||
PField *teamf = new PField("Teams", teamst, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&Teams);
|
||||
Namespaces.GlobalNamespace->Symbols.AddSymbol(teamf);
|
||||
|
||||
auto bindcls = NewNativeStruct("KeyBindings", nullptr);
|
||||
PField *binding = new PField("Bindings", bindcls, VARF_Native | VARF_Static, (intptr_t)&Bindings);
|
||||
Namespaces.GlobalNamespace->Symbols.AddSymbol(binding);
|
||||
|
@ -888,7 +906,13 @@ void InitThingdef()
|
|||
fieldptr = new PField("OptionMenuSettings", NewStruct("FOptionMenuSettings", nullptr), VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&OptionSettings);
|
||||
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
|
||||
|
||||
|
||||
fieldptr = new PField("gametic", TypeSInt32, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&gametic);
|
||||
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
|
||||
|
||||
fieldptr = new PField("demoplayback", TypeSInt32, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&demoplayback);
|
||||
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
|
||||
|
||||
|
||||
// Argh. It sucks when bad hacks need to be supported. WP_NOCHANGE is just a bogus pointer but it used everywhere as a special flag.
|
||||
// It cannot be defined as constant because constants can either be numbers or strings but nothing else, so the only 'solution'
|
||||
// is to create a static variable from it and reference that in the script. Yuck!!!
|
||||
|
@ -1195,10 +1219,20 @@ DEFINE_ACTION_FUNCTION(FStringStruct, Mid)
|
|||
ACTION_RETURN_STRING(s);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(FStringStruct, Len)
|
||||
DEFINE_ACTION_FUNCTION(FStringStruct, Left)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FString);
|
||||
ACTION_RETURN_INT((int)self->Len());
|
||||
PARAM_UINT(len);
|
||||
FString s = self->Left(len);
|
||||
ACTION_RETURN_STRING(s);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(FStringStruct, Truncate)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FString);
|
||||
PARAM_UINT(len);
|
||||
self->Truncate(len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// CharAt and CharCodeAt is how JS does it, and JS is similar here in that it doesn't have char type as int.
|
||||
|
@ -1221,3 +1255,10 @@ DEFINE_ACTION_FUNCTION(FStringStruct, CharCodeAt)
|
|||
ACTION_RETURN_INT(0);
|
||||
ACTION_RETURN_INT((*self)[pos]);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(FStringStruct, Filter)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FString);
|
||||
ACTION_RETURN_STRING(strbin1(*self));
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
#include "doomerrors.h"
|
||||
#include "memarena.h"
|
||||
|
||||
class DObject;
|
||||
|
||||
extern FMemArena ClassDataAllocator;
|
||||
|
||||
#define MAX_RETURNS 8 // Maximum number of results a function called by script code can return
|
||||
|
@ -1028,6 +1030,7 @@ void NullParam(const char *varname);
|
|||
#define PARAM_STATE_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_INT); FState *x = (FState *)StateLabels.GetState(param[p].i, self->GetClass());
|
||||
#define PARAM_STATE_ACTION_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_INT); FState *x = (FState *)StateLabels.GetState(param[p].i, stateowner->GetClass());
|
||||
#define PARAM_POINTER_AT(p,x,type) assert((p) < numparam); assert(param[p].Type == REGT_POINTER); type *x = (type *)param[p].a;
|
||||
#define PARAM_POINTERTYPE_AT(p,x,type) assert((p) < numparam); assert(param[p].Type == REGT_POINTER); type x = (type )param[p].a;
|
||||
#define PARAM_OBJECT_AT(p,x,type) assert((p) < numparam); assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_OBJECT || param[p].a == NULL)); type *x = (type *)param[p].a; assert(x == NULL || x->IsKindOf(RUNTIME_CLASS(type)));
|
||||
#define PARAM_CLASS_AT(p,x,base) assert((p) < numparam); assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_OBJECT || param[p].a == NULL)); base::MetaClass *x = (base::MetaClass *)param[p].a; assert(x == NULL || x->IsDescendantOf(RUNTIME_CLASS(base)));
|
||||
#define PARAM_POINTER_NOT_NULL_AT(p,x,type) assert((p) < numparam); assert(param[p].Type == REGT_POINTER); type *x = (type *)PARAM_NULLCHECK(param[p].a, #x);
|
||||
|
@ -1072,6 +1075,7 @@ void NullParam(const char *varname);
|
|||
#define PARAM_STATE(x) ++paramnum; PARAM_STATE_AT(paramnum,x)
|
||||
#define PARAM_STATE_ACTION(x) ++paramnum; PARAM_STATE_ACTION_AT(paramnum,x)
|
||||
#define PARAM_POINTER(x,type) ++paramnum; PARAM_POINTER_AT(paramnum,x,type)
|
||||
#define PARAM_POINTERTYPE(x,type) ++paramnum; PARAM_POINTERTYPE_AT(paramnum,x,type)
|
||||
#define PARAM_OBJECT(x,type) ++paramnum; PARAM_OBJECT_AT(paramnum,x,type)
|
||||
#define PARAM_CLASS(x,base) ++paramnum; PARAM_CLASS_AT(paramnum,x,base)
|
||||
#define PARAM_POINTER_NOT_NULL(x,type) ++paramnum; PARAM_POINTER_NOT_NULL_AT(paramnum,x,type)
|
||||
|
|
|
@ -1361,22 +1361,19 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n
|
|||
break;
|
||||
|
||||
case AST_DynArrayType:
|
||||
if (allowarraytypes)
|
||||
{
|
||||
auto atype = static_cast<ZCC_DynArrayType *>(ztype);
|
||||
auto ftype = DetermineType(outertype, field, name, atype->ElementType, false, true);
|
||||
if (ftype->GetRegType() == REGT_NIL || ftype->GetRegCount() > 1)
|
||||
{
|
||||
auto atype = static_cast<ZCC_DynArrayType *>(ztype);
|
||||
auto ftype = DetermineType(outertype, field, name, atype->ElementType, false, true);
|
||||
if (ftype->GetRegType() == REGT_NIL || ftype->GetRegCount() > 1)
|
||||
{
|
||||
Error(field, "%s: Base type for dynamic array types nust be integral, but got %s", name.GetChars(), ftype->DescriptiveName());
|
||||
}
|
||||
else
|
||||
{
|
||||
retval = NewDynArray(ftype);
|
||||
}
|
||||
break;
|
||||
Error(field, "%s: Base type for dynamic array types nust be integral, but got %s", name.GetChars(), ftype->DescriptiveName());
|
||||
}
|
||||
else
|
||||
{
|
||||
retval = NewDynArray(ftype);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
case AST_ClassType:
|
||||
{
|
||||
auto ctype = static_cast<ZCC_ClassType *>(ztype);
|
||||
|
@ -2135,7 +2132,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
|
|||
{
|
||||
auto type = DetermineType(c->Type(), p, f->Name, p->Type, false, false);
|
||||
int flags = 0;
|
||||
if (type->IsA(RUNTIME_CLASS(PStruct)) && type != TypeVector2 && type != TypeVector3)
|
||||
if ((type->IsA(RUNTIME_CLASS(PStruct)) && type != TypeVector2 && type != TypeVector3) || type->IsA(RUNTIME_CLASS(PDynArray)))
|
||||
{
|
||||
// Structs are being passed by pointer, but unless marked 'out' that pointer must be readonly.
|
||||
type = NewPointer(type /*, !(p->Flags & ZCC_Out)*/);
|
||||
|
|
|
@ -333,3 +333,6 @@ CCMD (teamlist)
|
|||
|
||||
Printf ("End of team list.\n");
|
||||
}
|
||||
|
||||
|
||||
DEFINE_FIELD_NAMED(FTeam, m_Name, mName)
|
|
@ -63,7 +63,9 @@ private:
|
|||
void ParseTeamDefinition (FScanner &Scan);
|
||||
void ClearTeams ();
|
||||
|
||||
public: // needed for script access.
|
||||
FString m_Name;
|
||||
private:
|
||||
int m_iPlayerColor;
|
||||
FString m_TextColor;
|
||||
FString m_Logo;
|
||||
|
|
|
@ -399,6 +399,20 @@ void DCanvas::Dim (PalEntry color, float damount, int x1, int y1, int w, int h)
|
|||
}
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_Screen, Dim)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_INT(color);
|
||||
PARAM_FLOAT(amount);
|
||||
PARAM_INT(x1);
|
||||
PARAM_INT(y1);
|
||||
PARAM_INT(w);
|
||||
PARAM_INT(h);
|
||||
screen->Dim(color, float(amount), x1, y1, w, h);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// DCanvas :: GetScreenshotBuffer
|
||||
|
|
|
@ -100,7 +100,4 @@ const char *GetVersionString();
|
|||
#endif
|
||||
|
||||
|
||||
// The maximum length of one save game description for the menus.
|
||||
#define SAVESTRINGSIZE 24
|
||||
|
||||
#endif //__VERSION_H__
|
||||
|
|
|
@ -9,16 +9,21 @@
|
|||
|
||||
#include "zscript/menu/menuitembase.txt"
|
||||
#include "zscript/menu/menu.txt"
|
||||
#include "zscript/menu/messagebox.txt"
|
||||
#include "zscript/menu/listmenu.txt"
|
||||
#include "zscript/menu/listmenuitems.txt"
|
||||
#include "zscript/menu/optionmenu.txt"
|
||||
#include "zscript/menu/optionmenuitems.txt"
|
||||
#include "zscript/menu/colorpickermenu.txt"
|
||||
#include "zscript/menu/joystickmenu.txt"
|
||||
#include "zscript/menu/loadsavemenu.txt"
|
||||
#include "zscript/menu/playermenu.txt"
|
||||
#include "zscript/menu/playerdisplay.txt"
|
||||
#include "zscript/menu/playercontrols.txt"
|
||||
#include "zscript/menu/textentermenu.txt"
|
||||
#include "zscript/menu/videomenu.txt"
|
||||
#include "zscript/menu/readthis.txt"
|
||||
#include "zscript/menu/conversationmenu.txt"
|
||||
|
||||
#include "zscript/inventory/inventory.txt"
|
||||
#include "zscript/inventory/inv_misc.txt"
|
||||
|
|
|
@ -158,15 +158,11 @@ enum DrawTextureTags
|
|||
|
||||
struct Screen native
|
||||
{
|
||||
int CleanWidth, CleanHeight;
|
||||
int CleanXFac, CleanYFac;
|
||||
int CleanWidth_1, CleanHeight_1;
|
||||
int CleanXFac_1, CleanYFac_1;
|
||||
|
||||
native static Color PaletteColor(int index);
|
||||
native static int GetWidth();
|
||||
native static int GetHeight();
|
||||
native static void Clear(int left, int top, int right, int bottom, Color color, int palcolor = -1);
|
||||
native static void Dim(Color col, double amount, int x, int y, int w, int h);
|
||||
|
||||
native static void DrawHUDTexture(TextureID tex, double x, double y);
|
||||
native static vararg void DrawTexture(TextureID tex, bool animate, double x, double y, ...);
|
||||
|
@ -175,13 +171,6 @@ struct Screen native
|
|||
native static void DrawFrame(int x, int y, int w, int h);
|
||||
}
|
||||
|
||||
class BrokenLines : Object native
|
||||
{
|
||||
native int Count();
|
||||
native int StringWidth(int line);
|
||||
native String StringAt(int line);
|
||||
}
|
||||
|
||||
struct Font native
|
||||
{
|
||||
enum EColorRange
|
||||
|
@ -252,7 +241,7 @@ struct Font native
|
|||
native static int FindFontColor(Name color);
|
||||
native static Font FindFont(Name fontname);
|
||||
native static Font GetFont(Name fontname);
|
||||
native static BrokenLines BreakLines(String text, int maxlen);
|
||||
native BrokenLines BreakLines(String text, int maxlen);
|
||||
}
|
||||
|
||||
struct Translation
|
||||
|
@ -309,6 +298,8 @@ struct GameInfoStruct native
|
|||
native String ArmorIcon1;
|
||||
native String ArmorIcon2;
|
||||
native int gametype;
|
||||
native bool norandomplayerclass;
|
||||
native Array<Name> infoPages;
|
||||
}
|
||||
|
||||
class Object native
|
||||
|
@ -335,6 +326,13 @@ class Object native
|
|||
virtual void OnDestroy() {}
|
||||
}
|
||||
|
||||
class BrokenLines : Object native
|
||||
{
|
||||
native int Count();
|
||||
native int StringWidth(int line);
|
||||
native String StringAt(int line);
|
||||
}
|
||||
|
||||
class Thinker : Object native
|
||||
{
|
||||
enum EStatnums
|
||||
|
@ -439,6 +437,7 @@ struct LevelLocals native
|
|||
native readonly String MapName;
|
||||
native String NextMap;
|
||||
native String NextSecretMap;
|
||||
native String F1Pic;
|
||||
native readonly int maptype;
|
||||
native readonly String Music;
|
||||
native readonly int musicorder;
|
||||
|
@ -464,6 +463,7 @@ struct LevelLocals native
|
|||
native bool nomonsters;
|
||||
native bool frozen;
|
||||
native bool infinite_flight;
|
||||
native bool no_dlg_freeze;
|
||||
// level_info_t *info cannot be done yet.
|
||||
|
||||
native String GetUDMFString(int type, int index, Name key);
|
||||
|
@ -580,10 +580,12 @@ struct StringStruct native
|
|||
native vararg void AppendFormat(String fmt, ...);
|
||||
|
||||
native void Replace(String pattern, String replacement);
|
||||
native String Left(int len);
|
||||
native String Mid(int pos = 0, int len = 2147483647);
|
||||
native int Len();
|
||||
native void Truncate(int newlen);
|
||||
native String CharAt(int pos);
|
||||
native int CharCodeAt(int pos);
|
||||
native String Filter();
|
||||
}
|
||||
|
||||
class Floor : Thinker native
|
||||
|
|
516
wadsrc/static/zscript/menu/conversationmenu.txt
Normal file
516
wadsrc/static/zscript/menu/conversationmenu.txt
Normal file
|
@ -0,0 +1,516 @@
|
|||
/*
|
||||
** conversationmenu.txt
|
||||
** The Strife dialogue display
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2010-2017 Christoph Oelckers
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
struct StrifeDialogueNode native
|
||||
{
|
||||
native Class<Actor> DropType;
|
||||
native int ThisNodeNum;
|
||||
native int ItemCheckNode;
|
||||
|
||||
native Class<Actor> SpeakerType;
|
||||
native String SpeakerName;
|
||||
native Sound SpeakerVoice;
|
||||
native String Backdrop;
|
||||
native String Dialogue;
|
||||
native String Goodbye;
|
||||
|
||||
native StrifeDialogueReply Children;
|
||||
}
|
||||
|
||||
// FStrifeDialogueReply holds responses the player can give to the NPC
|
||||
struct StrifeDialogueReply native
|
||||
{
|
||||
native StrifeDialogueReply Next;
|
||||
native Class<Actor> GiveType;
|
||||
native int ActionSpecial;
|
||||
native int Args[5];
|
||||
native int PrintAmount;
|
||||
native String Reply;
|
||||
native String QuickYes;
|
||||
native String QuickNo;
|
||||
native String LogString;
|
||||
native int NextNode; // index into StrifeDialogues
|
||||
native int LogNumber;
|
||||
native bool NeedsGold;
|
||||
|
||||
native bool ShouldSkipReply(PlayerInfo player);
|
||||
}
|
||||
|
||||
|
||||
class ConversationMenu : Menu
|
||||
{
|
||||
String mSpeaker;
|
||||
BrokenLines mDialogueLines;
|
||||
Array<String> mResponseLines;
|
||||
Array<uint> mResponses;
|
||||
bool mShowGold;
|
||||
StrifeDialogueNode mCurNode;
|
||||
int mYpos;
|
||||
PlayerInfo mPlayer;
|
||||
int mSelection;
|
||||
int ConversationPauseTic;
|
||||
|
||||
int SpeechWidth;
|
||||
int ReplyWidth;
|
||||
|
||||
native static void SendConversationReply(int node, int reply);
|
||||
|
||||
const NUM_RANDOM_LINES = 10;
|
||||
const NUM_RANDOM_GOODBYES = 3;
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// returns the y position of the replies boy for positioning the terminal response.
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
virtual int Init(StrifeDialogueNode CurNode, PlayerInfo player, int activereply)
|
||||
{
|
||||
mCurNode = CurNode;
|
||||
mPlayer = player;
|
||||
mShowGold = false;
|
||||
ConversationPauseTic = gametic + 20;
|
||||
DontDim = true;
|
||||
|
||||
ReplyWidth = 320-50-10;
|
||||
SpeechWidth = screen.GetWidth()/CleanXfac - 24*2;
|
||||
|
||||
FormatSpeakerMessage();
|
||||
return FormatReplies(activereply);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
virtual int FormatReplies(int activereply)
|
||||
{
|
||||
mSelection = -1;
|
||||
|
||||
StrifeDialogueReply reply;
|
||||
int r = -1;
|
||||
int i = 1,j;
|
||||
for (reply = mCurNode.Children; reply != NULL; reply = reply.Next)
|
||||
{
|
||||
r++;
|
||||
if (reply.ShouldSkipReply(mPlayer))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (activereply == r) mSelection = i - 1;
|
||||
|
||||
mShowGold |= reply.NeedsGold;
|
||||
|
||||
let ReplyText = Stringtable.Localize(reply.Reply);
|
||||
if (reply.NeedsGold) ReplyText.AppendFormat(" for %u", reply.PrintAmount);
|
||||
|
||||
let ReplyLines = SmallFont.BreakLines (ReplyText, ReplyWidth);
|
||||
|
||||
mResponses.Push(mResponseLines.Size());
|
||||
for (j = 0; j < ReplyLines.Count(); ++j)
|
||||
{
|
||||
mResponseLines.Push(ReplyLines.StringAt(j));
|
||||
}
|
||||
|
||||
++i;
|
||||
ReplyLines.Destroy();
|
||||
}
|
||||
if (mSelection == -1)
|
||||
{
|
||||
mSelection = r < activereply ? r + 1 : 0;
|
||||
}
|
||||
let goodbyestr = mCurNode.Goodbye;
|
||||
if (goodbyestr.Length() == 0)
|
||||
{
|
||||
goodbyestr = String.Format("$TXT_RANDOMGOODBYE_%d", Random[RandomSpeech](1, NUM_RANDOM_GOODBYES));
|
||||
}
|
||||
else if (goodbyestr.Left(7) == "RANDOM_")
|
||||
{
|
||||
goodbyestr = String.Format("$TXT_%s_%02d", goodbyestr, Random[RandomSpeech](1, NUM_RANDOM_LINES));
|
||||
}
|
||||
goodbyestr = Stringtable.Localize(goodbyestr);
|
||||
if (goodbyestr.Length() == 0 || goodbyestr.CharAt(0) == "$") goodbyestr = "Bye.";
|
||||
mResponses.Push(mResponseLines.Size());
|
||||
mResponseLines.Push(goodbyestr);
|
||||
|
||||
// Determine where the top of the reply list should be positioned.
|
||||
mYpos = MIN (140, 192 - mResponseLines.Size() * OptionMenuSettings.mLinespacing);
|
||||
i = 44 + mResponseLines.Size() * OptionMenuSettings.mLinespacing;
|
||||
if (mYpos - 100 < i - screen.GetHeight() / CleanYfac / 2)
|
||||
{
|
||||
mYpos = i - screen.GetHeight() / CleanYfac / 2 + 100;
|
||||
}
|
||||
|
||||
if (mSelection >= mResponses.Size())
|
||||
{
|
||||
mSelection = mResponses.Size() - 1;
|
||||
}
|
||||
return mYpos;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
virtual void FormatSpeakerMessage()
|
||||
{
|
||||
// Format the speaker's message.
|
||||
String toSay = mCurNode.Dialogue;
|
||||
if (toSay.Left(7) == "RANDOM_")
|
||||
{
|
||||
let dlgtext = String.Format("$TXT_%s_%02d", toSay, random[RandomSpeech](1, NUM_RANDOM_LINES));
|
||||
toSay = Stringtable.Localize(dlgtext);
|
||||
if (toSay.CharAt(0) == "$") toSay = Stringtable.Localize("$TXT_GOAWAY");
|
||||
}
|
||||
else
|
||||
{
|
||||
// handle string table replacement
|
||||
toSay = Stringtable.Localize(toSay);
|
||||
}
|
||||
if (toSay.Length() == 0)
|
||||
{
|
||||
toSay = ".";
|
||||
}
|
||||
mDialogueLines = SmallFont.BreakLines(toSay, SpeechWidth);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override void OnDestroy()
|
||||
{
|
||||
mDialogueLines.Destroy();
|
||||
SetMusicVolume (1);
|
||||
Super.OnDestroy();
|
||||
}
|
||||
|
||||
protected int GetReplyNum()
|
||||
{
|
||||
// This is needed because mSelection represents the replies currently being displayed which will
|
||||
// not match up with what's supposed to be selected if there are any hidden/skipped replies. [FishyClockwork]
|
||||
let reply = mCurNode.Children;
|
||||
int replynum = mSelection;
|
||||
for (int i = 0; i <= mSelection && reply != null; reply = reply.Next)
|
||||
{
|
||||
if (reply.ShouldSkipReply(mPlayer))
|
||||
replynum++;
|
||||
else
|
||||
i++;
|
||||
}
|
||||
return replynum;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool MenuEvent(int mkey, bool fromcontroller)
|
||||
{
|
||||
if (demoplayback)
|
||||
{ // During demo playback, don't let the user do anything besides close this menu.
|
||||
if (mkey == MKEY_Back)
|
||||
{
|
||||
Close();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (mkey == MKEY_Up)
|
||||
{
|
||||
if (--mSelection < 0) mSelection = mResponses.Size() - 1;
|
||||
return true;
|
||||
}
|
||||
else if (mkey == MKEY_Down)
|
||||
{
|
||||
if (++mSelection >= mResponses.Size()) mSelection = 0;
|
||||
return true;
|
||||
}
|
||||
else if (mkey == MKEY_Back)
|
||||
{
|
||||
SendConversationReply(-1, GetReplyNum());
|
||||
Close();
|
||||
return true;
|
||||
}
|
||||
else if (mkey == MKEY_Enter)
|
||||
{
|
||||
int replynum = GetReplyNum();
|
||||
if (mSelection >= mResponses.Size())
|
||||
{
|
||||
SendConversationReply(-2, replynum);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Send dialogue and reply numbers across the wire.
|
||||
SendConversationReply(mCurNode.ThisNodeNum, replynum);
|
||||
}
|
||||
Close();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool MouseEvent(int type, int x, int y)
|
||||
{
|
||||
int sel = -1;
|
||||
int fh = OptionMenuSettings.mLinespacing;
|
||||
|
||||
// convert x/y from screen to virtual coordinates, according to CleanX/Yfac use in DrawTexture
|
||||
x = ((x - (screen.GetWidth() / 2)) / CleanXfac) + 160;
|
||||
y = ((y - (screen.GetHeight() / 2)) / CleanYfac) + 100;
|
||||
|
||||
if (x >= 24 && x <= 320-24 && y >= mYpos && y < mYpos + fh * mResponseLines.Size())
|
||||
{
|
||||
sel = (y - mYpos) / fh;
|
||||
for(int i = 0; i < mResponses.Size(); i++)
|
||||
{
|
||||
if (mResponses[i] > sel)
|
||||
{
|
||||
sel = i-1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sel != -1 && sel != mSelection)
|
||||
{
|
||||
//S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
|
||||
}
|
||||
mSelection = sel;
|
||||
if (type == MOUSE_Release)
|
||||
{
|
||||
return MenuEvent(MKEY_Enter, true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool Responder(InputEventData ev)
|
||||
{
|
||||
if (demoplayback)
|
||||
{ // No interaction during demo playback
|
||||
return false;
|
||||
}
|
||||
if (ev.type == InputEventData.GUI_Event && ev.subtype == InputEventData.GUI_Char && ev.data1 >= 48 && ev.data1 <= 57)
|
||||
{ // Activate an item of type numberedmore (dialogue only)
|
||||
mSelection = ev.data1 == 48 ? 9 : ev.data1 - 49;
|
||||
return MenuEvent(MKEY_Enter, false);
|
||||
}
|
||||
return Super.Responder(ev);
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// Draw the backdrop, returns true if the text background should be dimmed
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
virtual bool DrawBackdrop()
|
||||
{
|
||||
let tex = TexMan.CheckForTexture (mCurNode.Backdrop, TexMan.Type_MiscPatch);
|
||||
if (tex.isValid())
|
||||
{
|
||||
screen.DrawTexture(tex, false, 0, 0, DTA_320x200, true);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// Draw the speaker text
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
virtual void DrawSpeakerText(bool dimbg)
|
||||
{
|
||||
String speakerName;
|
||||
int linesize = OptionMenuSettings.mLinespacing * CleanYfac;
|
||||
int cnt = mDialogueLines.Count();
|
||||
|
||||
// Who is talking to you?
|
||||
if (mCurNode.SpeakerName.Length() > 0)
|
||||
{
|
||||
speakerName = Stringtable.Localize(mCurNode.SpeakerName);
|
||||
}
|
||||
else
|
||||
{
|
||||
speakerName = players[consoleplayer].ConversationNPC.GetTag("Person");
|
||||
}
|
||||
|
||||
|
||||
// Dim the screen behind the dialogue (but only if there is no backdrop).
|
||||
if (dimbg)
|
||||
{
|
||||
int x = 14 * screen.GetWidth() / 320;
|
||||
int y = 13 * screen.GetHeight() / 200;
|
||||
int w = 294 * screen.GetWidth() / 320;
|
||||
int h = linesize * cnt + 6 * CleanYfac;
|
||||
if (speakerName.Length() > 0) h += linesize * 3 / 2;
|
||||
screen.Dim(0, 0.45f, x, y, w, h);
|
||||
}
|
||||
|
||||
int x = 16 * screen.GetWidth() / 320;
|
||||
int y = 16 * screen.GetHeight() / 200;
|
||||
|
||||
if (speakerName.Length() > 0)
|
||||
{
|
||||
screen.DrawText(SmallFont, Font.CR_WHITE, x, y, speakerName, DTA_CleanNoMove, true);
|
||||
y += linesize * 3 / 2;
|
||||
}
|
||||
x = 24 * screen.GetWidth() / 320;
|
||||
for (int i = 0; i < cnt; ++i)
|
||||
{
|
||||
screen.DrawText(SmallFont, Font.CR_UNTRANSLATED, x, y, mDialogueLines.StringAt(i), DTA_CleanNoMove, true);
|
||||
y += linesize;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// Draw the replies
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
virtual void DrawReplies()
|
||||
{
|
||||
// Dim the screen behind the PC's choices.
|
||||
screen.Dim(0, 0.45, (24 - 160) * CleanXfac + screen.GetWidth() / 2, (mYpos - 2 - 100) * CleanYfac + screen.GetHeight() / 2,
|
||||
272 * CleanXfac, MIN(mResponseLines.Size() * OptionMenuSettings.mLinespacing + 4, 200 - mYpos) * CleanYfac);
|
||||
|
||||
int y = mYpos;
|
||||
int fontheight = OptionMenuSettings.mLinespacing;
|
||||
|
||||
int response = 0;
|
||||
for (int i = 0; i < mResponseLines.Size(); i++)
|
||||
{
|
||||
int width = SmallFont.StringWidth(mResponseLines[i]);
|
||||
int x = 64;
|
||||
|
||||
screen.DrawText(SmallFont, Font.CR_GREEN, x, y, mResponseLines[i], DTA_Clean, true);
|
||||
|
||||
if (i == mResponses[response])
|
||||
{
|
||||
String tbuf;
|
||||
|
||||
response++;
|
||||
tbuf = String.Format("%d.", response);
|
||||
x = 50 - SmallFont.StringWidth(tbuf);
|
||||
screen.DrawText(SmallFont, Font.CR_GREY, x, y, tbuf, DTA_Clean, true);
|
||||
|
||||
if (response == mSelection + 1)
|
||||
{
|
||||
int colr = ((MenuTime() % 8) < 4) || GetCurrentMenu() != self ? Font.CR_RED : Font.CR_GREY;
|
||||
|
||||
x = (50 + 3 - 160) * CleanXfac + screen.GetWidth() / 2;
|
||||
int yy = (y + fontheight / 2 - 5 - 100) * CleanYfac + screen.GetHeight() / 2;
|
||||
screen.DrawText(ConFont, colr, x, yy, "\xd", DTA_CellX, 8 * CleanXfac, DTA_CellY, 8 * CleanYfac);
|
||||
}
|
||||
}
|
||||
y += fontheight;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void DrawGold()
|
||||
{
|
||||
if (mShowGold)
|
||||
{
|
||||
let coin = players[consoleplayer].ConversationPC.FindInventory("Coin");
|
||||
let icon = GetDefaultByType("Coin").Icon;
|
||||
let goldstr = String.Format("%d", coin != NULL ? coin.Amount : 0);
|
||||
screen.DrawText(SmallFont, Font.CR_GRAY, 21, 191, goldstr, DTA_320x200, true, DTA_FillColor, 0, DTA_Alpha, HR_SHADOW);
|
||||
screen.DrawTexture(icon, false, 3, 190, DTA_320x200, true, DTA_FillColor, 0, DTA_Alpha, HR_SHADOW);
|
||||
screen.DrawText(SmallFont, Font.CR_GRAY, 20, 190, goldstr, DTA_320x200, true);
|
||||
screen.DrawTexture(icon, false, 2, 189, DTA_320x200, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// DrawConversationMenu
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
override void Drawer()
|
||||
{
|
||||
if (mCurNode == NULL)
|
||||
{
|
||||
Close ();
|
||||
return;
|
||||
}
|
||||
|
||||
bool dimbg = DrawBackdrop();
|
||||
DrawSpeakerText(dimbg);
|
||||
DrawReplies();
|
||||
DrawGold();
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
override void Ticker()
|
||||
{
|
||||
// [CW] Freeze the game depending on MAPINFO options.
|
||||
if (ConversationPauseTic < gametic && !multiplayer && !level.no_dlg_freeze)
|
||||
{
|
||||
menuactive = Menu.On;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -40,14 +40,14 @@ class ListMenuDescriptor : MenuDescriptor native
|
|||
//
|
||||
//=============================================================================
|
||||
|
||||
class ListMenu : Menu native
|
||||
class ListMenu : Menu
|
||||
{
|
||||
native ListMenuDescriptor mDesc;
|
||||
native MenuItemBase mFocusControl;
|
||||
ListMenuDescriptor mDesc;
|
||||
MenuItemBase mFocusControl;
|
||||
|
||||
virtual void Init(Menu parent = NULL, ListMenuDescriptor desc = NULL)
|
||||
{
|
||||
mParentMenu = parent;
|
||||
Super.Init(parent);
|
||||
mDesc = desc;
|
||||
if (desc.mCenter)
|
||||
{
|
||||
|
@ -76,7 +76,13 @@ class ListMenu : Menu native
|
|||
}
|
||||
}
|
||||
|
||||
MenuItemBase GetItem(Name name)
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
ListMenuItem GetItem(Name name)
|
||||
{
|
||||
for(int i = 0; i < mDesc.mItems.Size(); i++)
|
||||
{
|
||||
|
@ -86,12 +92,173 @@ class ListMenu : Menu native
|
|||
return NULL;
|
||||
}
|
||||
|
||||
//bool Responder (InputEventData ev);
|
||||
//bool MenuEvent (int mkey, bool fromcontroller);
|
||||
//bool MouseEvent(int type, int x, int y);
|
||||
//void Ticker ();
|
||||
//void Drawer ();
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool Responder (InputEventData ev)
|
||||
{
|
||||
if (ev.type == InputEventData.GUI_Event)
|
||||
{
|
||||
if (ev.subtype == InputEventData.GUI_KeyDown)
|
||||
{
|
||||
// tolower
|
||||
int ch = ev.data1;
|
||||
ch = ch >= 65 && ch <91? ch + 32 : ch;
|
||||
|
||||
for(int i = mDesc.mSelectedItem + 1; i < mDesc.mItems.Size(); i++)
|
||||
{
|
||||
if (mDesc.mItems[i].CheckHotkey(ch))
|
||||
{
|
||||
mDesc.mSelectedItem = i;
|
||||
MenuSound("menu/cursor");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for(int i = 0; i < mDesc.mSelectedItem; i++)
|
||||
{
|
||||
if (mDesc.mItems[i].CheckHotkey(ch))
|
||||
{
|
||||
mDesc.mSelectedItem = i;
|
||||
MenuSound("menu/cursor");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Super.Responder(ev);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool MenuEvent (int mkey, bool fromcontroller)
|
||||
{
|
||||
int oldSelect = mDesc.mSelectedItem;
|
||||
int startedAt = mDesc.mSelectedItem;
|
||||
if (startedAt < 0) startedAt = 0;
|
||||
|
||||
switch (mkey)
|
||||
{
|
||||
case MKEY_Up:
|
||||
do
|
||||
{
|
||||
if (--mDesc.mSelectedItem < 0) mDesc.mSelectedItem = mDesc.mItems.Size()-1;
|
||||
}
|
||||
while (!mDesc.mItems[mDesc.mSelectedItem].Selectable() && mDesc.mSelectedItem != startedAt);
|
||||
if (mDesc.mSelectedItem == startedAt) mDesc.mSelectedItem = oldSelect;
|
||||
MenuSound("menu/cursor");
|
||||
return true;
|
||||
|
||||
case MKEY_Down:
|
||||
do
|
||||
{
|
||||
if (++mDesc.mSelectedItem >= mDesc.mItems.Size()) mDesc.mSelectedItem = 0;
|
||||
}
|
||||
while (!mDesc.mItems[mDesc.mSelectedItem].Selectable() && mDesc.mSelectedItem != startedAt);
|
||||
if (mDesc.mSelectedItem == startedAt) mDesc.mSelectedItem = oldSelect;
|
||||
MenuSound("menu/cursor");
|
||||
return true;
|
||||
|
||||
case MKEY_Enter:
|
||||
if (mDesc.mSelectedItem >= 0 && mDesc.mItems[mDesc.mSelectedItem].Activate())
|
||||
{
|
||||
MenuSound("menu/choose");
|
||||
}
|
||||
return true;
|
||||
|
||||
default:
|
||||
return Super.MenuEvent(mkey, fromcontroller);
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool MouseEvent(int type, int x, int y)
|
||||
{
|
||||
int sel = -1;
|
||||
|
||||
// convert x/y from screen to virtual coordinates, according to CleanX/Yfac use in DrawTexture
|
||||
x = ((x - (screen.GetWidth() / 2)) / CleanXfac) + 160;
|
||||
y = ((y - (screen.GetHeight() / 2)) / CleanYfac) + 100;
|
||||
|
||||
if (mFocusControl != NULL)
|
||||
{
|
||||
mFocusControl.MouseEvent(type, x, y);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((mDesc.mWLeft <= 0 || x > mDesc.mWLeft) &&
|
||||
(mDesc.mWRight <= 0 || x < mDesc.mWRight))
|
||||
{
|
||||
for(int i=0;i<mDesc.mItems.Size(); i++)
|
||||
{
|
||||
if (mDesc.mItems[i].CheckCoordinate(x, y))
|
||||
{
|
||||
if (i != mDesc.mSelectedItem)
|
||||
{
|
||||
//MenuSound("menu/cursor");
|
||||
}
|
||||
mDesc.mSelectedItem = i;
|
||||
mDesc.mItems[i].MouseEvent(type, x, y);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mDesc.mSelectedItem = -1;
|
||||
return Super.MouseEvent(type, x, y);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override void Ticker ()
|
||||
{
|
||||
Super.Ticker();
|
||||
for(int i=0;i<mDesc.mItems.Size(); i++)
|
||||
{
|
||||
mDesc.mItems[i].Ticker();
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override void Drawer ()
|
||||
{
|
||||
for(int i=0;i<mDesc.mItems.Size(); i++)
|
||||
{
|
||||
if (mDesc.mItems[i].mEnabled) mDesc.mItems[i].Drawer(mDesc.mSelectedItem == i);
|
||||
}
|
||||
if (mDesc.mSelectedItem >= 0 && mDesc.mSelectedItem < mDesc.mItems.Size())
|
||||
mDesc.mItems[mDesc.mSelectedItem].DrawSelector(mDesc.mSelectOfsX, mDesc.mSelectOfsY, mDesc.mSelector);
|
||||
Super.Drawer();
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override void SetFocus(MenuItemBase fc)
|
||||
{
|
||||
mFocusControl = fc;
|
||||
|
@ -106,3 +273,4 @@ class ListMenu : Menu native
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ class ListMenuItem : MenuItemBase
|
|||
}
|
||||
else
|
||||
{
|
||||
screen.DrawTexture (tex, mXpos + xofs, mYpos + yofs, DTA_Clean, true);
|
||||
screen.DrawTexture (tex, true, mXpos + xofs, mYpos + yofs, DTA_Clean, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
577
wadsrc/static/zscript/menu/loadsavemenu.txt
Normal file
577
wadsrc/static/zscript/menu/loadsavemenu.txt
Normal file
|
@ -0,0 +1,577 @@
|
|||
/*
|
||||
** loacpp
|
||||
** The load game and save game menus
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2001-2010 Randy Heit
|
||||
** Copyright 2010-2017 Christoph Oelckers
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
|
||||
struct SaveGameNode native
|
||||
{
|
||||
native String SaveTitle;
|
||||
native String Filename;
|
||||
native bool bOldVersion;
|
||||
native bool bMissingWads;
|
||||
native bool bNoDelete;
|
||||
}
|
||||
|
||||
struct SavegameManager native
|
||||
{
|
||||
native int WindowSize;
|
||||
native SaveGameNode quickSaveSlot;
|
||||
|
||||
native static SavegameManager GetManager();
|
||||
native void ReadSaveStrings();
|
||||
native void UnloadSaveData();
|
||||
|
||||
native int RemoveSaveSlot(int index);
|
||||
native void LoadSavegame(int Selected);
|
||||
native void DoSave(int Selected, String savegamestring);
|
||||
native int ExtractSaveData(int index);
|
||||
native void ClearSaveStuff();
|
||||
native bool DrawSavePic(int x, int y, int w, int h);
|
||||
native void DrawSaveComment(Font font, int cr, int x, int y, int scalefactor);
|
||||
native void SetFileInfo(int Selected);
|
||||
native int SavegameCount();
|
||||
native SaveGameNode GetSavegame(int i);
|
||||
native void InsertNewSaveNode();
|
||||
native bool RemoveNewSaveNode();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
class LoadSaveMenu : ListMenu
|
||||
{
|
||||
SavegameManager manager;
|
||||
int TopItem;
|
||||
int Selected;
|
||||
|
||||
int savepicLeft;
|
||||
int savepicTop;
|
||||
int savepicWidth;
|
||||
int savepicHeight;
|
||||
int rowHeight;
|
||||
int listboxLeft;
|
||||
int listboxTop;
|
||||
int listboxWidth;
|
||||
|
||||
int listboxRows;
|
||||
int listboxHeight;
|
||||
int listboxRight;
|
||||
int listboxBottom;
|
||||
|
||||
int commentLeft;
|
||||
int commentTop;
|
||||
int commentWidth;
|
||||
int commentHeight;
|
||||
int commentRight;
|
||||
int commentBottom;
|
||||
|
||||
bool mEntering;
|
||||
TextEnterMenu mInput;
|
||||
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override void Init(Menu parent, ListMenuDescriptor desc)
|
||||
{
|
||||
Super.Init(parent, desc);
|
||||
manager = SavegameManager.GetManager();
|
||||
manager.ReadSaveStrings();
|
||||
|
||||
savepicLeft = 10;
|
||||
savepicTop = 54*CleanYfac;
|
||||
savepicWidth = 216*screen.GetWidth()/640;
|
||||
savepicHeight = 135*screen.GetHeight()/400;
|
||||
manager.WindowSize = savepicWidth / CleanXfac;
|
||||
|
||||
rowHeight = (SmallFont.GetHeight() + 1) * CleanYfac;
|
||||
listboxLeft = savepicLeft + savepicWidth + 14;
|
||||
listboxTop = savepicTop;
|
||||
listboxWidth = screen.GetWidth() - listboxLeft - 10;
|
||||
int listboxHeight1 = screen.GetHeight() - listboxTop - 10;
|
||||
listboxRows = (listboxHeight1 - 1) / rowHeight;
|
||||
listboxHeight = listboxRows * rowHeight + 1;
|
||||
listboxRight = listboxLeft + listboxWidth;
|
||||
listboxBottom = listboxTop + listboxHeight;
|
||||
|
||||
commentLeft = savepicLeft;
|
||||
commentTop = savepicTop + savepicHeight + 16;
|
||||
commentWidth = savepicWidth;
|
||||
commentHeight = (51+(screen.GetHeight()>200?10:0))*CleanYfac;
|
||||
commentRight = commentLeft + commentWidth;
|
||||
commentBottom = commentTop + commentHeight;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override void OnDestroy()
|
||||
{
|
||||
manager.ClearSaveStuff ();
|
||||
Super.OnDestroy();
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override void Drawer ()
|
||||
{
|
||||
Super.Drawer();
|
||||
|
||||
SaveGameNode node;
|
||||
int i;
|
||||
int j;
|
||||
bool didSeeSelected = false;
|
||||
|
||||
// Draw picture area
|
||||
if (gameaction == ga_loadgame || gameaction == ga_loadgamehidecon || gameaction == ga_savegame)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Screen.DrawFrame (savepicLeft, savepicTop, savepicWidth, savepicHeight);
|
||||
if (!manager.DrawSavePic(savepicLeft, savepicTop, savepicWidth, savepicHeight))
|
||||
{
|
||||
screen.Clear (savepicLeft, savepicTop, savepicLeft+savepicWidth, savepicTop+savepicHeight, 0, 0);
|
||||
|
||||
if (manager.SavegameCount() > 0)
|
||||
{
|
||||
String text = (Selected == -1 || !manager.GetSavegame(Selected).bOldVersion)? Stringtable.Localize("$MNU_NOPICTURE") : Stringtable.Localize("$MNU_DIFFVERSION");
|
||||
int textlen = SmallFont.StringWidth(text) * CleanXfac;
|
||||
|
||||
screen.DrawText (SmallFont, Font.CR_GOLD, savepicLeft+(savepicWidth-textlen)/2,
|
||||
savepicTop+(savepicHeight-rowHeight)/2, text, DTA_CleanNoMove, true);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw comment area
|
||||
Screen.DrawFrame (commentLeft, commentTop, commentWidth, commentHeight);
|
||||
screen.Clear (commentLeft, commentTop, commentRight, commentBottom, 0, 0);
|
||||
|
||||
manager.DrawSaveComment(SmallFont, Font.CR_GOLD, commentLeft, commentTop, CleanYfac);
|
||||
|
||||
// Draw file area
|
||||
Screen.DrawFrame (listboxLeft, listboxTop, listboxWidth, listboxHeight);
|
||||
screen.Clear (listboxLeft, listboxTop, listboxRight, listboxBottom, 0, 0);
|
||||
|
||||
if (manager.SavegameCount() == 0)
|
||||
{
|
||||
String text = Stringtable.Localize("$MNU_NOFILES");
|
||||
int textlen = SmallFont.StringWidth(text) * CleanXfac;
|
||||
|
||||
screen.DrawText (SmallFont, Font.CR_GOLD, listboxLeft+(listboxWidth-textlen)/2, listboxTop+(listboxHeight-rowHeight)/2, text, DTA_CleanNoMove, true);
|
||||
return;
|
||||
}
|
||||
|
||||
j = TopItem;
|
||||
for (i = 0; i < listboxRows && j < manager.SavegameCount(); i++)
|
||||
{
|
||||
int colr;
|
||||
node = manager.GetSavegame(j);
|
||||
if (node.bOldVersion)
|
||||
{
|
||||
colr = Font.CR_BLUE;
|
||||
}
|
||||
else if (node.bMissingWads)
|
||||
{
|
||||
colr = Font.CR_ORANGE;
|
||||
}
|
||||
else if (j == Selected)
|
||||
{
|
||||
colr = Font.CR_WHITE;
|
||||
}
|
||||
else
|
||||
{
|
||||
colr = Font.CR_TAN;
|
||||
}
|
||||
|
||||
if (j == Selected)
|
||||
{
|
||||
screen.Clear (listboxLeft, listboxTop+rowHeight*i, listboxRight, listboxTop+rowHeight*(i+1), mEntering ? Color(255,255,0,0) : Color(255,0,0,255));
|
||||
didSeeSelected = true;
|
||||
if (!mEntering)
|
||||
{
|
||||
screen.DrawText (SmallFont, colr, listboxLeft+1, listboxTop+rowHeight*i+CleanYfac, node.SaveTitle, DTA_CleanNoMove, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
String s = mInput.GetText() .. SmallFont.GetCursor();
|
||||
screen.DrawText (SmallFont, Font.CR_WHITE, listboxLeft+1, listboxTop+rowHeight*i+CleanYfac, s, DTA_CleanNoMove, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
screen.DrawText (SmallFont, colr, listboxLeft+1, listboxTop+rowHeight*i+CleanYfac, node.SaveTitle, DTA_CleanNoMove, true);
|
||||
}
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool MenuEvent (int mkey, bool fromcontroller)
|
||||
{
|
||||
switch (mkey)
|
||||
{
|
||||
case MKEY_Up:
|
||||
if (manager.SavegameCount() > 1)
|
||||
{
|
||||
if (Selected == -1) Selected = TopItem;
|
||||
else
|
||||
{
|
||||
if (--Selected < 0) Selected = manager.SavegameCount()-1;
|
||||
if (Selected < TopItem) TopItem = Selected;
|
||||
else if (Selected >= TopItem + listboxRows) TopItem = MAX(0, Selected - listboxRows + 1);
|
||||
}
|
||||
manager.UnloadSaveData ();
|
||||
manager.ExtractSaveData (Selected);
|
||||
}
|
||||
return true;
|
||||
|
||||
case MKEY_Down:
|
||||
if (manager.SavegameCount() > 1)
|
||||
{
|
||||
if (Selected == -1) Selected = TopItem;
|
||||
else
|
||||
{
|
||||
if (++Selected >= manager.SavegameCount()) Selected = 0;
|
||||
if (Selected < TopItem) TopItem = Selected;
|
||||
else if (Selected >= TopItem + listboxRows) TopItem = MAX(0, Selected - listboxRows + 1);
|
||||
}
|
||||
manager.UnloadSaveData ();
|
||||
manager.ExtractSaveData (Selected);
|
||||
}
|
||||
return true;
|
||||
|
||||
case MKEY_PageDown:
|
||||
if (manager.SavegameCount() > 1)
|
||||
{
|
||||
if (TopItem >= manager.SavegameCount() - listboxRows)
|
||||
{
|
||||
TopItem = 0;
|
||||
if (Selected != -1) Selected = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
TopItem = MIN(TopItem + listboxRows, manager.SavegameCount() - listboxRows);
|
||||
if (TopItem > Selected && Selected != -1) Selected = TopItem;
|
||||
}
|
||||
manager.UnloadSaveData ();
|
||||
manager.ExtractSaveData (Selected);
|
||||
}
|
||||
return true;
|
||||
|
||||
case MKEY_PageUp:
|
||||
if (manager.SavegameCount() > 1)
|
||||
{
|
||||
if (TopItem == 0)
|
||||
{
|
||||
TopItem = MAX(0, manager.SavegameCount() - listboxRows);
|
||||
if (Selected != -1) Selected = TopItem;
|
||||
}
|
||||
else
|
||||
{
|
||||
TopItem = MAX(TopItem - listboxRows, 0);
|
||||
if (Selected >= TopItem + listboxRows) Selected = TopItem;
|
||||
}
|
||||
manager.UnloadSaveData ();
|
||||
manager.ExtractSaveData (Selected);
|
||||
}
|
||||
return true;
|
||||
|
||||
case MKEY_Enter:
|
||||
return false; // This event will be handled by the subclasses
|
||||
|
||||
case MKEY_MBYes:
|
||||
{
|
||||
if (Selected < manager.SavegameCount())
|
||||
{
|
||||
Selected = manager.RemoveSaveSlot (Selected);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
default:
|
||||
return Super.MenuEvent(mkey, fromcontroller);
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool MouseEvent(int type, int x, int y)
|
||||
{
|
||||
if (x >= listboxLeft && x < listboxLeft + listboxWidth &&
|
||||
y >= listboxTop && y < listboxTop + listboxHeight)
|
||||
{
|
||||
int lineno = (y - listboxTop) / rowHeight;
|
||||
|
||||
if (TopItem + lineno < manager.SavegameCount())
|
||||
{
|
||||
Selected = TopItem + lineno;
|
||||
manager.UnloadSaveData ();
|
||||
manager.ExtractSaveData (Selected);
|
||||
if (type == MOUSE_Release)
|
||||
{
|
||||
if (MenuEvent(MKEY_Enter, true))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else Selected = -1;
|
||||
}
|
||||
else Selected = -1;
|
||||
|
||||
return Super.MouseEvent(type, x, y);
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool Responder (InputEventData ev)
|
||||
{
|
||||
if (ev.type == InputEventData.GUI_Event)
|
||||
{
|
||||
if (ev.subtype == InputEventData.GUI_KeyDown)
|
||||
{
|
||||
if (Selected < manager.SavegameCount())
|
||||
{
|
||||
switch (ev.data1)
|
||||
{
|
||||
case UIEvent.Key_F1:
|
||||
manager.SetFileInfo(Selected);
|
||||
return true;
|
||||
|
||||
case UIEvent.Key_DEL:
|
||||
{
|
||||
String EndString;
|
||||
EndString = String.Format("%s%s%s%s?\n\n%s", Stringtable.Localize("$MNU_DELETESG"), TEXTCOLOR_WHITE, manager.GetSavegame(Selected).SaveTitle, TEXTCOLOR_NORMAL, Stringtable.Localize("$PRESSYN"));
|
||||
StartMessage (EndString, 0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ev.subtype == InputEventData.GUI_WheelUp)
|
||||
{
|
||||
if (TopItem > 0) TopItem--;
|
||||
return true;
|
||||
}
|
||||
else if (ev.subtype == InputEventData.GUI_WheelDown)
|
||||
{
|
||||
if (TopItem < manager.SavegameCount() - listboxRows) TopItem++;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return Super.Responder(ev);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
class SaveMenu : LoadSaveMenu
|
||||
{
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override void Init(Menu parent, ListMenuDescriptor desc)
|
||||
{
|
||||
Super.Init(parent, desc);
|
||||
manager.InsertNewSaveNode();
|
||||
TopItem = 0;
|
||||
Selected = manager.ExtractSaveData (-1);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override void OnDestroy()
|
||||
{
|
||||
if (manager.RemoveNewSaveNode())
|
||||
{
|
||||
Selected--;
|
||||
}
|
||||
Super.OnDestroy();
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
const SAVESTRINGSIZE = 32;
|
||||
|
||||
override bool MenuEvent (int mkey, bool fromcontroller)
|
||||
{
|
||||
|
||||
if (Super.MenuEvent(mkey, fromcontroller))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (Selected == -1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mkey == MKEY_Enter)
|
||||
{
|
||||
String SavegameString = (Selected != 0)? manager.GetSavegame(Selected).SaveTitle : "";
|
||||
mInput = TextEnterMenu.Open(self, SavegameString, SAVESTRINGSIZE, 1, fromcontroller);
|
||||
mInput.ActivateMenu();
|
||||
mEntering = true;
|
||||
}
|
||||
else if (mkey == MKEY_Input)
|
||||
{
|
||||
mEntering = false;
|
||||
manager.DoSave(Selected, mInput.GetText());
|
||||
mInput = null;
|
||||
}
|
||||
else if (mkey == MKEY_Abort)
|
||||
{
|
||||
mEntering = false;
|
||||
mInput = null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool Responder (InputEventData ev)
|
||||
{
|
||||
if (ev.subtype == InputEventData.GUI_KeyDown)
|
||||
{
|
||||
if (Selected != -1)
|
||||
{
|
||||
switch (ev.data1)
|
||||
{
|
||||
case UIEvent.Key_DEL:
|
||||
// cannot delete 'new save game' item
|
||||
if (Selected == 0) return true;
|
||||
break;
|
||||
|
||||
case 78://'N':
|
||||
Selected = TopItem = 0;
|
||||
manager.UnloadSaveData ();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Super.Responder(ev);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class LoadMenu : LoadSaveMenu
|
||||
{
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override void Init(Menu parent, ListMenuDescriptor desc)
|
||||
{
|
||||
Super.Init(parent, desc);
|
||||
TopItem = 0;
|
||||
Selected = manager.ExtractSaveData (-1);
|
||||
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool MenuEvent (int mkey, bool fromcontroller)
|
||||
{
|
||||
if (Super.MenuEvent(mkey, fromcontroller))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (Selected == -1 || manager.SavegameCount() == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mkey == MKEY_Enter)
|
||||
{
|
||||
manager.LoadSavegame(Selected);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -87,6 +87,9 @@ class Menu : Object native
|
|||
};
|
||||
|
||||
native Menu mParentMenu;
|
||||
native bool mMouseCapture;
|
||||
native bool mBackbuttonSelected;
|
||||
native bool DontDim;
|
||||
|
||||
void Init(Menu parent)
|
||||
{
|
||||
|
@ -111,7 +114,6 @@ class Menu : Object native
|
|||
native virtual void Ticker();
|
||||
native virtual void Drawer();
|
||||
native void Close();
|
||||
native MenuItemBase GetItem(Name n);
|
||||
native void ActivateMenu();
|
||||
|
||||
static void MenuSound(Sound snd)
|
||||
|
|
293
wadsrc/static/zscript/menu/messagebox.txt
Normal file
293
wadsrc/static/zscript/menu/messagebox.txt
Normal file
|
@ -0,0 +1,293 @@
|
|||
/*
|
||||
** messagebox.cpp
|
||||
** Confirmation, notification screns
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2010-2017 Christoph Oelckers
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
class MessageBoxMenu : Menu
|
||||
{
|
||||
BrokenLines mMessage;
|
||||
voidptr Handler;
|
||||
int mMessageMode;
|
||||
int messageSelection;
|
||||
int mMouseLeft, mMouseRight, mMouseY;
|
||||
Name mAction;
|
||||
|
||||
native static void CallHandler(voidptr hnd);
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void Init(Menu parent, String message, int messagemode, bool playsound = false, Name cmd = 'None', voidptr native_handler = null)
|
||||
{
|
||||
Super.Init(parent);
|
||||
mAction = cmd;
|
||||
messageSelection = 0;
|
||||
mMouseLeft = 140;
|
||||
mMouseY = 0x80000000;
|
||||
int mr1 = 170 + SmallFont.StringWidth(Stringtable.Localize("$TXT_YES"));
|
||||
int mr2 = 170 + SmallFont.StringWidth(Stringtable.Localize("$TXT_NO"));
|
||||
mMouseRight = MAX(mr1, mr2);
|
||||
mParentMenu = parent;
|
||||
mMessage = SmallFont.BreakLines(message, 300);
|
||||
mMessageMode = messagemode;
|
||||
if (playsound)
|
||||
{
|
||||
MenuSound ("menu/prompt");
|
||||
}
|
||||
Handler = native_handler;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override void Drawer ()
|
||||
{
|
||||
int i, y;
|
||||
|
||||
int fontheight = SmallFont.GetHeight();
|
||||
|
||||
y = 100;
|
||||
|
||||
int c = mMessage.Count();
|
||||
for (i = 0; i < c; i++)
|
||||
y -= SmallFont.GetHeight () / 2;
|
||||
|
||||
for (i = 0; i < c; i++)
|
||||
{
|
||||
screen.DrawText (SmallFont, Font.CR_UNTRANSLATED, 160 - mMessage.StringWidth(i)/2, y, mMessage.StringAt(i), DTA_Clean, true);
|
||||
y += fontheight;
|
||||
}
|
||||
|
||||
if (mMessageMode == 0)
|
||||
{
|
||||
y += fontheight;
|
||||
mMouseY = y;
|
||||
screen.DrawText(SmallFont, messageSelection == 0? OptionMenuSettings.mFontColorSelection : OptionMenuSettings.mFontColor, 160, y, Stringtable.Localize("$TXT_YES"), DTA_Clean, true);
|
||||
screen.DrawText(SmallFont, messageSelection == 1? OptionMenuSettings.mFontColorSelection : OptionMenuSettings.mFontColor, 160, y + fontheight + 1, Stringtable.Localize("$TXT_NO"), DTA_Clean, true);
|
||||
|
||||
if (messageSelection >= 0)
|
||||
{
|
||||
if ((MenuTime() % 8) < 6)
|
||||
{
|
||||
screen.DrawText(ConFont, OptionMenuSettings.mFontColorSelection,
|
||||
(150 - 160) * CleanXfac + screen.GetWidth() / 2,
|
||||
(y + (fontheight + 1) * messageSelection - 100 + fontheight/2 - 5) * CleanYfac + screen.GetHeight() / 2,
|
||||
"\xd", DTA_CellX, 8 * CleanXfac, DTA_CellY, 8 * CleanYfac);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
protected void CloseSound()
|
||||
{
|
||||
MenuSound (GetCurrentMenu() != NULL? "menu/backup" : "menu/dismiss");
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
virtual void HandleResult(bool res)
|
||||
{
|
||||
if (Handler != null)
|
||||
{
|
||||
if (res)
|
||||
{
|
||||
CallHandler(Handler);
|
||||
}
|
||||
else
|
||||
{
|
||||
Close();
|
||||
CloseSound();
|
||||
}
|
||||
}
|
||||
else if (mParentMenu != NULL)
|
||||
{
|
||||
if (mMessageMode == 0)
|
||||
{
|
||||
if (mAction == 'None')
|
||||
{
|
||||
mParentMenu.MenuEvent(res? MKEY_MBYes : MKEY_MBNo, false);
|
||||
Close();
|
||||
}
|
||||
else
|
||||
{
|
||||
Close();
|
||||
if (res) SetMenu(mAction, -1);
|
||||
}
|
||||
CloseSound();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool Responder(InputEventData ev)
|
||||
{
|
||||
if (ev.type == InputEventData.GUI_Event && ev.subtype == InputEventData.GUI_KeyDown)
|
||||
{
|
||||
if (mMessageMode == 0)
|
||||
{
|
||||
// tolower
|
||||
int ch = ev.data1;
|
||||
ch = ch >= 65 && ch <91? ch + 32 : ch;
|
||||
|
||||
if (ch == 78 /*'n'*/ || ch == 32)
|
||||
{
|
||||
HandleResult(false);
|
||||
return true;
|
||||
}
|
||||
else if (ch == 89 /*'y'*/)
|
||||
{
|
||||
HandleResult(true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Close();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else if (ev.type == InputEventData.KeyDown)
|
||||
{
|
||||
Close();
|
||||
return true;
|
||||
}
|
||||
return Super.Responder(ev);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool MenuEvent(int mkey, bool fromcontroller)
|
||||
{
|
||||
if (mMessageMode == 0)
|
||||
{
|
||||
if (mkey == MKEY_Up || mkey == MKEY_Down)
|
||||
{
|
||||
MenuSound("menu/cursor");
|
||||
messageSelection = !messageSelection;
|
||||
return true;
|
||||
}
|
||||
else if (mkey == MKEY_Enter)
|
||||
{
|
||||
// 0 is yes, 1 is no
|
||||
HandleResult(!messageSelection);
|
||||
return true;
|
||||
}
|
||||
else if (mkey == MKEY_Back)
|
||||
{
|
||||
HandleResult(false);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Close();
|
||||
CloseSound();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool MouseEvent(int type, int x, int y)
|
||||
{
|
||||
if (mMessageMode == 1)
|
||||
{
|
||||
if (type == MOUSE_Click)
|
||||
{
|
||||
return MenuEvent(MKEY_Enter, true);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
int sel = -1;
|
||||
int fh = SmallFont.GetHeight() + 1;
|
||||
|
||||
// convert x/y from screen to virtual coordinates, according to CleanX/Yfac use in DrawTexture
|
||||
x = ((x - (screen.GetWidth() / 2)) / CleanXfac) + 160;
|
||||
y = ((y - (screen.GetHeight() / 2)) / CleanYfac) + 100;
|
||||
|
||||
if (x >= mMouseLeft && x <= mMouseRight && y >= mMouseY && y < mMouseY + 2 * fh)
|
||||
{
|
||||
sel = y >= mMouseY + fh;
|
||||
}
|
||||
if (sel != -1 && sel != messageSelection)
|
||||
{
|
||||
//S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
|
||||
}
|
||||
messageSelection = sel;
|
||||
if (type == MOUSE_Release)
|
||||
{
|
||||
return MenuEvent(MKEY_Enter, true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -56,8 +56,6 @@ class OptionMenuDescriptor : MenuDescriptor native
|
|||
native int mPosition;
|
||||
native bool mDontDim;
|
||||
|
||||
native void CalcIndent();
|
||||
native OptionMenuItem GetItem(Name iname);
|
||||
void Reset()
|
||||
{
|
||||
// Reset the default settings (ignore all other values in the struct)
|
||||
|
@ -66,6 +64,25 @@ class OptionMenuDescriptor : MenuDescriptor native
|
|||
mIndent = 0;
|
||||
mDontDim = 0;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void CalcIndent()
|
||||
{
|
||||
// calculate the menu indent
|
||||
int widest = 0, thiswidth;
|
||||
|
||||
for (int i = 0; i < mItems.Size(); i++)
|
||||
{
|
||||
thiswidth = mItems[i].GetIndent();
|
||||
if (thiswidth > widest) widest = thiswidth;
|
||||
}
|
||||
mIndent = widest + 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -87,11 +104,29 @@ class OptionMenu : Menu
|
|||
{
|
||||
mParentMenu = parent;
|
||||
mDesc = desc;
|
||||
DontDim = desc.mDontDim;
|
||||
if (mDesc != NULL && mDesc.mSelectedItem == -1) mDesc.mSelectedItem = FirstSelectable();
|
||||
|
||||
mDesc.CalcIndent();
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
OptionMenuItem GetItem(Name name)
|
||||
{
|
||||
for(int i = 0; i < mDesc.mItems.Size(); i++)
|
||||
{
|
||||
Name nm = mDesc.mItems[i].GetAction();
|
||||
if (nm == name) return mDesc.mItems[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
|
|
|
@ -136,7 +136,7 @@ class OptionMenuItemCommand : OptionMenuItemSubmenu
|
|||
// don't execute if no menu is active
|
||||
if (m == null) return false;
|
||||
// don't execute if this item cannot be found in the current menu.
|
||||
if (m.mDesc.GetItem(mAction) != self) return false;
|
||||
if (m.GetItem(mAction) != self) return false;
|
||||
Menu.MenuSound("menu/choose");
|
||||
DoCommand(mAction);
|
||||
return true;
|
||||
|
|
595
wadsrc/static/zscript/menu/playermenu.txt
Normal file
595
wadsrc/static/zscript/menu/playermenu.txt
Normal file
|
@ -0,0 +1,595 @@
|
|||
/*
|
||||
** playermenu.cpp
|
||||
** The player setup menu
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2001-2010 Randy Heit
|
||||
** Copyright 2010-2017 Christoph Oelckers
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
class PlayerMenu : ListMenu
|
||||
{
|
||||
int mRotation;
|
||||
int PlayerClassIndex;
|
||||
PlayerClass mPlayerClass;
|
||||
Array<int> PlayerColorSets;
|
||||
Array<int> mPlayerSkins;
|
||||
|
||||
// All write function for the player config are native to prevent abuse.
|
||||
protected native void AutoaimChanged(float val);
|
||||
protected native void TeamChanged(int val);
|
||||
protected native void AlwaysRunChanged(int val);
|
||||
protected native void GenderChanged(int val);
|
||||
protected native void SwitchOnPickupChanged(int val);
|
||||
protected native void ColorChanged(int red, int green, int blue);
|
||||
protected native void ColorSetChanged(int red);
|
||||
protected native void PlayerNameChanged(String name);
|
||||
protected native void SkinChanged (int val);
|
||||
protected native void ClassChanged(int sel, PlayerClass cls);
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
protected void UpdateTranslation()
|
||||
{
|
||||
Translation.SetPlayerTranslation(TRANSLATION_Players, MAXPLAYERS, consoleplayer, mPlayerClass);
|
||||
}
|
||||
|
||||
protected void SendNewColor (int red, int green, int blue)
|
||||
{
|
||||
ColorChanged(red, green, blue);
|
||||
UpdateTranslation();
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override void Init(Menu parent, ListMenuDescriptor desc)
|
||||
{
|
||||
MenuItemBase li;
|
||||
PlayerInfo p = players[consoleplayer];
|
||||
|
||||
Super.Init(parent, desc);
|
||||
PickPlayerClass();
|
||||
mRotation = 0;
|
||||
|
||||
li = GetItem('Playerdisplay');
|
||||
if (li != NULL)
|
||||
{
|
||||
li.SetValue(ListMenuItemPlayerDisplay.PDF_ROTATION, 0);
|
||||
li.SetValue(ListMenuItemPlayerDisplay.PDF_MODE, 1);
|
||||
li.SetValue(ListMenuItemPlayerDisplay.PDF_TRANSLATE, 1);
|
||||
li.SetValue(ListMenuItemPlayerDisplay.PDF_CLASS, p.GetPlayerClassNum());
|
||||
if (mPlayerClass != NULL && !(GetDefaultByType (mPlayerClass.Type).bNoSkin) &&
|
||||
p.GetPlayerClassNum() != -1)
|
||||
{
|
||||
li.SetValue(ListMenuItemPlayerDisplay.PDF_SKIN, p.GetSkin());
|
||||
}
|
||||
}
|
||||
|
||||
li = GetItem('Playerbox');
|
||||
if (li != NULL)
|
||||
{
|
||||
li.SetString(0, p.GetUserName());
|
||||
}
|
||||
|
||||
li = GetItem('Team');
|
||||
if (li != NULL)
|
||||
{
|
||||
li.SetString(0, "None");
|
||||
for(int i=0;i<Teams.Size(); i++)
|
||||
{
|
||||
li.SetString(i+1, Teams[i].mName);
|
||||
}
|
||||
int myteam = players[consoleplayer].GetTeam();
|
||||
li.SetValue(0, myteam == Team.NoTeam? 0 : myteam + 1);
|
||||
}
|
||||
|
||||
int mycolorset = p.GetColorSet();
|
||||
Color colr = p.GetColor();
|
||||
|
||||
UpdateColorsets();
|
||||
|
||||
li = GetItem('Red');
|
||||
if (li != NULL)
|
||||
{
|
||||
li.Enable(mycolorset == -1);
|
||||
li.SetValue(0, colr.r);
|
||||
}
|
||||
|
||||
li = GetItem('Green');
|
||||
if (li != NULL)
|
||||
{
|
||||
li.Enable(mycolorset == -1);
|
||||
li.SetValue(0, colr.g);
|
||||
}
|
||||
|
||||
li = GetItem('Blue');
|
||||
if (li != NULL)
|
||||
{
|
||||
li.Enable(mycolorset == -1);
|
||||
li.SetValue(0, colr.b);
|
||||
}
|
||||
|
||||
li = GetItem('Class');
|
||||
if (li != NULL)
|
||||
{
|
||||
if (PlayerClasses.Size() == 1)
|
||||
{
|
||||
li.SetString(0, PlayerPawn.GetPrintableDisplayName(PlayerClasses[0].Type));
|
||||
li.SetValue(0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// [XA] Remove the "Random" option if the relevant gameinfo flag is set.
|
||||
if(!gameinfo.norandomplayerclass)
|
||||
li.SetString(0, "Random");
|
||||
for(int i=0; i< PlayerClasses.Size(); i++)
|
||||
{
|
||||
let cls = PlayerPawn.GetPrintableDisplayName(PlayerClasses[i].Type);
|
||||
li.SetString(gameinfo.norandomplayerclass ? i : i+1, cls);
|
||||
}
|
||||
int pclass = p.GetPlayerClassNum();
|
||||
li.SetValue(0, gameinfo.norandomplayerclass && pclass >= 0 ? pclass : pclass + 1);
|
||||
}
|
||||
}
|
||||
|
||||
UpdateSkins();
|
||||
|
||||
li = GetItem('Gender');
|
||||
if (li != NULL)
|
||||
{
|
||||
li.SetValue(0, p.GetGender());
|
||||
}
|
||||
|
||||
li = GetItem('Autoaim');
|
||||
if (li != NULL)
|
||||
{
|
||||
li.SetValue(0, int(p.GetAutoaim()));
|
||||
}
|
||||
|
||||
li = GetItem('Switch');
|
||||
if (li != NULL)
|
||||
{
|
||||
li.SetValue(0, p.GetNeverSwitch());
|
||||
}
|
||||
|
||||
li = GetItem('AlwaysRun');
|
||||
if (li != NULL)
|
||||
{
|
||||
li.SetValue(0, cl_run);
|
||||
}
|
||||
|
||||
if (mDesc.mSelectedItem < 0) mDesc.mSelectedItem = 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
protected void PickPlayerClass(int pick = -100)
|
||||
{
|
||||
int pclass = 0;
|
||||
// [GRB] Pick a class from player class list
|
||||
if (PlayerClasses.Size () > 1)
|
||||
{
|
||||
pclass = pick == -100? players[consoleplayer].GetPlayerClassNum() : pick;
|
||||
|
||||
if (pclass < 0)
|
||||
{
|
||||
pclass = (MenuTime() >> 7) % PlayerClasses.Size ();
|
||||
}
|
||||
}
|
||||
PlayerClassIndex = pclass;
|
||||
mPlayerClass = PlayerClasses[PlayerClassIndex];
|
||||
UpdateTranslation();
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
protected void UpdateColorsets()
|
||||
{
|
||||
let li = GetItem('Color');
|
||||
if (li != NULL)
|
||||
{
|
||||
int sel = 0;
|
||||
mPlayerClass.EnumColorSets(PlayerColorSets);
|
||||
li.SetString(0, "Custom");
|
||||
for(int i = 0; i < PlayerColorSets.Size(); i++)
|
||||
{
|
||||
let cname = mPlayerClass.GetColorSetName(PlayerColorSets[i]);
|
||||
li.SetString(i+1, cname);
|
||||
}
|
||||
int mycolorset = players[consoleplayer].GetColorSet();
|
||||
if (mycolorset != -1)
|
||||
{
|
||||
for(int i = 0; i < PlayerColorSets.Size(); i++)
|
||||
{
|
||||
if (PlayerColorSets[i] == mycolorset)
|
||||
{
|
||||
sel = i + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
li.SetValue(0, sel);
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
protected void UpdateSkins()
|
||||
{
|
||||
int sel = 0;
|
||||
int skin;
|
||||
let li = GetItem('Skin');
|
||||
if (li != NULL)
|
||||
{
|
||||
if (GetDefaultByType (mPlayerClass.Type).bNoSkin || players[consoleplayer].GetPlayerClassNum() == -1)
|
||||
{
|
||||
li.SetString(0, "Base");
|
||||
li.SetValue(0, 0);
|
||||
skin = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
mPlayerSkins.Clear();
|
||||
for (int i = 0; i < PlayerSkins.Size(); i++)
|
||||
{
|
||||
if (mPlayerClass.CheckSkin(i))
|
||||
{
|
||||
int j = mPlayerSkins.Push(i);
|
||||
li.SetString(j, PlayerSkins[i].SkinName);
|
||||
if (players[consoleplayer].GetSkin() == i)
|
||||
{
|
||||
sel = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
li.SetValue(0, sel);
|
||||
skin = mPlayerSkins[sel];
|
||||
}
|
||||
li = GetItem('Playerdisplay');
|
||||
if (li != NULL)
|
||||
{
|
||||
li.SetValue(ListMenuItemPlayerDisplay.PDF_SKIN, skin);
|
||||
}
|
||||
}
|
||||
UpdateTranslation();
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void ChangeClass (MenuItemBase li)
|
||||
{
|
||||
if (PlayerClasses.Size () == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool res;
|
||||
int sel;
|
||||
|
||||
[res, sel] = li.GetValue(0);
|
||||
if (res)
|
||||
{
|
||||
PickPlayerClass(gameinfo.norandomplayerclass ? sel : sel-1);
|
||||
ClassChanged(sel, mPlayerClass);
|
||||
UpdateSkins();
|
||||
UpdateColorsets();
|
||||
UpdateTranslation();
|
||||
|
||||
li = GetItem('Playerdisplay');
|
||||
if (li != NULL)
|
||||
{
|
||||
li.SetValue(ListMenuItemPlayerDisplay.PDF_CLASS, players[consoleplayer].GetPlayerClassNum());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
protected void ChangeSkin (MenuItemBase li)
|
||||
{
|
||||
if (GetDefaultByType (mPlayerClass.Type).bNoSkin || players[consoleplayer].GetPlayerClassNum() == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool res;
|
||||
int sel;
|
||||
|
||||
[res, sel] = li.GetValue(0);
|
||||
if (res)
|
||||
{
|
||||
sel = mPlayerSkins[sel];
|
||||
SkinChanged(sel);
|
||||
UpdateTranslation();
|
||||
|
||||
li = GetItem('Playerdisplay');
|
||||
if (li != NULL)
|
||||
{
|
||||
li.SetValue(ListMenuItemPlayerDisplay.PDF_SKIN, sel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool Responder (InputEventData ev)
|
||||
{
|
||||
if (ev.type == InputEventData.GUI_Event && ev.subtype == InputEventData.GUI_Char && ev.data1 == 32)
|
||||
{
|
||||
// turn the player sprite around
|
||||
mRotation = 8 - mRotation;
|
||||
MenuItemBase li = GetItem('Playerdisplay');
|
||||
if (li != NULL)
|
||||
{
|
||||
li.SetValue(ListMenuItemPlayerDisplay.PDF_ROTATION, mRotation);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return Super.Responder(ev);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool MenuEvent (int mkey, bool fromcontroller)
|
||||
{
|
||||
int v;
|
||||
bool res;
|
||||
String s;
|
||||
if (mDesc.mSelectedItem >= 0)
|
||||
{
|
||||
let li = mDesc.mItems[mDesc.mSelectedItem];
|
||||
if (li.MenuEvent(mkey, fromcontroller))
|
||||
{
|
||||
Name ctrl = li.GetAction();
|
||||
switch(ctrl)
|
||||
{
|
||||
// item specific handling comes here
|
||||
|
||||
case 'Playerbox':
|
||||
if (mkey == MKEY_Input)
|
||||
{
|
||||
[res, s] = li.GetString(0);
|
||||
if (res) PlayerNameChanged(s);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'Team':
|
||||
[res, v] = li.GetValue(0);
|
||||
if (res) TeamChanged(v);
|
||||
break;
|
||||
|
||||
case 'Color':
|
||||
[res, v] = li.GetValue(0);
|
||||
if (res)
|
||||
{
|
||||
int mycolorset = -1;
|
||||
|
||||
if (v > 0) mycolorset = PlayerColorSets[v - 1];
|
||||
|
||||
let red = GetItem('Red');
|
||||
let green = GetItem('Green');
|
||||
let blue = GetItem('Blue');
|
||||
|
||||
// disable the sliders if a valid colorset is selected
|
||||
if (red != NULL) red.Enable(mycolorset == -1);
|
||||
if (green != NULL) green.Enable(mycolorset == -1);
|
||||
if (blue != NULL) blue.Enable(mycolorset == -1);
|
||||
|
||||
ColorSetChanged(v - 1);
|
||||
UpdateTranslation();
|
||||
}
|
||||
break;
|
||||
|
||||
case 'Red':
|
||||
[res, v] = li.GetValue(0);
|
||||
if (res)
|
||||
{
|
||||
Color colr = players[consoleplayer].GetColor();
|
||||
SendNewColor (v, colr.g, colr.b);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'Green':
|
||||
[res, v] = li.GetValue(0);
|
||||
if (res)
|
||||
{
|
||||
Color colr = players[consoleplayer].GetColor();
|
||||
SendNewColor (colr.r, v, colr.b);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'Blue':
|
||||
[res, v] = li.GetValue(0);
|
||||
if (res)
|
||||
{
|
||||
Color colr = players[consoleplayer].GetColor();
|
||||
SendNewColor (colr.r, colr.g, v);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'Class':
|
||||
[res, v] = li.GetValue(0);
|
||||
if (res)
|
||||
{
|
||||
ChangeClass(li);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'Skin':
|
||||
ChangeSkin(li);
|
||||
break;
|
||||
|
||||
case 'Gender':
|
||||
[res, v] = li.GetValue(0);
|
||||
if (res)
|
||||
{
|
||||
GenderChanged(v);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'Autoaim':
|
||||
[res, v] = li.GetValue(0);
|
||||
if (res)
|
||||
{
|
||||
AutoaimChanged(v);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'Switch':
|
||||
[res, v] = li.GetValue(0);
|
||||
if (res)
|
||||
{
|
||||
SwitchOnPickupChanged(v);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'AlwaysRun':
|
||||
[res, v] = li.GetValue(0);
|
||||
if (res)
|
||||
{
|
||||
AlwaysRunChanged(v);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return Super.MenuEvent(mkey, fromcontroller);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool MouseEvent(int type, int x, int y)
|
||||
{
|
||||
let li = mFocusControl;
|
||||
bool res = Super.MouseEvent(type, x, y);
|
||||
if (li == NULL) li = mFocusControl;
|
||||
if (li != NULL)
|
||||
{
|
||||
// Check if the colors have changed
|
||||
Name ctrl = li.GetAction();
|
||||
bool resv;
|
||||
int v;
|
||||
[resv, v]= li.GetValue(0);
|
||||
switch(ctrl)
|
||||
{
|
||||
case 'Red':
|
||||
if (resv)
|
||||
{
|
||||
Color colr = players[consoleplayer].GetColor();
|
||||
SendNewColor (v, colr.g, colr.b);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'Green':
|
||||
if (resv)
|
||||
{
|
||||
Color colr = players[consoleplayer].GetColor();
|
||||
SendNewColor (colr.r, v, colr.b);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'Blue':
|
||||
if (resv)
|
||||
{
|
||||
Color colr = players[consoleplayer].GetColor();
|
||||
SendNewColor (colr.r, colr.g, v);
|
||||
}
|
||||
break;
|
||||
case 'Autoaim':
|
||||
AutoaimChanged(v);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override void Drawer ()
|
||||
{
|
||||
Super.Drawer();
|
||||
String str = "PRESS " .. TEXTCOLOR_WHITE .. "SPACE";
|
||||
screen.DrawText (SmallFont, Font.CR_GOLD, 320 - 32 - 32 - SmallFont.StringWidth (str)/2, 50 + 48 + 70, str, DTA_Clean, true);
|
||||
str = mRotation ? "TO SEE FRONT" : "TO SEE BACK";
|
||||
screen.DrawText (SmallFont, Font.CR_GOLD, 320 - 32 - 32 - SmallFont.StringWidth (str)/2, 50 + 48 + 70 + SmallFont.GetHeight (), str, DTA_Clean, true);
|
||||
|
||||
}
|
||||
|
||||
}
|
124
wadsrc/static/zscript/menu/readthis.txt
Normal file
124
wadsrc/static/zscript/menu/readthis.txt
Normal file
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
** readthis.cpp
|
||||
** Help screens
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2001-2010 Randy Heit
|
||||
** Copyright 2010 Christoph Oelckers
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
class ReadThisMenu : Menu
|
||||
{
|
||||
int mScreen;
|
||||
int mInfoTic;
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override void Drawer()
|
||||
{
|
||||
double alpha;
|
||||
TextureID tex, prevpic;
|
||||
|
||||
if (mScreen == 0)
|
||||
{
|
||||
mScreen = 1;
|
||||
mInfoTic = gametic;
|
||||
}
|
||||
|
||||
// Did the mapper choose a custom help page via MAPINFO?
|
||||
if (level.F1Pic.Length() != 0)
|
||||
{
|
||||
tex = TexMan.CheckForTexture(level.F1Pic, TexMan.Type_MiscPatch);
|
||||
mScreen = 1;
|
||||
}
|
||||
|
||||
if (!tex.IsValid())
|
||||
{
|
||||
tex = TexMan.CheckForTexture(gameinfo.infoPages[mScreen-1], TexMan.Type_MiscPatch);
|
||||
}
|
||||
|
||||
if (mScreen > 1)
|
||||
{
|
||||
prevpic = TexMan.CheckForTexture(gameinfo.infoPages[mScreen-2], TexMan.Type_MiscPatch);
|
||||
}
|
||||
|
||||
screen.Dim(0, 1.0, 0,0, screen.GetWidth(), screen.GetHeight());
|
||||
alpha = MIN((gametic - mInfoTic) * (3. / Thinker.TICRATE), 1.);
|
||||
if (alpha < 1. && prevpic.IsValid())
|
||||
{
|
||||
screen.DrawTexture (prevpic, false, 0, 0, DTA_Fullscreen, true);
|
||||
}
|
||||
else alpha = 1;
|
||||
screen.DrawTexture (tex, false, 0, 0, DTA_Fullscreen, true, DTA_Alpha, alpha);
|
||||
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool MenuEvent(int mkey, bool fromcontroller)
|
||||
{
|
||||
if (mkey == MKEY_Enter)
|
||||
{
|
||||
MenuSound("menu/choose");
|
||||
mScreen++;
|
||||
mInfoTic = gametic;
|
||||
if (level.F1Pic.Length() != 0 || mScreen > gameinfo.infoPages.Size())
|
||||
{
|
||||
Close();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else return Super.MenuEvent(mkey, fromcontroller);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool MouseEvent(int type, int x, int y)
|
||||
{
|
||||
if (type == MOUSE_Click)
|
||||
{
|
||||
return MenuEvent(MKEY_Enter, true);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,15 +1,365 @@
|
|||
/*
|
||||
** menuinput.cpp
|
||||
** The string input code
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2001-2010 Randy Heit
|
||||
** Copyright 2010-2017 Christoph Oelckers
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
// This is only the parts that are needed to make the menu fully work right now. More to come later.
|
||||
class TextEnterMenu : Menu native
|
||||
|
||||
class TextEnterMenu : Menu
|
||||
{
|
||||
native bool mInputGridOkay;
|
||||
const INPUTGRID_WIDTH = 13;
|
||||
const INPUTGRID_HEIGHT = 5;
|
||||
|
||||
native static TextEnterMenu Open(Menu parent, String text, int maxlen, int sizemode, bool fromcontroller);
|
||||
native String GetText();
|
||||
const Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+-=.,!?@'\":;[]()<>^#$%&*/_ \b";
|
||||
|
||||
String mEnterString;
|
||||
int mEnterSize;
|
||||
int mEnterPos;
|
||||
int mSizeMode; // 1: size is length in chars. 2: also check string width
|
||||
bool mInputGridOkay;
|
||||
int InputGridX;
|
||||
int InputGridY;
|
||||
bool AllowColors;
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
// [TP] Added allowcolors
|
||||
private void Init(Menu parent, String textbuffer, int maxlen, int sizemode, bool showgrid, bool allowcolors)
|
||||
{
|
||||
Super.init(parent);
|
||||
mEnterString = textbuffer;
|
||||
mEnterSize = maxlen < 0 ? 0x7fffffff : maxlen;
|
||||
mSizeMode = sizemode;
|
||||
mInputGridOkay = showgrid || m_showinputgrid;
|
||||
if (mEnterString.Length() > 0)
|
||||
{
|
||||
InputGridX = INPUTGRID_WIDTH - 1;
|
||||
InputGridY = INPUTGRID_HEIGHT - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we are naming a new save, don't start the cursor on "end".
|
||||
InputGridX = 0;
|
||||
InputGridY = 0;
|
||||
}
|
||||
AllowColors = allowcolors; // [TP]
|
||||
}
|
||||
|
||||
static TextEnterMenu Open(Menu parent, String textbuffer, int maxlen, int sizemode, bool showgrid = false, bool allowcolors = false)
|
||||
{
|
||||
let me = new("TextEnterMenu");
|
||||
me.Init(parent, textbuffer, maxlen, sizemode, showgrid, allowcolors);
|
||||
return me;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
String GetText()
|
||||
{
|
||||
return mEnterString;
|
||||
}
|
||||
|
||||
override bool TranslateKeyboardEvents()
|
||||
{
|
||||
return mInputGridOkay;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool Responder(InputEventData ev)
|
||||
{
|
||||
if (ev.type == InputEventData.GUI_Event)
|
||||
{
|
||||
// Save game and player name string input
|
||||
if (ev.subtype == InputEventData.GUI_Char)
|
||||
{
|
||||
mInputGridOkay = false;
|
||||
if (mEnterString.Length() < mEnterSize &&
|
||||
(mSizeMode == 2/*entering player name*/ || SmallFont.StringWidth(mEnterString) < (mEnterSize-1)*8))
|
||||
{
|
||||
mEnterString.AppendFormat("%c", ev.data1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
int ch = ev.data1;
|
||||
if ((ev.subtype == InputEventData.GUI_KeyDown || ev.subtype == InputEventData.GUI_KeyRepeat) && ch == 8)
|
||||
{
|
||||
if (mEnterString.Length() > 0)
|
||||
{
|
||||
mEnterString.Truncate(mEnterString.Length() - 1);
|
||||
}
|
||||
}
|
||||
else if (ev.subtype == InputEventData.GUI_KeyDown)
|
||||
{
|
||||
if (ch == UIEvent.Key_ESCAPE)
|
||||
{
|
||||
Menu parent = mParentMenu;
|
||||
Close();
|
||||
parent.MenuEvent(MKEY_Abort, false);
|
||||
return true;
|
||||
}
|
||||
else if (ch == 13)
|
||||
{
|
||||
if (mEnterString.Length() > 0)
|
||||
{
|
||||
// [TP] If we allow color codes, colorize the string now.
|
||||
if (AllowColors)
|
||||
mEnterString = mEnterString.Filter();
|
||||
|
||||
Menu parent = mParentMenu;
|
||||
parent.MenuEvent(MKEY_Input, false);
|
||||
Close();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ev.subtype == InputEventData.GUI_KeyDown || ev.subtype == InputEventData.GUI_KeyRepeat)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return Super.Responder(ev);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool MouseEvent(int type, int x, int y)
|
||||
{
|
||||
if (mMouseCapture || m_use_mouse == 1)
|
||||
{
|
||||
int cell_width = 18 * CleanXfac;
|
||||
int cell_height = 12 * CleanYfac;
|
||||
int screen_y = screen.GetHeight() - INPUTGRID_HEIGHT * cell_height;
|
||||
int screen_x = (screen.GetWidth() - INPUTGRID_WIDTH * cell_width) / 2;
|
||||
|
||||
if (x >= screen_x && x < screen_x + INPUTGRID_WIDTH * cell_width && y >= screen_y)
|
||||
{
|
||||
InputGridX = (x - screen_x) / cell_width;
|
||||
InputGridY = (y - screen_y) / cell_height;
|
||||
if (type == MOUSE_Release)
|
||||
{
|
||||
if (MenuEvent(MKEY_Enter, true))
|
||||
{
|
||||
MenuSound("menu/choose");
|
||||
if (m_use_mouse == 2) InputGridX = InputGridY = -1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
InputGridX = InputGridY = -1;
|
||||
}
|
||||
}
|
||||
return Super.MouseEvent(type, x, y);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool MenuEvent (int key, bool fromcontroller)
|
||||
{
|
||||
String InputGridChars = Chars;
|
||||
if (key == MKEY_Back)
|
||||
{
|
||||
mParentMenu.MenuEvent(MKEY_Abort, false);
|
||||
return Super.MenuEvent(key, fromcontroller);
|
||||
}
|
||||
if (fromcontroller)
|
||||
{
|
||||
mInputGridOkay = true;
|
||||
}
|
||||
|
||||
if (mInputGridOkay)
|
||||
{
|
||||
int ch;
|
||||
|
||||
if (InputGridX == -1 || InputGridY == -1)
|
||||
{
|
||||
InputGridX = InputGridY = 0;
|
||||
}
|
||||
switch (key)
|
||||
{
|
||||
case MKEY_Down:
|
||||
InputGridY = (InputGridY + 1) % INPUTGRID_HEIGHT;
|
||||
return true;
|
||||
|
||||
case MKEY_Up:
|
||||
InputGridY = (InputGridY + INPUTGRID_HEIGHT - 1) % INPUTGRID_HEIGHT;
|
||||
return true;
|
||||
|
||||
case MKEY_Right:
|
||||
InputGridX = (InputGridX + 1) % INPUTGRID_WIDTH;
|
||||
return true;
|
||||
|
||||
case MKEY_Left:
|
||||
InputGridX = (InputGridX + INPUTGRID_WIDTH - 1) % INPUTGRID_WIDTH;
|
||||
return true;
|
||||
|
||||
case MKEY_Clear:
|
||||
if (mEnterString.Length() > 0)
|
||||
{
|
||||
mEnterString.Truncate(mEnterString.Length() - 1);
|
||||
}
|
||||
return true;
|
||||
|
||||
case MKEY_Enter:
|
||||
if (mInputGridOkay)
|
||||
{
|
||||
String c = InputGridChars.CharAt(InputGridX + InputGridY * INPUTGRID_WIDTH);
|
||||
int ch = c.CharCodeAt(0);
|
||||
if (ch == 0) // end
|
||||
{
|
||||
if (mEnterString.Length() > 0)
|
||||
{
|
||||
Menu parent = mParentMenu;
|
||||
Close();
|
||||
parent.MenuEvent(MKEY_Input, false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (ch == 8) // bs
|
||||
{
|
||||
if (mEnterString.Length() > 0)
|
||||
{
|
||||
mEnterString.Truncate(mEnterString.Length() - 1);
|
||||
}
|
||||
}
|
||||
else if (mEnterString.Length() < mEnterSize &&
|
||||
(mSizeMode == 2/*entering player name*/ || SmallFont.StringWidth(mEnterString) < (mEnterSize-1)*8))
|
||||
{
|
||||
mEnterString = mEnterString .. c;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
default:
|
||||
break; // Keep GCC quiet
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override void Drawer ()
|
||||
{
|
||||
mParentMenu.Drawer();
|
||||
if (mInputGridOkay)
|
||||
{
|
||||
String InputGridChars = Chars;
|
||||
int cell_width = 18 * CleanXfac;
|
||||
int cell_height = 12 * CleanYfac;
|
||||
int top_padding = cell_height / 2 - SmallFont.GetHeight() * CleanYfac / 2;
|
||||
|
||||
// Darken the background behind the character grid.
|
||||
screen.Dim(0, 0.8, 0, screen.GetHeight() - INPUTGRID_HEIGHT * cell_height, screen.GetWidth(), INPUTGRID_HEIGHT * cell_height);
|
||||
|
||||
if (InputGridX >= 0 && InputGridY >= 0)
|
||||
{
|
||||
// Highlight the background behind the selected character.
|
||||
screen.Dim(Color(255,248,220), 0.6,
|
||||
InputGridX * cell_width - INPUTGRID_WIDTH * cell_width / 2 + screen.GetWidth() / 2,
|
||||
InputGridY * cell_height - INPUTGRID_HEIGHT * cell_height + screen.GetHeight(),
|
||||
cell_width, cell_height);
|
||||
}
|
||||
|
||||
for (int y = 0; y < INPUTGRID_HEIGHT; ++y)
|
||||
{
|
||||
int yy = y * cell_height - INPUTGRID_HEIGHT * cell_height + screen.GetHeight();
|
||||
for (int x = 0; x < INPUTGRID_WIDTH; ++x)
|
||||
{
|
||||
int xx = x * cell_width - INPUTGRID_WIDTH * cell_width / 2 + screen.GetWidth() / 2;
|
||||
int ch = InputGridChars.CharCodeAt(y * INPUTGRID_WIDTH + x);
|
||||
int width = SmallFont.GetCharWidth(ch);
|
||||
|
||||
// The highlighted character is yellow; the rest are dark gray.
|
||||
int colr = (x == InputGridX && y == InputGridY) ? Font.CR_YELLOW : Font.CR_DARKGRAY;
|
||||
Color palcolor = (x == InputGridX && y == InputGridY) ? Color(160, 120, 0) : Color(120, 120, 120);
|
||||
|
||||
if (ch > 32)
|
||||
{
|
||||
// Draw a normal character.
|
||||
screen.DrawChar(SmallFont, colr, xx + cell_width/2 - width*CleanXfac/2, yy + top_padding, ch, DTA_CleanNoMove, true);
|
||||
}
|
||||
else if (ch == 32)
|
||||
{
|
||||
// Draw the space as a box outline. We also draw it 50% wider than it really is.
|
||||
int x1 = xx + cell_width/2 - width * CleanXfac * 3 / 4;
|
||||
int x2 = x1 + width * 3 * CleanXfac / 2;
|
||||
int y1 = yy + top_padding;
|
||||
int y2 = y1 + SmallFont.GetHeight() * CleanYfac;
|
||||
screen.Clear(x1, y1, x2, y1+CleanYfac, palcolor); // top
|
||||
screen.Clear(x1, y2, x2, y2+CleanYfac, palcolor); // bottom
|
||||
screen.Clear(x1, y1+CleanYfac, x1+CleanXfac, y2, palcolor); // left
|
||||
screen.Clear(x2-CleanXfac, y1+CleanYfac, x2, y2, palcolor); // right
|
||||
}
|
||||
else if (ch == 8 || ch == 0)
|
||||
{
|
||||
// Draw the backspace and end "characters".
|
||||
String str = ch == 8 ? "BS" : "ED";
|
||||
screen.DrawText(SmallFont, colr,
|
||||
xx + cell_width/2 - SmallFont.StringWidth(str)*CleanXfac/2,
|
||||
yy + top_padding, str, DTA_CleanNoMove, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Super.Drawer();
|
||||
}
|
||||
|
||||
}
|
|
@ -136,6 +136,8 @@ class PlayerPawn : Actor native
|
|||
native int GetMaxHealth();
|
||||
native bool ResetAirSupply (bool playgasp = false);
|
||||
native void CheckWeaponSwitch(class<Inventory> item);
|
||||
native static String GetPrintableDisplayName(Class<Actor> cls);
|
||||
|
||||
}
|
||||
|
||||
class PlayerChunk : PlayerPawn
|
||||
|
@ -293,7 +295,6 @@ struct PlayerInfo native // this is what internally is known as player_t
|
|||
/* these are not doable yet
|
||||
ticcmd_t cmd;
|
||||
usercmd_t original_cmd;
|
||||
userinfo_t userinfo;
|
||||
*/
|
||||
|
||||
|
||||
|
@ -307,11 +308,18 @@ userinfo_t userinfo;
|
|||
native PSprite FindPSprite(int id);
|
||||
native void SetLogNumber (int text);
|
||||
native void SetLogText (String text);
|
||||
native String GetUserName();
|
||||
native bool GetNeverSwitch();
|
||||
native void DropWeapon();
|
||||
native void BringUpWeapon();
|
||||
|
||||
native String GetUserName();
|
||||
native Color GetColor();
|
||||
native int GetColorSet();
|
||||
native int GetPlayerClassNum();
|
||||
native int GetSkin();
|
||||
native bool GetNeverSwitch();
|
||||
native int GetGender();
|
||||
native int GetTeam();
|
||||
native float GetAutoaim();
|
||||
}
|
||||
|
||||
struct PlayerClass native
|
||||
|
@ -321,4 +329,27 @@ struct PlayerClass native
|
|||
native Array<int> Skins;
|
||||
|
||||
native bool CheckSkin(int skin);
|
||||
native void EnumColorsets(out Array<int> data);
|
||||
native Name GetColorsetName(int setnum);
|
||||
}
|
||||
|
||||
struct PlayerSkin native
|
||||
{
|
||||
native readonly String SkinName;
|
||||
native readonly String Face;
|
||||
native readonly uint8 gender;
|
||||
native readonly uint8 range0start;
|
||||
native readonly uint8 range0end;
|
||||
native readonly bool othergame;
|
||||
native readonly Vector2 Scale;
|
||||
native readonly int sprite;
|
||||
native readonly int crouchsprite;
|
||||
native readonly int namespc;
|
||||
};
|
||||
|
||||
struct Team native
|
||||
{
|
||||
const NoTeam = 255;
|
||||
const Max = 16;
|
||||
native String mName;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue