- exported all texts from Strife's dialogues to the string table.

Now all this content can be localized. However, since this is actual game content it was placed in a secondary file in zd_extra.pk3, so that it won't affect the GPL-compatible status of the main one.
This commit is contained in:
Christoph Oelckers 2019-02-05 13:39:38 +01:00
commit 0936a2fa19
3 changed files with 1209 additions and 148 deletions

View file

@ -103,10 +103,10 @@ static int ConversationMenuY;
static FStrifeDialogueNode *PrevNode;
static int StaticLastReply;
static bool LoadScriptFile(FLevelLocals *Level, int lumpnum, FileReader &lump, int numnodes, bool include, int type);
static FStrifeDialogueNode *ReadRetailNode (FLevelLocals *Level, FileReader &lump, uint32_t &prevSpeakerType);
static FStrifeDialogueNode *ReadTeaserNode (FLevelLocals *Level, FileReader &lump, uint32_t &prevSpeakerType);
static void ParseReplies (FStrifeDialogueReply **replyptr, Response *responses);
static bool LoadScriptFile(FLevelLocals *Level, const char *name, int lumpnum, FileReader &lump, int numnodes, bool include, int type);
static FStrifeDialogueNode *ReadRetailNode (FLevelLocals *Level, const char *name, FileReader &lump, uint32_t &prevSpeakerType);
static FStrifeDialogueNode *ReadTeaserNode (FLevelLocals *Level, const char *name, FileReader &lump, uint32_t &prevSpeakerType);
static void ParseReplies (const char *name, int pos, FStrifeDialogueReply **replyptr, Response *responses);
static bool DrawConversationMenu ();
static void PickConversationReply (int replyindex);
static void TerminalResponse (const char *str);
@ -165,7 +165,7 @@ void P_LoadStrifeConversations (FLevelLocals *Level, MapData *map, const char *m
{
if (map->Size(ML_CONVERSATION) > 0)
{
LoadScriptFile (Level, map->lumpnum, map->Reader(ML_CONVERSATION), map->Size(ML_CONVERSATION), false, 0);
LoadScriptFile (Level, nullptr, map->lumpnum, map->Reader(ML_CONVERSATION), map->Size(ML_CONVERSATION), false, 0);
}
else
{
@ -218,11 +218,16 @@ bool LoadScriptFile (FLevelLocals *Level, const char *name, bool include, int ty
}
FileReader lump = Wads.ReopenLumpReader (lumpnum);
bool res = LoadScriptFile(Level, lumpnum, lump, Wads.LumpLength(lumpnum), include, type);
auto fn = Wads.GetLumpFile(lumpnum);
auto wadname = Wads.GetWadName(fn);
if (stricmp(wadname, "STRIFE0.WAD") && stricmp(wadname, "STRIFE1.WAD") && stricmp(wadname, "SVE.WAD")) name = nullptr; // Only localize IWAD content.
if (name && !stricmp(name, "SCRIPT00")) name = nullptr; // This only contains random string references which already use the string table.
bool res = LoadScriptFile(Level, name, lumpnum, lump, Wads.LumpLength(lumpnum), include, type);
return res;
}
static bool LoadScriptFile(FLevelLocals *Level, int lumpnum, FileReader &lump, int numnodes, bool include, int type)
static bool LoadScriptFile(FLevelLocals *Level, const char *name, int lumpnum, FileReader &lump, int numnodes, bool include, int type)
{
int i;
uint32_t prevSpeakerType;
@ -279,11 +284,11 @@ static bool LoadScriptFile(FLevelLocals *Level, int lumpnum, FileReader &lump, i
{
if (!(gameinfo.flags & GI_SHAREWARE))
{
node = ReadRetailNode (Level, lump, prevSpeakerType);
node = ReadRetailNode (Level, name, lump, prevSpeakerType);
}
else
{
node = ReadTeaserNode (Level, lump, prevSpeakerType);
node = ReadTeaserNode (Level, name, lump, prevSpeakerType);
}
node->ThisNodeNum = Level->StrifeDialogues.Push(node);
}
@ -299,7 +304,17 @@ static bool LoadScriptFile(FLevelLocals *Level, int lumpnum, FileReader &lump, i
//
//============================================================================
static FStrifeDialogueNode *ReadRetailNode (FLevelLocals *Level, FileReader &lump, uint32_t &prevSpeakerType)
static FString TokenFromString(const char *speech)
{
FString token = speech;
token.ToUpper();
token.ReplaceChars(".,-+!?'", ' ');
token.Substitute(" ", "");
token.Truncate(5);
return token;
}
static FStrifeDialogueNode *ReadRetailNode (FLevelLocals *Level, const char *name, FileReader &lump, uint32_t &prevSpeakerType)
{
FStrifeDialogueNode *node;
Speech speech;
@ -309,6 +324,7 @@ static FStrifeDialogueNode *ReadRetailNode (FLevelLocals *Level, FileReader &lum
node = new FStrifeDialogueNode;
auto pos = lump.Tell();
lump.Read (&speech, sizeof(speech));
// Byte swap all the ints in the original data
@ -332,7 +348,16 @@ static FStrifeDialogueNode *ReadRetailNode (FLevelLocals *Level, FileReader &lum
}
// Convert the rest of the data to our own internal format.
node->Dialogue = speech.Dialogue;
if (name)
{
FStringf label("$TXT_DLG_%s_d%d_%s", name, int(pos), TokenFromString(speech.Dialogue));
node->Dialogue = label;
}
else
{
node->Dialogue = speech.Dialogue;
}
// The speaker's portrait, if any.
speech.Dialogue[0] = 0; //speech.Backdrop[8] = 0;
@ -362,7 +387,7 @@ static FStrifeDialogueNode *ReadRetailNode (FLevelLocals *Level, FileReader &lum
node->ItemCheckNode = speech.Link;
node->Children = NULL;
ParseReplies (&node->Children, &speech.Responses[0]);
ParseReplies (name, int(pos), &node->Children, &speech.Responses[0]);
return node;
}
@ -375,7 +400,7 @@ static FStrifeDialogueNode *ReadRetailNode (FLevelLocals *Level, FileReader &lum
//
//============================================================================
static FStrifeDialogueNode *ReadTeaserNode (FLevelLocals *Level, FileReader &lump, uint32_t &prevSpeakerType)
static FStrifeDialogueNode *ReadTeaserNode (FLevelLocals *Level, const char *name, FileReader &lump, uint32_t &prevSpeakerType)
{
FStrifeDialogueNode *node;
TeaserSpeech speech;
@ -385,6 +410,7 @@ static FStrifeDialogueNode *ReadTeaserNode (FLevelLocals *Level, FileReader &lum
node = new FStrifeDialogueNode;
auto pos = lump.Tell() * 1516 / 1488;
lump.Read (&speech, sizeof(speech));
// Byte swap all the ints in the original data
@ -407,7 +433,15 @@ static FStrifeDialogueNode *ReadTeaserNode (FLevelLocals *Level, FileReader &lum
}
// Convert the rest of the data to our own internal format.
node->Dialogue = speech.Dialogue;
if (name)
{
FStringf label("$TXT_DLG_%s_d%d_%s", name, pos, TokenFromString(speech.Dialogue));
node->Dialogue = label;
}
else
{
node->Dialogue = speech.Dialogue;
}
// The Teaser version doesn't have portraits.
node->Backdrop = "";
@ -440,7 +474,7 @@ static FStrifeDialogueNode *ReadTeaserNode (FLevelLocals *Level, FileReader &lum
node->ItemCheckNode = 0;
node->Children = NULL;
ParseReplies (&node->Children, &speech.Responses[0]);
ParseReplies (name, int(pos), &node->Children, &speech.Responses[0]);
return node;
}
@ -455,7 +489,7 @@ static FStrifeDialogueNode *ReadTeaserNode (FLevelLocals *Level, FileReader &lum
//
//============================================================================
static void ParseReplies (FStrifeDialogueReply **replyptr, Response *responses)
static void ParseReplies (const char *name, int pos, FStrifeDialogueReply **replyptr, Response *responses)
{
FStrifeDialogueReply *reply;
int j, k;
@ -509,24 +543,52 @@ static void ParseReplies (FStrifeDialogueReply **replyptr, Response *responses)
reply->ItemCheckRequire.Clear();
reply->ItemCheckExclude.Clear();
if (name)
{
FStringf label("$TXT_RPLY%d_%s_d%d_%s", j, name, pos, TokenFromString(rsp->Reply));
reply->Reply = label;
}
else
{
reply->Reply = rsp->Reply;
}
// 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 = 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)
// Note that empty nodes contain a '_' in retail Strife, a '.' in the teasers and an empty string in SVE.
if (((rsp->Yes[0] == '_' || rsp->Yes[0] == '.') && rsp->Yes[1] == 0) || rsp->Yes[0] == 0)
{
reply->QuickYes = "";
}
else
{
reply->QuickYes = rsp->Yes;
if (name)
{
FStringf label("$TXT_RYES%d_%s_d%d_%s", j, name, pos, TokenFromString(rsp->Yes));
reply->QuickYes = label;
}
else
{
reply->QuickYes = rsp->Yes;
}
}
if (reply->ItemCheck[0].Item != 0)
{
reply->QuickNo = rsp->No;
if (name && strncmp(rsp->No, "NO. ", 4)) // All 'no' nodes starting with 'NO.' won't ever be shown and they all contain broken text.
{
FStringf label("$TXT_RNO%d_%s_d%d_%s", j, name, pos, TokenFromString(rsp->No));
reply->QuickNo = label;
}
else
{
reply->QuickNo = rsp->No;
}
}
else
{