Add 'NAME' and 'ICON' control codes

This commit is contained in:
Lactozilla 2024-01-12 14:51:14 -03:00
parent 1b9bd6d275
commit e8b96f6dba
6 changed files with 221 additions and 104 deletions

View file

@ -2255,17 +2255,12 @@ static void readtextpromptpage(MYFILE *f, INT32 num, INT32 pagenum)
{ {
if (*word2 != '\0') if (*word2 != '\0')
{ {
size_t j; char name[256];
// HACK: Add yellow control char now strlcpy(name, word2, sizeof(name));
// so the drawing function doesn't call it repeatedly
char name[34];
name[0] = '\x82'; // color yellow
name[1] = 0;
strlcat(name, word2, sizeof(name));
// Replace _ with ' ' // Replace _ with ' '
for (j = 1; j < sizeof(name) && name[j]; j++) for (size_t j = 0; j < sizeof(name) && name[j]; j++)
{ {
if (name[j] == '_') if (name[j] == '_')
name[j] = ' '; name[j] = ' ';

View file

@ -249,7 +249,7 @@ typedef struct
char tag[33]; // page tag char tag[33]; // page tag
char name[34]; // narrator name, extra char for color char name[34]; // narrator name, extra char for color
char iconname[9]; // narrator icon lump char iconname[256]; // narrator icon lump
boolean rightside; // narrator side, false = left, true = right boolean rightside; // narrator side, false = left, true = right
boolean iconflip; // narrator flip icon horizontally boolean iconflip; // narrator flip icon horizontally
UINT8 hidehud; // hide hud, 0 = show all, 1 = hide depending on prompt position (top/bottom), 2 = hide all UINT8 hidehud; // hide hud, 0 = show all, 1 = hide depending on prompt position (top/bottom), 2 = hide all

View file

@ -209,6 +209,11 @@ static huddrawlist_h luahuddrawlist_title;
static textwriter_t textwriter; static textwriter_t textwriter;
static void F_ResetTextWriter(textwriter_t *writer, const char *basetext)
{
P_ResetTextWriter(writer, basetext, strlen(basetext));
}
// ============= // =============
// INTRO SCENE // INTRO SCENE
// ============= // =============
@ -414,7 +419,7 @@ void F_StartIntro(void)
gameaction = ga_nothing; gameaction = ga_nothing;
paused = false; paused = false;
CON_ToggleOff(); CON_ToggleOff();
P_ResetTextWriter(&textwriter, introtext[0]); F_ResetTextWriter(&textwriter, introtext[0]);
intro_scenenum = 0; intro_scenenum = 0;
finalecount = animtimer = stoptimer = 0; finalecount = animtimer = stoptimer = 0;
@ -847,7 +852,7 @@ void F_IntroTicker(void)
return; return;
} }
P_ResetTextWriter(&textwriter, introtext[++intro_scenenum]); F_ResetTextWriter(&textwriter, introtext[++intro_scenenum]);
timetonext = introscenetime[intro_scenenum]; timetonext = introscenetime[intro_scenenum];
F_WipeStartScreen(); F_WipeStartScreen();
@ -3795,7 +3800,7 @@ static void F_AdvanceToNextScene(void)
scene->musswitchposition, 0, 0); scene->musswitchposition, 0, 0);
// Fade to the next // Fade to the next
P_ResetTextWriter(&textwriter, scene->text); F_ResetTextWriter(&textwriter, scene->text);
picnum = 0; picnum = 0;
pic = &scene->pics[picnum]; pic = &scene->pics[picnum];
@ -3851,7 +3856,7 @@ void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean reset
paused = false; paused = false;
CON_ToggleOff(); CON_ToggleOff();
P_ResetTextWriter(&textwriter, cutscenes[cutscenenum]->scene[0].text); F_ResetTextWriter(&textwriter, cutscenes[cutscenenum]->scene[0].text);
cutsceneover = false; cutsceneover = false;
runningprecutscene = precutscene; runningprecutscene = precutscene;

View file

@ -118,9 +118,10 @@ UINT8 P_CutsceneWriteText(textwriter_t *writer)
return 1; return 1;
} }
void P_ResetTextWriter(textwriter_t *writer, const char *basetext) void P_ResetTextWriter(textwriter_t *writer, const char *basetext, size_t basetextlength)
{ {
writer->basetext = basetext; writer->basetext = basetext;
writer->basetextlength = basetextlength;
writer->writeptr = writer->baseptr = 0; writer->writeptr = writer->baseptr = 0;
writer->textspeed = 9; writer->textspeed = 9;
writer->textcount = TICRATE/2; writer->textcount = TICRATE/2;
@ -229,14 +230,17 @@ typedef struct
static void F_GetPageTextGeometry(dialog_t *dialog, dialog_geometry_t *geo) static void F_GetPageTextGeometry(dialog_t *dialog, dialog_geometry_t *geo)
{ {
lumpnum_t iconlump = W_CheckNumForName(dialog->page->iconname); lumpnum_t iconlump = LUMPERROR;
if (dialog->icon[0])
iconlump = W_CheckNumForLongName(dialog->icon);
INT32 pagelines = dialog->page->lines ? dialog->page->lines : 4; INT32 pagelines = dialog->page->lines ? dialog->page->lines : 4;
boolean rightside = (iconlump != LUMPERROR && dialog->page->rightside); boolean rightside = iconlump != LUMPERROR && dialog->page->rightside;
// Vertical calculations // Vertical calculations
INT32 boxh = pagelines*2; INT32 boxh = pagelines*2;
INT32 texth = dialog->page->name[0] ? (pagelines-1)*2 : pagelines*2; // name takes up first line if it exists INT32 texth = dialog->speaker[0] ? (pagelines-1)*2 : pagelines*2; // name takes up first line if it exists
INT32 namey = BASEVIDHEIGHT - ((boxh * 4) + (boxh/2)*4); INT32 namey = BASEVIDHEIGHT - ((boxh * 4) + (boxh/2)*4);
geo->texty = BASEVIDHEIGHT - ((texth * 4) + (texth/2)*4); geo->texty = BASEVIDHEIGHT - ((texth * 4) + (texth/2)*4);
@ -390,6 +394,18 @@ void P_SetPicsMetaPage(textpage_t *page, textpage_t *metapage)
memcpy(page->pics, metapage->pics, sizeof(cutscene_pic_t) * page->numpics); memcpy(page->pics, metapage->pics, sizeof(cutscene_pic_t) * page->numpics);
} }
static void P_SetDialogSpeaker(dialog_t *dialog, const char *speaker)
{
char name[256];
// Add yellow control char
name[0] = '\x82';
name[1] = 0;
strlcat(name, speaker, sizeof(name));
strlcpy(dialog->speaker, name, sizeof(dialog->speaker));
}
#define READ_NUM(where) { \ #define READ_NUM(where) { \
int temp = 0; \ int temp = 0; \
temp |= (*code) << 24; code++; \ temp |= (*code) << 24; code++; \
@ -399,19 +415,35 @@ void P_SetPicsMetaPage(textpage_t *page, textpage_t *metapage)
where = temp; \ where = temp; \
} }
static char *BytecodeReadString(const UINT8 **code)
{
const UINT8 *c = *code;
UINT8 sz = *c++;
if (!sz)
return NULL;
char *str = Z_Malloc(sz + 1, PU_STATIC, NULL);
char *str_p = str;
while (sz--)
*str_p++ = *c++;
*str_p = '\0';
*code = c;
return str;
}
// Dialog control codes // Dialog control codes
enum enum
{ {
TP_OP_SPEED, TP_OP_SPEED,
TP_OP_DELAY, TP_OP_DELAY,
TP_OP_NAME,
TP_OP_ICON,
TP_OP_CONTROL = 0xFF TP_OP_CONTROL = 0xFF
}; };
static const UINT8 *InterpretBytecode(const UINT8 *code, dialog_t *dialog, textwriter_t *writer) static const UINT8 *InterpretBytecode(const UINT8 *code, dialog_t *dialog, textwriter_t *writer)
{ {
(void)dialog;
int num = 0; int num = 0;
switch (*code++) switch (*code++)
@ -425,6 +457,24 @@ static const UINT8 *InterpretBytecode(const UINT8 *code, dialog_t *dialog, textw
writer->textcount = num; writer->textcount = num;
writer->numtowrite = 0; writer->numtowrite = 0;
break; break;
case TP_OP_NAME: {
char *speaker = BytecodeReadString(&code);
if (speaker)
{
P_SetDialogSpeaker(dialog, speaker);
Z_Free(speaker);
}
break;
}
case TP_OP_ICON: {
char *icon = BytecodeReadString(&code);
if (icon)
{
strlcpy(dialog->icon, icon, sizeof(dialog->icon));
Z_Free(icon);
}
break;
}
} }
return code; return code;
@ -440,6 +490,12 @@ static int SkipBytecode(const UINT8 *code)
case TP_OP_DELAY: case TP_OP_DELAY:
code += 4; code += 4;
break; break;
case TP_OP_NAME:
case TP_OP_ICON: {
UINT8 n = *code++;
code += n;
break;
}
} }
return code - baseptr; return code - baseptr;
@ -481,10 +537,10 @@ enum
static UINT8 P_DialogWriteText(dialog_t *dialog, textwriter_t *writer) static UINT8 P_DialogWriteText(dialog_t *dialog, textwriter_t *writer)
{ {
const UINT8 *baseptr = (const UINT8*)writer->basetext; const UINT8 *baseptr = (const UINT8*)writer->basetext;
if (!baseptr) if (!baseptr || writer->baseptr >= writer->basetextlength)
return DIALOG_WRITETEXT_DONE; return DIALOG_WRITETEXT_DONE;
UINT8 lastchar = 0; UINT8 lastchar = '\0';
writer->numtowrite = 1; writer->numtowrite = 1;
@ -500,21 +556,18 @@ static UINT8 P_DialogWriteText(dialog_t *dialog, textwriter_t *writer)
writer->numtowrite = 8 - writer->textspeed; writer->numtowrite = 8 - writer->textspeed;
} }
while (true) while (writer->numtowrite > 0)
{ {
if (writer->numtowrite <= 0)
break;
const UINT8 *c = &baseptr[writer->baseptr]; const UINT8 *c = &baseptr[writer->baseptr];
if (!*c) if (!*c)
return DIALOG_WRITETEXT_DONE; return DIALOG_WRITETEXT_DONE;
const UINT8 *code = (const UINT8*)c; const UINT8 *code = (const UINT8*)c;
if (*code == TP_OP_CONTROL) if (*code == TP_OP_CONTROL)
{ {
code = InterpretBytecode(code + 1, dialog, writer); code = InterpretBytecode(code + 1, dialog, writer);
writer->baseptr = code - baseptr; writer->baseptr = code - baseptr;
lastchar = '\0';
continue; continue;
} }
@ -523,7 +576,11 @@ static UINT8 P_DialogWriteText(dialog_t *dialog, textwriter_t *writer)
writer->writeptr++; writer->writeptr++;
writer->baseptr++; writer->baseptr++;
// Ignore other control codes (color) if (writer->numtowrite <= 0)
break;
// Ignore non-printable characters
// (that is, decrement numtowrite if this character is printable.)
if (lastchar < 0x80) if (lastchar < 0x80)
--writer->numtowrite; --writer->numtowrite;
} }
@ -537,7 +594,7 @@ static UINT8 P_DialogWriteText(dialog_t *dialog, textwriter_t *writer)
writer->textcount = writer->textspeed - 7; writer->textcount = writer->textspeed - 7;
} }
if (!lastchar || isspace(lastchar)) if (lastchar == '\0' || isspace(lastchar))
return DIALOG_WRITETEXT_SILENT; return DIALOG_WRITETEXT_SILENT;
else else
return DIALOG_WRITETEXT_TALK; return DIALOG_WRITETEXT_TALK;
@ -554,17 +611,21 @@ static void P_DialogSetDisplayText(dialog_t *dialog)
V_WordWrapInPlace(geo.textx, geo.textr, 0, dialog->disptext); V_WordWrapInPlace(geo.textx, geo.textr, 0, dialog->disptext);
} }
void P_DialogSetText(dialog_t *dialog, char *pagetext, size_t textlength, INT32 numchars) static char *P_ProcessPageText(char *pagetext, size_t textlength, size_t *outlength)
{
*outlength = textlength;
char *buf = Z_Calloc(textlength + 1, PU_STATIC, NULL);
memcpy(buf, pagetext, textlength);
buf[textlength] = '\0';
return buf;
}
void P_DialogSetText(dialog_t *dialog, char *pagetext, size_t textlength)
{ {
Z_Free(dialog->pagetext); Z_Free(dialog->pagetext);
if (pagetext && pagetext[0]) if (pagetext && pagetext[0])
{ dialog->pagetext = P_ProcessPageText(pagetext, textlength, &dialog->pagetextlength);
dialog->pagetextlength = textlength;
dialog->pagetext = Z_Calloc(textlength + 1, PU_STATIC, NULL);
memcpy(dialog->pagetext, pagetext, textlength);
dialog->pagetext[textlength] = '\0';
}
else else
{ {
dialog->pagetextlength = 0; dialog->pagetextlength = 0;
@ -577,37 +638,24 @@ void P_DialogSetText(dialog_t *dialog, char *pagetext, size_t textlength, INT32
textwriter_t *writer = &dialog->writer; textwriter_t *writer = &dialog->writer;
P_ResetTextWriter(writer, dialog->pagetext); P_ResetTextWriter(writer, dialog->pagetext, dialog->pagetextlength);
writer->textspeed = dialog->page->textspeed ? dialog->page->textspeed : TICRATE/5; writer->textspeed = dialog->page->textspeed ? dialog->page->textspeed : TICRATE/5;
writer->textcount = 0; // no delay in beginning writer->textcount = 0; // no delay in beginning
writer->boostspeed = false; // don't print 8 characters to start writer->boostspeed = false; // don't print 8 characters to start
P_DialogSetDisplayText(dialog); P_DialogSetDisplayText(dialog);
if (numchars <= 0)
return;
while (writer->writeptr < numchars)
{
P_DialogWriteText(dialog, writer);
const char *c = &writer->basetext[writer->baseptr];
if (!*c)
break;
}
} }
static void P_PreparePageText(dialog_t *dialog, char *pagetext, size_t textlength) static void P_PreparePageText(dialog_t *dialog, char *pagetext, size_t textlength)
{ {
P_DialogSetText(dialog, pagetext, textlength, 0); P_DialogSetText(dialog, pagetext, textlength);
// \todo update control hot strings on re-config // \todo update control hot strings on re-config
// and somehow don't reset cutscene text counters // and somehow don't reset cutscene text counters
} }
static void P_DialogStartPage(dialog_t *dialog) static void P_DialogStartPage(player_t *player, dialog_t *dialog)
{ {
P_PreparePageText(dialog, dialog->page->text, dialog->page->textlength); P_PreparePageText(dialog, dialog->page->text, dialog->page->textlength);
@ -658,7 +706,16 @@ static void P_DialogStartPage(dialog_t *dialog)
dialog->picmode = 0; dialog->picmode = 0;
} }
// Set up narrator
P_SetDialogSpeaker(dialog, dialog->page->name);
strlcpy(dialog->icon, dialog->page->iconname, sizeof(dialog->icon));
dialog->iconflip = dialog->page->iconflip;
// music change // music change
if (P_IsLocalPlayer(player) || globaltextprompt)
{
if (dialog->page->musswitch[0]) if (dialog->page->musswitch[0])
{ {
S_ChangeMusic(dialog->page->musswitch, S_ChangeMusic(dialog->page->musswitch,
@ -672,6 +729,7 @@ static void P_DialogStartPage(dialog_t *dialog)
true); true);
} }
} }
}
static boolean P_LoadNextPageAndPrompt(player_t *player, dialog_t *dialog, INT32 nextprompt, INT32 nextpage) static boolean P_LoadNextPageAndPrompt(player_t *player, dialog_t *dialog, INT32 nextprompt, INT32 nextpage)
{ {
@ -735,7 +793,7 @@ static boolean P_LoadNextPageAndPrompt(player_t *player, dialog_t *dialog, INT32
return false; return false;
} }
P_DialogStartPage(dialog); P_DialogStartPage(player, dialog);
return true; return true;
} }
@ -1009,7 +1067,7 @@ void P_StartTextPrompt(player_t *player, INT32 promptnum, INT32 pagenum, UINT16
dialog->prompt = textprompts[dialog->promptnum]; dialog->prompt = textprompts[dialog->promptnum];
dialog->page = &dialog->prompt->page[dialog->pagenum]; dialog->page = &dialog->prompt->page[dialog->pagenum];
P_DialogStartPage(dialog); P_DialogStartPage(player, dialog);
} }
else else
{ {
@ -1216,7 +1274,7 @@ void F_TextPromptDrawer(void)
if (!dialog) if (!dialog)
return; return;
lumpnum_t iconlump; lumpnum_t iconlump = LUMPERROR;
dialog_geometry_t geo; dialog_geometry_t geo;
INT32 draw_flags = V_PERPLAYER; INT32 draw_flags = V_PERPLAYER;
@ -1225,7 +1283,6 @@ void F_TextPromptDrawer(void)
// Data // Data
patch_t *patch; patch_t *patch;
iconlump = W_CheckNumForName(dialog->page->iconname);
F_GetPageTextGeometry(dialog, &geo); F_GetPageTextGeometry(dialog, &geo);
boolean rightside = geo.rightside; boolean rightside = geo.rightside;
@ -1250,10 +1307,13 @@ void F_TextPromptDrawer(void)
V_DrawPromptBack(boxh, dialog->page->backcolor, draw_flags|snap_flags); V_DrawPromptBack(boxh, dialog->page->backcolor, draw_flags|snap_flags);
// Draw narrator icon // Draw narrator icon
if (dialog->icon[0])
iconlump = W_CheckNumForLongName(dialog->icon);
if (iconlump != LUMPERROR) if (iconlump != LUMPERROR)
{ {
INT32 iconx, icony, scale, scaledsize; INT32 iconx, icony, scale, scaledsize;
patch = W_CachePatchLongName(dialog->page->iconname, PU_PATCH_LOWPRIORITY); patch = W_CachePatchLongName(dialog->icon, PU_PATCH_LOWPRIORITY);
// scale and center // scale and center
if (patch->width > patch->height) if (patch->width > patch->height)
@ -1278,10 +1338,10 @@ void F_TextPromptDrawer(void)
icony = namey << FRACBITS; icony = namey << FRACBITS;
} }
if (dialog->page->iconflip) if (dialog->iconflip)
iconx += FixedMul(patch->width, scale) << FRACBITS; iconx += FixedMul(patch->width, scale) << FRACBITS;
V_DrawFixedPatch(iconx, icony, scale, (draw_flags|snap_flags|(dialog->page->iconflip ? V_FLIP : 0)), patch, NULL); V_DrawFixedPatch(iconx, icony, scale, (draw_flags|snap_flags|(dialog->iconflip ? V_FLIP : 0)), patch, NULL);
W_UnlockCachedPatch(patch); W_UnlockCachedPatch(patch);
} }
@ -1291,8 +1351,8 @@ void F_TextPromptDrawer(void)
// Draw name // Draw name
// Don't use V_YELLOWMAP here so that the name color can be changed with control codes // Don't use V_YELLOWMAP here so that the name color can be changed with control codes
if (dialog->page->name[0]) if (dialog->speaker[0])
V_DrawString(textx, namey, (draw_flags|snap_flags|V_ALLOWLOWERCASE), dialog->page->name); V_DrawString(textx, namey, (draw_flags|snap_flags|V_ALLOWLOWERCASE), dialog->speaker);
// Draw choices // Draw choices
if (dialog->showchoices) if (dialog->showchoices)
@ -2103,6 +2163,14 @@ static void GetControlCodeEnd(char **input)
WRITE_CHAR((n >> 8) & 0xFF); \ WRITE_CHAR((n >> 8) & 0xFF); \
WRITE_CHAR((n) & 0xFF); \ WRITE_CHAR((n) & 0xFF); \
} }
#define WRITE_STRING(str) { \
size_t maxlen = strlen(str); \
if (maxlen > 255) \
maxlen = 255; \
WRITE_CHAR(maxlen); \
for (size_t i = 0; i < maxlen; i++) \
WRITE_CHAR(str[i]); \
}
#define EXPECTED_NUMBER(which) CONS_Alert(CONS_WARNING, "Expected integer in '%s', got '%s' instead\n", which, param) #define EXPECTED_NUMBER(which) CONS_Alert(CONS_WARNING, "Expected integer in '%s', got '%s' instead\n", which, param)
#define EXPECTED_PARAM(which) CONS_Alert(CONS_WARNING, "Expected parameter for '%s'\n", which) #define EXPECTED_PARAM(which) CONS_Alert(CONS_WARNING, "Expected parameter for '%s'\n", which)
@ -2143,6 +2211,32 @@ static void InterpretControlCode(char **input, UINT8 **buf, size_t *buffer_pos,
else else
EXPECTED_PARAM("SPEED"); EXPECTED_PARAM("SPEED");
} }
else if (MatchControlCode("NAME", input))
{
char *param = GetControlCodeParam(input);
if (param)
{
WRITE_OP(TP_OP_NAME);
WRITE_STRING(param);
Z_Free(param);
}
else
EXPECTED_PARAM("NAME");
}
else if (MatchControlCode("ICON", input))
{
char *param = GetControlCodeParam(input);
if (param)
{
WRITE_OP(TP_OP_ICON);
WRITE_STRING(param);
Z_Free(param);
}
else
EXPECTED_PARAM("ICON");
}
} }
static boolean InterpretCutsceneControlCode(UINT8 chr, UINT8 **buf, size_t *buffer_pos, size_t *buffer_capacity) static boolean InterpretCutsceneControlCode(UINT8 chr, UINT8 **buf, size_t *buffer_pos, size_t *buffer_capacity)
@ -2287,11 +2381,7 @@ static void ParsePage(textprompt_t *prompt, tokenizer_t *sc)
GET_TOKEN(); GET_TOKEN();
char name[34]; strlcpy(page->name, tkn, sizeof(page->name));
name[0] = '\x82'; // color yellow
name[1] = 0;
strlcat(name, tkn, sizeof(name));
strlcpy(page->name, name, sizeof(page->name));
EXPECT_TOKEN(";"); EXPECT_TOKEN(";");
} }

