This commit is contained in:
Rachael Alexanderson 2016-10-30 21:36:13 -04:00
commit de2122e2aa
7 changed files with 208 additions and 23 deletions

View file

@ -87,16 +87,14 @@ conversation // Starts a dialog.
page // Starts a new page. Pages are automatically numbered starting at 1.
{
name = <string>; // Name that goes in the upper left hand corner
panel = <string>; // Name of lump to render as the background.
voice = <string>; // Narration sound lump.
dialog = <string>; // Dialog of the page.
goodbye = <string>; // Custom goodbye message. If omitted then the
// generic goodbyes will be displayed instead.
drop = <integer>; // mobj for the object to drop if the actor is
// killed.
link = <integer>; // Page to jump to if all ifitem conditions are
// satisified.
name = <string>; // Name that goes in the upper left hand corner
panel = <string>; // Name of lump to render as the background.
voice = <string>; // Narration sound lump.
dialog = <string>; // Dialog of the page.
drop = <integer>; // mobj for the object to drop if the actor is
// killed.
link = <integer>; // Page to jump to if all ifitem conditions are
// satisified.
// jumps to the specified page if the player has the specified amount
// or more of item in their inventory. This can be repeated as many

View file

@ -76,8 +76,8 @@ namespace = "ZDoom";
III.A : Conversations
---------------------
This block only lists the newly added fields. Currently ZDoom only adds one
field to the specification:
This block only lists the newly added fields. Currently ZDoom only adds a few
fields to the specification:
conversation // Starts a dialog.
{
@ -86,6 +86,35 @@ 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.
page
{
goodbye = <string>; // Custom goodbye message. If omitted then the
// generic goodbyes will be displayed instead.
choice
{
// The amount of an item needed for this option to become available.
// You can have as many as needed. All require blocks must be satisfied
// to show this option.
require
{
item = <string>; // Item that is required to show this option.
amount = <integer>; // Minimum amount of the item needed.
}
// The undesired amount of an item. This option will become available
// if you have less than the specified amount. You can have as many
// as needed. All exclude blocks must be satisfied to show this option.
// Note: if both require and exclude are defined then all require
// and all exclude blocks must be satisfied to show this option.
exclude
{
item = <string>; // Item that is unwanted to show this option.
amount = <integer>; // Unwanted minimum amount of the item.
}
}
}
}
===============================================================================

View file

@ -585,6 +585,8 @@ xx(Ifitem)
xx(Choice)
xx(Link)
xx(Goodbye)
xx(Require)
xx(Exclude)
// Special menus
xx(Mainmenu)

View file

@ -516,6 +516,8 @@ static void ParseReplies (FStrifeDialogueReply **replyptr, Response *responses)
reply->ItemCheck[k].Item = dyn_cast<PClassInventory>(GetStrifeType(rsp->Item[k]));
reply->ItemCheck[k].Amount = rsp->Count[k];
}
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.
@ -656,6 +658,38 @@ CUSTOM_CVAR(Float, dlg_musicvolume, 1.0f, CVAR_ARCHIVE)
else if (self > 1.f) self = 1.f;
}
//============================================================================
//
// ShouldSkipReply
//
// Determines whether this reply should be skipped or not.
//
//============================================================================
static bool ShouldSkipReply(FStrifeDialogueReply *reply, player_t *player)
{
if (reply->Reply == nullptr)
return true;
int i;
for (i = 0; i < (int)reply->ItemCheckRequire.Size(); ++i)
{
if (!CheckStrifeItem(player, reply->ItemCheckRequire[i].Item, reply->ItemCheckRequire[i].Amount))
{
return true;
}
}
for (i = 0; i < (int)reply->ItemCheckExclude.Size(); ++i)
{
if (CheckStrifeItem(player, reply->ItemCheckExclude[i].Item, reply->ItemCheckExclude[i].Amount))
{
return true;
}
}
return false;
}
//============================================================================
//
// The conversation menu
@ -673,6 +707,7 @@ class DConversationMenu : public DMenu
bool mShowGold;
FStrifeDialogueNode *mCurNode;
int mYpos;
player_t *mPlayer;
public:
static int mSelection;
@ -683,9 +718,10 @@ public:
//
//=============================================================================
DConversationMenu(FStrifeDialogueNode *CurNode)
DConversationMenu(FStrifeDialogueNode *CurNode, player_t *player)
{
mCurNode = CurNode;
mPlayer = player;
mDialogueLines = NULL;
mShowGold = false;
@ -720,7 +756,7 @@ public:
int i,j;
for (reply = CurNode->Children, i = 1; reply != NULL; reply = reply->Next)
{
if (reply->Reply == NULL)
if (ShouldSkipReply(reply, mPlayer))
{
continue;
}
@ -778,6 +814,13 @@ public:
}
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;
}
}
//=============================================================================
@ -839,12 +882,24 @@ public:
}
else
{
// Send dialogue and reply numbers across the wire.
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(mSelection);
Net_WriteByte(replynum);
}
Close();
return true;
@ -1169,7 +1224,7 @@ 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);
DConversationMenu *cmenu = new DConversationMenu(CurNode, pc->player);
if (CurNode != PrevNode)

View file

@ -45,6 +45,8 @@ struct FStrifeDialogueReply
int ActionSpecial;
int Args[5];
TArray<FStrifeDialogueItemCheck> ItemCheck;
TArray<FStrifeDialogueItemCheck> ItemCheckRequire;
TArray<FStrifeDialogueItemCheck> ItemCheckExclude;
char *Reply;
char *QuickYes;
int NextNode; // index into StrifeDialogues

View file

@ -76,11 +76,11 @@ class USDFParser : public UDMFParserBase
//===========================================================================
//
// Parse a cost block
// Parse a cost/require/exclude block
//
//===========================================================================
bool ParseCost(FStrifeDialogueReply *response)
bool ParseCostRequireExclude(FStrifeDialogueReply *response, FName type)
{
FStrifeDialogueItemCheck check;
check.Item = NULL;
@ -101,7 +101,12 @@ class USDFParser : public UDMFParserBase
}
}
response->ItemCheck.Push(check);
switch (type)
{
case NAME_Cost: response->ItemCheck.Push(check); break;
case NAME_Require: response->ItemCheckRequire.Push(check); break;
case NAME_Exclude: response->ItemCheckExclude.Push(check); break;
}
return true;
}
@ -206,8 +211,15 @@ class USDFParser : public UDMFParserBase
switch(key)
{
case NAME_Cost:
ParseCost(reply);
break;
case NAME_Require:
case NAME_Exclude:
// Require and Exclude are exclusive to namespace ZDoom. [FishyClockwork]
if (key == NAME_Cost || namespace_bits == Zd)
{
ParseCostRequireExclude(reply, key);
break;
}
// Intentional fall-through
default:
sc.UnGet();
@ -333,7 +345,11 @@ class USDFParser : public UDMFParserBase
break;
case NAME_Goodbye:
Goodbye = CheckString(key);
// Custom goodbyes are exclusive to namespace ZDoom. [FishyClockwork]
if (namespace_bits == Zd)
{
Goodbye = CheckString(key);
}
break;
}
}

83
src/posix/zdoom.xpm Normal file
View file

@ -0,0 +1,83 @@
/* XPM */
static char * zdoom_xpm[] = {
"48 48 32 1",
" c None",
". c #ADA990",
"+ c #999966",
"@ c #666666",
"# c #393939",
"$ c #555555",
"% c #996666",
"& c #777777",
"* c #5F5F5F",
"= c #333333",
"- c #4D4D4D",
"; c #868686",
"> c #969696",
", c #1C1C1C",
"' c #339933",
") c #336633",
"! c #66CC66",
"~ c #66FF66",
"{ c #66CC33",
"] c #222222",
"^ c #333300",
"/ c #292929",
"( c #040404",
"_ c #0C0C0C",
": c #663333",
"< c #996633",
"[ c #CC9966",
"} c #CC6633",
"| c #CC9999",
"1 c #FFCC99",
"2 c #FF9966",
"3 c #FFCCCC",
" ... ",
" ++@##$+ ",
" +...+%&+ ",
" %*=-*&;$=&* ",
" %**=$@;>@=&*% ",
" &**@$*@@$-.+& ",
" %$%@*..$@.. ",
" ,#@+++@@#& ",
" $,#$$@@$#=$'' ",
" )!!!~!{=],,,,]^)'!{') =/, ",
" )){'~!!'')=],=))'{)'')) /=],( ",
" )'!!'!)~'{'),)''''''')) @@/==](( ",
" ^)''')'{{''')'''''),))) $$@$/,( ",
" ,^))),))''''))'')^,__/$$$-#-(( ",
" :<[}<,_)))))))),___,]#@@-/]] ",
" :<|12<:_,,,,,_,#$$-#/,^^=^}}< ",
" :<[1}::,^,,__,#$-==/,,::^:<<< ",
" ::&+@#^,,__/)#-=/,,,,-::^<::= ",
" :*+12[:==_,$-=/,,,,/,#::::=^ ",
" #*}331}-$]-==/,,,,// ##:=^ ",
" /]<13[---],,,,,,,]_] ",
" ,:--/,___]]]]:^___/ ",
" _______,^^,^,__/# ",
" ______:::::/$,,/# ",
" ____^:::=,^^^^,^^ ",
" __,,:=^,,)))^,,= ",
" _,,),,,,,^)^^^,, ",
" ,^,,),__,^))),,^ ",
" ,,,^^,,,,,)))),, ",
" ,,,,,,,)^))))^ ",
" ,,^,,,^^)))))^ ",
" ,^^,,,,)))))), ",
" ,^,,,,))^))), ",
" ],,,,,$&&&*$# ",
" ],,,]#****$# ",
" ]]]]]^####, ",
" ]]]]*,,,,#* ",
" ,_,#@&&@*/ ",
" __$####=# ",
" ,_/$$$$$# ",
" ,,,$*$$$ ",
" ],,,$**$# ",
" ],,,@&&@# ",
" ],,,$**#= ",
" ,,=+++%$ ",
" *%%%*$ ",
" /$*$#/ ",
" ],,]] "};