mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2025-01-20 08:20:52 +00:00
Implemented progressive text printing for TextPrompt
This commit is contained in:
parent
444462732b
commit
0a766dc93b
1 changed files with 80 additions and 27 deletions
103
src/f_finale.c
103
src/f_finale.c
|
@ -86,6 +86,7 @@ static boolean promptactive = false;
|
||||||
static mobj_t *promptmo;
|
static mobj_t *promptmo;
|
||||||
static INT16 promptpostexectag;
|
static INT16 promptpostexectag;
|
||||||
static boolean promptblockcontrols;
|
static boolean promptblockcontrols;
|
||||||
|
static char *promptpagetext = NULL;
|
||||||
|
|
||||||
//
|
//
|
||||||
// CUTSCENE TEXT WRITING
|
// CUTSCENE TEXT WRITING
|
||||||
|
@ -2029,6 +2030,52 @@ boolean F_CutsceneResponder(event_t *event)
|
||||||
// TEXT PROMPTS
|
// TEXT PROMPTS
|
||||||
// ==================
|
// ==================
|
||||||
|
|
||||||
|
static void F_GetPageTextGeometry(UINT8 *pagelines, boolean *rightside, INT32 *boxh, INT32 *texth, INT32 *texty, INT32 *namey, INT32 *chevrony, INT32 *textx, INT32 *textr)
|
||||||
|
{
|
||||||
|
// reuse:
|
||||||
|
// cutnum -> promptnum
|
||||||
|
// scenenum -> pagenum
|
||||||
|
lumpnum_t iconlump = W_CheckNumForName(textprompts[cutnum]->page[scenenum].iconname);
|
||||||
|
|
||||||
|
*pagelines = textprompts[cutnum]->page[scenenum].lines ? textprompts[cutnum]->page[scenenum].lines : 4;
|
||||||
|
*rightside = (iconlump != LUMPERROR && textprompts[cutnum]->page[scenenum].rightside);
|
||||||
|
|
||||||
|
// Vertical calculations
|
||||||
|
*boxh = *pagelines*2;
|
||||||
|
*texth = textprompts[cutnum]->page[scenenum].name[0] ? (*pagelines-1)*2 : *pagelines*2; // name takes up first line if it exists
|
||||||
|
*texty = BASEVIDHEIGHT - ((*texth * 4) + (*texth/2)*4);
|
||||||
|
*namey = BASEVIDHEIGHT - ((*boxh * 4) + (*boxh/2)*4);
|
||||||
|
*chevrony = BASEVIDHEIGHT - (((1*2) * 4) + ((1*2)/2)*4); // force on last line
|
||||||
|
|
||||||
|
// Horizontal calculations
|
||||||
|
// Shift text to the right if we have a character icon on the left side
|
||||||
|
// Add 4 margin against icon
|
||||||
|
*textx = (iconlump != LUMPERROR && !*rightside) ? ((*boxh * 4) + (*boxh/2)*4) + 4 : 4;
|
||||||
|
*textr = *rightside ? BASEVIDWIDTH - (((*boxh * 4) + (*boxh/2)*4) + 4) : BASEVIDWIDTH-4;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void F_PreparePageText(char *pagetext)
|
||||||
|
{
|
||||||
|
UINT8 pagelines;
|
||||||
|
boolean rightside;
|
||||||
|
INT32 boxh, texth, texty, namey, chevrony;
|
||||||
|
INT32 textx, textr;
|
||||||
|
|
||||||
|
F_GetPageTextGeometry(&pagelines, &rightside, &boxh, &texth, &texty, &namey, &chevrony, &textx, &textr);
|
||||||
|
|
||||||
|
if (promptpagetext)
|
||||||
|
Z_Free(promptpagetext);
|
||||||
|
promptpagetext = V_WordWrap(textx, textr, 0, pagetext);
|
||||||
|
|
||||||
|
F_NewCutscene(promptpagetext);
|
||||||
|
cutscene_textspeed = TICRATE/4; // \todo configurable speed by SOC
|
||||||
|
cutscene_textcount = 0; // no delay in beginning
|
||||||
|
cutscene_boostspeed = 0; // don't print 8 characters to start
|
||||||
|
|
||||||
|
// \todo update control hot strings on re-config
|
||||||
|
// and somehow don't reset cutscene text counters
|
||||||
|
}
|
||||||
|
|
||||||
static void F_AdvanceToNextPage(void)
|
static void F_AdvanceToNextPage(void)
|
||||||
{
|
{
|
||||||
UINT8 nextprompt = textprompts[cutnum]->page[scenenum].nextprompt,
|
UINT8 nextprompt = textprompts[cutnum]->page[scenenum].nextprompt,
|
||||||
|
@ -2064,12 +2111,20 @@ static void F_AdvanceToNextPage(void)
|
||||||
// close the prompt if either num is invalid
|
// close the prompt if either num is invalid
|
||||||
if (cutnum == INT32_MAX || scenenum == INT32_MAX)
|
if (cutnum == INT32_MAX || scenenum == INT32_MAX)
|
||||||
F_EndTextPrompt();
|
F_EndTextPrompt();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
timetonext = 1; // on page-mode, delay before boosting // \todo timed mode set by SOC, enable different behavior for a legitimate timer
|
||||||
|
F_PreparePageText(textprompts[cutnum]->page[scenenum].text);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void F_EndTextPrompt(void)
|
void F_EndTextPrompt(void)
|
||||||
{
|
{
|
||||||
promptactive = false;
|
promptactive = false;
|
||||||
|
|
||||||
|
if (promptmo && promptmo->player && promptblockcontrols)
|
||||||
|
promptmo->reactiontime = TICRATE/4; // prevent jumping right away // \todo account freeze realtime for this
|
||||||
|
|
||||||
// \todo net safety, maybe loop all player thinkers?
|
// \todo net safety, maybe loop all player thinkers?
|
||||||
if (promptpostexectag)
|
if (promptpostexectag)
|
||||||
{
|
{
|
||||||
|
@ -2106,6 +2161,12 @@ void F_StartTextPrompt(INT32 promptnum, INT32 pagenum, mobj_t *mo, UINT16 postex
|
||||||
cutnum = (textprompts[promptnum]) ? promptnum : INT32_MAX;
|
cutnum = (textprompts[promptnum]) ? promptnum : INT32_MAX;
|
||||||
scenenum = (pagenum <= textprompts[cutnum]->numpages-1) ? pagenum : INT32_MAX;
|
scenenum = (pagenum <= textprompts[cutnum]->numpages-1) ? pagenum : INT32_MAX;
|
||||||
promptactive = (cutnum != INT32_MAX && scenenum != INT32_MAX);
|
promptactive = (cutnum != INT32_MAX && scenenum != INT32_MAX);
|
||||||
|
|
||||||
|
if (promptactive)
|
||||||
|
{
|
||||||
|
timetonext = 1; // on page-mode, delay before boosting // \todo timed mode set by SOC, enable different behavior for a legitimate timer
|
||||||
|
F_PreparePageText(textprompts[cutnum]->page[scenenum].text);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void F_TextPromptDrawer(void)
|
void F_TextPromptDrawer(void)
|
||||||
|
@ -2121,27 +2182,12 @@ void F_TextPromptDrawer(void)
|
||||||
|
|
||||||
// Data
|
// Data
|
||||||
patch_t *patch;
|
patch_t *patch;
|
||||||
char *text;
|
|
||||||
|
|
||||||
if (!promptactive)
|
if (!promptactive)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
iconlump = W_CheckNumForName(textprompts[cutnum]->page[scenenum].iconname);
|
iconlump = W_CheckNumForName(textprompts[cutnum]->page[scenenum].iconname);
|
||||||
pagelines = textprompts[cutnum]->page[scenenum].lines ? textprompts[cutnum]->page[scenenum].lines : 4;
|
F_GetPageTextGeometry(&pagelines, &rightside, &boxh, &texth, &texty, &namey, &chevrony, &textx, &textr);
|
||||||
rightside = (iconlump != LUMPERROR && textprompts[cutnum]->page[scenenum].rightside);
|
|
||||||
|
|
||||||
// Vertical calculations
|
|
||||||
boxh = pagelines*2;
|
|
||||||
texth = textprompts[cutnum]->page[scenenum].name[0] ? (pagelines-1)*2 : pagelines*2; // name takes up first line if it exists
|
|
||||||
texty = BASEVIDHEIGHT - ((texth * 4) + (texth/2)*4);
|
|
||||||
namey = BASEVIDHEIGHT - ((boxh * 4) + (boxh/2)*4);
|
|
||||||
chevrony = BASEVIDHEIGHT - (((1*2) * 4) + ((1*2)/2)*4); // force on last line
|
|
||||||
|
|
||||||
// Horizontal calculations
|
|
||||||
// Shift text to the right if we have a character icon on the left side
|
|
||||||
// Add 4 margin against icon
|
|
||||||
textx = (iconlump != LUMPERROR && !rightside) ? ((boxh * 4) + (boxh/2)*4) + 4 : 4;
|
|
||||||
textr = rightside ? BASEVIDWIDTH - (((boxh * 4) + (boxh/2)*4) + 4) : BASEVIDWIDTH-4;
|
|
||||||
|
|
||||||
// Draw background
|
// Draw background
|
||||||
V_DrawTutorialBack(boxh);
|
V_DrawTutorialBack(boxh);
|
||||||
|
@ -2181,8 +2227,7 @@ void F_TextPromptDrawer(void)
|
||||||
|
|
||||||
// Draw text
|
// Draw text
|
||||||
// \todo Char-by-char printing, see f_finale.c F_WriteText
|
// \todo Char-by-char printing, see f_finale.c F_WriteText
|
||||||
text = V_WordWrap(textx, textr, 0, textprompts[cutnum]->page[scenenum].text);
|
V_DrawString(textx, texty, V_SNAPTOBOTTOM, cutscene_disptext);
|
||||||
V_DrawString(textx, texty, V_SNAPTOBOTTOM, text);
|
|
||||||
|
|
||||||
// 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
|
||||||
|
@ -2190,7 +2235,7 @@ void F_TextPromptDrawer(void)
|
||||||
V_DrawString(textx, namey, V_SNAPTOBOTTOM, textprompts[cutnum]->page[scenenum].name);
|
V_DrawString(textx, namey, V_SNAPTOBOTTOM, textprompts[cutnum]->page[scenenum].name);
|
||||||
|
|
||||||
// Draw chevron
|
// Draw chevron
|
||||||
if (promptblockcontrols) // \todo if !CloseTimer
|
if (promptblockcontrols && !timetonext) // \todo if !CloseTimer
|
||||||
V_DrawString(textr-8, chevrony + (skullAnimCounter/5), (V_SNAPTOBOTTOM|V_YELLOWMAP), "\x1B"); // down arrow
|
V_DrawString(textr-8, chevrony + (skullAnimCounter/5), (V_SNAPTOBOTTOM|V_YELLOWMAP), "\x1B"); // down arrow
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2223,22 +2268,30 @@ void F_TextPromptTicker(void)
|
||||||
|
|
||||||
if ((players[i].cmd.buttons & BT_USE) || (players[i].cmd.buttons & BT_JUMP))
|
if ((players[i].cmd.buttons & BT_USE) || (players[i].cmd.buttons & BT_JUMP))
|
||||||
{
|
{
|
||||||
|
if (timetonext > 1)
|
||||||
|
timetonext--;
|
||||||
|
else if (cutscene_baseptr) // don't set boost if we just reset the string
|
||||||
|
cutscene_boostspeed = 1; // only after a slight delay
|
||||||
|
|
||||||
if (keypressed)
|
if (keypressed)
|
||||||
return;
|
break;
|
||||||
|
|
||||||
cutscene_boostspeed = 1;
|
if (!timetonext) // is 0 when finished generating text
|
||||||
if (timetonext)
|
{
|
||||||
timetonext = 2;
|
|
||||||
F_AdvanceToNextPage();
|
F_AdvanceToNextPage();
|
||||||
keypressed = true; // prevent repeat events
|
|
||||||
|
|
||||||
if (promptactive)
|
if (promptactive)
|
||||||
S_StartSound(NULL, sfx_menu1);
|
S_StartSound(NULL, sfx_menu1);
|
||||||
}
|
}
|
||||||
|
keypressed = true; // prevent repeat events
|
||||||
|
}
|
||||||
else if (!(players[i].cmd.buttons & BT_USE) && !(players[i].cmd.buttons & BT_JUMP))
|
else if (!(players[i].cmd.buttons & BT_USE) && !(players[i].cmd.buttons & BT_JUMP))
|
||||||
keypressed = false;
|
keypressed = false;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// generate letter-by-letter text
|
||||||
|
if (!F_WriteText())
|
||||||
|
timetonext = 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue