mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-27 06:22:43 +00:00
Squashed commit of the following:
- Implement page string names for dialog lumps - Create special new GZDoom name space for ZSDF - add usdf_gzdoom spec document - fixed: restored original behavior with negative conversation id's for the original strife dialog lumps - reposition the binary strife fix in a more appropriate location - add compatibility fix for negative numbers in responses in USDF/ZSDF (don't know if it's actually necessary)
This commit is contained in:
parent
c7103cbe4d
commit
35e2d40641
5 changed files with 165 additions and 15 deletions
63
specs/usdf_gzdoom.txt
Normal file
63
specs/usdf_gzdoom.txt
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
===============================================================================
|
||||||
|
GZDoom Strife Dialog Format v1.0
|
||||||
|
based on ZDoom Strife Dialog Format ZDoom v1.1 - 23.08.2010
|
||||||
|
|
||||||
|
Copyright (c) 2019 Rachael Alexanderson
|
||||||
|
uses ZDoom Strife Dialog Format ZDoom v1.1 as a template,
|
||||||
|
original document Copyright (c) 2010 Christoph Oelckers.
|
||||||
|
Permission is granted to copy, distribute and/or modify this document
|
||||||
|
under the terms of the GNU Free Documentation License, Version 1.2
|
||||||
|
or any later version published by the Free Software Foundation;
|
||||||
|
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
|
||||||
|
|
||||||
|
===============================================================================
|
||||||
|
|
||||||
|
=======================================
|
||||||
|
I. Grammar / Syntax
|
||||||
|
=======================================
|
||||||
|
|
||||||
|
No changes.
|
||||||
|
|
||||||
|
=======================================
|
||||||
|
II. Implementation Semantics
|
||||||
|
=======================================
|
||||||
|
|
||||||
|
No changes.
|
||||||
|
|
||||||
|
=======================================
|
||||||
|
III. Changes to ZSDF spec
|
||||||
|
=======================================
|
||||||
|
|
||||||
|
GZDoom Strife Dialogue format implements the ZSDF base specification as described with
|
||||||
|
the improvement of being able to name pages using strings.
|
||||||
|
|
||||||
|
GZDoom-format dialogues need to start with this line:
|
||||||
|
|
||||||
|
namespace = "GZDoom";
|
||||||
|
|
||||||
|
|
||||||
|
---------------------
|
||||||
|
III.A : Conversations
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
This block only lists the newly added fields. Currently GZDoom only modifies the following
|
||||||
|
fields and adds the "pagename" field to the specification:
|
||||||
|
|
||||||
|
conversation // Starts a dialog.
|
||||||
|
{
|
||||||
|
page
|
||||||
|
{
|
||||||
|
pagename = <string>; // names the current page, for linking using links or responses
|
||||||
|
link = <string|int>; // if int, uses the old system of linking page by number
|
||||||
|
// if string, will parse item links to a named page
|
||||||
|
|
||||||
|
choice
|
||||||
|
{
|
||||||
|
next = <string|int>; // same as link above, can either go to a name or id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
===============================================================================
|
||||||
|
EOF
|
||||||
|
===============================================================================
|
|
@ -521,6 +521,11 @@ static void ParseReplies (const char *name, int pos, FStrifeDialogueReply **repl
|
||||||
|
|
||||||
// The next node to use when this reply is chosen.
|
// The next node to use when this reply is chosen.
|
||||||
reply->NextNode = rsp->Link;
|
reply->NextNode = rsp->Link;
|
||||||
|
if (reply->NextNode < 0)
|
||||||
|
{
|
||||||
|
reply->NextNode *= -1;
|
||||||
|
reply->CloseDialog = false;
|
||||||
|
}
|
||||||
|
|
||||||
// The message to record in the log for this reply.
|
// The message to record in the log for this reply.
|
||||||
reply->LogNumber = rsp->Log;
|
reply->LogNumber = rsp->Log;
|
||||||
|
@ -1073,14 +1078,13 @@ static void HandleReply(player_t *player, bool isconsole, int nodenum, int reply
|
||||||
if (reply->NextNode != 0)
|
if (reply->NextNode != 0)
|
||||||
{
|
{
|
||||||
int rootnode = npc->ConversationRoot;
|
int rootnode = npc->ConversationRoot;
|
||||||
const bool isNegative = reply->NextNode < 0;
|
const unsigned next = (unsigned)(rootnode + reply->NextNode - 1);
|
||||||
const unsigned next = (unsigned)(rootnode + (isNegative ? -1 : 1) * reply->NextNode - 1);
|
|
||||||
|
|
||||||
if (next < Level->StrifeDialogues.Size())
|
if (next < Level->StrifeDialogues.Size())
|
||||||
{
|
{
|
||||||
npc->Conversation = Level->StrifeDialogues[next];
|
npc->Conversation = Level->StrifeDialogues[next];
|
||||||
|
|
||||||
if (isNegative)
|
if (!(reply->CloseDialog))
|
||||||
{
|
{
|
||||||
if (gameaction != ga_slideshow)
|
if (gameaction != ga_slideshow)
|
||||||
{
|
{
|
||||||
|
|
|
@ -24,6 +24,8 @@ struct FStrifeDialogueNode
|
||||||
TArray<FStrifeDialogueItemCheck> ItemCheck;
|
TArray<FStrifeDialogueItemCheck> ItemCheck;
|
||||||
int ThisNodeNum = 0; // location of this node in StrifeDialogues
|
int ThisNodeNum = 0; // location of this node in StrifeDialogues
|
||||||
int ItemCheckNode = 0; // index into StrifeDialogues
|
int ItemCheckNode = 0; // index into StrifeDialogues
|
||||||
|
FString ThisNodeName = nullptr;
|
||||||
|
FString ItemCheckNodeName = nullptr;
|
||||||
|
|
||||||
PClassActor *SpeakerType = nullptr;
|
PClassActor *SpeakerType = nullptr;
|
||||||
FString SpeakerName;
|
FString SpeakerName;
|
||||||
|
@ -54,7 +56,9 @@ struct FStrifeDialogueReply
|
||||||
FString LogString;
|
FString LogString;
|
||||||
int NextNode = 0; // index into StrifeDialogues
|
int NextNode = 0; // index into StrifeDialogues
|
||||||
int LogNumber = 0;
|
int LogNumber = 0;
|
||||||
|
FString NextNodeName = nullptr;
|
||||||
bool NeedsGold = false;
|
bool NeedsGold = false;
|
||||||
|
bool CloseDialog = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MapData;
|
struct MapData;
|
||||||
|
|
101
src/p_usdf.cpp
101
src/p_usdf.cpp
|
@ -44,6 +44,7 @@
|
||||||
|
|
||||||
#define Zd 1
|
#define Zd 1
|
||||||
#define St 2
|
#define St 2
|
||||||
|
#define Gz 4
|
||||||
|
|
||||||
class USDFParser : public UDMFParserBase
|
class USDFParser : public UDMFParserBase
|
||||||
{
|
{
|
||||||
|
@ -62,7 +63,7 @@ class USDFParser : public UDMFParserBase
|
||||||
{
|
{
|
||||||
type = GetStrifeType(CheckInt(key));
|
type = GetStrifeType(CheckInt(key));
|
||||||
}
|
}
|
||||||
else if (namespace_bits == Zd)
|
else if (namespace_bits & ( Zd | Gz ))
|
||||||
{
|
{
|
||||||
PClassActor *cls = PClass::FindActor(CheckString(key));
|
PClassActor *cls = PClass::FindActor(CheckString(key));
|
||||||
if (cls == nullptr)
|
if (cls == nullptr)
|
||||||
|
@ -188,7 +189,10 @@ class USDFParser : public UDMFParserBase
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NAME_Nextpage:
|
case NAME_Nextpage:
|
||||||
reply->NextNode = CheckInt(key);
|
if (namespace_bits != Gz || sc.TokenType == TK_IntConst)
|
||||||
|
reply->NextNode = CheckInt(key);
|
||||||
|
else
|
||||||
|
reply->NextNodeName = CheckString(key);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NAME_Closedialog:
|
case NAME_Closedialog:
|
||||||
|
@ -202,7 +206,7 @@ class USDFParser : public UDMFParserBase
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NAME_SpecialName:
|
case NAME_SpecialName:
|
||||||
if (namespace_bits == Zd)
|
if (namespace_bits & ( Zd | Gz ))
|
||||||
reply->ActionSpecial = P_FindLineSpecial(CheckString(key));
|
reply->ActionSpecial = P_FindLineSpecial(CheckString(key));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -225,7 +229,7 @@ class USDFParser : public UDMFParserBase
|
||||||
case NAME_Require:
|
case NAME_Require:
|
||||||
case NAME_Exclude:
|
case NAME_Exclude:
|
||||||
// Require and Exclude are exclusive to namespace ZDoom. [FishyClockwork]
|
// Require and Exclude are exclusive to namespace ZDoom. [FishyClockwork]
|
||||||
if (key == NAME_Cost || namespace_bits == Zd)
|
if (key == NAME_Cost || (namespace_bits & ( Zd | Gz )))
|
||||||
{
|
{
|
||||||
ParseCostRequireExclude(reply, key);
|
ParseCostRequireExclude(reply, key);
|
||||||
break;
|
break;
|
||||||
|
@ -256,7 +260,15 @@ class USDFParser : public UDMFParserBase
|
||||||
reply->QuickNo = "";
|
reply->QuickNo = "";
|
||||||
}
|
}
|
||||||
reply->LogString = LogString;
|
reply->LogString = LogString;
|
||||||
if(!closeDialog) reply->NextNode *= -1;
|
if (reply->NextNode < 0) // compatibility: handle negative numbers
|
||||||
|
{
|
||||||
|
reply->CloseDialog = !closeDialog;
|
||||||
|
reply->NextNode *= -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reply->CloseDialog = closeDialog;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -318,6 +330,13 @@ class USDFParser : public UDMFParserBase
|
||||||
{
|
{
|
||||||
switch(key)
|
switch(key)
|
||||||
{
|
{
|
||||||
|
case NAME_Pagename:
|
||||||
|
if (namespace_bits != Gz)
|
||||||
|
sc.ScriptMessage("'PageName' keyword only supported in the GZDoom namespace!");
|
||||||
|
else
|
||||||
|
node->ThisNodeName = CheckString(key);
|
||||||
|
break;
|
||||||
|
|
||||||
case NAME_Name:
|
case NAME_Name:
|
||||||
SpeakerName = CheckString(key);
|
SpeakerName = CheckString(key);
|
||||||
break;
|
break;
|
||||||
|
@ -327,7 +346,7 @@ class USDFParser : public UDMFParserBase
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NAME_Userstring:
|
case NAME_Userstring:
|
||||||
if (namespace_bits == Zd)
|
if (namespace_bits & ( Zd | Gz ))
|
||||||
{
|
{
|
||||||
node->UserData = CheckString(key);
|
node->UserData = CheckString(key);
|
||||||
}
|
}
|
||||||
|
@ -341,7 +360,7 @@ class USDFParser : public UDMFParserBase
|
||||||
FString soundname = "svox/";
|
FString soundname = "svox/";
|
||||||
soundname += name;
|
soundname += name;
|
||||||
node->SpeakerVoice = FSoundID(S_FindSound(soundname));
|
node->SpeakerVoice = FSoundID(S_FindSound(soundname));
|
||||||
if (node->SpeakerVoice == 0 && namespace_bits == Zd)
|
if (node->SpeakerVoice == 0 && (namespace_bits & ( Zd | Gz )))
|
||||||
{
|
{
|
||||||
node->SpeakerVoice = FSoundID(S_FindSound(name));
|
node->SpeakerVoice = FSoundID(S_FindSound(name));
|
||||||
}
|
}
|
||||||
|
@ -358,12 +377,15 @@ class USDFParser : public UDMFParserBase
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NAME_Link:
|
case NAME_Link:
|
||||||
node->ItemCheckNode = CheckInt(key);
|
if (namespace_bits != Gz || sc.TokenType == TK_IntConst)
|
||||||
|
node->ItemCheckNode = CheckInt(key);
|
||||||
|
else
|
||||||
|
node->ItemCheckNodeName = CheckString(key);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NAME_Goodbye:
|
case NAME_Goodbye:
|
||||||
// Custom goodbyes are exclusive to namespace ZDoom. [FishyClockwork]
|
// Custom goodbyes are exclusive to namespace ZDoom. [FishyClockwork]
|
||||||
if (namespace_bits == Zd)
|
if (namespace_bits & ( Zd | Gz ))
|
||||||
{
|
{
|
||||||
Goodbye = CheckString(key);
|
Goodbye = CheckString(key);
|
||||||
}
|
}
|
||||||
|
@ -425,14 +447,14 @@ class USDFParser : public UDMFParserBase
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NAME_Id:
|
case NAME_Id:
|
||||||
if (namespace_bits == Zd)
|
if (namespace_bits & ( Zd | Gz ))
|
||||||
{
|
{
|
||||||
dlgid = CheckInt(key);
|
dlgid = CheckInt(key);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NAME_Class:
|
case NAME_Class:
|
||||||
if (namespace_bits == Zd)
|
if (namespace_bits & ( Zd | Gz ))
|
||||||
{
|
{
|
||||||
clsid = CheckString(key);
|
clsid = CheckString(key);
|
||||||
}
|
}
|
||||||
|
@ -487,6 +509,9 @@ public:
|
||||||
namespc = sc.String;
|
namespc = sc.String;
|
||||||
switch(namespc)
|
switch(namespc)
|
||||||
{
|
{
|
||||||
|
case NAME_GZDoom:
|
||||||
|
namespace_bits = Gz;
|
||||||
|
break;
|
||||||
case NAME_ZDoom:
|
case NAME_ZDoom:
|
||||||
namespace_bits = Zd;
|
namespace_bits = Zd;
|
||||||
break;
|
break;
|
||||||
|
@ -501,7 +526,7 @@ public:
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sc.ScriptMessage("Map does not define a namespace.\n");
|
sc.ScriptMessage("Dialog script does not define a namespace.\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -524,6 +549,58 @@ public:
|
||||||
Skip();
|
Skip();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (namespace_bits == Gz) // string page name linker
|
||||||
|
{
|
||||||
|
int numnodes = Level->StrifeDialogues.Size();
|
||||||
|
int usedstrings = false;
|
||||||
|
|
||||||
|
TMap<FString, int> nameToIndex;
|
||||||
|
for (int i = 0; i < numnodes; i++)
|
||||||
|
{
|
||||||
|
FString key = Level->StrifeDialogues[i]->ThisNodeName;
|
||||||
|
if (key.IsNotEmpty())
|
||||||
|
{
|
||||||
|
key.ToLower();
|
||||||
|
if (nameToIndex.CheckKey(key))
|
||||||
|
Printf("Warning! Duplicate page name '%s'!\n", Level->StrifeDialogues[i]->ThisNodeName.GetChars());
|
||||||
|
else
|
||||||
|
nameToIndex[key] = i;
|
||||||
|
usedstrings = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (usedstrings)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < numnodes; i++)
|
||||||
|
{
|
||||||
|
FString itemLinkKey = Level->StrifeDialogues[i]->ItemCheckNodeName;
|
||||||
|
if (itemLinkKey.IsNotEmpty())
|
||||||
|
{
|
||||||
|
itemLinkKey.ToLower();
|
||||||
|
if (nameToIndex.CheckKey(itemLinkKey))
|
||||||
|
Level->StrifeDialogues[i]->ItemCheckNode = nameToIndex[itemLinkKey] + 1;
|
||||||
|
else
|
||||||
|
Printf("Warning! Reference to non-existent item-linked dialogue page name '%s' in page %i!\n", Level->StrifeDialogues[i]->ItemCheckNodeName.GetChars(), i);
|
||||||
|
}
|
||||||
|
|
||||||
|
FStrifeDialogueReply *NodeCheck = Level->StrifeDialogues[i]->Children;
|
||||||
|
while (NodeCheck)
|
||||||
|
{
|
||||||
|
if (NodeCheck->NextNodeName.IsNotEmpty())
|
||||||
|
{
|
||||||
|
FString key = NodeCheck->NextNodeName;
|
||||||
|
key.ToLower();
|
||||||
|
if (nameToIndex.CheckKey(key))
|
||||||
|
NodeCheck->NextNode = nameToIndex[key] + 1;
|
||||||
|
else
|
||||||
|
Printf("Warning! Reference to non-existent reply-linked dialogue page name '%s' in page %i!\n", NodeCheck->NextNodeName.GetChars(), i);
|
||||||
|
}
|
||||||
|
NodeCheck = NodeCheck->Next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -565,6 +565,7 @@ xx(Monsterpush)
|
||||||
xx(ZDoom)
|
xx(ZDoom)
|
||||||
xx(ZDoomTranslated)
|
xx(ZDoomTranslated)
|
||||||
xx(Vavoom)
|
xx(Vavoom)
|
||||||
|
xx(GZDoom)
|
||||||
|
|
||||||
xx(Xpanningfloor)
|
xx(Xpanningfloor)
|
||||||
xx(Ypanningfloor)
|
xx(Ypanningfloor)
|
||||||
|
@ -742,6 +743,7 @@ xx(Require)
|
||||||
xx(Exclude)
|
xx(Exclude)
|
||||||
xx(Userstring)
|
xx(Userstring)
|
||||||
xx(Sky)
|
xx(Sky)
|
||||||
|
xx(Pagename)
|
||||||
|
|
||||||
// Special menus
|
// Special menus
|
||||||
xx(Mainmenu)
|
xx(Mainmenu)
|
||||||
|
|
Loading…
Reference in a new issue