mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2024-11-15 09:11:48 +00:00
Add 'NAME' and 'ICON' control codes
This commit is contained in:
parent
1b9bd6d275
commit
e8b96f6dba
6 changed files with 221 additions and 104 deletions
|
@ -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] = ' ';
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
194
src/p_dialog.c
194
src/p_dialog.c
|
@ -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(";");
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue