Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • STJr/SRB2
  • Sryder/SRB2
  • wolfy852/SRB2
  • Alpha2244/SRB2
  • Inuyasha/SRB2
  • yoshibot/SRB2
  • TehRealSalt/SRB2
  • PrisimaTF/SRB2
  • Hatninja/SRB2
  • SteelT/SRB2
  • james/SRB2
  • ShaderWraith/SRB2
  • SinnamonLat/SRB2
  • mazmazz_/SRB2
  • filpAM/SRB2
  • chaoloveicemdboy/SRB2
  • Whooa21/SRB2
  • Machturne/SRB2
  • Golden/SRB2
  • Tatsuru/SRB2
  • Snu/SRB2
  • Zwip-Zwap_Zapony/SRB2
  • fickleheart/SRB2
  • alphaRexJames/SRB2
  • JJK/SRB2
  • diskpoppy/SRB2
  • Hannu_Hanhi/SRB2
  • ZipperQR/SRB2
  • kays/SRB2
  • spherallic/SRB2
  • Zippy_Zolton/SRB2
  • namiishere/SRB2
  • Ors/SRB2
  • SMS_Alfredo/SRB2
  • sonic_edge/SRB2
  • lavla/SRB2
  • ashi/SRB2
  • X.organic/SRB2
  • Fafabis/SRB2
  • Meziu/SRB2
  • v-rob/SRB2
  • tertu/SRB2
  • bitten2up/SRB2
  • flarn2006/SRB2
  • Krabs/SRB2
  • clairebun/SRB2
  • Lactozilla/SRB2
  • thehackstack/SRB2
  • Spice/SRB2
  • win8linux/SRB2
  • JohnFrostFox/SRB2
  • talktoneon726/SRB2
  • Wane/SRB2
  • Lamibe/SRB2
  • spectrumuk2/srb-2
  • nerdyminer18/srb-2
  • 256nil/SRB2
  • ARJr/SRB2
  • Alam/SRB2
  • Zenya/srb-2-marathon-demos
  • Acelite/srb-2-archivedmodifications
  • MIDIMan/SRB2
  • Lach/SRB2
  • Frostiikin/bounce-tweaks
  • Hanicef/SRB2Classic
  • Jaden/SRB2
  • Tyron/SRB2
  • Astronight/SRB2
  • Mari0shi06/SRB2
  • aiire/SRB2
  • Galactice/SRB2
  • srb2-ports/srb2-dreamcast
  • sdasdas/SRB2
  • chreas/srb-2-vr
  • StarManiaKG/the-story-of-sinically-rocketing-and-botching-the-2nd
  • LoganAir/SRB2
  • NepDisk/srb-2
  • alufolie91/SRB2
  • Felicia.iso/SRB2
  • twi/SRB2
  • BarrelsOFun/SRB2
  • Speed2411/SRB2
  • Leather_Realms/SRB2
  • Ayemar/SRB2
  • Acelite/SRB2
  • VladDoc/SRB2
  • kaldrum/model-features
  • strawberryfox417/SRB2
  • Lugent/SRB2
  • Jisk/SRB2
  • Rem/SRB2
  • Refrag/SRB2
  • Henry_3230/srb-3230
  • TehPuertoRicanSpartan2/tprs-srb2
  • Leminn/srb-2-marathon-stuff
  • chromaticpipe2/SRB2
  • MiguelGustavo15/SRB2
  • Maru/srb-2-tests
  • SilicDev/SRB2
  • UnmatchedBracket/SRB2
  • HybridDog/SRB2
  • xordspar0/SRB2
  • jsjhbewfhh/SRB2
  • Fancy2209/SRB2
  • Lorsoen/SRB2
  • shindoukin/SRB2
  • GamerOfDays/SRB2
  • Craftyawesome/SRB2
  • tenshi-tensai-tennoji/SRB2
  • Scarfdudebalder/SRB2
  • luigi-budd/srb-2-fix-interplag-lockon
  • mskluesner/SRB2
  • johnpetersa19/SRB2
  • Pheazant/SRB2
  • chromaticpipe2/srb2classic
  • romoney5/SRB2
  • PAS/SRB2Classic
  • BlueStaggo/SRB2
118 results
Select Git revision
Show changes
Commits on Source (45)
===============================================================================
USDF-SRB2: SRB2 Strife Dialog Format v1.0
based on GZDoom Strife Dialog Format v1.0 - 2019
Copyright (c) 2024 Sonic Team Junior
uses GZDoom Strife Dialog Format v1.0 as a template,
original document Copyright (c) 2019 Rachael Alexanderson.
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.2
or any later version published by the Free Software Foundation;
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
===============================================================================
=======================================
I. Grammar / Syntax
=======================================
No changes.
=======================================
II. Implementation Semantics
=======================================
No changes.
=======================================
III. Changes to GZSDF spec
=======================================
SRB2 Strife Dialogue Format implements most of SRB2's text prompt features,
while using the GZSDF format as a base.
SRB2-format dialogues need to start with this line:
namespace = "srb2";
---------------------
III.A : Conversations
---------------------
conversation // Starts a dialog.
{
id = <string|int>; // Assigns an ID to a dialogue.
// If int, this corresponds to an SRB2 text prompt number.
page // Starts a new page. Pages are automatically numbered starting at 1.
{
pagename = <string>; // Name of the page. For use with next.
name = <string>; // Name of the speaker.
icon = <string>; // Icon lump.
textsound = <string>; // The sound that is played when the text is typed.
dialog = <string>; // Dialog of the page.
nextpage = <string|int>; // Sets the next page.
nextconversation = <string|int>; // Sets the next conversation.
nexttag = <string>; // Jumps to a page with this tag.
duration = <integer>; // Duration in frames of this page.
textspeed = <integer>; // The speed which the text is typed at.
// Default: 1/5th of a second
textlines = <integer>; // How many lines of text to display.
// Default: 4
iconside = <integer>; // Which side to display the icon.
// This must be either "left" or "right".
// Default: "left"
flipicon = <bool>; // Whether to flip the icon horizontally.
// Default: false
displayhud = <string>; // Whether or not to display the HUD. This must one of:
// - "show"
// - "hide"
// - "hideall"
// Default: "hide"
backcolor = <string>; // The color to use for the text box background.
// Default: "gray"
alignchoices = <string>; // Which side the dialog choices are displayed at.
// This must be either "left" or "right".
// Default: "right"
picturesequence = <string>; // How to play the picture sequence. This must one of:
// - "persist"
// - "loop"
// - "hide"
// Default: "persist"
music = <string>; // Which music to play.
musictrack = <integer>; // Which music track to play.
loopmusic = <bool>; // Whether to loop the music.
// Default: false
executelinedef = <integer>; // Executes every linedef with this tag. Execution is ignored if 0.
restoremusic = <bool>; // Whether to restore the map's music.
closedialog = <bool>; // Should the dialog be closed after this page?
// Default: false
// Choices shall be automatically numbered.
choice
{
text = <string>; // Name of the choice.
nextpage = <string|int>; // Sets the next page.
nextconversation = <string|int>; // Sets the next conversation.
nexttag = <string>; // Jumps to a page with this tag.
executelinedef = <integer>; // Executes every linedef with this tag. Execution is ignored if 0.
highlighted = <bool>; // Whether this is the choice to be highlighted
// when the list of choices appear.
// Default: false
nochoice = <bool>; // Is this the "No" choice?
// Default: false
closedialog = <bool>; // Should the dialog be closed upon selecting this choice?
// Default: false
}
// Used to configure a picture sequence.
picture
{
name = <string>; // Lump name of the picture.
x = <integer>; // X coordinate.
y = <integer>; // Y coordinate.
duration = <integer>; // Duration.
hires = <bool>; // Should the picture be displayed at 0.5 scale?
// Default: false
start = <bool>; // Is this the first picture in the sequence?
// Default: false
looppoint = <bool>; // Is this the loop point in the sequence?
// Default: false
}
}
}
===============================================================================
EOF
===============================================================================
\ No newline at end of file
...@@ -37,8 +37,11 @@ add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32 ...@@ -37,8 +37,11 @@ add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32
m_random.c m_random.c
m_tokenizer.c m_tokenizer.c
m_queue.c m_queue.c
m_writebuffer.c
info.c info.c
p_ceilng.c p_ceilng.c
p_dialog.c
p_dialogscript.c
p_enemy.c p_enemy.c
p_floor.c p_floor.c
p_inter.c p_inter.c
...@@ -76,6 +79,7 @@ add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32 ...@@ -76,6 +79,7 @@ add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32
r_portal.c r_portal.c
screen.c screen.c
taglist.c taglist.c
usdf.c
v_video.c v_video.c
s_sound.c s_sound.c
sounds.c sounds.c
......
...@@ -31,8 +31,11 @@ m_perfstats.c ...@@ -31,8 +31,11 @@ m_perfstats.c
m_random.c m_random.c
m_tokenizer.c m_tokenizer.c
m_queue.c m_queue.c
m_writebuffer.c
info.c info.c
p_ceilng.c p_ceilng.c
p_dialog.c
p_dialogscript.c
p_enemy.c p_enemy.c
p_floor.c p_floor.c
p_inter.c p_inter.c
...@@ -70,6 +73,7 @@ r_picformats.c ...@@ -70,6 +73,7 @@ r_picformats.c
r_portal.c r_portal.c
screen.c screen.c
taglist.c taglist.c
usdf.c
v_video.c v_video.c
s_sound.c s_sound.c
sounds.c sounds.c
......
...@@ -970,7 +970,7 @@ boolean CON_Responder(event_t *ev) ...@@ -970,7 +970,7 @@ boolean CON_Responder(event_t *ev)
// let go keyup events, don't eat them // let go keyup events, don't eat them
if (ev->type != ev_keydown && ev->type != ev_text && ev->type != ev_console) if (ev->type != ev_keydown && ev->type != ev_text && ev->type != ev_console)
{ {
if (ev->key == gamecontrol[GC_CONSOLE][0] || ev->key == gamecontrol[GC_CONSOLE][1]) if (G_IsGameControl(ev->key, GC_CONSOLE))
consdown = false; consdown = false;
return false; return false;
} }
...@@ -983,7 +983,7 @@ boolean CON_Responder(event_t *ev) ...@@ -983,7 +983,7 @@ boolean CON_Responder(event_t *ev)
if (modeattacking || metalrecording || marathonmode) if (modeattacking || metalrecording || marathonmode)
return false; return false;
if ((key == gamecontrol[GC_CONSOLE][0] || key == gamecontrol[GC_CONSOLE][1]) && !shiftdown) if (G_IsGameControl(key, GC_CONSOLE) && !shiftdown)
{ {
if (consdown) // ignore repeat if (consdown) // ignore repeat
return true; return true;
......
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
#include "m_misc.h" #include "m_misc.h"
#include "p_setup.h" #include "p_setup.h"
#include "p_saveg.h" #include "p_saveg.h"
#include "usdf.h"
#include "r_main.h" #include "r_main.h"
#include "r_local.h" #include "r_local.h"
#include "r_translation.h" #include "r_translation.h"
...@@ -556,7 +557,6 @@ static void D_Display(void) ...@@ -556,7 +557,6 @@ static void D_Display(void)
if (gamestate == GS_LEVEL) if (gamestate == GS_LEVEL)
{ {
ST_Drawer(); ST_Drawer();
F_TextPromptDrawer();
HU_Drawer(); HU_Drawer();
} }
else else
...@@ -1523,6 +1523,10 @@ void D_SRB2Main(void) ...@@ -1523,6 +1523,10 @@ void D_SRB2Main(void)
savedata.lives = 0; // flag this as not-used savedata.lives = 0; // flag this as not-used
// Parse all DIALOGUE lumps
for (UINT16 w = 0; w < numwadfiles; w++)
P_LoadDialogueLumps(w);
//------------------------------------------------ COMMAND LINE PARAMS //------------------------------------------------ COMMAND LINE PARAMS
// this must be done after loading gamedata, // this must be done after loading gamedata,
......
...@@ -609,6 +609,9 @@ typedef struct player_s ...@@ -609,6 +609,9 @@ typedef struct player_s
botmem_t botmem; botmem_t botmem;
boolean blocked; boolean blocked;
boolean promptactive;
struct dialog_s *textprompt;
tic_t jointime; // Timer when player joins game to change skin/color tic_t jointime; // Timer when player joins game to change skin/color
tic_t quittime; // Time elapsed since user disconnected, zero if connected tic_t quittime; // Time elapsed since user disconnected, zero if connected
tic_t lastinputtime; // the last tic the player has made any input tic_t lastinputtime; // the last tic the player has made any input
......
...@@ -26,6 +26,8 @@ ...@@ -26,6 +26,8 @@
#include "st_stuff.h" #include "st_stuff.h"
#include "i_system.h" #include "i_system.h"
#include "p_setup.h" #include "p_setup.h"
#include "p_dialog.h"
#include "usdf.h"
#include "r_data.h" #include "r_data.h"
#include "r_textures.h" #include "r_textures.h"
#include "r_draw.h" #include "r_draw.h"
...@@ -52,53 +54,10 @@ ...@@ -52,53 +54,10 @@
fixed_t get_number(const char *word) fixed_t get_number(const char *word)
{ {
return LUA_EvalMath(word); return LUA_EvalMath(word);
/*// DESPERATELY NEEDED: Order of operations support! :x
fixed_t i = find_const(&word);
INT32 o;
while(*word) {
o = operation_pad(&word);
if (o != -1)
i = OPERATIONS[o].v(i,find_const(&word));
else
break;
}
return i;*/
} }
#define PARAMCHECK(n) do { if (!params[n]) { deh_warning("Too few parameters, need %d", n); return; }} while (0) #define PARAMCHECK(n) do { if (!params[n]) { deh_warning("Too few parameters, need %d", n); return; }} while (0)
/* ======================================================================== */
// Load a dehacked file format
/* ======================================================================== */
/* a sample to see
Thing 1 (Player) { // MT_PLAYER
INT32 doomednum; ID # = 3232 -1, // doomednum
INT32 spawnstate; Initial frame = 32 "PLAY", // spawnstate
INT32 spawnhealth; Hit points = 3232 100, // spawnhealth
INT32 seestate; First moving frame = 32 "PLAY_RUN1", // seestate
INT32 seesound; Alert sound = 32 sfx_None, // seesound
INT32 reactiontime; Reaction time = 3232 0, // reactiontime
INT32 attacksound; Attack sound = 32 sfx_None, // attacksound
INT32 painstate; Injury frame = 32 "PLAY_PAIN", // painstate
INT32 painchance; Pain chance = 3232 255, // painchance
INT32 painsound; Pain sound = 32 sfx_plpain, // painsound
INT32 meleestate; Close attack frame = 32 "NULL", // meleestate
INT32 missilestate; Far attack frame = 32 "PLAY_ATK1", // missilestate
INT32 deathstate; Death frame = 32 "PLAY_DIE1", // deathstate
INT32 xdeathstate; Exploding frame = 32 "PLAY_XDIE1", // xdeathstate
INT32 deathsound; Death sound = 32 sfx_pldeth, // deathsound
INT32 speed; Speed = 3232 0, // speed
INT32 radius; Width = 211812352 16*FRACUNIT, // radius
INT32 height; Height = 211812352 56*FRACUNIT, // height
INT32 dispoffset; DispOffset = 0 0, // dispoffset
INT32 mass; Mass = 3232 100, // mass
INT32 damage; Missile damage = 3232 0, // damage
INT32 activesound; Action sound = 32 sfx_None, // activesound
INT32 flags; Bits = 3232 MF_SOLID|MF_SHOOTABLE|MF_DROPOFF|MF_PICKUP|MF_NOTDMATCH,
INT32 raisestate; Respawn frame = 32 S_NULL // raisestate
}, */
#ifdef HWRENDER #ifdef HWRENDER
static INT32 searchvalue(const char *s) static INT32 searchvalue(const char *s)
{ {
...@@ -1887,6 +1846,34 @@ void readlevelheader(MYFILE *f, INT32 num) ...@@ -1887,6 +1846,34 @@ void readlevelheader(MYFILE *f, INT32 num)
Z_Free(s); Z_Free(s);
} }
static boolean ParseCutscenePic(cutscene_pic_t *pic, UINT16 usi, const char *word, char *word2)
{
if (fastcmp(word, "NAME"))
{
strlcpy(pic->name, word2, sizeof(pic->name));
}
else if (fastcmp(word, "HIRES"))
{
pic->hires = (UINT8)(usi || word2[0] == 'T' || word2[0] == 'Y');
}
else if (fastcmp(word, "DURATION"))
{
pic->duration = usi;
}
else if (fastcmp(word, "XCOORD"))
{
pic->xcoord = usi;
}
else if (fastcmp(word, "YCOORD"))
{
pic->ycoord = usi;
}
else
return false;
return true;
}
static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum) static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum)
{ {
char *s = Z_Calloc(MAXLINELEN, PU_STATIC, NULL); char *s = Z_Calloc(MAXLINELEN, PU_STATIC, NULL);
...@@ -1969,7 +1956,6 @@ static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum) ...@@ -1969,7 +1956,6 @@ static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum)
i = atoi(word2); i = atoi(word2);
usi = (UINT16)i; usi = (UINT16)i;
if (fastcmp(word, "NUMBEROFPICS")) if (fastcmp(word, "NUMBEROFPICS"))
{ {
cutscenes[num]->scene[scenenum].numpics = (UINT8)i; cutscenes[num]->scene[scenenum].numpics = (UINT8)i;
...@@ -1977,40 +1963,21 @@ static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum) ...@@ -1977,40 +1963,21 @@ static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum)
else if (fastncmp(word, "PIC", 3)) else if (fastncmp(word, "PIC", 3))
{ {
picid = (UINT8)atoi(word + 3); picid = (UINT8)atoi(word + 3);
if (picid > 8 || picid == 0) if (picid > MAX_CUTSCENE_PICS || picid == 0)
{ {
deh_warning("CutSceneScene %d: unknown word '%s'", num, word); deh_warning("CutSceneScene %d: unknown word '%s'", num, word);
continue; continue;
} }
--picid; --picid;
if (fastcmp(word+4, "NAME")) cutscene_pic_t *pic = &cutscenes[num]->scene[scenenum].pics[picid];
{
strncpy(cutscenes[num]->scene[scenenum].picname[picid], word2, 8); if (!ParseCutscenePic(pic, usi, word+4, word2))
}
else if (fastcmp(word+4, "HIRES"))
{
cutscenes[num]->scene[scenenum].pichires[picid] = (UINT8)(i || word2[0] == 'T' || word2[0] == 'Y');
}
else if (fastcmp(word+4, "DURATION"))
{
cutscenes[num]->scene[scenenum].picduration[picid] = usi;
}
else if (fastcmp(word+4, "XCOORD"))
{
cutscenes[num]->scene[scenenum].xcoord[picid] = usi;
}
else if (fastcmp(word+4, "YCOORD"))
{
cutscenes[num]->scene[scenenum].ycoord[picid] = usi;
}
else
deh_warning("CutSceneScene %d: unknown word '%s'", num, word); deh_warning("CutSceneScene %d: unknown word '%s'", num, word);
} }
else if (fastcmp(word, "MUSIC")) else if (fastcmp(word, "MUSIC"))
{ {
strncpy(cutscenes[num]->scene[scenenum].musswitch, word2, 7); strlcpy(cutscenes[num]->scene[scenenum].musswitch, word2, sizeof(cutscenes[num]->scene[scenenum].musswitch));
cutscenes[num]->scene[scenenum].musswitch[6] = 0;
} }
else if (fastcmp(word, "MUSICTRACK")) else if (fastcmp(word, "MUSICTRACK"))
{ {
...@@ -2114,6 +2081,25 @@ void readcutscene(MYFILE *f, INT32 num) ...@@ -2114,6 +2081,25 @@ void readcutscene(MYFILE *f, INT32 num)
Z_Free(s); Z_Free(s);
} }
static char *gettextpromptpicnum(const char *word)
{
const char *num_start = word;
const char *num_end = num_start;
while (isdigit(*num_end))
num_end++;
size_t count = num_end - num_start;
char *buf = malloc(count + 1);
if (!buf)
return NULL;
strncpy(buf, num_start, count);
buf[count] = '\0';
return buf;
}
static void readtextpromptpage(MYFILE *f, INT32 num, INT32 pagenum) static void readtextpromptpage(MYFILE *f, INT32 num, INT32 pagenum)
{ {
char *s = Z_Calloc(MAXLINELEN, PU_STATIC, NULL); char *s = Z_Calloc(MAXLINELEN, PU_STATIC, NULL);
...@@ -2121,7 +2107,8 @@ static void readtextpromptpage(MYFILE *f, INT32 num, INT32 pagenum) ...@@ -2121,7 +2107,8 @@ static void readtextpromptpage(MYFILE *f, INT32 num, INT32 pagenum)
char *word2; char *word2;
INT32 i; INT32 i;
UINT16 usi; UINT16 usi;
UINT8 picid;
textpage_t *page = &textprompts[num]->page[pagenum];
do do
{ {
...@@ -2139,8 +2126,6 @@ static void readtextpromptpage(MYFILE *f, INT32 num, INT32 pagenum) ...@@ -2139,8 +2126,6 @@ static void readtextpromptpage(MYFILE *f, INT32 num, INT32 pagenum)
if (fastcmp(word, "PAGETEXT")) if (fastcmp(word, "PAGETEXT"))
{ {
char *pagetext = NULL; char *pagetext = NULL;
char *buffer;
const int bufferlen = 4096;
for (i = 0; i < MAXLINELEN; i++) for (i = 0; i < MAXLINELEN; i++)
{ {
...@@ -2153,8 +2138,9 @@ static void readtextpromptpage(MYFILE *f, INT32 num, INT32 pagenum) ...@@ -2153,8 +2138,9 @@ static void readtextpromptpage(MYFILE *f, INT32 num, INT32 pagenum)
if (!pagetext) if (!pagetext)
{ {
Z_Free(textprompts[num]->page[pagenum].text); Z_Free(page->text);
textprompts[num]->page[pagenum].text = NULL; page->text = NULL;
page->textlength = 0;
continue; continue;
} }
...@@ -2168,22 +2154,17 @@ static void readtextpromptpage(MYFILE *f, INT32 num, INT32 pagenum) ...@@ -2168,22 +2154,17 @@ static void readtextpromptpage(MYFILE *f, INT32 num, INT32 pagenum)
} }
} }
buffer = Z_Malloc(4096, PU_STATIC, NULL); const int bufferlen = 4096;
strcpy(buffer, pagetext);
// \todo trim trailing whitespace before the # char *buffer = Z_Malloc(bufferlen, PU_STATIC, NULL);
// and also support # at the end of a PAGETEXT with no line break
strcat(buffer, strlcpy(buffer, pagetext, bufferlen);
myhashfgets(pagetext, bufferlen strlcat(buffer, myhashfgets(pagetext, MAXLINELEN, f), bufferlen);
- strlen(buffer) - 1, f));
// A text prompt overwriting another one... // A text prompt overwriting another one...
Z_Free(textprompts[num]->page[pagenum].text); Z_Free(page->text);
textprompts[num]->page[pagenum].text = Z_StrDup(buffer);
Z_Free(buffer); page->text = P_ConvertSOCPageDialog(buffer, &page->textlength);
continue; continue;
} }
...@@ -2202,206 +2183,169 @@ static void readtextpromptpage(MYFILE *f, INT32 num, INT32 pagenum) ...@@ -2202,206 +2183,169 @@ static void readtextpromptpage(MYFILE *f, INT32 num, INT32 pagenum)
// copypasta from readcutscenescene // copypasta from readcutscenescene
if (fastcmp(word, "NUMBEROFPICS")) if (fastcmp(word, "NUMBEROFPICS"))
{ {
textprompts[num]->page[pagenum].numpics = (UINT8)i; if (i < 0 || i > MAX_PROMPT_PICS)
{
deh_warning("textpromptscene %d: invalid number of pictures %d (maximum is %d)'", num, i, MAX_PROMPT_PICS);
continue;
}
page->numpics = (UINT8)i;
if (!page->numpics)
Z_Free(page->pics);
else
page->pics = Z_Realloc(page->pics, sizeof(cutscene_pic_t) * page->numpics, PU_STATIC, NULL);
} }
else if (fastcmp(word, "PICMODE")) else if (fastcmp(word, "PICMODE"))
{ {
UINT8 picmode = 0; // PROMPT_PIC_PERSIST UINT8 picmode = 0; // PROMPT_PIC_PERSIST
if (usi == 1 || word2[0] == 'L') picmode = PROMPT_PIC_LOOP; if (usi == 1 || word2[0] == 'L') picmode = PROMPT_PIC_LOOP;
else if (usi == 2 || word2[0] == 'D' || word2[0] == 'H') picmode = PROMPT_PIC_DESTROY; else if (usi == 2 || word2[0] == 'D' || word2[0] == 'H') picmode = PROMPT_PIC_DESTROY;
textprompts[num]->page[pagenum].picmode = picmode; page->picmode = picmode;
} }
else if (fastcmp(word, "PICTOLOOP")) else if (fastcmp(word, "PICTOLOOP"))
textprompts[num]->page[pagenum].pictoloop = (UINT8)i; page->pictoloop = (UINT8)i;
else if (fastcmp(word, "PICTOSTART")) else if (fastcmp(word, "PICTOSTART"))
textprompts[num]->page[pagenum].pictostart = (UINT8)i; page->pictostart = (UINT8)i;
else if (fastcmp(word, "PICSMETAPAGE")) else if (fastcmp(word, "PICSMETAPAGE"))
{ {
if (usi && usi <= textprompts[num]->numpages) if (usi > 0 && usi <= textprompts[num]->numpages)
{ P_SetPicsMetaPage(page, &textprompts[num]->page[usi - 1]);
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)) else if (fastncmp(word, "PIC", 3))
{ {
picid = (UINT8)atoi(word + 3); char *word3 = word+3;
char *num_text = gettextpromptpicnum(word3);
if (!num_text)
continue;
UINT16 picid = (UINT16)atoi(num_text);
if (picid > MAX_PROMPT_PICS || picid == 0) if (picid > MAX_PROMPT_PICS || picid == 0)
{ {
deh_warning("textpromptscene %d: unknown word '%s'", num, word); deh_warning("textpromptscene %d: unknown word '%s'", num, word);
free(num_text);
continue; continue;
} }
--picid; --picid;
if (fastcmp(word+4, "NAME")) if (!page->pics || picid >= page->numpics)
{ page->pics = Z_Realloc(page->pics, sizeof(cutscene_pic_t) * (picid+1), PU_STATIC, NULL);
strncpy(textprompts[num]->page[pagenum].picname[picid], word2, 8);
} word3 += strlen(num_text);
else if (fastcmp(word+4, "HIRES"))
{ free(num_text);
textprompts[num]->page[pagenum].pichires[picid] = (UINT8)(i || word2[0] == 'T' || word2[0] == 'Y');
} if (!ParseCutscenePic(&page->pics[picid], usi, word3, word2))
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); deh_warning("textpromptscene %d: unknown word '%s'", num, word);
} }
else if (fastcmp(word, "MUSIC")) else if (fastcmp(word, "MUSIC"))
{ {
strncpy(textprompts[num]->page[pagenum].musswitch, word2, 7); strlcpy(page->musswitch, word2, sizeof(page->musswitch));
textprompts[num]->page[pagenum].musswitch[6] = 0;
} }
else if (fastcmp(word, "MUSICTRACK")) else if (fastcmp(word, "MUSICTRACK"))
{ {
textprompts[num]->page[pagenum].musswitchflags = ((UINT16)i) & MUSIC_TRACKMASK; page->musswitchflags = ((UINT16)i) & MUSIC_TRACKMASK;
} }
else if (fastcmp(word, "MUSICLOOP")) else if (fastcmp(word, "MUSICLOOP"))
{ {
textprompts[num]->page[pagenum].musicloop = (UINT8)(i || word2[0] == 'T' || word2[0] == 'Y'); page->musicloop = (UINT8)(i || word2[0] == 'T' || word2[0] == 'Y');
} }
// end copypasta from readcutscenescene // end copypasta from readcutscenescene
else if (fastcmp(word, "NAME")) else if (fastcmp(word, "NAME"))
{ {
Z_Free(page->name);
page->name = NULL;
if (*word2 != '\0') if (*word2 != '\0')
{ {
INT32 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;
strncat(name, word2, 33);
name[33] = 0;
// Replace _ with ' ' // Replace _ with ' '
for (j = 0; j < 32 && name[j]; j++) for (size_t j = 0; j < sizeof(name) && name[j]; j++)
{ {
if (name[j] == '_') if (name[j] == '_')
name[j] = ' '; name[j] = ' ';
} }
strncpy(textprompts[num]->page[pagenum].name, name, 32); page->name = Z_StrDup(name);
} }
else
*textprompts[num]->page[pagenum].name = '\0';
} }
else if (fastcmp(word, "ICON")) else if (fastcmp(word, "ICON"))
strncpy(textprompts[num]->page[pagenum].iconname, word2, 8); strlcpy(page->iconname, word2, sizeof(page->iconname));
else if (fastcmp(word, "ICONALIGN")) else if (fastcmp(word, "ICONALIGN"))
textprompts[num]->page[pagenum].rightside = (i || word2[0] == 'R'); page->rightside = (i || word2[0] == 'R');
else if (fastcmp(word, "ICONFLIP")) else if (fastcmp(word, "ICONFLIP"))
textprompts[num]->page[pagenum].iconflip = (i || word2[0] == 'T' || word2[0] == 'Y'); page->iconflip = (i || word2[0] == 'T' || word2[0] == 'Y');
else if (fastcmp(word, "LINES")) else if (fastcmp(word, "LINES"))
textprompts[num]->page[pagenum].lines = usi; {
if (i <= 0)
deh_warning("PromptPage %d: line count must be 1 or higher", num);
else
page->lines = usi;
}
else if (fastcmp(word, "BACKCOLOR")) else if (fastcmp(word, "BACKCOLOR"))
{ {
INT32 backcolor; INT32 backcolor = -1;
if (i == 0 || fastcmp(word2, "WHITE")) backcolor = 0;
else if (i == 1 || fastcmp(word2, "GRAY") || fastcmp(word2, "GREY") || if (i >= 256 && i < 512)
fastcmp(word2, "BLACK")) backcolor = 1; backcolor = i; // non-transparent palette index
else if (i == 2 || fastcmp(word2, "SEPIA")) backcolor = 2; else if (i < 0)
else if (i == 3 || fastcmp(word2, "BROWN")) backcolor = 3; backcolor = INT32_MAX; // CONS_BACKCOLOR user-configured
else if (i == 4 || fastcmp(word2, "PINK")) backcolor = 4; else
else if (i == 5 || fastcmp(word2, "RASPBERRY")) backcolor = 5; {
else if (i == 6 || fastcmp(word2, "RED")) backcolor = 6; strlwr(word2);
else if (i == 7 || fastcmp(word2, "CREAMSICLE")) backcolor = 7; backcolor = P_ParsePromptBackColor(word2);
else if (i == 8 || fastcmp(word2, "ORANGE")) backcolor = 8; }
else if (i == 9 || fastcmp(word2, "GOLD")) backcolor = 9;
else if (i == 10 || fastcmp(word2, "YELLOW")) backcolor = 10; if (backcolor < 0)
else if (i == 11 || fastcmp(word2, "EMERALD")) backcolor = 11; backcolor = 1; // default gray
else if (i == 12 || fastcmp(word2, "GREEN")) backcolor = 12;
else if (i == 13 || fastcmp(word2, "CYAN") || fastcmp(word2, "AQUA")) backcolor = 13; page->backcolor = backcolor;
else if (i == 14 || fastcmp(word2, "STEEL")) backcolor = 14;
else if (i == 15 || fastcmp(word2, "PERIWINKLE")) backcolor = 15;
else if (i == 16 || fastcmp(word2, "BLUE")) backcolor = 16;
else if (i == 17 || fastcmp(word2, "PURPLE")) backcolor = 17;
else if (i == 18 || fastcmp(word2, "LAVENDER")) backcolor = 18;
else if (i >= 256 && i < 512) backcolor = i; // non-transparent palette index
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")) else if (fastcmp(word, "ALIGN"))
{ {
UINT8 align = 0; // left UINT8 align = 0; // left
if (usi == 1 || word2[0] == 'R') align = 1; if (usi == 1 || word2[0] == 'R') align = 1;
else if (usi == 2 || word2[0] == 'C' || word2[0] == 'M') align = 2; else if (usi == 2 || word2[0] == 'C' || word2[0] == 'M') align = 2;
textprompts[num]->page[pagenum].align = align; page->align = align;
} }
else if (fastcmp(word, "VERTICALALIGN")) else if (fastcmp(word, "VERTICALALIGN"))
{ {
UINT8 align = 0; // top UINT8 align = 0; // top
if (usi == 1 || word2[0] == 'B') align = 1; if (usi == 1 || word2[0] == 'B') align = 1;
else if (usi == 2 || word2[0] == 'C' || word2[0] == 'M') align = 2; else if (usi == 2 || word2[0] == 'C' || word2[0] == 'M') align = 2;
textprompts[num]->page[pagenum].verticalalign = align; page->verticalalign = align;
} }
else if (fastcmp(word, "TEXTSPEED")) else if (fastcmp(word, "TEXTSPEED"))
textprompts[num]->page[pagenum].textspeed = get_number(word2); page->textspeed = get_number(word2);
else if (fastcmp(word, "TEXTSFX")) else if (fastcmp(word, "TEXTSFX"))
textprompts[num]->page[pagenum].textsfx = get_number(word2); page->textsfx = get_number(word2);
else if (fastcmp(word, "HIDEHUD")) else if (fastcmp(word, "HIDEHUD"))
{ {
UINT8 hidehud = 0; UINT8 hidehud = 0;
if ((word2[0] == 'F' && (word2[1] == 'A' || !word2[1])) || word2[0] == 'N') hidehud = 0; // false 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 == 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) 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; page->hidehud = hidehud;
} }
else if (fastcmp(word, "METAPAGE")) else if (fastcmp(word, "METAPAGE"))
{ {
if (usi && usi <= textprompts[num]->numpages) if (usi > 0 && usi <= textprompts[num]->numpages)
{ P_SetMetaPage(page, &textprompts[num]->page[usi - 1]);
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")) else if (fastcmp(word, "TAG"))
strncpy(textprompts[num]->page[pagenum].tag, word2, 33); strlcpy(page->tag, word2, sizeof(page->tag));
else if (fastcmp(word, "NEXTPROMPT")) else if (fastcmp(word, "NEXTPROMPT"))
textprompts[num]->page[pagenum].nextprompt = usi; page->nextprompt = usi;
else if (fastcmp(word, "NEXTPAGE")) else if (fastcmp(word, "NEXTPAGE"))
textprompts[num]->page[pagenum].nextpage = usi; page->nextpage = usi;
else if (fastcmp(word, "NEXTTAG")) else if (fastcmp(word, "NEXTTAG"))
strncpy(textprompts[num]->page[pagenum].nexttag, word2, 33); strlcpy(page->nexttag, word2, sizeof(page->nexttag));
else if (fastcmp(word, "TIMETONEXT")) else if (fastcmp(word, "TIMETONEXT"))
textprompts[num]->page[pagenum].timetonext = get_number(word2); page->timetonext = get_number(word2);
else else
deh_warning("PromptPage %d: unknown word '%s'", num, word); deh_warning("PromptPage %d: unknown word '%s'", num, word);
} }
...@@ -2458,13 +2402,13 @@ void readtextprompt(MYFILE *f, INT32 num) ...@@ -2458,13 +2402,13 @@ void readtextprompt(MYFILE *f, INT32 num)
{ {
if (1 <= value && value <= MAX_PAGES) if (1 <= value && value <= MAX_PAGES)
{ {
textprompts[num]->page[value - 1].backcolor = 1; // default to gray textpage_t *page = &textprompts[num]->page[value - 1];
textprompts[num]->page[value - 1].hidehud = 1; // hide appropriate HUD elements if (page->lines == 0)
P_InitTextPromptPage(page);
readtextpromptpage(f, num, value - 1); readtextpromptpage(f, num, value - 1);
} }
else else
deh_warning("Page number %d out of range (1 - %d)", value, MAX_PAGES); deh_warning("Page number %d out of range (1 - %d)", value, MAX_PAGES);
} }
else else
deh_warning("Prompt %d: unknown word '%s', Page <num> expected.", num, word); deh_warning("Prompt %d: unknown word '%s', Page <num> expected.", num, word);
......
...@@ -162,15 +162,22 @@ extern tic_t countdowntimer; ...@@ -162,15 +162,22 @@ extern tic_t countdowntimer;
extern boolean countdowntimeup; extern boolean countdowntimeup;
extern boolean exitfadestarted; extern boolean exitfadestarted;
typedef struct
{
char name[256];
UINT8 hires;
INT16 xcoord;
INT16 ycoord;
UINT16 duration;
} cutscene_pic_t;
#define MAX_CUTSCENE_PICS 8
typedef struct typedef struct
{ {
UINT8 numpics; UINT8 numpics;
char picname[8][8];
UINT8 pichires[8];
char *text; char *text;
UINT16 xcoord[8]; cutscene_pic_t pics[MAX_CUTSCENE_PICS];
UINT16 ycoord[8];
UINT16 picduration[8];
UINT8 musicloop; UINT8 musicloop;
UINT16 textxpos; UINT16 textxpos;
UINT16 textypos; UINT16 textypos;
...@@ -199,29 +206,50 @@ extern cutscene_t *cutscenes[128]; ...@@ -199,29 +206,50 @@ extern cutscene_t *cutscenes[128];
#define MAX_PROMPTS (TUTORIAL_PROMPT+TUTORIAL_AREAS*TUTORIAL_AREA_PROMPTS*3) // 3 control modes #define MAX_PROMPTS (TUTORIAL_PROMPT+TUTORIAL_AREAS*TUTORIAL_AREA_PROMPTS*3) // 3 control modes
#define MAX_PAGES 128 #define MAX_PAGES 128
#define PROMPT_PIC_PERSIST 0 enum
#define PROMPT_PIC_LOOP 1 {
#define PROMPT_PIC_DESTROY 2 PROMPT_PIC_PERSIST,
#define MAX_PROMPT_PICS 8 PROMPT_PIC_LOOP,
PROMPT_PIC_DESTROY
};
#define MAX_PROMPT_PICS 512
#define MAX_PROMPT_CHOICES 12
typedef struct typedef struct
{ {
UINT8 numpics; UINT16 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 *nextpromptname;
char *nextpagename;
char nexttag[33]; // next tag to jump to. If set, this overrides nextprompt and nextpage.
INT16 exectag;
boolean endprompt;
char *text;
} promptchoice_t;
typedef struct
{
char *pagename;
UINT16 numpics;
UINT8 picmode; // sequence mode after displaying last pic, 0 = persist, 1 = loop, 2 = destroy 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 pictoloop; // if picmode == loop, which pic to loop to?
UINT8 pictostart; // initial pic number to show UINT8 pictostart; // initial pic number to show
char picname[MAX_PROMPT_PICS][8]; cutscene_pic_t *pics;
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]; char musswitch[7];
UINT16 musswitchflags; UINT16 musswitchflags;
UINT8 musicloop; UINT8 musicloop;
boolean restoremusic;
INT16 exectag;
boolean endprompt;
char tag[33]; // page tag char tag[33]; // page tag
char name[34]; // narrator name, extra char for color char *name; // narrator name
char iconname[8]; // 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
...@@ -229,17 +257,26 @@ typedef struct ...@@ -229,17 +257,26 @@ typedef struct
INT32 backcolor; // see CON_SetupBackColormap: 0-11, INT32_MAX for user-defined (CONS_BACKCOLOR) 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 align; // text alignment, 0 = left, 1 = right, 2 = center
UINT8 verticalalign; // vertical text alignment, 0 = top, 1 = bottom, 2 = middle UINT8 verticalalign; // vertical text alignment, 0 = top, 1 = bottom, 2 = middle
UINT8 textspeed; // text speed, delay in tics between characters. SINT8 textspeed; // text speed, delay in tics between characters.
sfxenum_t textsfx; // sfx_ id for printing text sfxenum_t textsfx; // sfx_ id for printing text
UINT8 nextprompt; // next prompt to jump to, one-based. 0 = current prompt UINT16 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 UINT8 nextpage; // next page to jump to, one-based. 0 = next page within prompt->numpages
char *nextpromptname;
char *nextpagename;
char nexttag[33]; // next tag to jump to. If set, this overrides nextprompt and nextpage. 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 INT32 timetonext; // time in tics to jump to next page automatically. 0 = don't jump automatically
char *text; char *text;
size_t textlength;
INT32 numchoices;
promptchoice_t *choices;
INT32 startchoice;
INT32 nochoice;
boolean choicesleftside;
} textpage_t; } textpage_t;
typedef struct typedef struct
{ {
char *name;
textpage_t page[MAX_PAGES]; textpage_t page[MAX_PAGES];
INT32 numpages; // Number of pages in this prompt INT32 numpages; // Number of pages in this prompt
} textprompt_t; } textprompt_t;
......
This diff is collapsed.
...@@ -34,7 +34,6 @@ void F_IntroTicker(void); ...@@ -34,7 +34,6 @@ void F_IntroTicker(void);
void F_TitleScreenTicker(boolean run); void F_TitleScreenTicker(boolean run);
void F_CutsceneTicker(void); void F_CutsceneTicker(void);
void F_TitleDemoTicker(void); void F_TitleDemoTicker(void);
void F_TextPromptTicker(void);
// Called by main loop. // Called by main loop.
void F_GameEndDrawer(void); void F_GameEndDrawer(void);
...@@ -56,13 +55,6 @@ void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean reset ...@@ -56,13 +55,6 @@ void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean reset
void F_CutsceneDrawer(void); void F_CutsceneDrawer(void);
void F_EndCutScene(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_StartGameEnd(void);
void F_StartIntro(void); void F_StartIntro(void);
void F_StartTitleScreen(void); void F_StartTitleScreen(void);
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "f_finale.h" #include "f_finale.h"
#include "p_setup.h" #include "p_setup.h"
#include "p_saveg.h" #include "p_saveg.h"
#include "p_dialog.h"
#include "i_time.h" #include "i_time.h"
#include "i_system.h" #include "i_system.h"
#include "am_map.h" #include "am_map.h"
...@@ -158,6 +159,8 @@ boolean exitfadestarted = false; ...@@ -158,6 +159,8 @@ boolean exitfadestarted = false;
cutscene_t *cutscenes[128]; cutscene_t *cutscenes[128];
textprompt_t *textprompts[MAX_PROMPTS]; textprompt_t *textprompts[MAX_PROMPTS];
struct dialog_s *globaltextprompt = NULL;
INT16 nextmapoverride; INT16 nextmapoverride;
UINT8 skipstats; UINT8 skipstats;
INT16 nextgametype = -1; INT16 nextgametype = -1;
...@@ -2010,9 +2013,9 @@ static boolean ViewpointSwitchResponder(event_t *ev) ...@@ -2010,9 +2013,9 @@ static boolean ViewpointSwitchResponder(event_t *ev)
UINT8 canSwitchView = 0; UINT8 canSwitchView = 0;
INT32 direction = 0; INT32 direction = 0;
if (ev->key == KEY_F12 || ev->key == gamecontrol[GC_VIEWPOINTNEXT][0] || ev->key == gamecontrol[GC_VIEWPOINTNEXT][1]) if (ev->key == KEY_F12 || G_IsGameControl(ev->key, GC_VIEWPOINTNEXT))
direction = 1; direction = 1;
if (ev->key == gamecontrol[GC_VIEWPOINTPREV][0] || ev->key == gamecontrol[GC_VIEWPOINTPREV][1]) if (G_IsGameControl(ev->key, GC_VIEWPOINTPREV))
direction = -1; direction = -1;
// This enabled reverse-iterating with shift+F12, sadly I had to // This enabled reverse-iterating with shift+F12, sadly I had to
// disable this in case your shift key is bound to a control =(( // disable this in case your shift key is bound to a control =((
...@@ -2083,6 +2086,122 @@ static boolean ViewpointSwitchResponder(event_t *ev) ...@@ -2083,6 +2086,122 @@ static boolean ViewpointSwitchResponder(event_t *ev)
return true; return true;
} }
static boolean G_TextPromptResponder(event_t *ev)
{
if (ev->type != ev_keydown)
return false;
player_t *player = NULL;
dialog_t *dialog = NULL;
UINT8 localplayer = 0;
INT32 key = KEY_NULL;
if (!splitscreen)
{
player = &players[consoleplayer];
if (!player->promptactive)
return false;
dialog = P_GetPlayerDialog(player);
if (!dialog || !dialog->showchoices)
return false;
}
else
{
// Check P2
if (G_IsGameControlP2(ev->key, GC_FORWARD))
{
key = KEY_UPARROW;
localplayer = 1;
}
else if (G_IsGameControlP2(ev->key, GC_BACKWARD))
{
key = KEY_DOWNARROW;
localplayer = 1;
}
else if (G_IsGameControlP2(ev->key, GC_JUMP))
{
key = KEY_ENTER;
localplayer = 1;
}
else if (G_IsGameControlP2(ev->key, GC_SPIN))
{
key = KEY_BACKSPACE;
localplayer = 1;
}
}
// Check P1
if (localplayer == 0)
{
if (G_IsGameControl(ev->key, GC_FORWARD))
key = KEY_UPARROW;
else if (G_IsGameControl(ev->key, GC_BACKWARD))
key = KEY_DOWNARROW;
else if (G_IsGameControl(ev->key, GC_JUMP))
key = KEY_ENTER;
else if (G_IsGameControl(ev->key, GC_SPIN))
key = KEY_BACKSPACE;
}
// No key was hit
if (key == KEY_NULL)
return false;
// If on splitscreen, get the player that might correspond to this key press
if (splitscreen)
{
player = (localplayer == 1) ? &players[secondarydisplayplayer] : &players[consoleplayer];
if (!player->promptactive)
return false;
dialog = P_GetPlayerDialog(player);
if (!dialog || !dialog->showchoices)
return false;
}
// Get the player that started this prompt
// If this is not a global text prompt, it will be the same player.
player_t *promptplayer = globaltextprompt ? globaltextprompt->player : player;
if (player != promptplayer)
return false;
if (key == KEY_UPARROW)
{
INT32 choice = dialog->curchoice - 1;
if (choice < 0)
choice = dialog->numchoices - 1;
D_SendTextPromptChoice(choice, localplayer);
return true;
}
else if (key == KEY_DOWNARROW)
{
INT32 choice = dialog->curchoice + 1;
if (choice >= dialog->numchoices)
choice = 0;
D_SendTextPromptChoice(choice, localplayer);
return true;
}
else if (!ev->repeated)
{
// Ignore repeated key events if the key was jump or spin
if (key == KEY_ENTER)
{
D_SendTextPromptConfirm(dialog->curchoice, localplayer);
return true;
}
else if (dialog->nochoice > 0 && dialog->nochoice <= dialog->numchoices && key == KEY_BACKSPACE)
{
D_SendTextPromptChoice(dialog->nochoice, localplayer);
return true;
}
}
return false;
}
// //
// G_Responder // G_Responder
// Get info needed to make ticcmd_ts for the players. // Get info needed to make ticcmd_ts for the players.
...@@ -2173,12 +2292,13 @@ boolean G_Responder(event_t *ev) ...@@ -2173,12 +2292,13 @@ boolean G_Responder(event_t *ev)
// update keys current state // update keys current state
G_MapEventsToControls(ev); G_MapEventsToControls(ev);
if (G_TextPromptResponder(ev))
return true;
switch (ev->type) switch (ev->type)
{ {
case ev_keydown: case ev_keydown:
if (ev->key == gamecontrol[GC_PAUSE][0] if (G_IsGameControl(ev->key, GC_PAUSE) || ev->key == KEY_PAUSE)
|| ev->key == gamecontrol[GC_PAUSE][1]
|| ev->key == KEY_PAUSE)
{ {
if (modeattacking && !demoplayback && (gamestate == GS_LEVEL)) if (modeattacking && !demoplayback && (gamestate == GS_LEVEL))
{ {
...@@ -2207,8 +2327,7 @@ boolean G_Responder(event_t *ev) ...@@ -2207,8 +2327,7 @@ boolean G_Responder(event_t *ev)
} }
} }
} }
if (ev->key == gamecontrol[GC_CAMTOGGLE][0] if (G_IsGameControl(ev->key, GC_CAMTOGGLE))
|| ev->key == gamecontrol[GC_CAMTOGGLE][1])
{ {
if (!camtoggledelay) if (!camtoggledelay)
{ {
...@@ -2216,8 +2335,7 @@ boolean G_Responder(event_t *ev) ...@@ -2216,8 +2335,7 @@ boolean G_Responder(event_t *ev)
CV_SetValue(&cv_chasecam, cv_chasecam.value ? 0 : 1); CV_SetValue(&cv_chasecam, cv_chasecam.value ? 0 : 1);
} }
} }
if (ev->key == gamecontrolbis[GC_CAMTOGGLE][0] if (G_IsGameControlP2(ev->key, GC_CAMTOGGLE))
|| ev->key == gamecontrolbis[GC_CAMTOGGLE][1])
{ {
if (!camtoggledelay2) if (!camtoggledelay2)
{ {
...@@ -2422,7 +2540,6 @@ void G_Ticker(boolean run) ...@@ -2422,7 +2540,6 @@ void G_Ticker(boolean run)
F_TitleDemoTicker(); F_TitleDemoTicker();
P_Ticker(run); // tic the game P_Ticker(run); // tic the game
ST_Ticker(run); ST_Ticker(run);
F_TextPromptTicker();
AM_Ticker(); AM_Ticker();
HU_Ticker(); HU_Ticker();
......
...@@ -45,7 +45,7 @@ extern INT16 rw_maximums[NUM_WEAPONS]; ...@@ -45,7 +45,7 @@ extern INT16 rw_maximums[NUM_WEAPONS];
extern INT32 pausedelay; extern INT32 pausedelay;
extern boolean pausebreakkey; extern boolean pausebreakkey;
extern boolean promptactive; extern struct dialog_s *globaltextprompt;
extern consvar_t cv_pauseifunfocused; extern consvar_t cv_pauseifunfocused;
......
...@@ -102,6 +102,16 @@ static dclick_t joy2dclicks[JOYBUTTONS + JOYHATS*4]; ...@@ -102,6 +102,16 @@ static dclick_t joy2dclicks[JOYBUTTONS + JOYHATS*4];
// protos // protos
static UINT8 G_CheckDoubleClick(UINT8 state, dclick_t *dt); static UINT8 G_CheckDoubleClick(UINT8 state, dclick_t *dt);
boolean G_IsGameControl(INT32 key, gamecontrols_e gc)
{
return key == gamecontrol[gc][0] || key == gamecontrol[gc][1];
}
boolean G_IsGameControlP2(INT32 key, gamecontrols_e gc)
{
return key == gamecontrolbis[gc][0] || key == gamecontrolbis[gc][1];
}
// //
// Remaps the inputs to game controls. // Remaps the inputs to game controls.
// //
......
...@@ -179,6 +179,9 @@ extern const INT32 gcl_jump_spin[num_gcl_jump_spin]; ...@@ -179,6 +179,9 @@ extern const INT32 gcl_jump_spin[num_gcl_jump_spin];
// remaps the input event to a game control. // remaps the input event to a game control.
void G_MapEventsToControls(event_t *ev); void G_MapEventsToControls(event_t *ev);
boolean G_IsGameControl(INT32 key, gamecontrols_e gc);
boolean G_IsGameControlP2(INT32 key, gamecontrols_e gc);
// returns the name of a key // returns the name of a key
const char *G_KeyNumToName(INT32 keynum); const char *G_KeyNumToName(INT32 keynum);
INT32 G_KeyNameToNum(const char *keystr); INT32 G_KeyNameToNum(const char *keystr);
......
...@@ -1203,9 +1203,9 @@ patch_t *HWR_GetCachedGLPatchPwad(UINT16 wadnum, UINT16 lumpnum) ...@@ -1203,9 +1203,9 @@ patch_t *HWR_GetCachedGLPatchPwad(UINT16 wadnum, UINT16 lumpnum)
lumpcache_t *lumpcache = wadfiles[wadnum]->patchcache; lumpcache_t *lumpcache = wadfiles[wadnum]->patchcache;
if (!lumpcache[lumpnum]) if (!lumpcache[lumpnum])
{ {
void *ptr = Z_Calloc(sizeof(patch_t), PU_PATCH, &lumpcache[lumpnum]); patch_t *patch = Patch_Create(NULL, 0);
Patch_Create(NULL, 0, ptr); Z_SetUser(patch, &lumpcache[lumpnum]);
Patch_AllocateHardwarePatch(ptr); Patch_AllocateHardwarePatch(patch);
} }
return (patch_t *)(lumpcache[lumpnum]); return (patch_t *)(lumpcache[lumpnum]);
} }
......
...@@ -115,7 +115,6 @@ void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option) ...@@ -115,7 +115,6 @@ void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option)
flags = PF_Translucent|PF_NoDepthTest; flags = PF_Translucent|PF_NoDepthTest;
// clip it since it is used for bunny scroll in doom I
HWD.pfnDrawPolygon(NULL, v, 4, flags); HWD.pfnDrawPolygon(NULL, v, 4, flags);
} }
...@@ -338,7 +337,215 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p ...@@ -338,7 +337,215 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p
v[0].t = v[1].t = 0.0f; v[0].t = v[1].t = 0.0f;
v[2].t = v[3].t = hwrPatch->max_t; v[2].t = v[3].t = hwrPatch->max_t;
// clip it since it is used for bunny scroll in doom I flags = HWR_GetBlendModeFlag(blendmode+1)|PF_NoDepthTest;
if (alphalevel)
{
FSurfaceInfo Surf;
Surf.PolyColor.s.red = Surf.PolyColor.s.green = Surf.PolyColor.s.blue = 0xff;
if (alphalevel == 10) Surf.PolyColor.s.alpha = softwaretranstogl_lo[st_translucency]; // V_HUDTRANSHALF
else if (alphalevel == 11) Surf.PolyColor.s.alpha = softwaretranstogl[st_translucency]; // V_HUDTRANS
else if (alphalevel == 12) Surf.PolyColor.s.alpha = softwaretranstogl_hi[st_translucency]; // V_HUDTRANSDOUBLE
else Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel];
flags |= PF_Modulated;
HWD.pfnDrawPolygon(&Surf, v, 4, flags);
}
else
HWD.pfnDrawPolygon(NULL, v, 4, flags);
}
void HWR_DrawTexture(INT32 texturenum, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option)
{
FOutVector v[4];
FBITFIELD flags;
float cx = FIXED_TO_FLOAT(x);
float cy = FIXED_TO_FLOAT(y);
UINT8 alphalevel = ((option & V_ALPHAMASK) >> V_ALPHASHIFT);
UINT8 blendmode = ((option & V_BLENDMASK) >> V_BLENDSHIFT);
// 3--2
// | /|
// |/ |
// 0--1
float dup, fscalew, fscaleh, fwidth, fheight;
UINT8 perplayershuffle = 0;
if (texturenum < 0 || texturenum >= numtextures)
return;
// make texture ready in hardware cache
HWR_GetTexture(texturenum);
INT32 texwidth = textures[texturenum]->width;
INT32 texheight = textures[texturenum]->height;
dup = (float)vid.dup;
switch (option & V_SCALEPATCHMASK)
{
case V_NOSCALEPATCH:
dup = 1.0f;
break;
case V_SMALLSCALEPATCH:
dup = (float)vid.smalldup;
break;
case V_MEDSCALEPATCH:
dup = (float)vid.meddup;
break;
}
fscalew = fscaleh = FIXED_TO_FLOAT(pscale);
if (vscale != pscale)
fscaleh = FIXED_TO_FLOAT(vscale);
if (option & V_FLIP)
cx -= (float)(texwidth) * fscalew;
if (splitscreen && (option & V_PERPLAYER))
{
float adjusty = ((option & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)/2.0f;
fscaleh /= 2;
cy /= 2;
#ifdef QUADS
if (splitscreen > 1) // 3 or 4 players
{
float adjustx = ((option & V_NOSCALESTART) ? vid.width : BASEVIDWIDTH)/2.0f;
fscalew /= 2;
cx /= 2;
if (stplyr == &players[displayplayer])
{
if (!(option & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
perplayershuffle |= 1;
if (!(option & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
perplayershuffle |= 4;
option &= ~V_SNAPTOBOTTOM|V_SNAPTORIGHT;
}
else if (stplyr == &players[secondarydisplayplayer])
{
if (!(option & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
perplayershuffle |= 1;
if (!(option & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
perplayershuffle |= 8;
cx += adjustx;
option &= ~V_SNAPTOBOTTOM|V_SNAPTOLEFT;
}
else if (stplyr == &players[thirddisplayplayer])
{
if (!(option & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
perplayershuffle |= 2;
if (!(option & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
perplayershuffle |= 4;
cy += adjusty;
option &= ~V_SNAPTOTOP|V_SNAPTORIGHT;
}
else if (stplyr == &players[fourthdisplayplayer])
{
if (!(option & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
perplayershuffle |= 2;
if (!(option & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
perplayershuffle |= 8;
cx += adjustx;
cy += adjusty;
option &= ~V_SNAPTOTOP|V_SNAPTOLEFT;
}
}
else
#endif
// 2 players
{
if (stplyr == &players[displayplayer])
{
if (!(option & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
perplayershuffle = 1;
option &= ~V_SNAPTOBOTTOM;
}
else //if (stplyr == &players[secondarydisplayplayer])
{
if (!(option & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
perplayershuffle = 2;
cy += adjusty;
option &= ~V_SNAPTOTOP;
}
}
}
if (!(option & V_NOSCALESTART))
{
cx = cx * dup;
cy = cy * dup;
if (!(option & V_SCALEPATCHMASK))
{
// centre screen
if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dup) > 1.0E-36f)
{
if (option & V_SNAPTORIGHT)
cx += ((float)vid.width - ((float)BASEVIDWIDTH * dup));
else if (!(option & V_SNAPTOLEFT))
cx += ((float)vid.width - ((float)BASEVIDWIDTH * dup))/2;
if (perplayershuffle & 4)
cx -= ((float)vid.width - ((float)BASEVIDWIDTH * dup))/4;
else if (perplayershuffle & 8)
cx += ((float)vid.width - ((float)BASEVIDWIDTH * dup))/4;
}
if (fabsf((float)vid.height - (float)BASEVIDHEIGHT * dup) > 1.0E-36f)
{
if (option & V_SNAPTOBOTTOM)
cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dup));
else if (!(option & V_SNAPTOTOP))
cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dup))/2;
if (perplayershuffle & 1)
cy -= ((float)vid.height - ((float)BASEVIDHEIGHT * dup))/4;
else if (perplayershuffle & 2)
cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dup))/4;
}
}
}
if (pscale != FRACUNIT || vscale != FRACUNIT || (splitscreen && option & V_PERPLAYER))
{
fwidth = (float)(texwidth) * fscalew * dup;
fheight = (float)(texheight) * fscaleh * dup;
}
else
{
fwidth = (float)(texwidth) * dup;
fheight = (float)(texheight) * dup;
}
// positions of the cx, cy, are between 0 and vid.width/vid.height now, we need them to be between -1 and 1
cx = -1 + (cx / (vid.width/2));
cy = 1 - (cy / (vid.height/2));
// fwidth and fheight are similar
fwidth /= vid.width / 2;
fheight /= vid.height / 2;
// set the polygon vertices to the right positions
v[0].x = v[3].x = cx;
v[2].x = v[1].x = cx + fwidth;
v[0].y = v[1].y = cy;
v[2].y = v[3].y = cy - fheight;
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
if (option & V_FLIP)
{
v[0].s = v[3].s = 1.0f;
v[2].s = v[1].s = 0.0f;
}
else
{
v[0].s = v[3].s = 0.0f;
v[2].s = v[1].s = 1.0f;
}
v[0].t = v[1].t = 0.0f;
v[2].t = v[3].t = 1.0f;
flags = HWR_GetBlendModeFlag(blendmode+1)|PF_NoDepthTest; flags = HWR_GetBlendModeFlag(blendmode+1)|PF_NoDepthTest;
if (alphalevel) if (alphalevel)
...@@ -585,18 +792,8 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, ...@@ -585,18 +792,8 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
return; return;
v[2].y = v[3].y = 0; // Clamp the polygon edge vertex position v[2].y = v[3].y = 0; // Clamp the polygon edge vertex position
// Now for the UV-map... Uh-oh, math time!
// On second thought, a basic linear interpolation suffices
//float full_height = fheight;
//float cropped_height = fheight - cy;
//float remaining_height = cy;
//float cropped_percentage = (fheight - cy) / fheight;
//float remaining_percentage = cy / fheight;
//v[2].t = v[3].t = lerp(v[2].t, v[0].t, cropped_percentage);
// By swapping v[2] and v[0], we can use remaining_percentage for less operations
//v[2].t = v[3].t = lerp(v[0].t, v[2].t, remaining_percentage);
// Now for the UV-map... Uh-oh, math time!
v[2].t = v[3].t = flerp(v[0].t, v[2].t, cy/fheight); v[2].t = v[3].t = flerp(v[0].t, v[2].t, cy/fheight);
} }
} }
...@@ -611,16 +808,8 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, ...@@ -611,16 +808,8 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
return; return;
v[0].y = v[1].y = 0; // Clamp the polygon edge vertex position v[0].y = v[1].y = 0; // Clamp the polygon edge vertex position
// Now for the UV-map... Uh-oh, math time!
// On second thought, a basic linear interpolation suffices
//float full_height = fheight;
//float cropped_height = cy;
//float remaining_height = fheight - cy;
//float cropped_percentage = cy / fheight;
//float remaining_percentage = (fheight - cy) / fheight;
//v[0].t = v[1].t = lerp(v[0].t, v[2].t, cropped_percentage);
// Now for the UV-map... Uh-oh, math time!
v[0].t = v[1].t = flerp(v[0].t, v[2].t, cy/fheight); v[0].t = v[1].t = flerp(v[0].t, v[2].t, cy/fheight);
} }
} }
...@@ -628,7 +817,6 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, ...@@ -628,7 +817,6 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
#undef flerp #undef flerp
} }
// clip it since it is used for bunny scroll in doom I
flags = HWR_GetBlendModeFlag(blendmode+1)|PF_NoDepthTest; flags = HWR_GetBlendModeFlag(blendmode+1)|PF_NoDepthTest;
if (alphalevel) if (alphalevel)
......
...@@ -42,6 +42,7 @@ void HWR_SetViewSize(void); ...@@ -42,6 +42,7 @@ void HWR_SetViewSize(void);
void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option); void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option);
void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap); void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap);
void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h); void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h);
void HWR_DrawTexture(INT32 texturenum, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option);
void HWR_MakePatch(const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap); void HWR_MakePatch(const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap);
void HWR_CreatePlanePolygons(INT32 bspnum); void HWR_CreatePlanePolygons(INT32 bspnum);
void HWR_CreateStaticLightmaps(INT32 bspnum); void HWR_CreateStaticLightmaps(INT32 bspnum);
......
...@@ -379,7 +379,10 @@ static void md2_loadTexture(md2_t *model) ...@@ -379,7 +379,10 @@ static void md2_loadTexture(md2_t *model)
Z_Free(grPatch->mipmap->data); Z_Free(grPatch->mipmap->data);
} }
else else
model->grpatch = patch = Patch_Create(NULL, 0, NULL); model->grpatch = patch = Patch_Create(NULL, 0);
if (!patch)
return;
if (!patch->hardware) if (!patch->hardware)
Patch_AllocateHardwarePatch(patch); Patch_AllocateHardwarePatch(patch);
...@@ -444,7 +447,10 @@ static void md2_loadBlendTexture(md2_t *model) ...@@ -444,7 +447,10 @@ static void md2_loadBlendTexture(md2_t *model)
Z_Free(grPatch->mipmap->data); Z_Free(grPatch->mipmap->data);
} }
else else
model->blendgrpatch = patch = Patch_Create(NULL, 0, NULL); model->blendgrpatch = patch = Patch_Create(NULL, 0);
if (!patch)
return;
if (!patch->hardware) if (!patch->hardware)
Patch_AllocateHardwarePatch(patch); Patch_AllocateHardwarePatch(patch);
......
...@@ -1073,7 +1073,7 @@ boolean HU_Responder(event_t *ev) ...@@ -1073,7 +1073,7 @@ boolean HU_Responder(event_t *ev)
return false; return false;
// enter chat mode // enter chat mode
if ((ev->key == gamecontrol[GC_TALKKEY][0] || ev->key == gamecontrol[GC_TALKKEY][1]) if (G_IsGameControl(ev->key, GC_TALKKEY)
&& netgame && !OLD_MUTE) // check for old chat mute, still let the players open the chat incase they want to scroll otherwise. && netgame && !OLD_MUTE) // check for old chat mute, still let the players open the chat incase they want to scroll otherwise.
{ {
chat_on = true; chat_on = true;
...@@ -1084,7 +1084,7 @@ boolean HU_Responder(event_t *ev) ...@@ -1084,7 +1084,7 @@ boolean HU_Responder(event_t *ev)
typelines = 1; typelines = 1;
return true; return true;
} }
if ((ev->key == gamecontrol[GC_TEAMKEY][0] || ev->key == gamecontrol[GC_TEAMKEY][1]) if (G_IsGameControl(ev->key, GC_TEAMKEY)
&& netgame && !OLD_MUTE) && netgame && !OLD_MUTE)
{ {
chat_on = true; chat_on = true;
...@@ -1167,8 +1167,7 @@ boolean HU_Responder(event_t *ev) ...@@ -1167,8 +1167,7 @@ boolean HU_Responder(event_t *ev)
I_UpdateMouseGrab(); I_UpdateMouseGrab();
} }
else if (c == KEY_ESCAPE else if (c == KEY_ESCAPE
|| ((c == gamecontrol[GC_TALKKEY][0] || c == gamecontrol[GC_TALKKEY][1] || ((G_IsGameControl(c, GC_TALKKEY) || G_IsGameControl(c, GC_TEAMKEY))
|| c == gamecontrol[GC_TEAMKEY][0] || c == gamecontrol[GC_TEAMKEY][1])
&& c >= KEY_MOUSE1)) // If it's not a keyboard key, then the chat button is used as a toggle. && c >= KEY_MOUSE1)) // If it's not a keyboard key, then the chat button is used as a toggle.
{ {
chat_on = false; chat_on = false;
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "p_local.h" #include "p_local.h"
#include "p_setup.h" // So we can have P_SetupLevelSky #include "p_setup.h" // So we can have P_SetupLevelSky
#include "p_slopes.h" // P_GetSlopeZAt #include "p_slopes.h" // P_GetSlopeZAt
#include "p_dialog.h"
#include "z_zone.h" #include "z_zone.h"
#include "r_main.h" #include "r_main.h"
#include "r_draw.h" #include "r_draw.h"
...@@ -1857,6 +1858,79 @@ static int lib_pPlayerShouldUseSpinHeight(lua_State *L) ...@@ -1857,6 +1858,79 @@ static int lib_pPlayerShouldUseSpinHeight(lua_State *L)
return 1; return 1;
} }
static int lib_pStartTextPrompt(lua_State *L)
{
player_t *player;
INT32 promptnum = INT32_MAX, pagenum = 1;
const char *promptname = NULL, *pagename = NULL;
boolean blockcontrols;
boolean allplayers;
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
if (lua_type(L, 2) == LUA_TSTRING)
promptname = luaL_checkstring(L, 2);
else
promptnum = luaL_checkinteger(L, 2);
if (lua_type(L, 3) == LUA_TSTRING)
pagename = luaL_checkstring(L, 3);
else if (!lua_isnoneornil(L, 3))
pagenum = luaL_checkinteger(L, 3);
blockcontrols = lua_optboolean(L, 4);
allplayers = lua_optboolean(L, 5);
NOHUD
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
if (promptname) {
promptnum = P_GetTextPromptByName(promptname);
if (promptnum == -1)
return luaL_error(L, "no text prompt named '%s'", promptname);
}
else {
if (promptnum <= 0 || promptnum > MAX_PROMPTS)
return luaL_error(L, "text prompt %d out of range (1 - %d)", promptnum, MAX_PROMPTS);
promptnum--;
}
textprompt_t *textprompt = textprompts[promptnum];
if (!textprompt)
return luaL_error(L, "invalid text prompt %d", promptnum);
if (pagename) {
pagenum = P_GetPromptPageByName(textprompt, pagename);
if (pagenum == -1)
return luaL_error(L, "no text prompt page named '%s'", pagename);
}
else {
if (pagenum <= 0 || pagenum > textprompt->numpages)
return luaL_error(L, "text prompt page %d out of range (1 - %d)", pagenum, textprompt->numpages);
pagenum--;
}
P_StartTextPrompt(player, promptnum, pagenum, 0, blockcontrols, false, allplayers);
return 0;
}
static int lib_pEndTextPrompt(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
boolean noexec = lua_optboolean(L, 2);
NOHUD
INLEVEL
P_EndTextPrompt(player, false, noexec);
return 0;
}
// P_MAP // P_MAP
/////////// ///////////
...@@ -4382,6 +4456,10 @@ static luaL_Reg lib[] = { ...@@ -4382,6 +4456,10 @@ static luaL_Reg lib[] = {
{"P_PlayerCanEnterSpinGaps",lib_pPlayerCanEnterSpinGaps}, {"P_PlayerCanEnterSpinGaps",lib_pPlayerCanEnterSpinGaps},
{"P_PlayerShouldUseSpinHeight",lib_pPlayerShouldUseSpinHeight}, {"P_PlayerShouldUseSpinHeight",lib_pPlayerShouldUseSpinHeight},
// p_dialog
{"P_StartTextPrompt",lib_pStartTextPrompt},
{"P_EndTextPrompt",lib_pEndTextPrompt},
// p_map // p_map
{"P_CheckPosition",lib_pCheckPosition}, {"P_CheckPosition",lib_pCheckPosition},
{"P_TryMove",lib_pTryMove}, {"P_TryMove",lib_pTryMove},
......