mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2024-11-18 02:21:47 +00:00
Merge branch 'text-prompts' into 'master'
SOC and Line Exec Text Prompts See merge request STJr/SRB2Internal!200
This commit is contained in:
commit
da0084095c
15 changed files with 1241 additions and 14 deletions
|
@ -232,18 +232,20 @@ UINT8 *yellowmap, *magentamap, *lgreenmap, *bluemap, *graymap, *redmap, *orangem
|
|||
|
||||
// Console BG color
|
||||
UINT8 *consolebgmap = NULL;
|
||||
UINT8 *promptbgmap = NULL;
|
||||
static UINT8 promptbgcolor = UINT8_MAX;
|
||||
|
||||
void CON_SetupBackColormap(void)
|
||||
void CON_SetupBackColormapEx(INT32 color, boolean prompt)
|
||||
{
|
||||
UINT16 i, palsum;
|
||||
UINT8 j, palindex, shift;
|
||||
UINT8 *pal = W_CacheLumpName(GetPalette(), PU_CACHE);
|
||||
|
||||
if (!consolebgmap)
|
||||
consolebgmap = (UINT8 *)Z_Malloc(256, PU_STATIC, NULL);
|
||||
if (color == INT32_MAX)
|
||||
color = cons_backcolor.value;
|
||||
|
||||
shift = 6; // 12 colors -- shift of 7 means 6 colors
|
||||
switch (cons_backcolor.value)
|
||||
switch (color)
|
||||
{
|
||||
case 0: palindex = 15; break; // White
|
||||
case 1: palindex = 31; break; // Gray
|
||||
|
@ -257,20 +259,42 @@ void CON_SetupBackColormap(void)
|
|||
case 9: palindex = 187; break; // Magenta
|
||||
case 10: palindex = 139; break; // Aqua
|
||||
// Default green
|
||||
default: palindex = 175; break;
|
||||
}
|
||||
default: palindex = 175; color = 11; break;
|
||||
}
|
||||
|
||||
if (prompt)
|
||||
{
|
||||
if (!promptbgmap)
|
||||
promptbgmap = (UINT8 *)Z_Malloc(256, PU_STATIC, NULL);
|
||||
|
||||
if (color == promptbgcolor)
|
||||
return;
|
||||
else
|
||||
promptbgcolor = color;
|
||||
}
|
||||
else if (!consolebgmap)
|
||||
consolebgmap = (UINT8 *)Z_Malloc(256, PU_STATIC, NULL);
|
||||
|
||||
// setup background colormap
|
||||
for (i = 0, j = 0; i < 768; i += 3, j++)
|
||||
{
|
||||
palsum = (pal[i] + pal[i+1] + pal[i+2]) >> shift;
|
||||
consolebgmap[j] = (UINT8)(palindex - palsum);
|
||||
if (prompt)
|
||||
promptbgmap[j] = (UINT8)(palindex - palsum);
|
||||
else
|
||||
consolebgmap[j] = (UINT8)(palindex - palsum);
|
||||
}
|
||||
}
|
||||
|
||||
void CON_SetupBackColormap(void)
|
||||
{
|
||||
CON_SetupBackColormapEx(cons_backcolor.value, false);
|
||||
CON_SetupBackColormapEx(1, true); // default to gray
|
||||
}
|
||||
|
||||
static void CONS_backcolor_Change(void)
|
||||
{
|
||||
CON_SetupBackColormap();
|
||||
CON_SetupBackColormapEx(cons_backcolor.value, false);
|
||||
}
|
||||
|
||||
static void CON_SetupColormaps(void)
|
||||
|
|
|
@ -38,7 +38,9 @@ extern UINT8 *yellowmap, *magentamap, *lgreenmap, *bluemap, *graymap, *redmap, *
|
|||
|
||||
// Console bg color (auto updated to match)
|
||||
extern UINT8 *consolebgmap;
|
||||
extern UINT8 *promptbgmap;
|
||||
|
||||
void CON_SetupBackColormapEx(INT32 color, boolean prompt);
|
||||
void CON_SetupBackColormap(void);
|
||||
void CON_ClearHUD(void); // clear heads up messages
|
||||
|
||||
|
|
|
@ -425,6 +425,7 @@ static void D_Display(void)
|
|||
if (gamestate == GS_LEVEL)
|
||||
{
|
||||
ST_Drawer();
|
||||
F_TextPromptDrawer();
|
||||
HU_Drawer();
|
||||
}
|
||||
else
|
||||
|
|
378
src/dehacked.c
378
src/dehacked.c
|
@ -166,9 +166,14 @@ static char *myhashfgets(char *buf, size_t bufsize, MYFILE *f)
|
|||
if (c == '\n') // Ensure debug line is right...
|
||||
dbg_line++;
|
||||
if (c == '#')
|
||||
{
|
||||
if (i > 0) // don't let i wrap past 0
|
||||
i--; // don't include hash char in string
|
||||
break;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
if (buf[i] != '#') // don't include hash char in string
|
||||
i++;
|
||||
buf[i] = '\0';
|
||||
|
||||
return buf;
|
||||
|
@ -1549,6 +1554,365 @@ static void readcutscene(MYFILE *f, INT32 num)
|
|||
Z_Free(s);
|
||||
}
|
||||
|
||||
static void readtextpromptpage(MYFILE *f, INT32 num, INT32 pagenum)
|
||||
{
|
||||
char *s = Z_Calloc(MAXLINELEN, PU_STATIC, NULL);
|
||||
char *word;
|
||||
char *word2;
|
||||
INT32 i;
|
||||
UINT16 usi;
|
||||
UINT8 picid;
|
||||
|
||||
do
|
||||
{
|
||||
if (myfgets(s, MAXLINELEN, f))
|
||||
{
|
||||
if (s[0] == '\n')
|
||||
break;
|
||||
|
||||
word = strtok(s, " ");
|
||||
if (word)
|
||||
strupr(word);
|
||||
else
|
||||
break;
|
||||
|
||||
if (fastcmp(word, "PAGETEXT"))
|
||||
{
|
||||
char *pagetext = NULL;
|
||||
char *buffer;
|
||||
const int bufferlen = 4096;
|
||||
|
||||
for (i = 0; i < MAXLINELEN; i++)
|
||||
{
|
||||
if (s[i] == '=')
|
||||
{
|
||||
pagetext = &s[i+2];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!pagetext)
|
||||
{
|
||||
Z_Free(textprompts[num]->page[pagenum].text);
|
||||
textprompts[num]->page[pagenum].text = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXLINELEN; i++)
|
||||
{
|
||||
if (s[i] == '\0')
|
||||
{
|
||||
s[i] = '\n';
|
||||
s[i+1] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
buffer = Z_Malloc(4096, PU_STATIC, NULL);
|
||||
strcpy(buffer, pagetext);
|
||||
|
||||
// \todo trim trailing whitespace before the #
|
||||
// and also support # at the end of a PAGETEXT with no line break
|
||||
|
||||
strcat(buffer,
|
||||
myhashfgets(pagetext, bufferlen
|
||||
- strlen(buffer) - 1, f));
|
||||
|
||||
// A text prompt overwriting another one...
|
||||
Z_Free(textprompts[num]->page[pagenum].text);
|
||||
|
||||
textprompts[num]->page[pagenum].text = Z_StrDup(buffer);
|
||||
|
||||
Z_Free(buffer);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
word2 = strtok(NULL, " = ");
|
||||
if (word2)
|
||||
strupr(word2);
|
||||
else
|
||||
break;
|
||||
|
||||
if (word2[strlen(word2)-1] == '\n')
|
||||
word2[strlen(word2)-1] = '\0';
|
||||
i = atoi(word2);
|
||||
usi = (UINT16)i;
|
||||
|
||||
// copypasta from readcutscenescene
|
||||
if (fastcmp(word, "NUMBEROFPICS"))
|
||||
{
|
||||
textprompts[num]->page[pagenum].numpics = (UINT8)i;
|
||||
}
|
||||
else if (fastcmp(word, "PICMODE"))
|
||||
{
|
||||
UINT8 picmode = 0; // PROMPT_PIC_PERSIST
|
||||
if (usi == 1 || word2[0] == 'L') picmode = PROMPT_PIC_LOOP;
|
||||
else if (usi == 2 || word2[0] == 'D' || word2[0] == 'H') picmode = PROMPT_PIC_DESTROY;
|
||||
textprompts[num]->page[pagenum].picmode = picmode;
|
||||
}
|
||||
else if (fastcmp(word, "PICTOLOOP"))
|
||||
textprompts[num]->page[pagenum].pictoloop = (UINT8)i;
|
||||
else if (fastcmp(word, "PICTOSTART"))
|
||||
textprompts[num]->page[pagenum].pictostart = (UINT8)i;
|
||||
else if (fastcmp(word, "PICSMETAPAGE"))
|
||||
{
|
||||
if (usi && usi <= textprompts[num]->numpages)
|
||||
{
|
||||
UINT8 metapagenum = usi - 1;
|
||||
|
||||
textprompts[num]->page[pagenum].numpics = textprompts[num]->page[metapagenum].numpics;
|
||||
textprompts[num]->page[pagenum].picmode = textprompts[num]->page[metapagenum].picmode;
|
||||
textprompts[num]->page[pagenum].pictoloop = textprompts[num]->page[metapagenum].pictoloop;
|
||||
textprompts[num]->page[pagenum].pictostart = textprompts[num]->page[metapagenum].pictostart;
|
||||
|
||||
for (picid = 0; picid < MAX_PROMPT_PICS; picid++)
|
||||
{
|
||||
strncpy(textprompts[num]->page[pagenum].picname[picid], textprompts[num]->page[metapagenum].picname[picid], 8);
|
||||
textprompts[num]->page[pagenum].pichires[picid] = textprompts[num]->page[metapagenum].pichires[picid];
|
||||
textprompts[num]->page[pagenum].picduration[picid] = textprompts[num]->page[metapagenum].picduration[picid];
|
||||
textprompts[num]->page[pagenum].xcoord[picid] = textprompts[num]->page[metapagenum].xcoord[picid];
|
||||
textprompts[num]->page[pagenum].ycoord[picid] = textprompts[num]->page[metapagenum].ycoord[picid];
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (fastncmp(word, "PIC", 3))
|
||||
{
|
||||
picid = (UINT8)atoi(word + 3);
|
||||
if (picid > MAX_PROMPT_PICS || picid == 0)
|
||||
{
|
||||
deh_warning("textpromptscene %d: unknown word '%s'", num, word);
|
||||
continue;
|
||||
}
|
||||
--picid;
|
||||
|
||||
if (fastcmp(word+4, "NAME"))
|
||||
{
|
||||
strncpy(textprompts[num]->page[pagenum].picname[picid], word2, 8);
|
||||
}
|
||||
else if (fastcmp(word+4, "HIRES"))
|
||||
{
|
||||
textprompts[num]->page[pagenum].pichires[picid] = (UINT8)(i || word2[0] == 'T' || word2[0] == 'Y');
|
||||
}
|
||||
else if (fastcmp(word+4, "DURATION"))
|
||||
{
|
||||
textprompts[num]->page[pagenum].picduration[picid] = usi;
|
||||
}
|
||||
else if (fastcmp(word+4, "XCOORD"))
|
||||
{
|
||||
textprompts[num]->page[pagenum].xcoord[picid] = usi;
|
||||
}
|
||||
else if (fastcmp(word+4, "YCOORD"))
|
||||
{
|
||||
textprompts[num]->page[pagenum].ycoord[picid] = usi;
|
||||
}
|
||||
else
|
||||
deh_warning("textpromptscene %d: unknown word '%s'", num, word);
|
||||
}
|
||||
else if (fastcmp(word, "MUSIC"))
|
||||
{
|
||||
strncpy(textprompts[num]->page[pagenum].musswitch, word2, 7);
|
||||
textprompts[num]->page[pagenum].musswitch[6] = 0;
|
||||
}
|
||||
#ifdef MUSICSLOT_COMPATIBILITY
|
||||
else if (fastcmp(word, "MUSICSLOT"))
|
||||
{
|
||||
i = get_mus(word2, true);
|
||||
if (i && i <= 1035)
|
||||
snprintf(textprompts[num]->page[pagenum].musswitch, 7, "%sM", G_BuildMapName(i));
|
||||
else if (i && i <= 1050)
|
||||
strncpy(textprompts[num]->page[pagenum].musswitch, compat_special_music_slots[i - 1036], 7);
|
||||
else
|
||||
textprompts[num]->page[pagenum].musswitch[0] = 0; // becomes empty string
|
||||
textprompts[num]->page[pagenum].musswitch[6] = 0;
|
||||
}
|
||||
#endif
|
||||
else if (fastcmp(word, "MUSICTRACK"))
|
||||
{
|
||||
textprompts[num]->page[pagenum].musswitchflags = ((UINT16)i) & MUSIC_TRACKMASK;
|
||||
}
|
||||
else if (fastcmp(word, "MUSICLOOP"))
|
||||
{
|
||||
textprompts[num]->page[pagenum].musicloop = (UINT8)(i || word2[0] == 'T' || word2[0] == 'Y');
|
||||
}
|
||||
// end copypasta from readcutscenescene
|
||||
else if (fastcmp(word, "NAME"))
|
||||
{
|
||||
INT32 j;
|
||||
|
||||
// HACK: Add yellow control char now
|
||||
// so the drawing function doesn't call it repeatedly
|
||||
char name[34];
|
||||
name[0] = '\x82'; // color yellow
|
||||
name[1] = 0;
|
||||
strncat(name, word2, 33);
|
||||
name[33] = 0;
|
||||
|
||||
// Replace _ with ' '
|
||||
for (j = 0; j < 32 && name[j]; j++)
|
||||
{
|
||||
if (name[j] == '_')
|
||||
name[j] = ' ';
|
||||
}
|
||||
|
||||
strncpy(textprompts[num]->page[pagenum].name, name, 32);
|
||||
}
|
||||
else if (fastcmp(word, "ICON"))
|
||||
strncpy(textprompts[num]->page[pagenum].iconname, word2, 8);
|
||||
else if (fastcmp(word, "ICONALIGN"))
|
||||
textprompts[num]->page[pagenum].rightside = (i || word2[0] == 'R');
|
||||
else if (fastcmp(word, "ICONFLIP"))
|
||||
textprompts[num]->page[pagenum].iconflip = (i || word2[0] == 'T' || word2[0] == 'Y');
|
||||
else if (fastcmp(word, "LINES"))
|
||||
textprompts[num]->page[pagenum].lines = usi;
|
||||
else if (fastcmp(word, "BACKCOLOR"))
|
||||
{
|
||||
INT32 backcolor;
|
||||
if (i == 0 || fastcmp(word2, "WHITE")) backcolor = 0;
|
||||
else if (i == 1 || fastcmp(word2, "GRAY") || fastcmp(word2, "GREY") ||
|
||||
fastcmp(word2, "BLACK")) backcolor = 1;
|
||||
else if (i == 2 || fastcmp(word2, "BROWN")) backcolor = 2;
|
||||
else if (i == 3 || fastcmp(word2, "RED")) backcolor = 3;
|
||||
else if (i == 4 || fastcmp(word2, "ORANGE")) backcolor = 4;
|
||||
else if (i == 5 || fastcmp(word2, "YELLOW")) backcolor = 5;
|
||||
else if (i == 6 || fastcmp(word2, "GREEN")) backcolor = 6;
|
||||
else if (i == 7 || fastcmp(word2, "BLUE")) backcolor = 7;
|
||||
else if (i == 8 || fastcmp(word2, "PURPLE")) backcolor = 8;
|
||||
else if (i == 9 || fastcmp(word2, "MAGENTA")) backcolor = 9;
|
||||
else if (i == 10 || fastcmp(word2, "AQUA")) backcolor = 10;
|
||||
else if (i < 0) backcolor = INT32_MAX; // CONS_BACKCOLOR user-configured
|
||||
else backcolor = 1; // default gray
|
||||
textprompts[num]->page[pagenum].backcolor = backcolor;
|
||||
}
|
||||
else if (fastcmp(word, "ALIGN"))
|
||||
{
|
||||
UINT8 align = 0; // left
|
||||
if (usi == 1 || word2[0] == 'R') align = 1;
|
||||
else if (usi == 2 || word2[0] == 'C' || word2[0] == 'M') align = 2;
|
||||
textprompts[num]->page[pagenum].align = align;
|
||||
}
|
||||
else if (fastcmp(word, "VERTICALALIGN"))
|
||||
{
|
||||
UINT8 align = 0; // top
|
||||
if (usi == 1 || word2[0] == 'B') align = 1;
|
||||
else if (usi == 2 || word2[0] == 'C' || word2[0] == 'M') align = 2;
|
||||
textprompts[num]->page[pagenum].verticalalign = align;
|
||||
}
|
||||
else if (fastcmp(word, "TEXTSPEED"))
|
||||
textprompts[num]->page[pagenum].textspeed = get_number(word2);
|
||||
else if (fastcmp(word, "TEXTSFX"))
|
||||
textprompts[num]->page[pagenum].textsfx = get_number(word2);
|
||||
else if (fastcmp(word, "HIDEHUD"))
|
||||
{
|
||||
UINT8 hidehud = 0;
|
||||
if ((word2[0] == 'F' && (word2[1] == 'A' || !word2[1])) || word2[0] == 'N') hidehud = 0; // false
|
||||
else if (usi == 1 || word2[0] == 'T' || word2[0] == 'Y') hidehud = 1; // true (hide appropriate HUD elements)
|
||||
else if (usi == 2 || word2[0] == 'A' || (word2[0] == 'F' && word2[1] == 'O')) hidehud = 2; // force (hide all HUD elements)
|
||||
textprompts[num]->page[pagenum].hidehud = hidehud;
|
||||
}
|
||||
else if (fastcmp(word, "METAPAGE"))
|
||||
{
|
||||
if (usi && usi <= textprompts[num]->numpages)
|
||||
{
|
||||
UINT8 metapagenum = usi - 1;
|
||||
|
||||
strncpy(textprompts[num]->page[pagenum].name, textprompts[num]->page[metapagenum].name, 32);
|
||||
strncpy(textprompts[num]->page[pagenum].iconname, textprompts[num]->page[metapagenum].iconname, 8);
|
||||
textprompts[num]->page[pagenum].rightside = textprompts[num]->page[metapagenum].rightside;
|
||||
textprompts[num]->page[pagenum].iconflip = textprompts[num]->page[metapagenum].iconflip;
|
||||
textprompts[num]->page[pagenum].lines = textprompts[num]->page[metapagenum].lines;
|
||||
textprompts[num]->page[pagenum].backcolor = textprompts[num]->page[metapagenum].backcolor;
|
||||
textprompts[num]->page[pagenum].align = textprompts[num]->page[metapagenum].align;
|
||||
textprompts[num]->page[pagenum].verticalalign = textprompts[num]->page[metapagenum].verticalalign;
|
||||
textprompts[num]->page[pagenum].textspeed = textprompts[num]->page[metapagenum].textspeed;
|
||||
textprompts[num]->page[pagenum].textsfx = textprompts[num]->page[metapagenum].textsfx;
|
||||
textprompts[num]->page[pagenum].hidehud = textprompts[num]->page[metapagenum].hidehud;
|
||||
|
||||
// music: don't copy, else each page change may reset the music
|
||||
}
|
||||
}
|
||||
else if (fastcmp(word, "TAG"))
|
||||
strncpy(textprompts[num]->page[pagenum].tag, word2, 33);
|
||||
else if (fastcmp(word, "NEXTPROMPT"))
|
||||
textprompts[num]->page[pagenum].nextprompt = usi;
|
||||
else if (fastcmp(word, "NEXTPAGE"))
|
||||
textprompts[num]->page[pagenum].nextpage = usi;
|
||||
else if (fastcmp(word, "NEXTTAG"))
|
||||
strncpy(textprompts[num]->page[pagenum].nexttag, word2, 33);
|
||||
else if (fastcmp(word, "TIMETONEXT"))
|
||||
textprompts[num]->page[pagenum].timetonext = get_number(word2);
|
||||
else
|
||||
deh_warning("PromptPage %d: unknown word '%s'", num, word);
|
||||
}
|
||||
} while (!myfeof(f)); // finish when the line is empty
|
||||
|
||||
Z_Free(s);
|
||||
}
|
||||
|
||||
static void readtextprompt(MYFILE *f, INT32 num)
|
||||
{
|
||||
char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
|
||||
char *word;
|
||||
char *word2;
|
||||
char *tmp;
|
||||
INT32 value;
|
||||
|
||||
// Allocate memory for this prompt if we don't yet have any
|
||||
if (!textprompts[num])
|
||||
textprompts[num] = Z_Calloc(sizeof (textprompt_t), PU_STATIC, NULL);
|
||||
|
||||
do
|
||||
{
|
||||
if (myfgets(s, MAXLINELEN, f))
|
||||
{
|
||||
if (s[0] == '\n')
|
||||
break;
|
||||
|
||||
tmp = strchr(s, '#');
|
||||
if (tmp)
|
||||
*tmp = '\0';
|
||||
if (s == tmp)
|
||||
continue; // Skip comment lines, but don't break.
|
||||
|
||||
word = strtok(s, " ");
|
||||
if (word)
|
||||
strupr(word);
|
||||
else
|
||||
break;
|
||||
|
||||
word2 = strtok(NULL, " ");
|
||||
if (word2)
|
||||
value = atoi(word2);
|
||||
else
|
||||
{
|
||||
deh_warning("No value for token %s", word);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fastcmp(word, "NUMPAGES"))
|
||||
{
|
||||
textprompts[num]->numpages = min(max(value, 0), MAX_PAGES);
|
||||
}
|
||||
else if (fastcmp(word, "PAGE"))
|
||||
{
|
||||
if (1 <= value && value <= MAX_PAGES)
|
||||
{
|
||||
textprompts[num]->page[value - 1].backcolor = 1; // default to gray
|
||||
textprompts[num]->page[value - 1].hidehud = 1; // hide appropriate HUD elements
|
||||
readtextpromptpage(f, num, value - 1);
|
||||
}
|
||||
else
|
||||
deh_warning("Page number %d out of range (1 - %d)", value, MAX_PAGES);
|
||||
|
||||
}
|
||||
else
|
||||
deh_warning("Prompt %d: unknown word '%s', Page <num> expected.", num, word);
|
||||
}
|
||||
} while (!myfeof(f)); // finish when the line is empty
|
||||
|
||||
Z_Free(s);
|
||||
}
|
||||
|
||||
static void readhuditem(MYFILE *f, INT32 num)
|
||||
{
|
||||
char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
|
||||
|
@ -3252,6 +3616,16 @@ static void DEH_LoadDehackedFile(MYFILE *f)
|
|||
ignorelines(f);
|
||||
}
|
||||
}
|
||||
else if (fastcmp(word, "PROMPT"))
|
||||
{
|
||||
if (i > 0 && i < MAX_PROMPTS)
|
||||
readtextprompt(f, i - 1);
|
||||
else
|
||||
{
|
||||
deh_warning("Prompt number %d out of range (1 - %d)", i, MAX_PROMPTS);
|
||||
ignorelines(f);
|
||||
}
|
||||
}
|
||||
else if (fastcmp(word, "FRAME") || fastcmp(word, "STATE"))
|
||||
{
|
||||
if (i == 0 && word2[0] != '0') // If word2 isn't a number
|
||||
|
@ -7925,7 +8299,7 @@ struct {
|
|||
|
||||
{"V_CHARCOLORSHIFT",V_CHARCOLORSHIFT},
|
||||
{"V_ALPHASHIFT",V_ALPHASHIFT},
|
||||
|
||||
|
||||
//Kick Reasons
|
||||
{"KR_KICK",KR_KICK},
|
||||
{"KR_PINGLIMIT",KR_PINGLIMIT},
|
||||
|
|
|
@ -174,6 +174,60 @@ typedef struct
|
|||
|
||||
extern cutscene_t *cutscenes[128];
|
||||
|
||||
// Reserve prompt space for tutorials
|
||||
#define TUTORIAL_PROMPT 201 // one-based
|
||||
#define TUTORIAL_AREAS 6
|
||||
#define TUTORIAL_AREA_PROMPTS 5
|
||||
#define MAX_PROMPTS (TUTORIAL_PROMPT+TUTORIAL_AREAS*TUTORIAL_AREA_PROMPTS*3) // 3 control modes
|
||||
#define MAX_PAGES 128
|
||||
|
||||
#define PROMPT_PIC_PERSIST 0
|
||||
#define PROMPT_PIC_LOOP 1
|
||||
#define PROMPT_PIC_DESTROY 2
|
||||
#define MAX_PROMPT_PICS 8
|
||||
typedef struct
|
||||
{
|
||||
UINT8 numpics;
|
||||
UINT8 picmode; // sequence mode after displaying last pic, 0 = persist, 1 = loop, 2 = destroy
|
||||
UINT8 pictoloop; // if picmode == loop, which pic to loop to?
|
||||
UINT8 pictostart; // initial pic number to show
|
||||
char picname[MAX_PROMPT_PICS][8];
|
||||
UINT8 pichires[MAX_PROMPT_PICS];
|
||||
UINT16 xcoord[MAX_PROMPT_PICS]; // gfx
|
||||
UINT16 ycoord[MAX_PROMPT_PICS]; // gfx
|
||||
UINT16 picduration[MAX_PROMPT_PICS];
|
||||
|
||||
char musswitch[7];
|
||||
UINT16 musswitchflags;
|
||||
UINT8 musicloop;
|
||||
|
||||
char tag[33]; // page tag
|
||||
char name[34]; // narrator name, extra char for color
|
||||
char iconname[8]; // narrator icon lump
|
||||
boolean rightside; // narrator side, false = left, true = right
|
||||
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 lines; // # of lines to show. If name is specified, name takes one of the lines. If 0, defaults to 4.
|
||||
INT32 backcolor; // see CON_SetupBackColormap: 0-11, INT32_MAX for user-defined (CONS_BACKCOLOR)
|
||||
UINT8 align; // text alignment, 0 = left, 1 = right, 2 = center
|
||||
UINT8 verticalalign; // vertical text alignment, 0 = top, 1 = bottom, 2 = middle
|
||||
UINT8 textspeed; // text speed, delay in tics between characters.
|
||||
sfxenum_t textsfx; // sfx_ id for printing text
|
||||
UINT8 nextprompt; // next prompt to jump to, one-based. 0 = current prompt
|
||||
UINT8 nextpage; // next page to jump to, one-based. 0 = next page within prompt->numpages
|
||||
char nexttag[33]; // next tag to jump to. If set, this overrides nextprompt and nextpage.
|
||||
INT32 timetonext; // time in tics to jump to next page automatically. 0 = don't jump automatically
|
||||
char *text;
|
||||
} textpage_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
textpage_t page[MAX_PAGES];
|
||||
INT32 numpages; // Number of pages in this prompt
|
||||
} textprompt_t;
|
||||
|
||||
extern textprompt_t *textprompts[MAX_PROMPTS];
|
||||
|
||||
// For the Custom Exit linedef.
|
||||
extern INT16 nextmapoverride;
|
||||
extern boolean skipstats;
|
||||
|
|
631
src/f_finale.c
631
src/f_finale.c
|
@ -33,6 +33,8 @@
|
|||
#include "m_cond.h"
|
||||
#include "p_local.h"
|
||||
#include "p_setup.h"
|
||||
#include "st_stuff.h" // hud hiding
|
||||
#include "fastcmp.h"
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
#include "lua_hud.h"
|
||||
|
@ -48,6 +50,7 @@ static INT32 timetonext; // Delay between screen changes
|
|||
static INT32 continuetime; // Short delay when continuing
|
||||
|
||||
static tic_t animtimer; // Used for some animation timings
|
||||
static INT16 skullAnimCounter; // Chevron animation
|
||||
static INT32 roidtics; // Asteroid spinning
|
||||
|
||||
static INT32 deplete;
|
||||
|
@ -78,6 +81,18 @@ static patch_t *ttspop7;
|
|||
|
||||
static void F_SkyScroll(INT32 scrollspeed);
|
||||
|
||||
//
|
||||
// PROMPT STATE
|
||||
//
|
||||
static boolean promptactive = false;
|
||||
static mobj_t *promptmo;
|
||||
static INT16 promptpostexectag;
|
||||
static boolean promptblockcontrols;
|
||||
static char *promptpagetext = NULL;
|
||||
static INT32 callpromptnum = INT32_MAX;
|
||||
static INT32 callpagenum = INT32_MAX;
|
||||
static INT32 callplayer = INT32_MAX;
|
||||
|
||||
//
|
||||
// CUTSCENE TEXT WRITING
|
||||
//
|
||||
|
@ -1809,7 +1824,7 @@ boolean F_ContinueResponder(event_t *event)
|
|||
// CUSTOM CUTSCENES
|
||||
// ==================
|
||||
static INT32 scenenum, cutnum;
|
||||
static INT32 picxpos, picypos, picnum, pictime;
|
||||
static INT32 picxpos, picypos, picnum, pictime, picmode, numpics, pictoloop;
|
||||
static INT32 textxpos, textypos;
|
||||
static boolean dofadenow = false, cutsceneover = false;
|
||||
static boolean runningprecutscene = false, precutresetplayer = false;
|
||||
|
@ -2016,3 +2031,617 @@ boolean F_CutsceneResponder(event_t *event)
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
// ==================
|
||||
// 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 fixed_t F_GetPromptHideHudBound(void)
|
||||
{
|
||||
UINT8 pagelines;
|
||||
boolean rightside;
|
||||
INT32 boxh, texth, texty, namey, chevrony;
|
||||
INT32 textx, textr;
|
||||
|
||||
if (cutnum == INT32_MAX || scenenum == INT32_MAX || !textprompts[cutnum] || scenenum >= textprompts[cutnum]->numpages ||
|
||||
!textprompts[cutnum]->page[scenenum].hidehud ||
|
||||
(splitscreen && textprompts[cutnum]->page[scenenum].hidehud != 2)) // don't hide on splitscreen, unless hide all is forced
|
||||
return 0;
|
||||
else if (textprompts[cutnum]->page[scenenum].hidehud == 2) // hide all
|
||||
return BASEVIDHEIGHT;
|
||||
|
||||
F_GetPageTextGeometry(&pagelines, &rightside, &boxh, &texth, &texty, &namey, &chevrony, &textx, &textr);
|
||||
|
||||
// calc boxheight (see V_DrawPromptBack)
|
||||
boxh *= vid.dupy;
|
||||
boxh = (boxh * 4) + (boxh/2)*5; // 4 lines of space plus gaps between and some leeway
|
||||
|
||||
// return a coordinate to check
|
||||
// if negative: don't show hud elements below this coordinate (visually)
|
||||
// if positive: don't show hud elements above this coordinate (visually)
|
||||
return 0 - boxh; // \todo: if prompt at top of screen (someday), make this return positive
|
||||
}
|
||||
|
||||
boolean F_GetPromptHideHudAll(void)
|
||||
{
|
||||
if (cutnum == INT32_MAX || scenenum == INT32_MAX || !textprompts[cutnum] || scenenum >= textprompts[cutnum]->numpages ||
|
||||
!textprompts[cutnum]->page[scenenum].hidehud ||
|
||||
(splitscreen && textprompts[cutnum]->page[scenenum].hidehud != 2)) // don't hide on splitscreen, unless hide all is forced
|
||||
return false;
|
||||
else if (textprompts[cutnum]->page[scenenum].hidehud == 2) // hide all
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean F_GetPromptHideHud(fixed_t y)
|
||||
{
|
||||
INT32 ybound;
|
||||
boolean fromtop;
|
||||
fixed_t ytest;
|
||||
|
||||
if (!promptactive)
|
||||
return false;
|
||||
|
||||
ybound = F_GetPromptHideHudBound();
|
||||
fromtop = (ybound >= 0);
|
||||
ytest = (fromtop ? ybound : BASEVIDHEIGHT + ybound);
|
||||
|
||||
return (fromtop ? y < ytest : y >= ytest); // true means hide
|
||||
}
|
||||
|
||||
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 = (pagetext && pagetext[0]) ? V_WordWrap(textx, textr, 0, pagetext) : Z_StrDup("");
|
||||
|
||||
F_NewCutscene(promptpagetext);
|
||||
cutscene_textspeed = textprompts[cutnum]->page[scenenum].textspeed ? textprompts[cutnum]->page[scenenum].textspeed : TICRATE/5;
|
||||
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)
|
||||
{
|
||||
INT32 nextprompt = textprompts[cutnum]->page[scenenum].nextprompt ? textprompts[cutnum]->page[scenenum].nextprompt - 1 : INT32_MAX,
|
||||
nextpage = textprompts[cutnum]->page[scenenum].nextpage ? textprompts[cutnum]->page[scenenum].nextpage - 1 : INT32_MAX,
|
||||
oldcutnum = cutnum;
|
||||
|
||||
if (textprompts[cutnum]->page[scenenum].nexttag[0])
|
||||
F_GetPromptPageByNamedTag(textprompts[cutnum]->page[scenenum].nexttag, &nextprompt, &nextpage);
|
||||
|
||||
// determine next prompt
|
||||
if (nextprompt != INT32_MAX)
|
||||
{
|
||||
if (nextprompt <= MAX_PROMPTS && textprompts[nextprompt])
|
||||
cutnum = nextprompt;
|
||||
else
|
||||
cutnum = INT32_MAX;
|
||||
}
|
||||
|
||||
// determine next page
|
||||
if (nextpage != INT32_MAX)
|
||||
{
|
||||
if (cutnum != INT32_MAX)
|
||||
{
|
||||
scenenum = nextpage;
|
||||
if (scenenum >= MAX_PAGES || scenenum > textprompts[cutnum]->numpages-1)
|
||||
scenenum = INT32_MAX;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cutnum != oldcutnum)
|
||||
scenenum = 0;
|
||||
else if (scenenum + 1 < MAX_PAGES && scenenum < textprompts[cutnum]->numpages-1)
|
||||
scenenum++;
|
||||
else
|
||||
scenenum = INT32_MAX;
|
||||
}
|
||||
|
||||
// close the prompt if either num is invalid
|
||||
if (cutnum == INT32_MAX || scenenum == INT32_MAX)
|
||||
F_EndTextPrompt(false, false);
|
||||
else
|
||||
{
|
||||
// on page mode, number of tics before allowing boost
|
||||
// on timer mode, number of tics until page advances
|
||||
timetonext = textprompts[cutnum]->page[scenenum].timetonext ? textprompts[cutnum]->page[scenenum].timetonext : TICRATE/10;
|
||||
F_PreparePageText(textprompts[cutnum]->page[scenenum].text);
|
||||
|
||||
// gfx
|
||||
picnum = textprompts[cutnum]->page[scenenum].pictostart;
|
||||
numpics = textprompts[cutnum]->page[scenenum].numpics;
|
||||
picmode = textprompts[cutnum]->page[scenenum].picmode;
|
||||
pictoloop = textprompts[cutnum]->page[scenenum].pictoloop > 0 ? textprompts[cutnum]->page[scenenum].pictoloop - 1 : 0;
|
||||
picxpos = textprompts[cutnum]->page[scenenum].xcoord[picnum];
|
||||
picypos = textprompts[cutnum]->page[scenenum].ycoord[picnum];
|
||||
animtimer = pictime = textprompts[cutnum]->page[scenenum].picduration[picnum];
|
||||
|
||||
// music change
|
||||
if (textprompts[cutnum]->page[scenenum].musswitch[0])
|
||||
S_ChangeMusic(textprompts[cutnum]->page[scenenum].musswitch,
|
||||
textprompts[cutnum]->page[scenenum].musswitchflags,
|
||||
textprompts[cutnum]->page[scenenum].musicloop);
|
||||
}
|
||||
}
|
||||
|
||||
void F_EndTextPrompt(boolean forceexec, boolean noexec)
|
||||
{
|
||||
boolean promptwasactive = promptactive;
|
||||
promptactive = false;
|
||||
callpromptnum = callpagenum = callplayer = INT32_MAX;
|
||||
|
||||
if (promptwasactive)
|
||||
{
|
||||
if (promptmo && promptmo->player && promptblockcontrols)
|
||||
promptmo->reactiontime = TICRATE/4; // prevent jumping right away // \todo account freeze realtime for this)
|
||||
// \todo reset frozen realtime?
|
||||
}
|
||||
|
||||
// \todo net safety, maybe loop all player thinkers?
|
||||
if ((promptwasactive || forceexec) && !noexec && promptpostexectag)
|
||||
{
|
||||
if (tmthing) // edge case where starting an invalid prompt immediately on level load will make P_MapStart fail
|
||||
P_LinedefExecute(promptpostexectag, promptmo, NULL);
|
||||
else
|
||||
{
|
||||
P_MapStart();
|
||||
P_LinedefExecute(promptpostexectag, promptmo, NULL);
|
||||
P_MapEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void F_StartTextPrompt(INT32 promptnum, INT32 pagenum, mobj_t *mo, UINT16 postexectag, boolean blockcontrols, boolean freezerealtime)
|
||||
{
|
||||
INT32 i;
|
||||
|
||||
// if splitscreen and we already have a prompt active, ignore.
|
||||
// \todo Proper per-player splitscreen support (individual prompts)
|
||||
if (promptactive && splitscreen && promptnum == callpromptnum && pagenum == callpagenum)
|
||||
return;
|
||||
|
||||
// \todo proper netgame support
|
||||
if (netgame)
|
||||
{
|
||||
F_EndTextPrompt(true, false); // run the post-effects immediately
|
||||
return;
|
||||
}
|
||||
|
||||
// We share vars, so no starting text prompts over cutscenes or title screens!
|
||||
keypressed = false;
|
||||
finalecount = 0;
|
||||
timetonext = 0;
|
||||
animtimer = 0;
|
||||
stoptimer = 0;
|
||||
skullAnimCounter = 0;
|
||||
|
||||
// Set up state
|
||||
promptmo = mo;
|
||||
promptpostexectag = postexectag;
|
||||
promptblockcontrols = blockcontrols;
|
||||
(void)freezerealtime; // \todo freeze player->realtime, maybe this needs to cycle through player thinkers
|
||||
|
||||
// Initialize current prompt and scene
|
||||
callpromptnum = promptnum;
|
||||
callpagenum = pagenum;
|
||||
cutnum = (promptnum < MAX_PROMPTS && textprompts[promptnum]) ? promptnum : INT32_MAX;
|
||||
scenenum = (cutnum != INT32_MAX && pagenum < MAX_PAGES && pagenum <= textprompts[cutnum]->numpages-1) ? pagenum : INT32_MAX;
|
||||
promptactive = (cutnum != INT32_MAX && scenenum != INT32_MAX);
|
||||
|
||||
if (promptactive)
|
||||
{
|
||||
// on page mode, number of tics before allowing boost
|
||||
// on timer mode, number of tics until page advances
|
||||
timetonext = textprompts[cutnum]->page[scenenum].timetonext ? textprompts[cutnum]->page[scenenum].timetonext : TICRATE/10;
|
||||
F_PreparePageText(textprompts[cutnum]->page[scenenum].text);
|
||||
|
||||
// gfx
|
||||
picnum = textprompts[cutnum]->page[scenenum].pictostart;
|
||||
numpics = textprompts[cutnum]->page[scenenum].numpics;
|
||||
picmode = textprompts[cutnum]->page[scenenum].picmode;
|
||||
pictoloop = textprompts[cutnum]->page[scenenum].pictoloop > 0 ? textprompts[cutnum]->page[scenenum].pictoloop - 1 : 0;
|
||||
picxpos = textprompts[cutnum]->page[scenenum].xcoord[picnum];
|
||||
picypos = textprompts[cutnum]->page[scenenum].ycoord[picnum];
|
||||
animtimer = pictime = textprompts[cutnum]->page[scenenum].picduration[picnum];
|
||||
|
||||
// music change
|
||||
if (textprompts[cutnum]->page[scenenum].musswitch[0])
|
||||
S_ChangeMusic(textprompts[cutnum]->page[scenenum].musswitch,
|
||||
textprompts[cutnum]->page[scenenum].musswitchflags,
|
||||
textprompts[cutnum]->page[scenenum].musicloop);
|
||||
|
||||
// get the calling player
|
||||
if (promptblockcontrols && mo && mo->player)
|
||||
{
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (players[i].mo == mo)
|
||||
{
|
||||
callplayer = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
F_EndTextPrompt(true, false); // run the post-effects immediately
|
||||
}
|
||||
|
||||
static boolean F_GetTextPromptTutorialTag(char *tag, INT32 length)
|
||||
{
|
||||
INT32 gcs = gcs_custom;
|
||||
boolean suffixed = true;
|
||||
|
||||
if (!tag || !tag[0] || !tutorialmode)
|
||||
return false;
|
||||
|
||||
if (!strncmp(tag, "TAM", 3)) // Movement
|
||||
gcs = G_GetControlScheme(gamecontrol, gcl_movement, num_gcl_movement);
|
||||
else if (!strncmp(tag, "TAC", 3)) // Camera
|
||||
{
|
||||
// Check for gcl_movement so we can differentiate between FPS and Platform schemes.
|
||||
gcs = G_GetControlScheme(gamecontrol, gcl_movement, num_gcl_movement);
|
||||
if (gcs == gcs_custom) // try again, maybe we'll get a match
|
||||
gcs = G_GetControlScheme(gamecontrol, gcl_camera, num_gcl_camera);
|
||||
if (gcs == gcs_fps && !cv_usemouse.value)
|
||||
gcs = gcs_platform; // Platform (arrow) scheme is stand-in for no mouse
|
||||
}
|
||||
else if (!strncmp(tag, "TAD", 3)) // Movement and Camera
|
||||
gcs = G_GetControlScheme(gamecontrol, gcl_movement_camera, num_gcl_movement_camera);
|
||||
else if (!strncmp(tag, "TAJ", 3)) // Jump
|
||||
gcs = G_GetControlScheme(gamecontrol, gcl_jump, num_gcl_jump);
|
||||
else if (!strncmp(tag, "TAS", 3)) // Spin
|
||||
gcs = G_GetControlScheme(gamecontrol, gcl_use, num_gcl_use);
|
||||
else if (!strncmp(tag, "TAA", 3)) // Char ability
|
||||
gcs = G_GetControlScheme(gamecontrol, gcl_jump, num_gcl_jump);
|
||||
else if (!strncmp(tag, "TAW", 3)) // Shield ability
|
||||
gcs = G_GetControlScheme(gamecontrol, gcl_jump_use, num_gcl_jump_use);
|
||||
else
|
||||
gcs = G_GetControlScheme(gamecontrol, gcl_tutorial_used, num_gcl_tutorial_used);
|
||||
|
||||
switch (gcs)
|
||||
{
|
||||
case gcs_fps:
|
||||
// strncat(tag, "FPS", length);
|
||||
suffixed = false;
|
||||
break;
|
||||
|
||||
case gcs_platform:
|
||||
strncat(tag, "PLATFORM", length);
|
||||
break;
|
||||
|
||||
default:
|
||||
strncat(tag, "CUSTOM", length);
|
||||
break;
|
||||
}
|
||||
|
||||
return suffixed;
|
||||
}
|
||||
|
||||
void F_GetPromptPageByNamedTag(const char *tag, INT32 *promptnum, INT32 *pagenum)
|
||||
{
|
||||
INT32 nosuffixpromptnum = INT32_MAX, nosuffixpagenum = INT32_MAX;
|
||||
INT32 tutorialpromptnum = (tutorialmode) ? TUTORIAL_PROMPT-1 : 0;
|
||||
boolean suffixed = false, found = false;
|
||||
char suffixedtag[33];
|
||||
|
||||
*promptnum = *pagenum = INT32_MAX;
|
||||
|
||||
if (!tag || !tag[0])
|
||||
return;
|
||||
|
||||
strncpy(suffixedtag, tag, 33);
|
||||
suffixedtag[32] = 0;
|
||||
tutorialmode = true;
|
||||
if (tutorialmode)
|
||||
suffixed = F_GetTextPromptTutorialTag(suffixedtag, 33); tutorialmode = false;
|
||||
|
||||
for (*promptnum = 0 + tutorialpromptnum; *promptnum < MAX_PROMPTS; (*promptnum)++)
|
||||
{
|
||||
if (!textprompts[*promptnum])
|
||||
continue;
|
||||
|
||||
for (*pagenum = 0; *pagenum < textprompts[*promptnum]->numpages && *pagenum < MAX_PAGES; (*pagenum)++)
|
||||
{
|
||||
if (suffixed && fastcmp(suffixedtag, textprompts[*promptnum]->page[*pagenum].tag))
|
||||
{
|
||||
// this goes first because fastcmp ends early if first string is shorter
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
else if (nosuffixpromptnum == INT32_MAX && nosuffixpagenum == INT32_MAX && fastcmp(tag, textprompts[*promptnum]->page[*pagenum].tag))
|
||||
{
|
||||
if (suffixed)
|
||||
{
|
||||
nosuffixpromptnum = *promptnum;
|
||||
nosuffixpagenum = *pagenum;
|
||||
// continue searching for the suffixed tag
|
||||
}
|
||||
else
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
break;
|
||||
}
|
||||
|
||||
if (suffixed && !found && nosuffixpromptnum != INT32_MAX && nosuffixpagenum != INT32_MAX)
|
||||
{
|
||||
found = true;
|
||||
*promptnum = nosuffixpromptnum;
|
||||
*pagenum = nosuffixpagenum;
|
||||
}
|
||||
|
||||
if (!found)
|
||||
CONS_Debug(DBG_GAMELOGIC, "Text prompt: Can't find a page with named tag %s or suffixed tag %s\n", tag, suffixedtag);
|
||||
}
|
||||
|
||||
void F_TextPromptDrawer(void)
|
||||
{
|
||||
// reuse:
|
||||
// cutnum -> promptnum
|
||||
// scenenum -> pagenum
|
||||
lumpnum_t iconlump;
|
||||
UINT8 pagelines;
|
||||
boolean rightside;
|
||||
INT32 boxh, texth, texty, namey, chevrony;
|
||||
INT32 textx, textr;
|
||||
|
||||
// Data
|
||||
patch_t *patch;
|
||||
|
||||
if (!promptactive)
|
||||
return;
|
||||
|
||||
iconlump = W_CheckNumForName(textprompts[cutnum]->page[scenenum].iconname);
|
||||
F_GetPageTextGeometry(&pagelines, &rightside, &boxh, &texth, &texty, &namey, &chevrony, &textx, &textr);
|
||||
|
||||
// Draw gfx first
|
||||
if (picnum >= 0 && picnum < numpics && textprompts[cutnum]->page[scenenum].picname[picnum][0] != '\0')
|
||||
{
|
||||
if (textprompts[cutnum]->page[scenenum].pichires[picnum])
|
||||
V_DrawSmallScaledPatch(picxpos, picypos, 0,
|
||||
W_CachePatchName(textprompts[cutnum]->page[scenenum].picname[picnum], PU_CACHE));
|
||||
else
|
||||
V_DrawScaledPatch(picxpos,picypos, 0,
|
||||
W_CachePatchName(textprompts[cutnum]->page[scenenum].picname[picnum], PU_CACHE));
|
||||
}
|
||||
|
||||
// Draw background
|
||||
V_DrawPromptBack(boxh, textprompts[cutnum]->page[scenenum].backcolor);
|
||||
|
||||
// Draw narrator icon
|
||||
if (iconlump != LUMPERROR)
|
||||
{
|
||||
INT32 iconx, icony, scale, scaledsize;
|
||||
patch = W_CachePatchName(textprompts[cutnum]->page[scenenum].iconname, PU_CACHE);
|
||||
|
||||
// scale and center
|
||||
if (patch->width > patch->height)
|
||||
{
|
||||
scale = FixedDiv(((boxh * 4) + (boxh/2)*4) - 4, patch->width);
|
||||
scaledsize = FixedMul(patch->height, scale);
|
||||
iconx = (rightside ? BASEVIDWIDTH - (((boxh * 4) + (boxh/2)*4)) : 4) << FRACBITS;
|
||||
icony = ((namey-4) << FRACBITS) + FixedDiv(BASEVIDHEIGHT - namey + 4 - scaledsize, 2); // account for 4 margin
|
||||
}
|
||||
else if (patch->height > patch->width)
|
||||
{
|
||||
scale = FixedDiv(((boxh * 4) + (boxh/2)*4) - 4, patch->height);
|
||||
scaledsize = FixedMul(patch->width, scale);
|
||||
iconx = (rightside ? BASEVIDWIDTH - (((boxh * 4) + (boxh/2)*4)) : 4) << FRACBITS;
|
||||
icony = namey << FRACBITS;
|
||||
iconx += FixedDiv(FixedMul(patch->height, scale) - scaledsize, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
scale = FixedDiv(((boxh * 4) + (boxh/2)*4) - 4, patch->width);
|
||||
iconx = (rightside ? BASEVIDWIDTH - (((boxh * 4) + (boxh/2)*4)) : 4) << FRACBITS;
|
||||
icony = namey << FRACBITS;
|
||||
}
|
||||
|
||||
if (textprompts[cutnum]->page[scenenum].iconflip)
|
||||
iconx += FixedMul(patch->width, scale) << FRACBITS;
|
||||
|
||||
V_DrawFixedPatch(iconx, icony, scale, (V_SNAPTOBOTTOM|(textprompts[cutnum]->page[scenenum].iconflip ? V_FLIP : 0)), patch, NULL);
|
||||
W_UnlockCachedPatch(patch);
|
||||
}
|
||||
|
||||
// Draw text
|
||||
V_DrawString(textx, texty, (V_SNAPTOBOTTOM|V_ALLOWLOWERCASE), cutscene_disptext);
|
||||
|
||||
// Draw name
|
||||
// Don't use V_YELLOWMAP here so that the name color can be changed with control codes
|
||||
if (textprompts[cutnum]->page[scenenum].name[0])
|
||||
V_DrawString(textx, namey, (V_SNAPTOBOTTOM|V_ALLOWLOWERCASE), textprompts[cutnum]->page[scenenum].name);
|
||||
|
||||
// Draw chevron
|
||||
if (promptblockcontrols && !timetonext)
|
||||
V_DrawString(textr-8, chevrony + (skullAnimCounter/5), (V_SNAPTOBOTTOM|V_YELLOWMAP), "\x1B"); // down arrow
|
||||
}
|
||||
|
||||
void F_TextPromptTicker(void)
|
||||
{
|
||||
INT32 i;
|
||||
|
||||
if (!promptactive || paused || P_AutoPause())
|
||||
return;
|
||||
|
||||
// advance animation
|
||||
finalecount++;
|
||||
cutscene_boostspeed = 0;
|
||||
|
||||
// for the chevron
|
||||
if (--skullAnimCounter <= 0)
|
||||
skullAnimCounter = 8;
|
||||
|
||||
// button handling
|
||||
if (textprompts[cutnum]->page[scenenum].timetonext)
|
||||
{
|
||||
if (promptblockcontrols) // same procedure as below, just without the button handling
|
||||
{
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (netgame && i != serverplayer && i != adminplayer)
|
||||
continue;
|
||||
else if (splitscreen) {
|
||||
// Both players' controls are locked,
|
||||
// But only consoleplayer can advance the prompt.
|
||||
// \todo Proper per-player splitscreen support (individual prompts)
|
||||
if (i == consoleplayer || i == secondarydisplayplayer)
|
||||
players[i].powers[pw_nocontrol] = 1;
|
||||
}
|
||||
else if (i == consoleplayer)
|
||||
players[i].powers[pw_nocontrol] = 1;
|
||||
|
||||
if (!splitscreen)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (timetonext >= 1)
|
||||
timetonext--;
|
||||
|
||||
if (!timetonext)
|
||||
F_AdvanceToNextPage();
|
||||
|
||||
F_WriteText();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (promptblockcontrols)
|
||||
{
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (netgame && i != serverplayer && i != adminplayer)
|
||||
continue;
|
||||
else if (splitscreen) {
|
||||
// Both players' controls are locked,
|
||||
// But only the triggering player can advance the prompt.
|
||||
if (i == consoleplayer || i == secondarydisplayplayer)
|
||||
{
|
||||
players[i].powers[pw_nocontrol] = 1;
|
||||
|
||||
if (callplayer == consoleplayer || callplayer == secondarydisplayplayer)
|
||||
{
|
||||
if (i != callplayer)
|
||||
continue;
|
||||
}
|
||||
else if (i != consoleplayer)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
}
|
||||
else if (i == consoleplayer)
|
||||
players[i].powers[pw_nocontrol] = 1;
|
||||
else
|
||||
continue;
|
||||
|
||||
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 (!splitscreen)
|
||||
break;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!timetonext) // is 0 when finished generating text
|
||||
{
|
||||
F_AdvanceToNextPage();
|
||||
if (promptactive)
|
||||
S_StartSound(NULL, sfx_menu1);
|
||||
}
|
||||
keypressed = true; // prevent repeat events
|
||||
}
|
||||
else if (!(players[i].cmd.buttons & BT_USE) && !(players[i].cmd.buttons & BT_JUMP))
|
||||
keypressed = false;
|
||||
|
||||
if (!splitscreen)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// generate letter-by-letter text
|
||||
if (scenenum >= MAX_PAGES ||
|
||||
!textprompts[cutnum]->page[scenenum].text ||
|
||||
!textprompts[cutnum]->page[scenenum].text[0] ||
|
||||
!F_WriteText())
|
||||
timetonext = !promptblockcontrols; // never show the chevron if we can't toggle pages
|
||||
}
|
||||
|
||||
// gfx
|
||||
if (picnum >= 0 && picnum < numpics)
|
||||
{
|
||||
if (animtimer <= 0)
|
||||
{
|
||||
boolean persistanimtimer = false;
|
||||
|
||||
if (picnum < numpics-1 && textprompts[cutnum]->page[scenenum].picname[picnum+1][0] != '\0')
|
||||
picnum++;
|
||||
else if (picmode == PROMPT_PIC_LOOP)
|
||||
picnum = pictoloop;
|
||||
else if (picmode == PROMPT_PIC_DESTROY)
|
||||
picnum = -1;
|
||||
else // if (picmode == PROMPT_PIC_PERSIST)
|
||||
persistanimtimer = true;
|
||||
|
||||
if (!persistanimtimer && picnum >= 0)
|
||||
{
|
||||
picxpos = textprompts[cutnum]->page[scenenum].xcoord[picnum];
|
||||
picypos = textprompts[cutnum]->page[scenenum].ycoord[picnum];
|
||||
pictime = textprompts[cutnum]->page[scenenum].picduration[picnum];
|
||||
animtimer = pictime;
|
||||
}
|
||||
}
|
||||
else
|
||||
animtimer--;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include "doomtype.h"
|
||||
#include "d_event.h"
|
||||
#include "p_mobj.h"
|
||||
|
||||
//
|
||||
// FINALE
|
||||
|
@ -33,6 +34,7 @@ void F_IntroTicker(void);
|
|||
void F_TitleScreenTicker(boolean run);
|
||||
void F_CutsceneTicker(void);
|
||||
void F_TitleDemoTicker(void);
|
||||
void F_TextPromptTicker(void);
|
||||
|
||||
// Called by main loop.
|
||||
void F_GameEndDrawer(void);
|
||||
|
@ -50,6 +52,13 @@ void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean reset
|
|||
void F_CutsceneDrawer(void);
|
||||
void F_EndCutScene(void);
|
||||
|
||||
void F_StartTextPrompt(INT32 promptnum, INT32 pagenum, mobj_t *mo, UINT16 postexectag, boolean blockcontrols, boolean freezerealtime);
|
||||
void F_GetPromptPageByNamedTag(const char *tag, INT32 *promptnum, INT32 *pagenum);
|
||||
void F_TextPromptDrawer(void);
|
||||
void F_EndTextPrompt(boolean forceexec, boolean noexec);
|
||||
boolean F_GetPromptHideHudAll(void);
|
||||
boolean F_GetPromptHideHud(fixed_t y);
|
||||
|
||||
void F_StartGameEnd(void);
|
||||
void F_StartIntro(void);
|
||||
void F_StartTitleScreen(void);
|
||||
|
|
|
@ -146,6 +146,7 @@ tic_t countdowntimer = 0;
|
|||
boolean countdowntimeup = false;
|
||||
|
||||
cutscene_t *cutscenes[128];
|
||||
textprompt_t *textprompts[MAX_PROMPTS];
|
||||
|
||||
INT16 nextmapoverride;
|
||||
boolean skipstats;
|
||||
|
@ -1941,6 +1942,7 @@ void G_Ticker(boolean run)
|
|||
F_TitleDemoTicker();
|
||||
P_Ticker(run); // tic the game
|
||||
ST_Ticker();
|
||||
F_TextPromptTicker();
|
||||
AM_Ticker();
|
||||
HU_Ticker();
|
||||
break;
|
||||
|
|
|
@ -716,6 +716,32 @@ void HWR_DrawConsoleBack(UINT32 color, INT32 height)
|
|||
HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest);
|
||||
}
|
||||
|
||||
// Very similar to HWR_DrawConsoleBack, except we draw from the middle(-ish) of the screen to the bottom.
|
||||
void HWR_DrawTutorialBack(UINT32 color, INT32 boxheight)
|
||||
{
|
||||
FOutVector v[4];
|
||||
FSurfaceInfo Surf;
|
||||
INT32 height = (boxheight * 4) + (boxheight/2)*5; // 4 lines of space plus gaps between and some leeway
|
||||
|
||||
// setup some neat-o translucency effect
|
||||
|
||||
v[0].x = v[3].x = -1.0f;
|
||||
v[2].x = v[1].x = 1.0f;
|
||||
v[0].y = v[1].y = -1.0f;
|
||||
v[2].y = v[3].y = -1.0f+((height<<1)/(float)vid.height);
|
||||
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
|
||||
|
||||
v[0].sow = v[3].sow = 0.0f;
|
||||
v[2].sow = v[1].sow = 1.0f;
|
||||
v[0].tow = v[1].tow = 1.0f;
|
||||
v[2].tow = v[3].tow = 0.0f;
|
||||
|
||||
Surf.FlatColor.rgba = UINT2RGBA(color);
|
||||
Surf.FlatColor.s.alpha = (color == 0 ? 0xC0 : 0x80); // make black darker, like software
|
||||
|
||||
HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest);
|
||||
}
|
||||
|
||||
|
||||
// ==========================================================================
|
||||
// R_DRAW.C STUFF
|
||||
|
|
|
@ -35,6 +35,7 @@ void HWR_clearAutomap(void);
|
|||
void HWR_drawAMline(const fline_t *fl, INT32 color);
|
||||
void HWR_FadeScreenMenuBack(UINT16 color, UINT8 strength);
|
||||
void HWR_DrawConsoleBack(UINT32 color, INT32 height);
|
||||
void HWR_DrawTutorialBack(UINT32 color, INT32 boxheight);
|
||||
void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player);
|
||||
void HWR_RenderPlayerView(INT32 viewnumber, player_t *player);
|
||||
void HWR_DrawViewBorder(INT32 clearlines);
|
||||
|
|
|
@ -1541,6 +1541,7 @@ static void P_LoadRawSideDefs2(void *data)
|
|||
}
|
||||
|
||||
case 443: // Calls a named Lua function
|
||||
case 459: // Control text prompt (named tag)
|
||||
{
|
||||
char process[8*3+1];
|
||||
memset(process,0,8*3+1);
|
||||
|
@ -2753,6 +2754,9 @@ boolean P_SetupLevel(boolean skipprecip)
|
|||
I_UpdateNoVsync();
|
||||
}
|
||||
|
||||
// Close text prompt before freeing the old level
|
||||
F_EndTextPrompt(false, true);
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
LUA_InvalidateLevel();
|
||||
#endif
|
||||
|
|
28
src/p_spec.c
28
src/p_spec.c
|
@ -35,6 +35,7 @@
|
|||
#include "m_misc.h"
|
||||
#include "m_cond.h" //unlock triggers
|
||||
#include "lua_hook.h" // LUAh_LinedefExecute
|
||||
#include "f_finale.h" // control text prompt
|
||||
|
||||
#ifdef HW3SOUND
|
||||
#include "hardware/hw3sound.h"
|
||||
|
@ -3792,6 +3793,33 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
|
|||
}
|
||||
break;
|
||||
|
||||
case 459: // Control Text Prompt
|
||||
// console player only unless NOCLIMB is set
|
||||
if (mo && mo->player && P_IsLocalPlayer(mo->player) && (!bot || bot != mo))
|
||||
{
|
||||
INT32 promptnum = max(0, (sides[line->sidenum[0]].textureoffset>>FRACBITS)-1);
|
||||
INT32 pagenum = max(0, (sides[line->sidenum[0]].rowoffset>>FRACBITS)-1);
|
||||
INT32 postexectag = abs((line->sidenum[1] != 0xFFFF) ? sides[line->sidenum[1]].textureoffset>>FRACBITS : line->tag);
|
||||
|
||||
boolean closetextprompt = (line->flags & ML_BLOCKMONSTERS);
|
||||
//boolean allplayers = (line->flags & ML_NOCLIMB);
|
||||
boolean runpostexec = (line->flags & ML_EFFECT1);
|
||||
boolean blockcontrols = !(line->flags & ML_EFFECT2);
|
||||
boolean freezerealtime = !(line->flags & ML_EFFECT3);
|
||||
//boolean freezethinkers = (line->flags & ML_EFFECT4);
|
||||
boolean callbynamedtag = (line->flags & ML_TFERLINE);
|
||||
|
||||
if (closetextprompt)
|
||||
F_EndTextPrompt(false, false);
|
||||
else
|
||||
{
|
||||
if (callbynamedtag && sides[line->sidenum[0]].text && sides[line->sidenum[0]].text[0])
|
||||
F_GetPromptPageByNamedTag(sides[line->sidenum[0]].text, &promptnum, &pagenum);
|
||||
F_StartTextPrompt(promptnum, pagenum, mo, runpostexec ? postexectag : 0, blockcontrols, freezerealtime);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef POLYOBJECTS
|
||||
case 480: // Polyobj_DoorSlide
|
||||
case 481: // Polyobj_DoorSwing
|
||||
|
|
|
@ -603,6 +603,9 @@ static void ST_drawDebugInfo(void)
|
|||
|
||||
static void ST_drawScore(void)
|
||||
{
|
||||
if (F_GetPromptHideHud(hudinfo[HUD_SCORE].y))
|
||||
return;
|
||||
|
||||
// SCORE:
|
||||
ST_DrawPatchFromHud(HUD_SCORE, sboscore, V_HUDTRANS);
|
||||
if (objectplacing)
|
||||
|
@ -712,6 +715,9 @@ static void ST_drawTime(void)
|
|||
tictrn = G_TicsToCentiseconds(tics);
|
||||
}
|
||||
|
||||
if (F_GetPromptHideHud(hudinfo[HUD_TIME].y))
|
||||
return;
|
||||
|
||||
// TIME:
|
||||
ST_DrawPatchFromHud(HUD_TIME, ((downwards && (tics < 30*TICRATE) && (leveltime/5 & 1)) ? sboredtime : sbotime), V_HUDTRANS);
|
||||
|
||||
|
@ -738,6 +744,9 @@ static inline void ST_drawRings(void)
|
|||
{
|
||||
INT32 ringnum;
|
||||
|
||||
if (F_GetPromptHideHud(hudinfo[HUD_RINGS].y))
|
||||
return;
|
||||
|
||||
ST_DrawPatchFromHud(HUD_RINGS, ((!stplyr->spectator && stplyr->rings <= 0 && leveltime/5 & 1) ? sboredrings : sborings), ((stplyr->spectator) ? V_HUDTRANSHALF : V_HUDTRANS));
|
||||
|
||||
ringnum = ((objectplacing) ? op_currentdoomednum : max(stplyr->rings, 0));
|
||||
|
@ -756,6 +765,9 @@ static void ST_drawLivesArea(void)
|
|||
if (!stplyr->skincolor)
|
||||
return; // Just joined a server, skin isn't loaded yet!
|
||||
|
||||
if (F_GetPromptHideHud(hudinfo[HUD_LIVES].y))
|
||||
return;
|
||||
|
||||
// face background
|
||||
V_DrawSmallScaledPatch(hudinfo[HUD_LIVES].x, hudinfo[HUD_LIVES].y,
|
||||
hudinfo[HUD_LIVES].f|V_PERPLAYER|V_HUDTRANS, livesback);
|
||||
|
@ -927,6 +939,9 @@ static void ST_drawInput(void)
|
|||
if (stplyr->powers[pw_carry] == CR_NIGHTSMODE)
|
||||
y -= 16;
|
||||
|
||||
if (F_GetPromptHideHud(y))
|
||||
return;
|
||||
|
||||
// O backing
|
||||
V_DrawFill(x, y-1, 16, 16, hudinfo[HUD_LIVES].f|20);
|
||||
V_DrawFill(x, y+15, 16, 1, hudinfo[HUD_LIVES].f|29);
|
||||
|
@ -1202,6 +1217,9 @@ static void ST_drawPowerupHUD(void)
|
|||
static INT32 flagoffs[2] = {0, 0}, shieldoffs[2] = {0, 0};
|
||||
#define ICONSEP (16+4) // matches weapon rings HUD
|
||||
|
||||
if (F_GetPromptHideHud(hudinfo[HUD_POWERUPS].y))
|
||||
return;
|
||||
|
||||
if (stplyr->spectator || stplyr->playerstate != PST_LIVE)
|
||||
return;
|
||||
|
||||
|
@ -1364,7 +1382,7 @@ static void ST_drawFirstPersonHUD(void)
|
|||
p = W_CachePatchNum(sprframe->lumppat[0], PU_CACHE);
|
||||
|
||||
// Display the countdown drown numbers!
|
||||
if (p)
|
||||
if (p && !F_GetPromptHideHud(60 - SHORT(p->topoffset)))
|
||||
V_DrawScaledPatch((BASEVIDWIDTH/2) - (SHORT(p->width)/2) + SHORT(p->leftoffset), 60 - SHORT(p->topoffset),
|
||||
V_PERPLAYER|V_PERPLAYER|V_TRANSLUCENT, p);
|
||||
}
|
||||
|
@ -1908,6 +1926,9 @@ static void ST_drawMatchHUD(void)
|
|||
const INT32 y = 176; // HUD_LIVES
|
||||
INT32 offset = (BASEVIDWIDTH / 2) - (NUM_WEAPONS * 10) - 6;
|
||||
|
||||
if (F_GetPromptHideHud(y))
|
||||
return;
|
||||
|
||||
if (!G_RingSlingerGametype())
|
||||
return;
|
||||
|
||||
|
@ -1954,6 +1975,9 @@ static void ST_drawTextHUD(void)
|
|||
y -= 8;\
|
||||
}
|
||||
|
||||
if (F_GetPromptHideHud(y))
|
||||
return;
|
||||
|
||||
if ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) && (!stplyr->spectator))
|
||||
{
|
||||
if (leveltime < hidetime * TICRATE)
|
||||
|
@ -2087,6 +2111,9 @@ static void ST_drawTeamHUD(void)
|
|||
patch_t *p;
|
||||
#define SEP 20
|
||||
|
||||
if (F_GetPromptHideHud(0)) // y base is 0
|
||||
return;
|
||||
|
||||
if (gametype == GT_CTF)
|
||||
p = bflagico;
|
||||
else
|
||||
|
@ -2200,7 +2227,8 @@ static INT32 ST_drawEmeraldHuntIcon(mobj_t *hunt, patch_t **patches, INT32 offse
|
|||
interval = 0;
|
||||
}
|
||||
|
||||
V_DrawScaledPatch(hudinfo[HUD_HUNTPICS].x+offset, hudinfo[HUD_HUNTPICS].y, hudinfo[HUD_HUNTPICS].f|V_PERPLAYER|V_HUDTRANS, patches[i]);
|
||||
if (!F_GetPromptHideHud(hudinfo[HUD_HUNTPICS].y))
|
||||
V_DrawScaledPatch(hudinfo[HUD_HUNTPICS].x+offset, hudinfo[HUD_HUNTPICS].y, hudinfo[HUD_HUNTPICS].f|V_PERPLAYER|V_HUDTRANS, patches[i]);
|
||||
return interval;
|
||||
}
|
||||
|
||||
|
@ -2298,7 +2326,8 @@ static void ST_overlayDrawer(void)
|
|||
//hu_showscores = auto hide score/time/rings when tab rankings are shown
|
||||
if (!(hu_showscores && (netgame || multiplayer)))
|
||||
{
|
||||
if (maptol & TOL_NIGHTS || G_IsSpecialStage(gamemap))
|
||||
if ((maptol & TOL_NIGHTS || G_IsSpecialStage(gamemap)) &&
|
||||
!F_GetPromptHideHudAll())
|
||||
ST_drawNiGHTSHUD();
|
||||
else
|
||||
{
|
||||
|
|
|
@ -1489,6 +1489,49 @@ void V_DrawFadeConsBack(INT32 plines)
|
|||
*buf = consolebgmap[*buf];
|
||||
}
|
||||
|
||||
// Very similar to F_DrawFadeConsBack, except we draw from the middle(-ish) of the screen to the bottom.
|
||||
void V_DrawPromptBack(INT32 boxheight, INT32 color)
|
||||
{
|
||||
UINT8 *deststop, *buf;
|
||||
|
||||
boxheight *= vid.dupy;
|
||||
|
||||
if (color == INT32_MAX)
|
||||
color = cons_backcolor.value;
|
||||
|
||||
#ifdef HWRENDER
|
||||
if (rendermode != render_soft && rendermode != render_none)
|
||||
{
|
||||
UINT32 hwcolor;
|
||||
switch (color)
|
||||
{
|
||||
case 0: hwcolor = 0xffffff00; break; // White
|
||||
case 1: hwcolor = 0x00000000; break; // Gray // Note this is different from V_DrawFadeConsBack
|
||||
case 2: hwcolor = 0x40201000; break; // Brown
|
||||
case 3: hwcolor = 0xff000000; break; // Red
|
||||
case 4: hwcolor = 0xff800000; break; // Orange
|
||||
case 5: hwcolor = 0x80800000; break; // Yellow
|
||||
case 6: hwcolor = 0x00800000; break; // Green
|
||||
case 7: hwcolor = 0x0000ff00; break; // Blue
|
||||
case 8: hwcolor = 0x4080ff00; break; // Cyan
|
||||
// Default green
|
||||
default: hwcolor = 0x00800000; break;
|
||||
}
|
||||
HWR_DrawTutorialBack(hwcolor, boxheight);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
CON_SetupBackColormapEx(color, true);
|
||||
|
||||
// heavily simplified -- we don't need to know x or y position,
|
||||
// just the start and stop positions
|
||||
deststop = screens[0] + vid.rowbytes * vid.height;
|
||||
buf = deststop - vid.rowbytes * ((boxheight * 4) + (boxheight/2)*5); // 4 lines of space plus gaps between and some leeway
|
||||
for (; buf < deststop; ++buf)
|
||||
*buf = promptbgmap[*buf];
|
||||
}
|
||||
|
||||
// Gets string colormap, used for 0x80 color codes
|
||||
//
|
||||
static const UINT8 *V_GetStringColormap(INT32 colorflags)
|
||||
|
|
|
@ -158,6 +158,7 @@ void V_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatnum);
|
|||
void V_DrawFadeScreen(UINT16 color, UINT8 strength);
|
||||
|
||||
void V_DrawFadeConsBack(INT32 plines);
|
||||
void V_DrawPromptBack(INT32 boxheight, INT32 color);
|
||||
|
||||
// draw a single character
|
||||
void V_DrawCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed);
|
||||
|
|
Loading…
Reference in a new issue