View file

@ -25,10 +25,11 @@
typedef struct typedef struct
{ {
const char *basetext; const char *basetext;
size_t basetextlength;
char *disptext; char *disptext;
size_t disptextsize; size_t disptextsize;
INT32 baseptr; UINT32 baseptr;
INT32 writeptr; UINT32 writeptr;
INT32 textcount; INT32 textcount;
INT32 textspeed; INT32 textspeed;
INT32 numtowrite; INT32 numtowrite;
@ -36,7 +37,7 @@ typedef struct
} textwriter_t; } textwriter_t;
UINT8 P_CutsceneWriteText(textwriter_t *writer); UINT8 P_CutsceneWriteText(textwriter_t *writer);
void P_ResetTextWriter(textwriter_t *writer, const char *basetext); void P_ResetTextWriter(textwriter_t *writer, const char *basetext, size_t basetextlength);
// //
// PROMPT STATE // PROMPT STATE
@ -45,23 +46,32 @@ typedef struct dialog_s
{ {
INT32 promptnum; INT32 promptnum;
INT32 pagenum; INT32 pagenum;
textprompt_t *prompt; textprompt_t *prompt;
textpage_t *page; textpage_t *page;
INT32 timetonext; player_t *callplayer;
textwriter_t writer; textwriter_t writer;
INT16 postexectag;
boolean blockcontrols;
char *pagetext; char *pagetext;
size_t pagetextlength; size_t pagetextlength;
char *disptext; char *disptext;
size_t disptextsize; size_t disptextsize;
player_t *callplayer;
boolean blockcontrols;
INT32 timetonext;
INT16 postexectag;
INT32 picnum; INT32 picnum;
INT32 pictoloop; INT32 pictoloop;
INT32 pictimer; INT32 pictimer;
INT32 picmode; INT32 picmode;
INT32 numpics; INT32 numpics;
cutscene_pic_t *pics; cutscene_pic_t *pics;
char speaker[256];
char icon[256];
boolean iconflip;
boolean showchoices; boolean showchoices;
INT32 curchoice; INT32 curchoice;
INT32 numchoices; INT32 numchoices;
@ -77,7 +87,7 @@ void P_EndTextPrompt(player_t *player, boolean forceexec, boolean noexec);
void P_EndAllTextPrompts(boolean forceexec, boolean noexec); void P_EndAllTextPrompts(boolean forceexec, boolean noexec);
void P_RunDialog(player_t *player); void P_RunDialog(player_t *player);
void P_FreeDialog(dialog_t *dialog); void P_FreeDialog(dialog_t *dialog);
void P_DialogSetText(dialog_t *dialog, char *pagetext, size_t textlength, INT32 numchars); void P_DialogSetText(dialog_t *dialog, char *pagetext, size_t textlength);
void P_DialogUpdateLongestChoice(dialog_t *dialog); void P_DialogUpdateLongestChoice(dialog_t *dialog);
boolean P_SetCurrentDialogChoice(player_t *player, INT32 choice); boolean P_SetCurrentDialogChoice(player_t *player, INT32 choice);

View file

@ -580,7 +580,7 @@ static void P_NetUnArchivePlayers(void)
if (globaltextprompt) if (globaltextprompt)
players[i].textprompt = globaltextprompt; players[i].textprompt = globaltextprompt;
else else if (players[i].promptactive)
{ {
players[i].textprompt = Z_Calloc(sizeof(dialog_t), PU_LEVEL, NULL); players[i].textprompt = Z_Calloc(sizeof(dialog_t), PU_LEVEL, NULL);
P_NetUnArchiveDialog(players[i].textprompt); P_NetUnArchiveDialog(players[i].textprompt);
@ -4951,17 +4951,23 @@ static void P_NetArchiveDialog(dialog_t *dialog)
WRITEINT32(save_p, dialog->picnum); WRITEINT32(save_p, dialog->picnum);
WRITEINT32(save_p, dialog->pictoloop); WRITEINT32(save_p, dialog->pictoloop);
WRITEINT32(save_p, dialog->pictimer); WRITEINT32(save_p, dialog->pictimer);
WRITEINT32(save_p, dialog->writer.writeptr); WRITEUINT32(save_p, dialog->writer.baseptr);
WRITEUINT32(save_p, dialog->writer.writeptr);
WRITEINT32(save_p, dialog->writer.textcount); WRITEINT32(save_p, dialog->writer.textcount);
WRITEINT32(save_p, dialog->writer.textspeed); WRITEINT32(save_p, dialog->writer.textspeed);
WRITEINT32(save_p, dialog->writer.boostspeed); WRITEUINT8(save_p, (UINT8)dialog->writer.boostspeed);
WRITESTRINGN(save_p, dialog->speaker, sizeof(dialog->speaker) - 1);
WRITESTRINGN(save_p, dialog->icon, sizeof(dialog->icon) - 1);
WRITEUINT8(save_p, (UINT8)dialog->iconflip);
} }
static void P_NetUnArchiveDialog(dialog_t *dialog) static void P_NetUnArchiveDialog(dialog_t *dialog)
{ {
UINT8 playernum; UINT8 playernum;
UINT32 baseptr, writeptr;
INT32 numchars, textcount, textspeed, boostspeed; INT32 textcount, textspeed;
char speaker[256], icon[256];
boolean iconflip, boostspeed;
if (dialog == NULL) if (dialog == NULL)
I_Error("P_NetUnArchiveDialog: dialog == NULL"); I_Error("P_NetUnArchiveDialog: dialog == NULL");
@ -4993,10 +4999,15 @@ static void P_NetUnArchiveDialog(dialog_t *dialog)
dialog->picnum = READINT32(save_p); dialog->picnum = READINT32(save_p);
dialog->pictoloop = READINT32(save_p); dialog->pictoloop = READINT32(save_p);
dialog->pictimer = READINT32(save_p); dialog->pictimer = READINT32(save_p);
numchars = READINT32(save_p); baseptr = READUINT32(save_p);
writeptr = READUINT32(save_p);
textcount = READINT32(save_p); textcount = READINT32(save_p);
textspeed = READINT32(save_p); textspeed = READINT32(save_p);
boostspeed = READINT32(save_p); boostspeed = (boolean)READUINT8(save_p);
READSTRINGN(save_p, speaker, sizeof(speaker) - 1);
READSTRINGN(save_p, icon, sizeof(icon) - 1);
iconflip = (boolean)READUINT8(save_p);
if (dialog->promptnum < 0 || dialog->promptnum >= MAX_PROMPTS || !textprompts[dialog->promptnum]) if (dialog->promptnum < 0 || dialog->promptnum >= MAX_PROMPTS || !textprompts[dialog->promptnum])
I_Error("Invalid text prompt %d from server", dialog->promptnum); I_Error("Invalid text prompt %d from server", dialog->promptnum);
@ -5020,8 +5031,14 @@ static void P_NetUnArchiveDialog(dialog_t *dialog)
I_Error("Invalid text prompt nochoice %d from server", dialog->nochoice); I_Error("Invalid text prompt nochoice %d from server", dialog->nochoice);
} }
P_DialogSetText(dialog, dialog->page->text, dialog->page->textlength, numchars); P_DialogSetText(dialog, dialog->page->text, dialog->page->textlength);
strlcpy(dialog->speaker, speaker, sizeof(dialog->speaker));
strlcpy(dialog->icon, icon, sizeof(dialog->icon));
dialog->iconflip = iconflip;
dialog->writer.baseptr = baseptr;
dialog->writer.writeptr = writeptr;
dialog->writer.textcount = textcount; dialog->writer.textcount = textcount;
dialog->writer.textspeed = textspeed; dialog->writer.textspeed = textspeed;
dialog->writer.boostspeed = boostspeed; dialog->writer.boostspeed = boostspeed;