Merge branch SRB2:next into mobj-alpha

This commit is contained in:
MIDIMan 2024-03-11 00:03:44 +00:00
commit 8fb5f88f89
32 changed files with 3467 additions and 4592 deletions

View file

@ -1707,11 +1707,11 @@ static void CON_DrawHudlines(void)
} }
if (c >= con_width) if (c >= con_width)
break; break;
if (*p < HU_FONTSTART) if (*p < FONTSTART)
;//charwidth = 4 * con_scalefactor; ;//charwidth = 4 * con_scalefactor;
else else
{ {
//charwidth = (hu_font['A'-HU_FONTSTART]->width) * con_scalefactor; //charwidth = (hu_font.chars['A'-FONTSTART]->width) * con_scalefactor;
V_DrawCharacter(x, y, (INT32)(*p) | charflags | cv_constextsize.value | V_NOSCALESTART, true); V_DrawCharacter(x, y, (INT32)(*p) | charflags | cv_constextsize.value | V_NOSCALESTART, true);
} }
} }

View file

@ -5096,6 +5096,10 @@ struct int_const_s const INT_CONST[] = {
{"RF_SHADOWEFFECTS",RF_SHADOWEFFECTS}, {"RF_SHADOWEFFECTS",RF_SHADOWEFFECTS},
{"RF_DROPSHADOW",RF_DROPSHADOW}, {"RF_DROPSHADOW",RF_DROPSHADOW},
// Animation flags
{"SPR2F_MASK",SPR2F_MASK},
{"SPR2F_SUPER",SPR2F_SUPER},
// Level flags // Level flags
{"LF_SCRIPTISFILE",LF_SCRIPTISFILE}, {"LF_SCRIPTISFILE",LF_SCRIPTISFILE},
{"LF_SPEEDMUSIC",LF_SPEEDMUSIC}, {"LF_SPEEDMUSIC",LF_SPEEDMUSIC},

View file

@ -108,6 +108,7 @@ char *nongnu_strcasestr(const char *in, const char *what);
int startswith (const char *base, const char *tag); int startswith (const char *base, const char *tag);
int endswith (const char *base, const char *tag); int endswith (const char *base, const char *tag);
char *xstrtok(char *line, const char *delims);
#if defined (_WIN32) || defined (__HAIKU__) #if defined (_WIN32) || defined (__HAIKU__)
#define HAVE_DOSSTR_FUNCS #define HAVE_DOSSTR_FUNCS

View file

@ -3530,7 +3530,7 @@ void F_TitleDemoTicker(void)
// ========== // ==========
static skin_t *contskins[2]; static skin_t *contskins[2];
static UINT8 cont_spr2[2][6]; static UINT16 cont_spr2[2][6];
static UINT8 *contcolormaps[2]; static UINT8 *contcolormaps[2];
void F_StartContinue(void) void F_StartContinue(void)

View file

@ -413,7 +413,7 @@ void G_WriteGhostTic(mobj_t *ghost)
{ {
oldghost.sprite2 = ghost->sprite2; oldghost.sprite2 = ghost->sprite2;
ziptic |= GZT_SPR2; ziptic |= GZT_SPR2;
WRITEUINT8(demo_p,oldghost.sprite2); WRITEUINT16(demo_p,oldghost.sprite2);
} }
// Check for sprite set changes // Check for sprite set changes
@ -513,7 +513,7 @@ void G_WriteGhostTic(mobj_t *ghost)
temp = ghost->player->followmobj->z-ghost->z; temp = ghost->player->followmobj->z-ghost->z;
WRITEFIXED(demo_p,temp); WRITEFIXED(demo_p,temp);
if (followtic & FZT_SKIN) if (followtic & FZT_SKIN)
WRITEUINT8(demo_p,ghost->player->followmobj->sprite2); WRITEUINT16(demo_p,ghost->player->followmobj->sprite2);
WRITEUINT16(demo_p,ghost->player->followmobj->sprite); WRITEUINT16(demo_p,ghost->player->followmobj->sprite);
WRITEUINT8(demo_p,(ghost->player->followmobj->frame & FF_FRAMEMASK)); WRITEUINT8(demo_p,(ghost->player->followmobj->frame & FF_FRAMEMASK));
WRITEUINT16(demo_p,ghost->player->followmobj->color); WRITEUINT16(demo_p,ghost->player->followmobj->color);
@ -575,7 +575,7 @@ void G_ConsGhostTic(void)
if (ziptic & GZT_FRAME) if (ziptic & GZT_FRAME)
demo_p++; demo_p++;
if (ziptic & GZT_SPR2) if (ziptic & GZT_SPR2)
demo_p++; demo_p += (demoversion < 0x0011) ? sizeof(UINT8) : sizeof(UINT16);
if (ziptic & GZT_EXTRA) if (ziptic & GZT_EXTRA)
{ // But wait, there's more! { // But wait, there's more!
@ -644,7 +644,7 @@ void G_ConsGhostTic(void)
// momx, momy and momz // momx, momy and momz
demo_p += (demoversion < 0x000e) ? sizeof(INT16) * 3 : sizeof(fixed_t) * 3; demo_p += (demoversion < 0x000e) ? sizeof(INT16) * 3 : sizeof(fixed_t) * 3;
if (followtic & FZT_SKIN) if (followtic & FZT_SKIN)
demo_p++; demo_p += (demoversion < 0x0011) ? sizeof(UINT8) : sizeof(UINT16);
demo_p += sizeof(UINT16); demo_p += sizeof(UINT16);
demo_p++; demo_p++;
demo_p += (demoversion==0x000c) ? 1 : sizeof(UINT16); demo_p += (demoversion==0x000c) ? 1 : sizeof(UINT16);
@ -726,7 +726,7 @@ void G_GhostTicker(void)
if (ziptic & GZT_FRAME) if (ziptic & GZT_FRAME)
g->oldmo.frame = READUINT8(g->p); g->oldmo.frame = READUINT8(g->p);
if (ziptic & GZT_SPR2) if (ziptic & GZT_SPR2)
g->oldmo.sprite2 = READUINT8(g->p); g->oldmo.sprite2 = (g->version < 0x0011) ? READUINT8(g->p) : READUINT16(g->p);
// Update ghost // Update ghost
P_UnsetThingPosition(g->mo); P_UnsetThingPosition(g->mo);
@ -941,7 +941,7 @@ void G_GhostTicker(void)
follow->z = g->mo->z + temp; follow->z = g->mo->z + temp;
P_SetThingPosition(follow); P_SetThingPosition(follow);
if (followtic & FZT_SKIN) if (followtic & FZT_SKIN)
follow->sprite2 = READUINT8(g->p); follow->sprite2 = (g->version < 0x0011) ? READUINT8(g->p) : READUINT16(g->p);
else else
follow->sprite2 = 0; follow->sprite2 = 0;
follow->sprite = READUINT16(g->p); follow->sprite = READUINT16(g->p);
@ -1056,7 +1056,7 @@ void G_ReadMetalTic(mobj_t *metal)
oldmetal.frame = G_ConvertOldFrameFlags(oldmetal.frame); oldmetal.frame = G_ConvertOldFrameFlags(oldmetal.frame);
} }
if (ziptic & GZT_SPR2) if (ziptic & GZT_SPR2)
oldmetal.sprite2 = READUINT8(metal_p); oldmetal.sprite2 = (metalversion < 0x0011) ? READUINT8(metal_p) : READUINT16(metal_p);
// Set movement, position, and angle // Set movement, position, and angle
// oldmetal contains where you're supposed to be. // oldmetal contains where you're supposed to be.
@ -1199,7 +1199,7 @@ void G_ReadMetalTic(mobj_t *metal)
follow->z = metal->z + temp; follow->z = metal->z + temp;
P_SetThingPosition(follow); P_SetThingPosition(follow);
if (followtic & FZT_SKIN) if (followtic & FZT_SKIN)
follow->sprite2 = READUINT8(metal_p); follow->sprite2 = (metalversion < 0x0011) ? READUINT8(metal_p) : READUINT16(metal_p);
else else
follow->sprite2 = 0; follow->sprite2 = 0;
follow->sprite = READUINT16(metal_p); follow->sprite = READUINT16(metal_p);
@ -1207,7 +1207,7 @@ void G_ReadMetalTic(mobj_t *metal)
if (metalversion < 0x000f) if (metalversion < 0x000f)
follow->frame = G_ConvertOldFrameFlags(follow->frame); follow->frame = G_ConvertOldFrameFlags(follow->frame);
follow->angle = metal->angle; follow->angle = metal->angle;
follow->color = (metalversion==0x000c) ? READUINT8(metal_p) : READUINT16(metal_p); follow->color = (metalversion == 0x000c) ? READUINT8(metal_p) : READUINT16(metal_p);
if (!(followtic & FZT_SPAWNED)) if (!(followtic & FZT_SPAWNED))
{ {
@ -1308,7 +1308,7 @@ void G_WriteMetalTic(mobj_t *metal)
{ {
oldmetal.sprite2 = metal->sprite2; oldmetal.sprite2 = metal->sprite2;
ziptic |= GZT_SPR2; ziptic |= GZT_SPR2;
WRITEUINT8(demo_p,oldmetal.sprite2); WRITEUINT16(demo_p,oldmetal.sprite2);
} }
// Check for sprite set changes // Check for sprite set changes
@ -1383,7 +1383,7 @@ void G_WriteMetalTic(mobj_t *metal)
temp = metal->player->followmobj->z-metal->z; temp = metal->player->followmobj->z-metal->z;
WRITEFIXED(demo_p,temp); WRITEFIXED(demo_p,temp);
if (followtic & FZT_SKIN) if (followtic & FZT_SKIN)
WRITEUINT8(demo_p,metal->player->followmobj->sprite2); WRITEUINT16(demo_p,metal->player->followmobj->sprite2);
WRITEUINT16(demo_p,metal->player->followmobj->sprite); WRITEUINT16(demo_p,metal->player->followmobj->sprite);
WRITEUINT32(demo_p,metal->player->followmobj->frame); // NOT & FF_FRAMEMASK here, so 32 bits WRITEUINT32(demo_p,metal->player->followmobj->frame); // NOT & FF_FRAMEMASK here, so 32 bits
WRITEUINT16(demo_p,metal->player->followmobj->color); WRITEUINT16(demo_p,metal->player->followmobj->color);
@ -2607,10 +2607,10 @@ void G_AddGhost(char *defdemoname)
} }
gh->oldmo.color = gh->mo->color; gh->oldmo.color = gh->mo->color;
gh->mo->state = states+S_PLAY_STND; gh->mo->state = &states[S_PLAY_STND];
gh->mo->sprite = gh->mo->state->sprite; gh->mo->sprite = gh->mo->state->sprite;
gh->mo->sprite2 = (gh->mo->state->frame & FF_FRAMEMASK); gh->mo->sprite2 = P_GetStateSprite2(gh->mo->state);
//gh->mo->frame = tr_trans30<<FF_TRANSSHIFT; gh->mo->frame = (gh->mo->state->frame & ~FF_FRAMEMASK) | P_GetSprite2StateFrame(gh->mo->state);
gh->mo->flags2 |= MF2_DONTDRAW; gh->mo->flags2 |= MF2_DONTDRAW;
gh->fadein = (9-3)*6; // fade from invisible to trans30 over as close to 35 tics as possible gh->fadein = (9-3)*6; // fade from invisible to trans30 over as close to 35 tics as possible
gh->mo->tics = -1; gh->mo->tics = -1;

View file

@ -4377,9 +4377,9 @@ static void HWR_ProjectSprite(mobj_t *thing)
//Fab : 02-08-98: 'skin' override spritedef currently used for skin //Fab : 02-08-98: 'skin' override spritedef currently used for skin
if (thing->skin && thing->sprite == SPR_PLAY) if (thing->skin && thing->sprite == SPR_PLAY)
{ {
sprdef = &((skin_t *)thing->skin)->sprites[thing->sprite2]; sprdef = P_GetSkinSpritedef(thing->skin, thing->sprite2);
#ifdef ROTSPRITE #ifdef ROTSPRITE
sprinfo = &((skin_t *)thing->skin)->sprinfo[thing->sprite2]; sprinfo = P_GetSkinSpriteInfo(thing->skin, thing->sprite2);
#endif #endif
} }
else else
@ -5966,7 +5966,7 @@ void HWR_DoPostProcessor(player_t *player)
if (*type == postimg_water) if (*type == postimg_water)
{ {
WAVELENGTH = 5; WAVELENGTH = 5;
AMPLITUDE = 20; AMPLITUDE = 40;
FREQUENCY = 8; FREQUENCY = 8;
} }
else else

View file

@ -1078,30 +1078,47 @@ static boolean HWR_CanInterpolateSprite2(modelspr2frames_t *spr2frame)
return spr2frame->interpolate; return spr2frame->interpolate;
} }
// static modelspr2frames_t *HWR_GetModelSprite2Frames(md2_t *md2, UINT16 spr2)
// HWR_GetModelSprite2 (see P_GetSkinSprite2)
// For non-super players, tries each sprite2's immediate predecessor until it finds one with a number of frames or ends up at standing.
// For super players, does the same as above - but tries the super equivalent for each sprite2 before the non-super version.
//
static UINT8 HWR_GetModelSprite2(md2_t *md2, skin_t *skin, UINT8 spr2, player_t *player)
{ {
UINT8 super = 0, i = 0; if (!md2 || !md2->model)
return NULL;
if (!md2 || !md2->model || !md2->model->spr2frames || !skin) boolean is_super = spr2 & SPR2F_SUPER;
return 0;
if ((playersprite_t)(spr2 & ~FF_SPR2SUPER) >= free_spr2) spr2 &= SPR2F_MASK;
return 0;
while (!md2->model->spr2frames[spr2].numframes if (spr2 >= free_spr2)
&& spr2 != SPR2_STND return NULL;
&& ++i != 32) // recursion limiter
if (is_super)
{ {
if (spr2 & FF_SPR2SUPER) modelspr2frames_t *frames = md2->model->superspr2frames;
if (frames && md2->model->superspr2frames[spr2].numframes)
return &md2->model->superspr2frames[spr2];
}
if (md2->model->spr2frames)
return &md2->model->spr2frames[spr2];
return NULL;
}
static modelspr2frames_t *HWR_GetModelSprite2(md2_t *md2, skin_t *skin, UINT16 spr2, player_t *player)
{
UINT16 super = 0;
UINT8 i = 0;
if (!md2 || !md2->model || !skin)
return HWR_GetModelSprite2Frames(md2, 0);
while (!HWR_GetModelSprite2Frames(md2, spr2)
&& spr2 != SPR2_STND
&& ++i < 32) // recursion limiter
{
if (spr2 & SPR2F_SUPER)
{ {
super = FF_SPR2SUPER; super = SPR2F_SUPER;
spr2 &= ~FF_SPR2SUPER; spr2 &= ~SPR2F_SUPER;
continue; continue;
} }
@ -1130,9 +1147,9 @@ static UINT8 HWR_GetModelSprite2(md2_t *md2, skin_t *skin, UINT8 spr2, player_t
} }
if (i >= 32) // probably an infinite loop... if (i >= 32) // probably an infinite loop...
return 0; spr2 = 0;
return spr2; return HWR_GetModelSprite2Frames(md2, spr2);
} }
// Adjust texture coords of model to fit into a patch's max_s and max_t // Adjust texture coords of model to fit into a patch's max_s and max_t
@ -1188,7 +1205,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
char filename[64]; char filename[64];
INT32 frame = 0; INT32 frame = 0;
INT32 nextFrame = -1; INT32 nextFrame = -1;
UINT8 spr2 = 0; modelspr2frames_t *spr2frames = NULL;
FTransform p; FTransform p;
FSurfaceInfo Surf; FSurfaceInfo Surf;
@ -1418,18 +1435,24 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
tics = (float)spr->mobj->anim_duration; tics = (float)spr->mobj->anim_duration;
} }
if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY)
sprdef = P_GetSkinSpritedef(spr->mobj->skin, spr->mobj->sprite2);
else
sprdef = &sprites[spr->mobj->sprite];
frame = (spr->mobj->frame & FF_FRAMEMASK); frame = (spr->mobj->frame & FF_FRAMEMASK);
if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY && md2->model->spr2frames) if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY)
spr2frames = HWR_GetModelSprite2(md2, spr->mobj->skin, spr->mobj->sprite2, spr->mobj->player);
if (spr2frames)
{ {
spr2 = HWR_GetModelSprite2(md2, spr->mobj->skin, spr->mobj->sprite2, spr->mobj->player); mod = spr2frames->numframes;
mod = md2->model->spr2frames[spr2].numframes;
#ifndef DONTHIDEDIFFANIMLENGTH // by default, different anim length is masked by the mod #ifndef DONTHIDEDIFFANIMLENGTH // by default, different anim length is masked by the mod
if (mod > (INT32)((skin_t *)spr->mobj->skin)->sprites[spr2].numframes) if (mod > (INT32)sprdef->numframes)
mod = ((skin_t *)spr->mobj->skin)->sprites[spr2].numframes; mod = sprdef->numframes;
#endif #endif
if (!mod) if (!mod)
mod = 1; mod = 1;
frame = md2->model->spr2frames[spr2].frames[frame%mod]; frame = spr2frames->frames[frame % mod];
} }
else else
{ {
@ -1449,13 +1472,18 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
if (durs > INTERPOLERATION_LIMIT) if (durs > INTERPOLERATION_LIMIT)
durs = INTERPOLERATION_LIMIT; durs = INTERPOLERATION_LIMIT;
if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY && md2->model->spr2frames) if (spr2frames)
{ {
if (HWR_CanInterpolateSprite2(&md2->model->spr2frames[spr2]) UINT16 next_spr2 = P_GetStateSprite2(&states[spr->mobj->state->nextstate]);
// Add or remove SPR2F_SUPER based on certain conditions
next_spr2 = P_ApplySuperFlagToSprite2(next_spr2, spr->mobj);
if (HWR_CanInterpolateSprite2(spr2frames)
&& (spr->mobj->frame & FF_ANIMATE && (spr->mobj->frame & FF_ANIMATE
|| (spr->mobj->state->nextstate != S_NULL || (spr->mobj->state->nextstate != S_NULL
&& states[spr->mobj->state->nextstate].sprite == SPR_PLAY && states[spr->mobj->state->nextstate].sprite == SPR_PLAY
&& ((P_GetSkinSprite2(spr->mobj->skin, (((spr->mobj->player && spr->mobj->player->powers[pw_super]) ? FF_SPR2SUPER : 0)|states[spr->mobj->state->nextstate].frame) & FF_FRAMEMASK, spr->mobj->player) == spr->mobj->sprite2))))) && ((P_GetSkinSprite2(spr->mobj->skin, next_spr2, spr->mobj->player) == spr->mobj->sprite2)))))
{ {
nextFrame = (spr->mobj->frame & FF_FRAMEMASK) + 1; nextFrame = (spr->mobj->frame & FF_FRAMEMASK) + 1;
if (nextFrame >= mod) if (nextFrame >= mod)
@ -1466,7 +1494,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
nextFrame = 0; nextFrame = 0;
} }
if (frame || !(spr->mobj->state->frame & FF_SPR2ENDSTATE)) if (frame || !(spr->mobj->state->frame & FF_SPR2ENDSTATE))
nextFrame = md2->model->spr2frames[spr2].frames[nextFrame]; nextFrame = spr2frames->frames[nextFrame];
else else
nextFrame = -1; nextFrame = -1;
} }
@ -1502,11 +1530,6 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
else else
p.z = FIXED_TO_FLOAT(interp.z); p.z = FIXED_TO_FLOAT(interp.z);
if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY)
sprdef = &((skin_t *)spr->mobj->skin)->sprites[spr->mobj->sprite2];
else
sprdef = &sprites[spr->mobj->sprite];
sprframe = &sprdef->spriteframes[spr->mobj->frame & FF_FRAMEMASK]; sprframe = &sprdef->spriteframes[spr->mobj->frame & FF_FRAMEMASK];
if (sprframe->rotate || papersprite) if (sprframe->rotate || papersprite)

View file

@ -292,6 +292,7 @@ void LoadModelSprite2(model_t *model)
{ {
INT32 i; INT32 i;
modelspr2frames_t *spr2frames = NULL; modelspr2frames_t *spr2frames = NULL;
modelspr2frames_t *superspr2frames = NULL;
INT32 numframes = model->meshes[0].numFrames; INT32 numframes = model->meshes[0].numFrames;
char *framename = model->frameNames; char *framename = model->frameNames;
@ -335,25 +336,33 @@ void LoadModelSprite2(model_t *model)
spr2idx = 0; spr2idx = 0;
while (spr2idx < free_spr2) while (spr2idx < free_spr2)
{ {
modelspr2frames_t *frames = NULL;
if (!memcmp(spr2names[spr2idx], name, 4)) if (!memcmp(spr2names[spr2idx], name, 4))
{ {
if (!spr2frames) if (!spr2frames)
spr2frames = (modelspr2frames_t*)Z_Calloc(sizeof(modelspr2frames_t)*NUMPLAYERSPRITES*2, PU_STATIC, NULL); spr2frames = (modelspr2frames_t*)Z_Calloc(sizeof(modelspr2frames_t)*NUMPLAYERSPRITES, PU_STATIC, NULL);
frames = spr2frames;
if (super) if (super)
spr2idx |= FF_SPR2SUPER; {
if (!superspr2frames)
superspr2frames = (modelspr2frames_t*)Z_Calloc(sizeof(modelspr2frames_t)*NUMPLAYERSPRITES, PU_STATIC, NULL);
frames = superspr2frames;
}
if (framechars[0]) if (framechars[0])
{ {
frame = atoi(framechars); frame = atoi(framechars);
if (spr2frames[spr2idx].numframes < frame+1) if (frames[spr2idx].numframes < frame+1)
spr2frames[spr2idx].numframes = frame+1; frames[spr2idx].numframes = frame+1;
} }
else else
{ {
frame = spr2frames[spr2idx].numframes; frame = frames[spr2idx].numframes;
spr2frames[spr2idx].numframes++; frames[spr2idx].numframes++;
} }
spr2frames[spr2idx].frames[frame] = i; frames[spr2idx].frames[frame] = i;
spr2frames[spr2idx].interpolate = interpolate; frames[spr2idx].interpolate = interpolate;
break; break;
} }
spr2idx++; spr2idx++;
@ -366,7 +375,10 @@ void LoadModelSprite2(model_t *model)
if (model->spr2frames) if (model->spr2frames)
Z_Free(model->spr2frames); Z_Free(model->spr2frames);
if (model->superspr2frames)
Z_Free(model->superspr2frames);
model->spr2frames = spr2frames; model->spr2frames = spr2frames;
model->superspr2frames = superspr2frames;
} }
// //

View file

@ -101,6 +101,7 @@ typedef struct model_s
char *frameNames; char *frameNames;
boolean interpolate[256]; boolean interpolate[256];
modelspr2frames_t *spr2frames; modelspr2frames_t *spr2frames;
modelspr2frames_t *superspr2frames;
// the max_s and max_t values that the uvs are currently adjusted to // the max_s and max_t values that the uvs are currently adjusted to
// (if a sprite is used as a texture) // (if a sprite is used as a texture)

View file

@ -61,21 +61,22 @@
#define HU_CSAY 2 // Server CECHOes to everyone. #define HU_CSAY 2 // Server CECHOes to everyone.
//------------------------------------------- //-------------------------------------------
// heads up font // Fonts & stuff
//------------------------------------------- //-------------------------------------------
patch_t *hu_font[HU_FONTSIZE]; // Font definitions
patch_t *tny_font[HU_FONTSIZE]; fontdef_t hu_font;
fontdef_t tny_font;
fontdef_t cred_font;
fontdef_t lt_font;
fontdef_t ntb_font;
fontdef_t nto_font;
// Numbers
patch_t *tallnum[10]; // 0-9 patch_t *tallnum[10]; // 0-9
patch_t *nightsnum[10]; // 0-9 patch_t *nightsnum[10]; // 0-9
// Level title and credits fonts
patch_t *lt_font[LT_FONTSIZE];
patch_t *cred_font[CRED_FONTSIZE];
patch_t *ttlnum[10]; // act numbers (0-9) patch_t *ttlnum[10]; // act numbers (0-9)
patch_t *tallminus;
// Name tag fonts patch_t *tallinfin;
patch_t *ntb_font[NT_FONTSIZE];
patch_t *nto_font[NT_FONTSIZE];
static player_t *plr; static player_t *plr;
boolean chat_on; // entering a chat message? boolean chat_on; // entering a chat message?
@ -91,8 +92,6 @@ patch_t *bflagico;
patch_t *rmatcico; patch_t *rmatcico;
patch_t *bmatcico; patch_t *bmatcico;
patch_t *tagico; patch_t *tagico;
patch_t *tallminus;
patch_t *tallinfin;
//------------------------------------------- //-------------------------------------------
// coop hud // coop hud
@ -188,53 +187,26 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum);
void HU_LoadGraphics(void) void HU_LoadGraphics(void)
{ {
char buffer[9]; char buffer[9];
INT32 i, j; INT32 i;
if (dedicated) if (dedicated)
return; return;
j = HU_FONTSTART; // Cache fonts
for (i = 0; i < HU_FONTSIZE; i++, j++) HU_LoadFontCharacters(&hu_font, "STCFN");
{ HU_LoadFontCharacters(&tny_font, "TNYFN");
// cache the heads-up font for entire game execution HU_LoadFontCharacters(&cred_font, "CRFNT");
sprintf(buffer, "STCFN%.3d", j); HU_LoadFontCharacters(&lt_font, "LTFNT");
if (W_CheckNumForName(buffer) == LUMPERROR) HU_LoadFontCharacters(&ntb_font, "NTFNT");
hu_font[i] = NULL; HU_LoadFontCharacters(&nto_font, "NTFNO");
else
hu_font[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
// tiny version of the heads-up font // For each font, set kerning, space width, character width and line spacing
sprintf(buffer, "TNYFN%.3d", j); HU_SetFontProperties(&hu_font, 0, 4, 8, 12);
if (W_CheckNumForName(buffer) == LUMPERROR) HU_SetFontProperties(&tny_font, 0, 2, 4, 12);
tny_font[i] = NULL; HU_SetFontProperties(&cred_font, 0, 16, 16, 16);
else HU_SetFontProperties(&lt_font, 0, 16, 20, 20);
tny_font[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX); HU_SetFontProperties(&ntb_font, 2, 4, 20, 21);
} HU_SetFontProperties(&nto_font, 0, 4, 20, 21);
j = LT_FONTSTART;
for (i = 0; i < LT_FONTSIZE; i++)
{
sprintf(buffer, "LTFNT%.3d", j);
j++;
if (W_CheckNumForName(buffer) == LUMPERROR)
lt_font[i] = NULL;
else
lt_font[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
}
// cache the credits font for entire game execution (why not?)
j = CRED_FONTSTART;
for (i = 0; i < CRED_FONTSIZE; i++)
{
sprintf(buffer, "CRFNT%.3d", j);
j++;
if (W_CheckNumForName(buffer) == LUMPERROR)
cred_font[i] = NULL;
else
cred_font[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
}
//cache numbers too! //cache numbers too!
for (i = 0; i < 10; i++) for (i = 0; i < 10; i++)
@ -243,45 +215,14 @@ void HU_LoadGraphics(void)
tallnum[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX); tallnum[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
sprintf(buffer, "NGTNUM%d", i); sprintf(buffer, "NGTNUM%d", i);
nightsnum[i] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX); nightsnum[i] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX);
sprintf(buffer, "TTL%.2d", i);
ttlnum[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
} }
// minus for negative tallnums // minus for negative tallnums
tallminus = (patch_t *)W_CachePatchName("STTMINUS", PU_HUDGFX); tallminus = (patch_t *)W_CachePatchName("STTMINUS", PU_HUDGFX);
tallinfin = (patch_t *)W_CachePatchName("STTINFIN", PU_HUDGFX); tallinfin = (patch_t *)W_CachePatchName("STTINFIN", PU_HUDGFX);
// cache act numbers for level titles
for (i = 0; i < 10; i++)
{
sprintf(buffer, "TTL%.2d", i);
ttlnum[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
}
// cache the base name tag font for entire game execution
j = NT_FONTSTART;
for (i = 0; i < NT_FONTSIZE; i++)
{
sprintf(buffer, "NTFNT%.3d", j);
j++;
if (W_CheckNumForName(buffer) == LUMPERROR)
ntb_font[i] = NULL;
else
ntb_font[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
}
// cache the outline name tag font for entire game execution
j = NT_FONTSTART;
for (i = 0; i < NT_FONTSIZE; i++)
{
sprintf(buffer, "NTFNO%.3d", j);
j++;
if (W_CheckNumForName(buffer) == LUMPERROR)
nto_font[i] = NULL;
else
nto_font[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
}
// cache the crosshairs, don't bother to know which one is being used, // cache the crosshairs, don't bother to know which one is being used,
// just cache all 3, they're so small anyway. // just cache all 3, they're so small anyway.
for (i = 0; i < HU_CROSSHAIRS; i++) for (i = 0; i < HU_CROSSHAIRS; i++)
@ -323,6 +264,29 @@ void HU_LoadGraphics(void)
//emeraldpics[2][7] = W_CachePatchName("EMBOX8", PU_HUDGFX); -- unused //emeraldpics[2][7] = W_CachePatchName("EMBOX8", PU_HUDGFX); -- unused
} }
void HU_LoadFontCharacters(fontdef_t *font, const char *prefix)
{
char buffer[9];
INT32 i, j = FONTSTART;
for (i = 0; i < FONTSIZE; i++, j++)
{
sprintf(buffer, "%.5s%.3d", prefix, j);
if (W_CheckNumForName(buffer) == LUMPERROR)
font->chars[i] = NULL;
else
font->chars[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
}
}
void HU_SetFontProperties(fontdef_t *font, INT32 kerning, UINT32 spacewidth, UINT32 charwidth, UINT32 linespacing)
{
font->kerning = kerning;
font->spacewidth = spacewidth;
font->charwidth = charwidth;
font->linespacing = linespacing;
}
// Initialise Heads up // Initialise Heads up
// once at game startup. // once at game startup.
// //
@ -1117,7 +1081,7 @@ boolean HU_Responder(event_t *ev)
if (ev->type == ev_text) if (ev->type == ev_text)
{ {
if ((c < HU_FONTSTART || c > HU_FONTEND || !hu_font[c-HU_FONTSTART]) if ((c < FONTSTART || c > FONTEND || !hu_font.chars[c-FONTSTART])
&& c != ' ') // Allow spaces, of course && c != ' ') // Allow spaces, of course
{ {
return false; return false;
@ -1236,199 +1200,81 @@ boolean HU_Responder(event_t *ev)
// HEADS UP DRAWING // HEADS UP DRAWING
//====================================================================== //======================================================================
// Precompile a wordwrapped string to any given width.
// This is a muuuch better method than V_WORDWRAP.
// again stolen and modified a bit from video.c, don't mind me, will need to rearrange this one day.
// this one is simplified for the chat drawer.
static char *CHAT_WordWrap(INT32 x, INT32 w, INT32 option, const char *string)
{
INT32 c;
size_t chw, i, lastusablespace = 0;
size_t slen;
char *newstring = Z_StrDup(string);
INT32 spacewidth = (vid.width < 640) ? 8 : 4, charwidth = (vid.width < 640) ? 8 : 4;
slen = strlen(string);
x = 0;
for (i = 0; i < slen; ++i)
{
c = newstring[i];
if ((UINT8)c >= 0x80 && (UINT8)c <= 0x89) //color parsing! -Inuyasha 2.16.09
continue;
if (c == '\n')
{
x = 0;
lastusablespace = 0;
continue;
}
if (!(option & V_ALLOWLOWERCASE))
c = toupper(c);
c -= HU_FONTSTART;
if (c < 0 || c >= HU_FONTSIZE || !hu_font[c])
{
chw = spacewidth;
lastusablespace = i;
}
else
chw = charwidth;
x += chw;
if (lastusablespace != 0 && x > w)
{
//CONS_Printf("Wrap at index %d\n", i);
newstring[lastusablespace] = '\n';
i = lastusablespace+1;
lastusablespace = 0;
x = 0;
}
}
return newstring;
}
// 30/7/18: chaty is now the distance at which the lowest point of the chat will be drawn if that makes any sense. // 30/7/18: chaty is now the distance at which the lowest point of the chat will be drawn if that makes any sense.
INT16 chatx = 13, chaty = 169; // let's use this as our coordinates INT16 chatx = 13, chaty = 169; // let's use this as our coordinates
// chat stuff by VincyTM LOL XD!
// HU_DrawMiniChat // HU_DrawMiniChat
static void HU_drawMiniChat(void) static void HU_drawMiniChat(void)
{ {
INT32 x = chatx+2; INT32 x = chatx+2, y;
INT32 chatheight = 0;
INT32 charwidth = 4, charheight = 6; INT32 charwidth = 4, charheight = 6;
INT32 boxw = cv_chatwidth.value; INT32 boxw = cv_chatwidth.value;
INT32 dx = 0, dy = 0; INT32 dx = 0, dy = 0;
size_t i = chat_nummsg_min;
boolean prev_linereturn = false; // a hack to prevent double \n while I have no idea why they happen in the first place.
INT32 msglines = 0;
// process all messages once without rendering anything or doing anything fancy so that we know how many lines each message has...
INT32 y;
if (!chat_nummsg_min) if (!chat_nummsg_min)
return; // needless to say it's useless to do anything if we don't have anything to draw. return; // needless to say it's useless to do anything if we don't have anything to draw.
/*if (splitscreen > 1) for (size_t i = chat_nummsg_min; i > 0; i--)
boxw = max(64, boxw/2);*/
for (; i>0; i--)
{ {
char *msg = CHAT_WordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i-1]); char *msg = V_ChatWordWrap(chatx, boxw-charwidth, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i-1]);
size_t j = 0; for(size_t j = 0; msg[j]; j++) // iterate through msg
INT32 linescount = 0;
while(msg[j]) // iterate through msg
{ {
if (msg[j] < HU_FONTSTART) // don't draw if (msg[j] == '\n') // get back down.
{
if (msg[j] == '\n') // get back down.
{
++j;
if (!prev_linereturn)
{
linescount += 1;
dx = 0;
}
prev_linereturn = true;
continue;
}
else if (msg[j] & 0x80) // stolen from video.c, nice.
{
++j;
continue;
}
++j;
}
else
{
j++;
}
prev_linereturn = false;
dx += charwidth;
if (dx >= boxw)
{ {
chatheight += charheight;
dx = 0; dx = 0;
linescount += 1; }
else if (msg[j] >= FONTSTART)
{
dx += charwidth;
if (dx >= boxw)
{
dx = 0;
chatheight += charheight;
}
} }
} }
dy = 0;
dx = 0; dx = 0;
msglines += linescount+1; chatheight += charheight;
if (msg) if (msg)
Z_Free(msg); Z_Free(msg);
} }
y = chaty - charheight*(msglines+1); y = chaty - (chatheight + charheight);
/*if (splitscreen) for (size_t i = 0; i < chat_nummsg_min; i++) // iterate through our hot messages
{ {
y -= BASEVIDHEIGHT/2;
if (splitscreen > 1)
y += 16;
}*/
dx = 0;
dy = 0;
i = 0;
prev_linereturn = false;
for (; i<=(chat_nummsg_min-1); i++) // iterate through our hot messages
{
INT32 clrflag = 0;
INT32 timer = ((cv_chattime.value*TICRATE)-chat_timers[i]) - cv_chattime.value*TICRATE+9; // see below... INT32 timer = ((cv_chattime.value*TICRATE)-chat_timers[i]) - cv_chattime.value*TICRATE+9; // see below...
INT32 transflag = (timer >= 0 && timer <= 9) ? (timer*V_10TRANS) : 0; // you can make bad jokes out of this one. INT32 transflag = (timer >= 0 && timer <= 9) ? (timer*V_10TRANS) : 0; // you can make bad jokes out of this one.
size_t j = 0; char *msg = V_ChatWordWrap(chatx, boxw-charwidth, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i]); // get the current message, and word wrap it.
char *msg = CHAT_WordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i]); // get the current message, and word wrap it.
UINT8 *colormap = NULL; UINT8 *colormap = NULL;
while(msg[j]) // iterate through msg for(size_t j = 0; msg[j]; j++) // iterate through msg
{ {
if (msg[j] < HU_FONTSTART) // don't draw if (msg[j] == '\n') // get back down.
{ {
if (msg[j] == '\n') // get back down. dy += charheight;
{ dx = 0;
++j;
if (!prev_linereturn)
{
dy += charheight;
dx = 0;
}
prev_linereturn = true;
continue;
}
else if (msg[j] & 0x80) // stolen from video.c, nice.
{
clrflag = ((msg[j] & 0x7f) << V_CHARCOLORSHIFT) & V_CHARCOLORMASK;
colormap = V_GetStringColormap(clrflag);
++j;
continue;
}
++j;
} }
else else if (msg[j] & 0x80) // get colormap
colormap = V_GetStringColormap(((msg[j] & 0x7f) << V_CHARCOLORSHIFT) & V_CHARCOLORMASK);
else if (msg[j] >= FONTSTART)
{ {
if (cv_chatbacktint.value) // on request of wolfy if (cv_chatbacktint.value) // on request of wolfy
V_DrawFillConsoleMap(x + dx + 2, y+dy, charwidth, charheight, 239|V_SNAPTOBOTTOM|V_SNAPTOLEFT); V_DrawFillConsoleMap(x + dx + 2, y+dy, charwidth, charheight, 239|V_SNAPTOBOTTOM|V_SNAPTOLEFT);
V_DrawChatCharacter(x + dx + 2, y+dy, msg[j++] |V_SNAPTOBOTTOM|V_SNAPTOLEFT|transflag, true, colormap); V_DrawChatCharacter(x + dx + 2, y+dy, msg[j] |V_SNAPTOBOTTOM|V_SNAPTOLEFT|transflag, true, colormap);
}
dx += charwidth; dx += charwidth;
prev_linereturn = false; if (dx >= boxw)
if (dx >= boxw) {
{ dx = 0;
dx = 0; dy += charheight;
dy += charheight; }
} }
} }
dy += charheight; dy += charheight;
@ -1440,7 +1286,6 @@ static void HU_drawMiniChat(void)
// decrement addy and make that shit smooth: // decrement addy and make that shit smooth:
addy /= 2; addy /= 2;
} }
// HU_DrawChatLog // HU_DrawChatLog
@ -1485,44 +1330,28 @@ static void HU_drawChatLog(INT32 offset)
for (i=0; i<chat_nummsg_log; i++) // iterate through our chatlog for (i=0; i<chat_nummsg_log; i++) // iterate through our chatlog
{ {
INT32 clrflag = 0; char *msg = V_ChatWordWrap(chatx, boxw-charwidth, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_log[i]); // get the current message, and word wrap it.
INT32 j = 0;
char *msg = CHAT_WordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_log[i]); // get the current message, and word wrap it.
UINT8 *colormap = NULL; UINT8 *colormap = NULL;
while(msg[j]) // iterate through msg for(size_t j = 0; msg[j]; j++) // iterate through msg
{ {
if (msg[j] < HU_FONTSTART) // don't draw if (msg[j] == '\n') // get back down.
{ {
if (msg[j] == '\n') // get back down. dy += charheight;
{ dx = 0;
++j;
dy += charheight;
dx = 0;
continue;
}
else if (msg[j] & 0x80) // stolen from video.c, nice.
{
clrflag = ((msg[j] & 0x7f) << V_CHARCOLORSHIFT) & V_CHARCOLORMASK;
colormap = V_GetStringColormap(clrflag);
++j;
continue;
}
++j;
} }
else else if (msg[j] & 0x80) // get colormap
colormap = V_GetStringColormap(((msg[j] & 0x7f) << V_CHARCOLORSHIFT) & V_CHARCOLORMASK);
else if (msg[j] >= FONTSTART)
{ {
if ((y+dy+2 >= chat_topy) && (y+dy < (chat_bottomy))) if ((y+dy+2 >= chat_topy) && (y+dy < (chat_bottomy)))
V_DrawChatCharacter(x + dx + 2, y+dy+2, msg[j++] |V_SNAPTOBOTTOM|V_SNAPTOLEFT, true, colormap); V_DrawChatCharacter(x + dx + 2, y+dy+2, msg[j] |V_SNAPTOBOTTOM|V_SNAPTOLEFT, true, colormap);
else
j++; // don't forget to increment this or we'll get stuck in the limbo.
}
dx += charwidth; dx += charwidth;
if (dx >= boxw-charwidth-2 && i<chat_nummsg_log && msg[j] >= HU_FONTSTART) // end of message shouldn't count, nor should invisible characters!!!! if (dx >= boxw-charwidth-2 && i<chat_nummsg_log) // end of message shouldn't count, nor should invisible characters!!!!
{ {
dx = 0; dx = 0;
dy += charheight; dy += charheight;
}
} }
} }
dy += charheight; dy += charheight;
@ -1532,30 +1361,25 @@ static void HU_drawChatLog(INT32 offset)
Z_Free(msg); Z_Free(msg);
} }
if (((chat_scroll >= chat_maxscroll) || (chat_scrollmedown)) && !(justscrolleddown || justscrolledup || chat_scrolltime)) // was already at the bottom of the page before new maxscroll calculation and was NOT scrolling. if (((chat_scroll >= chat_maxscroll) || (chat_scrollmedown)) && !(justscrolleddown || justscrolledup || chat_scrolltime)) // was already at the bottom of the page before new maxscroll calculation and was NOT scrolling.
{
atbottom = true; // we should scroll atbottom = true; // we should scroll
}
chat_scrollmedown = false; chat_scrollmedown = false;
// getmaxscroll through a lazy hack. We do all these loops, // getmaxscroll through a lazy hack. We do all these loops, so let's not do more loops that are gonna lag the game more. :P
// so let's not do more loops that are gonna lag the game more. :P
chat_maxscroll = max(dy / charheight - cv_chatheight.value, 0); chat_maxscroll = max(dy / charheight - cv_chatheight.value, 0);
// if we're not bound by the time, autoscroll for next frame: // if we're not bound by the time, autoscroll for next frame:
if (atbottom) if (atbottom)
chat_scroll = chat_maxscroll; chat_scroll = chat_maxscroll;
// draw arrows to indicate that we can (or not) scroll. // draw arrows to indicate that we can (or not) scroll, accounting for Y = -1 offset in tinyfont
// account for Y = -1 offset in tinyfont
if (chat_scroll > 0) if (chat_scroll > 0)
V_DrawThinString(chatx-8, ((justscrolledup) ? (chat_topy-1) : (chat_topy)) - 1, V_SNAPTOBOTTOM | V_SNAPTOLEFT | V_YELLOWMAP, "\x1A"); // up arrow V_DrawThinString(chatx-8, ((justscrolledup) ? (chat_topy-1) : (chat_topy)) - 1, V_SNAPTOBOTTOM | V_SNAPTOLEFT | V_YELLOWMAP, "\x1A"); // up arrow
if (chat_scroll < chat_maxscroll) if (chat_scroll < chat_maxscroll)
V_DrawThinString(chatx-8, chat_bottomy-((justscrolleddown) ? 5 : 6) - 1, V_SNAPTOBOTTOM | V_SNAPTOLEFT | V_YELLOWMAP, "\x1B"); // down arrow V_DrawThinString(chatx-8, chat_bottomy-((justscrolleddown) ? 5 : 6) - 1, V_SNAPTOBOTTOM | V_SNAPTOLEFT | V_YELLOWMAP, "\x1B"); // down arrow
justscrolleddown = false; justscrolleddown = justscrolledup = false;
justscrolledup = false;
} }
// //
@ -1587,15 +1411,7 @@ static void HU_DrawChat(void)
#endif #endif
if (teamtalk) if (teamtalk)
{
talk = ttalk; talk = ttalk;
#if 0
if (players[consoleplayer].ctfteam == 1)
t = 0x500; // Red
else if (players[consoleplayer].ctfteam == 2)
t = 0x400; // Blue
#endif
}
if (CHAT_MUTE) if (CHAT_MUTE)
{ {
@ -1609,16 +1425,10 @@ static void HU_DrawChat(void)
V_DrawFillConsoleMap(chatx, y-1, boxw, (typelines*charheight), 239 | V_SNAPTOBOTTOM | V_SNAPTOLEFT); V_DrawFillConsoleMap(chatx, y-1, boxw, (typelines*charheight), 239 | V_SNAPTOBOTTOM | V_SNAPTOLEFT);
while (talk[i]) for (i = 0; talk[i]; i++)
{ {
if (talk[i] < HU_FONTSTART) if (talk[i] >= FONTSTART)
++i;
else
{
V_DrawChatCharacter(chatx + c + 2, y, talk[i] |V_SNAPTOBOTTOM|V_SNAPTOLEFT|cflag, true, V_GetStringColormap(talk[i]|cflag)); V_DrawChatCharacter(chatx + c + 2, y, talk[i] |V_SNAPTOBOTTOM|V_SNAPTOLEFT|cflag, true, V_GetStringColormap(talk[i]|cflag));
i++;
}
c += charwidth; c += charwidth;
} }
@ -1629,13 +1439,12 @@ static void HU_DrawChat(void)
return; return;
} }
i = 0;
typelines = 1; typelines = 1;
if ((strlen(w_chat) == 0 || c_input == 0) && hu_tick < 4) if ((strlen(w_chat) == 0 || c_input == 0) && hu_tick < 4)
V_DrawChatCharacter(chatx + 2 + c, y+1, '_' |V_SNAPTOBOTTOM|V_SNAPTOLEFT|t, true, NULL); V_DrawChatCharacter(chatx + 2 + c, y+1, '_' |V_SNAPTOBOTTOM|V_SNAPTOLEFT|t, true, NULL);
while (w_chat[i]) for (i = 0; w_chat[i]; i++)
{ {
boolean skippedline = false; boolean skippedline = false;
if (c_input == (i+1)) if (c_input == (i+1))
@ -1652,14 +1461,11 @@ static void HU_DrawChat(void)
} }
} }
//Hurdler: isn't it better like that? if (w_chat[i] >= FONTSTART)
if (w_chat[i] < HU_FONTSTART) V_DrawChatCharacter(chatx + c + 2, y, w_chat[i] | V_SNAPTOBOTTOM|V_SNAPTOLEFT | t, true, NULL);
++i;
else
V_DrawChatCharacter(chatx + c + 2, y, w_chat[i++] | V_SNAPTOBOTTOM|V_SNAPTOLEFT | t, true, NULL);
c += charwidth; c += charwidth;
if (c > boxw-(charwidth*2) && !skippedline) if (c > boxw-charwidth && !skippedline)
{ {
c = 0; c = 0;
y += charheight; y += charheight;
@ -1681,8 +1487,7 @@ static void HU_DrawChat(void)
} }
#endif #endif
i = 0; for(i=0; i<MAXPLAYERS; i++)
for(i=0; (i<MAXPLAYERS); i++)
{ {
// filter: (code needs optimization pls help I'm bad with C) // filter: (code needs optimization pls help I'm bad with C)
if (w_chat[3]) if (w_chat[3])
@ -1697,32 +1502,16 @@ static void HU_DrawChat(void)
playernum[3] = 0; playernum[3] = 0;
n = atoi(playernum); // turn that into a number n = atoi(playernum); // turn that into a number
// special cases: // special cases:
if ((n == 0) && !(w_chat[4] == '0') && (!(i<10)))
if ((n == 0) && !(w_chat[4] == '0')) continue;
{ else if ((n == 1) && !(w_chat[3] == '0') && (!((i == 1) || ((i >= 10) && (i <= 19)))))
if (!(i<10)) continue;
continue; else if ((n == 2) && !(w_chat[3] == '0') && (!((i == 2) || ((i >= 20) && (i <= 29)))))
} continue;
else if ((n == 1) && !(w_chat[3] == '0')) else if ((n == 3) && !(w_chat[3] == '0') && (!((i == 3) || ((i >= 30) && (i <= 31)))))
{ continue;
if (!((i == 1) || ((i >= 10) && (i <= 19))))
continue;
}
else if ((n == 2) && !(w_chat[3] == '0'))
{
if (!((i == 2) || ((i >= 20) && (i <= 29))))
continue;
}
else if ((n == 3) && !(w_chat[3] == '0'))
{
if (!((i == 3) || ((i >= 30) && (i <= 31))))
continue;
}
else // general case. else // general case.
{ if (i != n) continue;
if (i != n)
continue;
}
} }
if (playeringame[i]) if (playeringame[i])
@ -1753,41 +1542,22 @@ static void HU_DrawChat_Old(void)
size_t i = 0; size_t i = 0;
const char *ntalk = "Say: ", *ttalk = "Say-Team: "; const char *ntalk = "Say: ", *ttalk = "Say-Team: ";
const char *talk = ntalk; const char *talk = ntalk;
INT32 charwidth = 8 * con_scalefactor; //(hu_font['A'-HU_FONTSTART]->width) * con_scalefactor; INT32 charwidth = 8 * con_scalefactor, charheight = 8 * con_scalefactor;
INT32 charheight = 8 * con_scalefactor; //(hu_font['A'-HU_FONTSTART]->height) * con_scalefactor;
if (teamtalk) if (teamtalk)
{
talk = ttalk; talk = ttalk;
#if 0
if (players[consoleplayer].ctfteam == 1)
t = 0x500; // Red
else if (players[consoleplayer].ctfteam == 2)
t = 0x400; // Blue
#endif
}
while (talk[i]) for (i = 0; talk[i]; i++)
{ {
if (talk[i] < HU_FONTSTART) if (talk[i] >= FONTSTART)
{ V_DrawCharacter(HU_INPUTX + c, y, talk[i] | cv_constextsize.value | V_NOSCALESTART, true);
++i;
//charwidth = 4 * con_scalefactor;
}
else
{
//charwidth = (hu_font[talk[i]-HU_FONTSTART]->width) * con_scalefactor;
V_DrawCharacter(HU_INPUTX + c, y, talk[i++] | cv_constextsize.value | V_NOSCALESTART, true);
}
c += charwidth; c += charwidth;
} }
if ((strlen(w_chat) == 0 || c_input == 0) && hu_tick < 4) if ((strlen(w_chat) == 0 || c_input == 0) && hu_tick < 4)
V_DrawCharacter(HU_INPUTX+c, y+2*con_scalefactor, '_' |cv_constextsize.value | V_NOSCALESTART|t, true); V_DrawCharacter(HU_INPUTX+c, y+2*con_scalefactor, '_' |cv_constextsize.value | V_NOSCALESTART|t, true);
i = 0; for (i = 0; w_chat[i]; i++)
while (w_chat[i])
{ {
if (c_input == (i+1) && hu_tick < 4) if (c_input == (i+1) && hu_tick < 4)
{ {
INT32 cursorx = (HU_INPUTX+c+charwidth < vid.width) ? (HU_INPUTX + c + charwidth) : (HU_INPUTX); // we may have to go down. INT32 cursorx = (HU_INPUTX+c+charwidth < vid.width) ? (HU_INPUTX + c + charwidth) : (HU_INPUTX); // we may have to go down.
@ -1795,17 +1565,8 @@ static void HU_DrawChat_Old(void)
V_DrawCharacter(cursorx, cursory+2*con_scalefactor, '_' |cv_constextsize.value | V_NOSCALESTART|t, true); V_DrawCharacter(cursorx, cursory+2*con_scalefactor, '_' |cv_constextsize.value | V_NOSCALESTART|t, true);
} }
//Hurdler: isn't it better like that? if (w_chat[i] >= FONTSTART)
if (w_chat[i] < HU_FONTSTART) V_DrawCharacter(HU_INPUTX + c, y, w_chat[i] | cv_constextsize.value | V_NOSCALESTART | t, true);
{
++i;
//charwidth = 4 * con_scalefactor;
}
else
{
//charwidth = (hu_font[w_chat[i]-HU_FONTSTART]->width) * con_scalefactor;
V_DrawCharacter(HU_INPUTX + c, y, w_chat[i++] | cv_constextsize.value | V_NOSCALESTART | t, true);
}
c += charwidth; c += charwidth;
if (c >= vid.width) if (c >= vid.width)
@ -1814,9 +1575,6 @@ static void HU_DrawChat_Old(void)
y += charheight; y += charheight;
} }
} }
if (hu_tick < 4)
V_DrawCharacter(HU_INPUTX + c, y, '_' | cv_constextsize.value |V_NOSCALESTART|t, true);
} }
// Draw crosshairs at the exact center of the view. // Draw crosshairs at the exact center of the view.
@ -1902,21 +1660,6 @@ static void HU_DrawCEcho(void)
} }
} }
static void HU_drawGametype(void)
{
const char *strvalue = NULL;
if (gametype < 0 || gametype >= gametypecount)
return; // not a valid gametype???
strvalue = Gametype_Names[gametype];
if (splitscreen)
V_DrawString(4, 184, 0, strvalue);
else
V_DrawString(4, 192, 0, strvalue);
}
// //
// demo info stuff // demo info stuff
// //
@ -2778,7 +2521,8 @@ static void HU_DrawRankings(void)
UINT32 whiteplayer; UINT32 whiteplayer;
// draw the current gametype in the lower right // draw the current gametype in the lower right
HU_drawGametype(); if (gametype >= 0 && gametype < gametypecount)
V_DrawString(4, splitscreen ? 184 : 192, 0, Gametype_Names[gametype]);
if (gametyperules & (GTR_TIMELIMIT|GTR_POINTLIMIT)) if (gametyperules & (GTR_TIMELIMIT|GTR_POINTLIMIT))
{ {

View file

@ -19,33 +19,34 @@
#include "r_defs.h" #include "r_defs.h"
//------------------------------------ //------------------------------------
// heads up font // Fonts & stuff
//------------------------------------ //------------------------------------
#define HU_FONTSTART '\x16' // the first font character #define FONTSTART '\x16' // the first font character
#define HU_FONTEND '~' #define FONTEND '~'
#define FONTSIZE (FONTEND - FONTSTART + 1)
#define HU_FONTSIZE (HU_FONTEND - HU_FONTSTART + 1)
// Level title font
#define LT_FONTSTART '!' // the first font characters
#define LT_FONTEND 'z' // the last font characters
#define LT_FONTSIZE (LT_FONTEND - LT_FONTSTART + 1)
#define CRED_FONTSTART '!' // the first font character
#define CRED_FONTEND 'Z' // the last font character
#define CRED_FONTSIZE (CRED_FONTEND - CRED_FONTSTART + 1)
// Name tag font
// Used by base and outline font set
#define NT_FONTSTART '!' // the first font character
#define NT_FONTEND 'Z' // the last font character
#define NT_FONTSIZE (NT_FONTEND - NT_FONTSTART + 1)
#define HU_CROSSHAIRS 3 // maximum of 9 - see HU_Init(); #define HU_CROSSHAIRS 3 // maximum of 9 - see HU_Init();
extern char *shiftxform; // english translation shift table extern char *shiftxform; // english translation shift table
extern char english_shiftxform[]; extern char english_shiftxform[];
typedef struct
{
patch_t *chars[FONTSIZE];
INT32 kerning;
UINT32 spacewidth;
UINT32 charwidth;
UINT32 linespacing;
} fontdef_t;
extern fontdef_t hu_font, tny_font, cred_font, lt_font;
extern fontdef_t ntb_font, nto_font;
extern patch_t *tallnum[10];
extern patch_t *nightsnum[10];
extern patch_t *ttlnum[10];
extern patch_t *tallminus;
extern patch_t *tallinfin;
//------------------------------------ //------------------------------------
// sorted player lines // sorted player lines
//------------------------------------ //------------------------------------
@ -78,22 +79,12 @@ void HU_AddChatText(const char *text, boolean playsound);
// set true when entering a chat message // set true when entering a chat message
extern boolean chat_on; extern boolean chat_on;
extern patch_t *hu_font[HU_FONTSIZE], *tny_font[HU_FONTSIZE];
extern patch_t *tallnum[10];
extern patch_t *nightsnum[10];
extern patch_t *lt_font[LT_FONTSIZE];
extern patch_t *cred_font[CRED_FONTSIZE];
extern patch_t *ntb_font[NT_FONTSIZE];
extern patch_t *nto_font[NT_FONTSIZE];
extern patch_t *ttlnum[10];
extern patch_t *emeraldpics[3][8]; extern patch_t *emeraldpics[3][8];
extern patch_t *rflagico; extern patch_t *rflagico;
extern patch_t *bflagico; extern patch_t *bflagico;
extern patch_t *rmatcico; extern patch_t *rmatcico;
extern patch_t *bmatcico; extern patch_t *bmatcico;
extern patch_t *tagico; extern patch_t *tagico;
extern patch_t *tallminus;
extern patch_t *tallinfin;
extern patch_t *tokenicon; extern patch_t *tokenicon;
// set true whenever the tab rankings are being shown for any reason // set true whenever the tab rankings are being shown for any reason
@ -103,6 +94,8 @@ extern boolean hu_showscores;
void HU_Init(void); void HU_Init(void);
void HU_LoadGraphics(void); void HU_LoadGraphics(void);
void HU_LoadFontCharacters(fontdef_t *font, const char *prefix);
void HU_SetFontProperties(fontdef_t *font, INT32 kerning, UINT32 spacewidth, UINT32 charwidth, UINT32 linespacing);
// reset heads up when consoleplayer respawns. // reset heads up when consoleplayer respawns.
void HU_Start(void); void HU_Start(void);

5290
src/info.c

File diff suppressed because it is too large Load diff

View file

@ -1078,9 +1078,6 @@ typedef enum sprite
NUMSPRITES NUMSPRITES
} spritenum_t; } spritenum_t;
// Make sure to be conscious of FF_FRAMEMASK and the fact sprite2 is stored as a UINT8 whenever you change this table.
// Currently, FF_FRAMEMASK is 0xff, or 255 - but the second half is used by FF_SPR2SUPER, so the limitation is 0x7f.
// Since this is zero-based, there can be at most 128 different SPR2_'s without changing that.
typedef enum playersprite typedef enum playersprite
{ {
SPR2_STND = 0, SPR2_STND = 0,
@ -1160,15 +1157,17 @@ typedef enum playersprite
SPR2_XTRA, // stuff that isn't in-map - "would this ever need an md2 or variable length animation?" SPR2_XTRA, // stuff that isn't in-map - "would this ever need an md2 or variable length animation?"
SPR2_FIRSTFREESLOT, SPR2_FIRSTFREESLOT,
SPR2_LASTFREESLOT = 0x7f, SPR2_LASTFREESLOT = 1024, // Do not make higher than SPR2F_MASK (currently 0x3FF) plus one
NUMPLAYERSPRITES NUMPLAYERSPRITES
} playersprite_t; } playersprite_t;
// SPR2_XTRA enum
#define XTRA_LIFEPIC 0 // Life icon patch {
#define XTRA_CHARSEL 1 // Character select picture XTRA_LIFEPIC,
#define XTRA_CONTINUE 2 // Continue icon XTRA_CHARSEL,
#define XTRA_ENDING 3 // Ending finale patches XTRA_CONTINUE,
XTRA_ENDING
};
typedef enum state typedef enum state
{ {
@ -4380,6 +4379,7 @@ typedef struct
INT32 var1; INT32 var1;
INT32 var2; INT32 var2;
statenum_t nextstate; statenum_t nextstate;
UINT16 sprite2;
} state_t; } state_t;
extern state_t states[NUMSTATES]; extern state_t states[NUMSTATES];

View file

@ -674,17 +674,15 @@ static int lib_pRemoveMobj(lua_State *L)
return 0; return 0;
} }
// P_IsValidSprite2 technically doesn't exist, and probably never should... but too much would need to be exposed to allow this to be checked by other methods.
static int lib_pIsValidSprite2(lua_State *L) static int lib_pIsValidSprite2(lua_State *L)
{ {
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
UINT8 spr2 = (UINT8)luaL_checkinteger(L, 2); UINT16 spr2 = (UINT16)luaL_checkinteger(L, 2);
//HUDSAFE //HUDSAFE
INLEVEL INLEVEL
if (!mobj) if (!mobj)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, (mobj->skin && (((skin_t *)mobj->skin)->sprites[spr2].numframes))); lua_pushboolean(L, mobj->skin && P_IsValidSprite2(mobj->skin, spr2));
return 1; return 1;
} }
@ -3039,6 +3037,9 @@ static int lib_rFrame2Char(lua_State *L)
return 2; return 2;
} }
// R_SKINS
////////////
// R_SetPlayerSkin technically doesn't exist either, although it's basically just SetPlayerSkin and SetPlayerSkinByNum handled in one place for convenience // R_SetPlayerSkin technically doesn't exist either, although it's basically just SetPlayerSkin and SetPlayerSkinByNum handled in one place for convenience
static int lib_rSetPlayerSkin(lua_State *L) static int lib_rSetPlayerSkin(lua_State *L)
{ {
@ -3101,6 +3102,47 @@ static int lib_rSkinUsable(lua_State *L)
return 1; return 1;
} }
static int lib_pGetStateSprite2(lua_State *L)
{
int statenum = luaL_checkinteger(L, 1);
if (statenum < 0 || statenum >= NUMSTATES)
return luaL_error(L, "state %d out of range (0 - %d)", statenum, NUMSTATES-1);
lua_pushinteger(L, P_GetStateSprite2(&states[statenum]));
return 1;
}
static int lib_pGetSprite2StateFrame(lua_State *L)
{
int statenum = luaL_checkinteger(L, 1);
if (statenum < 0 || statenum >= NUMSTATES)
return luaL_error(L, "state %d out of range (0 - %d)", statenum, NUMSTATES-1);
lua_pushinteger(L, P_GetSprite2StateFrame(&states[statenum]));
return 1;
}
static int lib_pIsStateSprite2Super(lua_State *L)
{
int statenum = luaL_checkinteger(L, 1);
if (statenum < 0 || statenum >= NUMSTATES)
return luaL_error(L, "state %d out of range (0 - %d)", statenum, NUMSTATES-1);
lua_pushboolean(L, P_IsStateSprite2Super(&states[statenum]));
return 1;
}
// Not a real function. Who cares? I know I don't.
static int lib_pGetSuperSprite2(lua_State *L)
{
int animID = luaL_checkinteger(L, 1) & SPR2F_MASK;
if (animID < 0 || animID >= NUMPLAYERSPRITES)
return luaL_error(L, "sprite2 %d out of range (0 - %d)", animID, NUMPLAYERSPRITES-1);
lua_pushinteger(L, animID | SPR2F_SUPER);
return 1;
}
// R_DATA // R_DATA
//////////// ////////////
@ -4506,7 +4548,13 @@ static luaL_Reg lib[] = {
{"R_Char2Frame",lib_rChar2Frame}, {"R_Char2Frame",lib_rChar2Frame},
{"R_Frame2Char",lib_rFrame2Char}, {"R_Frame2Char",lib_rFrame2Char},
{"R_SetPlayerSkin",lib_rSetPlayerSkin}, {"R_SetPlayerSkin",lib_rSetPlayerSkin},
// r_skins
{"R_SkinUsable",lib_rSkinUsable}, {"R_SkinUsable",lib_rSkinUsable},
{"P_GetStateSprite2",lib_pGetStateSprite2},
{"P_GetSprite2StateFrame",lib_pGetSprite2StateFrame},
{"P_IsStateSprite2Super",lib_pIsStateSprite2Super},
{"P_GetSuperSprite2",lib_pGetSuperSprite2},
// r_data // r_data
{"R_CheckTextureNumForName",lib_rCheckTextureNumForName}, {"R_CheckTextureNumForName",lib_rCheckTextureNumForName},

View file

@ -556,7 +556,7 @@ static int libd_getSprite2Patch(lua_State *L)
UINT8 angle = 0; UINT8 angle = 0;
spritedef_t *sprdef; spritedef_t *sprdef;
spriteframe_t *sprframe; spriteframe_t *sprframe;
boolean super = false; // add FF_SPR2SUPER to sprite2 if true boolean super = false; // add SPR2F_SUPER to sprite2 if true
HUDONLY HUDONLY
// get skin first! // get skin first!
@ -583,11 +583,12 @@ static int libd_getSprite2Patch(lua_State *L)
if (lua_isnumber(L, 1)) // sprite number given, e.g. SPR2_STND if (lua_isnumber(L, 1)) // sprite number given, e.g. SPR2_STND
{ {
j = lua_tonumber(L, 1); j = lua_tonumber(L, 1);
if (j & FF_SPR2SUPER) // e.g. SPR2_STND|FF_SPR2SUPER if (j & SPR2F_SUPER) // e.g. SPR2_STND|SPR2F_SUPER
{ {
super = true; super = true;
j &= ~FF_SPR2SUPER; // remove flag so the next check doesn't fail j &= ~SPR2F_SUPER; // remove flag so the next check doesn't fail
} }
if (j >= free_spr2) if (j >= free_spr2)
return 0; return 0;
} }
@ -606,17 +607,15 @@ static int libd_getSprite2Patch(lua_State *L)
if (lua_isboolean(L, 2)) // optional boolean for superness if (lua_isboolean(L, 2)) // optional boolean for superness
{ {
super = lua_toboolean(L, 2); // note: this can override FF_SPR2SUPER from sprite number super = lua_toboolean(L, 2); // note: this can override SPR2F_SUPER from sprite number
lua_remove(L, 2); // remove lua_remove(L, 2); // remove
} }
// if it's not boolean then just assume it's the frame number // if it's not boolean then just assume it's the frame number
if (super) if (super)
j |= FF_SPR2SUPER; j |= SPR2F_SUPER;
j = P_GetSkinSprite2(skins[i], j, NULL); // feed skin and current sprite2 through to change sprite2 used if necessary sprdef = P_GetSkinSpritedef(skins[i], j);
sprdef = &skins[i]->sprites[j];
// set frame number // set frame number
frame = luaL_optinteger(L, 2, 0); frame = luaL_optinteger(L, 2, 0);
@ -644,7 +643,7 @@ static int libd_getSprite2Patch(lua_State *L)
INT32 rot = R_GetRollAngle(rollangle); INT32 rot = R_GetRollAngle(rollangle);
if (rot) { if (rot) {
patch_t *rotsprite = Patch_GetRotatedSprite(sprframe, frame, angle, sprframe->flip & (1<<angle), &skins[i]->sprinfo[j], rot); patch_t *rotsprite = Patch_GetRotatedSprite(sprframe, frame, angle, sprframe->flip & (1<<angle), P_GetSkinSpriteInfo(skins[i], j), rot);
LUA_PushUserdata(L, rotsprite, META_PATCH); LUA_PushUserdata(L, rotsprite, META_PATCH);
lua_pushboolean(L, false); lua_pushboolean(L, false);
lua_pushboolean(L, true); lua_pushboolean(L, true);

View file

@ -165,7 +165,7 @@ static int lib_getSpr2default(lua_State *L)
static int lib_setSpr2default(lua_State *L) static int lib_setSpr2default(lua_State *L)
{ {
playersprite_t i; playersprite_t i;
UINT8 j = 0; UINT16 j = 0;
if (hud_running) if (hud_running)
return luaL_error(L, "Do not alter spr2defaults[] in HUD rendering code!"); return luaL_error(L, "Do not alter spr2defaults[] in HUD rendering code!");

View file

@ -569,7 +569,7 @@ static int mobj_set(lua_State *L)
mo->frame = (UINT32)luaL_checkinteger(L, 3); mo->frame = (UINT32)luaL_checkinteger(L, 3);
break; break;
case mobj_sprite2: case mobj_sprite2:
mo->sprite2 = P_GetSkinSprite2(((skin_t *)mo->skin), (UINT8)luaL_checkinteger(L, 3), mo->player); mo->sprite2 = P_GetSkinSprite2(((skin_t *)mo->skin), (UINT16)luaL_checkinteger(L, 3), mo->player);
break; break;
case mobj_anim_duration: case mobj_anim_duration:
mo->anim_duration = (UINT16)luaL_checkinteger(L, 3); mo->anim_duration = (UINT16)luaL_checkinteger(L, 3);

View file

@ -55,6 +55,7 @@ enum skin {
skin_contangle, skin_contangle,
skin_soundsid, skin_soundsid,
skin_sprites, skin_sprites,
skin_supersprites,
skin_natkcolor skin_natkcolor
}; };
@ -95,6 +96,7 @@ static const char *const skin_opt[] = {
"contangle", "contangle",
"soundsid", "soundsid",
"sprites", "sprites",
"supersprites",
"natkcolor", "natkcolor",
NULL}; NULL};
@ -220,6 +222,9 @@ static int skin_get(lua_State *L)
case skin_sprites: case skin_sprites:
LUA_PushUserdata(L, skin->sprites, META_SKINSPRITES); LUA_PushUserdata(L, skin->sprites, META_SKINSPRITES);
break; break;
case skin_supersprites:
LUA_PushUserdata(L, skin->super.sprites, META_SKINSPRITES);
break;
case skin_natkcolor: case skin_natkcolor:
lua_pushinteger(L, skin->natkcolor); lua_pushinteger(L, skin->natkcolor);
break; break;
@ -347,17 +352,17 @@ static int lib_getSkinSprite(lua_State *L)
spritedef_t *sksprites = *(spritedef_t **)luaL_checkudata(L, 1, META_SKINSPRITES); spritedef_t *sksprites = *(spritedef_t **)luaL_checkudata(L, 1, META_SKINSPRITES);
playersprite_t i = luaL_checkinteger(L, 2); playersprite_t i = luaL_checkinteger(L, 2);
if (i < 0 || i >= NUMPLAYERSPRITES*2) if (i < 0 || i >= NUMPLAYERSPRITES)
return luaL_error(L, LUA_QL("skin_t") " field 'sprites' index %d out of range (0 - %d)", i, (NUMPLAYERSPRITES*2)-1); return luaL_error(L, "skin sprites index %d out of range (0 - %d)", i, NUMPLAYERSPRITES-1);
LUA_PushUserdata(L, &sksprites[i], META_SKINSPRITESLIST); LUA_PushUserdata(L, &sksprites[i], META_SKINSPRITESLIST);
return 1; return 1;
} }
// #skin.sprites -> NUMPLAYERSPRITES*2 // #skin.sprites -> NUMPLAYERSPRITES
static int lib_numSkinsSprites(lua_State *L) static int lib_numSkinsSprites(lua_State *L)
{ {
lua_pushinteger(L, NUMPLAYERSPRITES*2); lua_pushinteger(L, NUMPLAYERSPRITES);
return 1; return 1;
} }

View file

@ -4956,22 +4956,6 @@ static void M_DrawCenteredMenu(void)
} }
} }
//
// M_StringHeight
//
// Find string height from hu_font chars
//
static inline size_t M_StringHeight(const char *string)
{
size_t h = 8, i;
for (i = 0; i < strlen(string); i++)
if (string[i] == '\n')
h += 8;
return h;
}
// ========================================================================== // ==========================================================================
// Extraneous menu patching functions // Extraneous menu patching functions
// ========================================================================== // ==========================================================================
@ -6089,56 +6073,16 @@ menu_t MessageDef =
NULL NULL
}; };
void M_StartMessage(const char *string, void *routine, menumessagetype_t itemtype)
void M_StartMessage(const char *string, void *routine,
menumessagetype_t itemtype)
{ {
size_t max = 0, start = 0, i, strlines; static char *message;
static char *message = NULL;
Z_Free(message); Z_Free(message);
message = Z_StrDup(string); message = V_WordWrap(0,0,V_ALLOWLOWERCASE,string);
DEBFILE(message); DEBFILE(message);
// Rudementary word wrapping.
// Simple and effective. Does not handle nonuniform letter sizes, colors, etc. but who cares.
strlines = 0;
for (i = 0; message[i]; i++)
{
if (message[i] == ' ')
{
start = i;
max += 4;
}
else if (message[i] == '\n')
{
strlines = i;
start = 0;
max = 0;
continue;
}
else
max += 8;
// Start trying to wrap if presumed length exceeds the screen width.
if (max >= BASEVIDWIDTH && start > 0)
{
message[start] = '\n';
max -= (start-strlines)*8;
strlines = start;
start = 0;
}
}
start = 0;
max = 0;
M_StartControlPanel(); // can't put menuactive to true M_StartControlPanel(); // can't put menuactive to true
if (currentMenu == &MessageDef) // Prevent recursion MessageDef.prevMenu = (currentMenu == &MessageDef) ? &MainDef : currentMenu; // Prevent recursion
MessageDef.prevMenu = &MainDef;
else
MessageDef.prevMenu = currentMenu;
MessageDef.menuitems[0].text = message; MessageDef.menuitems[0].text = message;
MessageDef.menuitems[0].alphaKey = (UINT8)itemtype; MessageDef.menuitems[0].alphaKey = (UINT8)itemtype;
if (!routine && itemtype != MM_NOTHING) itemtype = MM_NOTHING; if (!routine && itemtype != MM_NOTHING) itemtype = MM_NOTHING;
@ -6157,51 +6101,17 @@ void M_StartMessage(const char *string, void *routine,
MessageDef.menuitems[0].itemaction = routine; MessageDef.menuitems[0].itemaction = routine;
break; break;
} }
//added : 06-02-98: now draw a textbox around the message MessageDef.x = (INT16)((BASEVIDWIDTH - V_StringWidth(message, 0)-32)/2);
// compute lenght max and the numbers of lines MessageDef.y = (INT16)((BASEVIDHEIGHT - V_StringHeight(message, V_RETURN8))/2);
for (strlines = 0; *(message+start); strlines++)
{
for (i = 0;i < strlen(message+start);i++)
{
if (*(message+start+i) == '\n')
{
if (i > max)
max = i;
start += i;
i = (size_t)-1; //added : 07-02-98 : damned!
start++;
break;
}
}
if (i == strlen(message+start))
start += i;
}
MessageDef.x = (INT16)((BASEVIDWIDTH - 8*max-16)/2);
MessageDef.y = (INT16)((BASEVIDHEIGHT - M_StringHeight(message))/2);
MessageDef.lastOn = (INT16)((strlines<<8)+max);
//M_SetupNextMenu();
currentMenu = &MessageDef; currentMenu = &MessageDef;
itemOn = 0; itemOn = 0;
} }
#define MAXMSGLINELEN 256
static void M_DrawMessageMenu(void) static void M_DrawMessageMenu(void)
{ {
INT32 y = currentMenu->y;
size_t i, start = 0;
INT16 max;
char string[MAXMSGLINELEN];
INT32 mlines;
const char *msg = currentMenu->menuitems[0].text; const char *msg = currentMenu->menuitems[0].text;
mlines = currentMenu->lastOn>>8;
max = (INT16)((UINT8)(currentMenu->lastOn & 0xFF)*8);
// hack: draw RA background in RA menus // hack: draw RA background in RA menus
if (gamestate == GS_TIMEATTACK) if (gamestate == GS_TIMEATTACK)
{ {
@ -6225,51 +6135,8 @@ static void M_DrawMessageMenu(void)
V_DrawFadeScreen(0xFF00, curfadevalue); V_DrawFadeScreen(0xFF00, curfadevalue);
} }
M_DrawTextBox(currentMenu->x, y - 8, (max+7)>>3, mlines); M_DrawTextBox(currentMenu->x, currentMenu->y - 8, 2+V_StringWidth(msg, 0)/8, V_StringHeight(msg, V_RETURN8)/8);
V_DrawCenteredString(BASEVIDWIDTH/2, currentMenu->y, V_ALLOWLOWERCASE|V_RETURN8, msg);
while (*(msg+start))
{
size_t len = strlen(msg+start);
for (i = 0; i < len; i++)
{
if (*(msg+start+i) == '\n')
{
memset(string, 0, MAXMSGLINELEN);
if (i >= MAXMSGLINELEN)
{
CONS_Printf("M_DrawMessageMenu: too long segment in %s\n", msg);
return;
}
else
{
strncpy(string,msg+start, i);
string[i] = '\0';
start += i;
i = (size_t)-1; //added : 07-02-98 : damned!
start++;
}
break;
}
}
if (i == strlen(msg+start))
{
if (i >= MAXMSGLINELEN)
{
CONS_Printf("M_DrawMessageMenu: too long segment in %s\n", msg);
return;
}
else
{
strcpy(string, msg + start);
start += i;
}
}
V_DrawString((BASEVIDWIDTH - V_StringWidth(string, 0))/2,y,V_ALLOWLOWERCASE,string);
y += 8; //hu_font[0]->height;
}
} }
// default message handler // default message handler
@ -7956,7 +7823,7 @@ static void M_DrawSoundTest(void)
{ {
V_DrawFill(165+140-9, y-4, 8, 16, 150); V_DrawFill(165+140-9, y-4, 8, 16, 150);
//V_DrawCharacter(165+140-8, y, '\x19' | V_YELLOWMAP, false); //V_DrawCharacter(165+140-8, y, '\x19' | V_YELLOWMAP, false);
V_DrawFixedPatch((165+140-9)<<FRACBITS, (y<<FRACBITS)-(bounce*4), FRACUNIT, 0, hu_font['\x19'-HU_FONTSTART], V_GetStringColormap(V_YELLOWMAP)); V_DrawFixedPatch((165+140-9)<<FRACBITS, (y<<FRACBITS)-(bounce*4), FRACUNIT, 0, hu_font.chars['\x19'-FONTSTART], V_GetStringColormap(V_YELLOWMAP));
} }
} }
t++; t++;
@ -12056,7 +11923,7 @@ static void M_HandleConnectIP(INT32 choice)
static fixed_t multi_tics; static fixed_t multi_tics;
static UINT8 multi_frame; static UINT8 multi_frame;
static UINT8 multi_spr2; static UINT16 multi_spr2;
static boolean multi_paused; static boolean multi_paused;
static boolean multi_invcolor; static boolean multi_invcolor;

View file

@ -1362,7 +1362,7 @@ static void IdleUpdate(void)
for (i = 1; i < MAXPLAYERS; i++) for (i = 1; i < MAXPLAYERS; i++)
{ {
if (cv_idletime.value && playeringame[i] && playernode[i] != UINT8_MAX && !players[i].quittime && !players[i].spectator && !players[i].bot && !IsPlayerAdmin(i) && i != serverplayer) if (cv_idletime.value && playeringame[i] && playernode[i] != UINT8_MAX && !players[i].quittime && !players[i].spectator && !players[i].bot && !IsPlayerAdmin(i) && i != serverplayer && gamestate == GS_LEVEL)
{ {
if (players[i].cmd.forwardmove || players[i].cmd.sidemove || players[i].cmd.buttons) if (players[i].cmd.forwardmove || players[i].cmd.sidemove || players[i].cmd.buttons)
players[i].lastinputtime = 0; players[i].lastinputtime = 0;

View file

@ -85,9 +85,15 @@ void P_AddCachedAction(mobj_t *mobj, INT32 statenum)
// //
static void P_SetupStateAnimation(mobj_t *mobj, state_t *st) static void P_SetupStateAnimation(mobj_t *mobj, state_t *st)
{ {
INT32 animlength = (mobj->sprite == SPR_PLAY && mobj->skin) INT32 animlength;
? (INT32)(((skin_t *)mobj->skin)->sprites[mobj->sprite2].numframes) - 1
: st->var1; if (mobj->sprite == SPR_PLAY && mobj->skin)
{
spritedef_t *spritedef = P_GetSkinSpritedef(mobj->skin, mobj->sprite2);
animlength = (INT32)(spritedef->numframes);
}
else
animlength = st->var1;
if (!(st->frame & FF_ANIMATE)) if (!(st->frame & FF_ANIMATE))
return; return;
@ -138,8 +144,13 @@ FUNCINLINE static ATTRINLINE void P_CycleStateAnimation(mobj_t *mobj)
} }
// sprite2 version of above // sprite2 version of above
if (mobj->skin && (((++mobj->frame) & FF_FRAMEMASK) >= (UINT32)(((skin_t *)mobj->skin)->sprites[mobj->sprite2].numframes))) if (mobj->skin)
mobj->frame &= ~FF_FRAMEMASK; {
spritedef_t *spritedef = P_GetSkinSpritedef(mobj->skin, mobj->sprite2);
UINT32 anim_length = (UINT32)(spritedef->numframes);
if (((++mobj->frame) & FF_FRAMEMASK) >= anim_length)
mobj->frame &= ~FF_FRAMEMASK;
}
} }
// //
@ -395,31 +406,23 @@ static boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
{ {
skin_t *skin = ((skin_t *)mobj->skin); skin_t *skin = ((skin_t *)mobj->skin);
UINT16 frame = (mobj->frame & FF_FRAMEMASK)+1; UINT16 frame = (mobj->frame & FF_FRAMEMASK)+1;
UINT8 numframes, spr2; UINT8 numframes;
UINT16 spr2;
if (skin) if (skin)
{ {
UINT16 stateframe = st->frame; spr2 = P_GetStateSprite2(st);
// Add/Remove FF_SPR2SUPER based on certain conditions // Add or remove SPR2F_SUPER based on certain conditions
if (player->charflags & SF_NOSUPERSPRITES || (player->powers[pw_carry] == CR_NIGHTSMODE && (player->charflags & SF_NONIGHTSSUPER))) spr2 = P_ApplySuperFlagToSprite2(spr2, mobj);
stateframe = stateframe & ~FF_SPR2SUPER;
else if (player->powers[pw_super] || (player->powers[pw_carry] == CR_NIGHTSMODE && (player->charflags & SF_SUPER)))
stateframe = stateframe | FF_SPR2SUPER;
if (stateframe & FF_SPR2SUPER) // Get the needed sprite2 and frame number
{ spr2 = P_GetSkinSprite2(skin, spr2, mobj->player);
if (mobj->eflags & MFE_FORCENOSUPER)
stateframe = stateframe & ~FF_SPR2SUPER;
}
else if (mobj->eflags & MFE_FORCESUPER)
stateframe = stateframe | FF_SPR2SUPER;
// Get the sprite2 and frame number spritedef_t *sprdef = P_GetSkinSpritedef(skin, spr2);
spr2 = P_GetSkinSprite2(skin, (stateframe & FF_FRAMEMASK), mobj->player); numframes = sprdef->numframes;
numframes = skin->sprites[spr2].numframes;
if (state == S_PLAY_STND && (spr2 & FF_SPR2SUPER) && skin->sprites[SPR2_WAIT|FF_SPR2SUPER].numframes == 0) if (state == S_PLAY_STND && (spr2 & SPR2F_SUPER) && sprdef[SPR2_WAIT].numframes == 0)
mobj->tics = -1; // If no super wait, don't wait at all mobj->tics = -1; // If no super wait, don't wait at all
} }
else else
@ -432,12 +435,19 @@ static boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
if (mobj->sprite != SPR_PLAY) if (mobj->sprite != SPR_PLAY)
{ {
mobj->sprite = SPR_PLAY; mobj->sprite = SPR_PLAY;
frame = 0; frame = P_GetSprite2StateFrame(st);
} }
else if (mobj->sprite2 != spr2) else if (mobj->sprite2 != spr2)
{ {
if ((st->frame & FF_SPR2MIDSTART) && numframes && P_RandomChance(FRACUNIT/2)) if (st->frame & FF_SPR2MIDSTART)
frame = numframes/2; {
if (numframes && P_RandomChance(FRACUNIT/2))
frame = numframes/2;
else
frame = 0;
}
else if (numframes)
frame = P_GetSprite2StateFrame(st) % numframes;
else else
frame = 0; frame = 0;
} }
@ -452,6 +462,7 @@ static boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
{ {
if (mobj->frame & FF_FRAMEMASK) if (mobj->frame & FF_FRAMEMASK)
mobj->frame--; mobj->frame--;
return P_SetPlayerMobjState(mobj, st->var1); return P_SetPlayerMobjState(mobj, st->var1);
} }
} }
@ -539,26 +550,23 @@ boolean P_SetMobjState(mobj_t *mobj, statenum_t state)
{ {
skin_t *skin = ((skin_t *)mobj->skin); skin_t *skin = ((skin_t *)mobj->skin);
UINT16 frame = (mobj->frame & FF_FRAMEMASK)+1; UINT16 frame = (mobj->frame & FF_FRAMEMASK)+1;
UINT8 numframes, spr2; UINT8 numframes;
UINT16 spr2;
if (skin) if (skin)
{ {
UINT16 stateframe = st->frame; spr2 = P_GetStateSprite2(st);
// Add/Remove FF_SPR2SUPER based on certain conditions // Add or remove SPR2F_SUPER based on certain conditions
if (stateframe & FF_SPR2SUPER) spr2 = P_ApplySuperFlagToSprite2(spr2, mobj);
{
if (mobj->eflags & MFE_FORCENOSUPER)
stateframe = stateframe & ~FF_SPR2SUPER;
}
else if (mobj->eflags & MFE_FORCESUPER)
stateframe = stateframe | FF_SPR2SUPER;
// Get the sprite2 and frame number // Get the needed sprite2 and frame number
spr2 = P_GetSkinSprite2(skin, (stateframe & FF_FRAMEMASK), NULL); spr2 = P_GetSkinSprite2(skin, spr2, NULL);
numframes = skin->sprites[spr2].numframes;
if (state == S_PLAY_STND && (spr2 & FF_SPR2SUPER) && skin->sprites[SPR2_WAIT|FF_SPR2SUPER].numframes == 0) spritedef_t *sprdef = P_GetSkinSpritedef(skin, spr2);
numframes = sprdef->numframes;
if (state == S_PLAY_STND && (spr2 & SPR2F_SUPER) && sprdef[SPR2_WAIT].numframes == 0)
mobj->tics = -1; // If no super wait, don't wait at all mobj->tics = -1; // If no super wait, don't wait at all
} }
else else
@ -571,12 +579,19 @@ boolean P_SetMobjState(mobj_t *mobj, statenum_t state)
if (mobj->sprite != SPR_PLAY) if (mobj->sprite != SPR_PLAY)
{ {
mobj->sprite = SPR_PLAY; mobj->sprite = SPR_PLAY;
frame = 0; frame = P_GetSprite2StateFrame(st);
} }
else if (mobj->sprite2 != spr2) else if (mobj->sprite2 != spr2)
{ {
if ((st->frame & FF_SPR2MIDSTART) && numframes && P_RandomChance(FRACUNIT/2)) if (st->frame & FF_SPR2MIDSTART)
frame = numframes/2; {
if (numframes && P_RandomChance(FRACUNIT/2))
frame = numframes/2;
else
frame = 0;
}
else if (numframes)
frame = P_GetSprite2StateFrame(st) % numframes;
else else
frame = 0; frame = 0;
} }
@ -591,6 +606,7 @@ boolean P_SetMobjState(mobj_t *mobj, statenum_t state)
{ {
if (mobj->frame & FF_FRAMEMASK) if (mobj->frame & FF_FRAMEMASK)
mobj->frame--; mobj->frame--;
return P_SetMobjState(mobj, st->var1); return P_SetMobjState(mobj, st->var1);
} }
} }
@ -11195,7 +11211,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...)
if (mobj->skin) // correct inadequecies above. if (mobj->skin) // correct inadequecies above.
{ {
mobj->sprite2 = P_GetSkinSprite2(mobj->skin, (mobj->frame & FF_FRAMEMASK), NULL); mobj->sprite2 = P_GetSkinSprite2(mobj->skin, P_GetStateSprite2(mobj->state), NULL);
mobj->frame &= ~FF_FRAMEMASK; mobj->frame &= ~FF_FRAMEMASK;
} }

View file

@ -308,7 +308,7 @@ typedef struct mobj_s
angle_t spriteroll, old_spriteroll, old_spriteroll2; angle_t spriteroll, old_spriteroll, old_spriteroll2;
spritenum_t sprite; // used to find patch_t and flip value spritenum_t sprite; // used to find patch_t and flip value
UINT32 frame; // frame number, plus bits see p_pspr.h UINT32 frame; // frame number, plus bits see p_pspr.h
UINT8 sprite2; // player sprites UINT16 sprite2; // player sprites
UINT16 anim_duration; // for FF_ANIMATE states UINT16 anim_duration; // for FF_ANIMATE states
UINT32 renderflags; // render flags UINT32 renderflags; // render flags
@ -452,7 +452,7 @@ typedef struct precipmobj_s
angle_t spriteroll, old_spriteroll, old_spriteroll2; angle_t spriteroll, old_spriteroll, old_spriteroll2;
spritenum_t sprite; // used to find patch_t and flip value spritenum_t sprite; // used to find patch_t and flip value
UINT32 frame; // frame number, plus bits see p_pspr.h UINT32 frame; // frame number, plus bits see p_pspr.h
UINT8 sprite2; // player sprites UINT16 sprite2; // player sprites
UINT16 anim_duration; // for FF_ANIMATE states UINT16 anim_duration; // for FF_ANIMATE states
UINT32 renderflags; // render flags UINT32 renderflags; // render flags

View file

@ -97,6 +97,11 @@
/// \brief Frame flags - Animate: Start at a random place in the animation (mutually exclusive with above) /// \brief Frame flags - Animate: Start at a random place in the animation (mutually exclusive with above)
#define FF_RANDOMANIM 0x40000000 #define FF_RANDOMANIM 0x40000000
/// \brief Animation flags: Bits used for the animation ID
#define SPR2F_MASK 0x3FF
/// \brief Animation flags: "Super" flag
#define SPR2F_SUPER 0x400
/** \brief translucency tables /** \brief translucency tables
\todo add another asm routine which use the fg and bg indexes in the \todo add another asm routine which use the fg and bg indexes in the

View file

@ -1883,7 +1883,7 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
diff |= MD_TICS; diff |= MD_TICS;
if (mobj->sprite != mobj->state->sprite) if (mobj->sprite != mobj->state->sprite)
diff |= MD_SPRITE; diff |= MD_SPRITE;
if (mobj->sprite == SPR_PLAY && mobj->sprite2 != (mobj->state->frame&FF_FRAMEMASK)) if (mobj->sprite == SPR_PLAY && mobj->sprite2 != P_GetStateSprite2(mobj->state))
diff |= MD_SPRITE; diff |= MD_SPRITE;
if (mobj->frame != mobj->state->frame) if (mobj->frame != mobj->state->frame)
diff |= MD_FRAME; diff |= MD_FRAME;
@ -2069,7 +2069,7 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
if (diff & MD_SPRITE) { if (diff & MD_SPRITE) {
WRITEUINT16(save_p, mobj->sprite); WRITEUINT16(save_p, mobj->sprite);
if (mobj->sprite == SPR_PLAY) if (mobj->sprite == SPR_PLAY)
WRITEUINT8(save_p, mobj->sprite2); WRITEUINT16(save_p, mobj->sprite2);
} }
if (diff & MD_FRAME) if (diff & MD_FRAME)
{ {
@ -3101,12 +3101,12 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
if (diff & MD_SPRITE) { if (diff & MD_SPRITE) {
mobj->sprite = READUINT16(save_p); mobj->sprite = READUINT16(save_p);
if (mobj->sprite == SPR_PLAY) if (mobj->sprite == SPR_PLAY)
mobj->sprite2 = READUINT8(save_p); mobj->sprite2 = READUINT16(save_p);
} }
else { else {
mobj->sprite = mobj->state->sprite; mobj->sprite = mobj->state->sprite;
if (mobj->sprite == SPR_PLAY) if (mobj->sprite == SPR_PLAY)
mobj->sprite2 = mobj->state->frame&FF_FRAMEMASK; mobj->sprite2 = P_GetStateSprite2(mobj->state);
} }
if (diff & MD_FRAME) if (diff & MD_FRAME)
{ {

View file

@ -1400,7 +1400,7 @@ void P_DoSuperDetransformation(player_t *player)
if (!G_CoopGametype()) if (!G_CoopGametype())
player->powers[pw_flashing] = flashingtics-1; player->powers[pw_flashing] = flashingtics-1;
if (player->mo->sprite2 & FF_SPR2SUPER) if (player->mo->sprite2 & SPR2F_SUPER)
P_SetMobjState(player->mo, player->mo->state-states); P_SetMobjState(player->mo, player->mo->state-states);
// Inform the netgame that the champion has fallen in the heat of battle. // Inform the netgame that the champion has fallen in the heat of battle.
@ -9802,9 +9802,10 @@ static CV_PossibleValue_t CV_CamSpeed[] = {{0, "MIN"}, {1*FRACUNIT, "MAX"}, {0,
static CV_PossibleValue_t rotation_cons_t[] = {{1, "MIN"}, {25, "MAX"}, {0, NULL}}; static CV_PossibleValue_t rotation_cons_t[] = {{1, "MIN"}, {25, "MAX"}, {0, NULL}};
static CV_PossibleValue_t CV_CamRotate[] = {{-720, "MIN"}, {720, "MAX"}, {0, NULL}}; static CV_PossibleValue_t CV_CamRotate[] = {{-720, "MIN"}, {720, "MAX"}, {0, NULL}};
static CV_PossibleValue_t multiplier_cons_t[] = {{0, "MIN"}, {3*FRACUNIT, "MAX"}, {0, NULL}}; static CV_PossibleValue_t multiplier_cons_t[] = {{0, "MIN"}, {3*FRACUNIT, "MAX"}, {0, NULL}};
static CV_PossibleValue_t campos_cons_t[] = { {INT32_MIN, "MIN"}, {INT32_MAX, "MAX"}, {0, NULL} };
consvar_t cv_cam_dist = CVAR_INIT ("cam_curdist", "160", CV_FLOAT|CV_ALLOWLUA, NULL, NULL); consvar_t cv_cam_dist = CVAR_INIT ("cam_curdist", "160", CV_FLOAT|CV_ALLOWLUA, campos_cons_t, NULL);
consvar_t cv_cam_height = CVAR_INIT ("cam_curheight", "25", CV_FLOAT|CV_ALLOWLUA, NULL, NULL); consvar_t cv_cam_height = CVAR_INIT ("cam_curheight", "25", CV_FLOAT|CV_ALLOWLUA, campos_cons_t, NULL);
consvar_t cv_cam_still = CVAR_INIT ("cam_still", "Off", CV_ALLOWLUA, CV_OnOff, NULL); consvar_t cv_cam_still = CVAR_INIT ("cam_still", "Off", CV_ALLOWLUA, CV_OnOff, NULL);
consvar_t cv_cam_speed = CVAR_INIT ("cam_speed", "0.3", CV_FLOAT|CV_SAVE|CV_ALLOWLUA, CV_CamSpeed, NULL); consvar_t cv_cam_speed = CVAR_INIT ("cam_speed", "0.3", CV_FLOAT|CV_SAVE|CV_ALLOWLUA, CV_CamSpeed, NULL);
consvar_t cv_cam_rotate = CVAR_INIT ("cam_rotate", "0", CV_CALL|CV_NOINIT|CV_ALLOWLUA, CV_CamRotate, CV_CamRotate_OnChange); consvar_t cv_cam_rotate = CVAR_INIT ("cam_rotate", "0", CV_CALL|CV_NOINIT|CV_ALLOWLUA, CV_CamRotate, CV_CamRotate_OnChange);
@ -9812,8 +9813,8 @@ consvar_t cv_cam_rotspeed = CVAR_INIT ("cam_rotspeed", "10", CV_SAVE|CV_ALLOWLUA
consvar_t cv_cam_turnmultiplier = CVAR_INIT ("cam_turnmultiplier", "0.75", CV_FLOAT|CV_SAVE|CV_ALLOWLUA, multiplier_cons_t, NULL); consvar_t cv_cam_turnmultiplier = CVAR_INIT ("cam_turnmultiplier", "0.75", CV_FLOAT|CV_SAVE|CV_ALLOWLUA, multiplier_cons_t, NULL);
consvar_t cv_cam_orbit = CVAR_INIT ("cam_orbit", "Off", CV_SAVE|CV_ALLOWLUA, CV_OnOff, NULL); consvar_t cv_cam_orbit = CVAR_INIT ("cam_orbit", "Off", CV_SAVE|CV_ALLOWLUA, CV_OnOff, NULL);
consvar_t cv_cam_adjust = CVAR_INIT ("cam_adjust", "On", CV_SAVE|CV_ALLOWLUA, CV_OnOff, NULL); consvar_t cv_cam_adjust = CVAR_INIT ("cam_adjust", "On", CV_SAVE|CV_ALLOWLUA, CV_OnOff, NULL);
consvar_t cv_cam2_dist = CVAR_INIT ("cam2_curdist", "160", CV_FLOAT|CV_ALLOWLUA, NULL, NULL); consvar_t cv_cam2_dist = CVAR_INIT ("cam2_curdist", "160", CV_FLOAT|CV_ALLOWLUA, campos_cons_t, NULL);
consvar_t cv_cam2_height = CVAR_INIT ("cam2_curheight", "25", CV_FLOAT|CV_ALLOWLUA, NULL, NULL); consvar_t cv_cam2_height = CVAR_INIT ("cam2_curheight", "25", CV_FLOAT|CV_ALLOWLUA, campos_cons_t, NULL);
consvar_t cv_cam2_still = CVAR_INIT ("cam2_still", "Off", CV_ALLOWLUA, CV_OnOff, NULL); consvar_t cv_cam2_still = CVAR_INIT ("cam2_still", "Off", CV_ALLOWLUA, CV_OnOff, NULL);
consvar_t cv_cam2_speed = CVAR_INIT ("cam2_speed", "0.3", CV_FLOAT|CV_SAVE|CV_ALLOWLUA, CV_CamSpeed, NULL); consvar_t cv_cam2_speed = CVAR_INIT ("cam2_speed", "0.3", CV_FLOAT|CV_SAVE|CV_ALLOWLUA, CV_CamSpeed, NULL);
consvar_t cv_cam2_rotate = CVAR_INIT ("cam2_rotate", "0", CV_CALL|CV_NOINIT|CV_ALLOWLUA, CV_CamRotate, CV_CamRotate2_OnChange); consvar_t cv_cam2_rotate = CVAR_INIT ("cam2_rotate", "0", CV_CALL|CV_NOINIT|CV_ALLOWLUA, CV_CamRotate, CV_CamRotate2_OnChange);
@ -9825,23 +9826,23 @@ consvar_t cv_cam2_adjust = CVAR_INIT ("cam2_adjust", "On", CV_SAVE|CV_ALLOWLUA,
// [standard vs simple][p1 or p2] // [standard vs simple][p1 or p2]
consvar_t cv_cam_savedist[2][2] = { consvar_t cv_cam_savedist[2][2] = {
{ // standard { // standard
CVAR_INIT ("cam_dist", "192", CV_FLOAT|CV_SAVE|CV_CALL|CV_ALLOWLUA, NULL, CV_UpdateCamDist), CVAR_INIT ("cam_dist", "192", CV_FLOAT|CV_SAVE|CV_CALL|CV_ALLOWLUA, campos_cons_t, CV_UpdateCamDist),
CVAR_INIT ("cam2_dist", "192", CV_FLOAT|CV_SAVE|CV_CALL|CV_ALLOWLUA, NULL, CV_UpdateCam2Dist), CVAR_INIT ("cam2_dist", "192", CV_FLOAT|CV_SAVE|CV_CALL|CV_ALLOWLUA, campos_cons_t, CV_UpdateCam2Dist),
}, },
{ // simple { // simple
CVAR_INIT ("cam_simpledist", "256", CV_FLOAT|CV_SAVE|CV_CALL|CV_ALLOWLUA, NULL, CV_UpdateCamDist), CVAR_INIT ("cam_simpledist", "256", CV_FLOAT|CV_SAVE|CV_CALL|CV_ALLOWLUA, campos_cons_t, CV_UpdateCamDist),
CVAR_INIT ("cam2_simpledist", "256", CV_FLOAT|CV_SAVE|CV_CALL|CV_ALLOWLUA, NULL, CV_UpdateCam2Dist), CVAR_INIT ("cam2_simpledist", "256", CV_FLOAT|CV_SAVE|CV_CALL|CV_ALLOWLUA, campos_cons_t, CV_UpdateCam2Dist),
} }
}; };
consvar_t cv_cam_saveheight[2][2] = { consvar_t cv_cam_saveheight[2][2] = {
{ // standard { // standard
CVAR_INIT ("cam_height", "40", CV_FLOAT|CV_SAVE|CV_CALL|CV_ALLOWLUA, NULL, CV_UpdateCamDist), CVAR_INIT ("cam_height", "40", CV_FLOAT|CV_SAVE|CV_CALL|CV_ALLOWLUA, campos_cons_t, CV_UpdateCamDist),
CVAR_INIT ("cam2_height", "40", CV_FLOAT|CV_SAVE|CV_CALL|CV_ALLOWLUA, NULL, CV_UpdateCam2Dist), CVAR_INIT ("cam2_height", "40", CV_FLOAT|CV_SAVE|CV_CALL|CV_ALLOWLUA, campos_cons_t, CV_UpdateCam2Dist),
}, },
{ // simple { // simple
CVAR_INIT ("cam_simpleheight", "60", CV_FLOAT|CV_SAVE|CV_CALL|CV_ALLOWLUA, NULL, CV_UpdateCamDist), CVAR_INIT ("cam_simpleheight", "60", CV_FLOAT|CV_SAVE|CV_CALL|CV_ALLOWLUA, campos_cons_t, CV_UpdateCamDist),
CVAR_INIT ("cam2_simpleheight", "60", CV_FLOAT|CV_SAVE|CV_CALL|CV_ALLOWLUA, NULL, CV_UpdateCam2Dist), CVAR_INIT ("cam2_simpleheight", "60", CV_FLOAT|CV_SAVE|CV_CALL|CV_ALLOWLUA, campos_cons_t, CV_UpdateCam2Dist),
} }
}; };
@ -11418,10 +11419,10 @@ void P_DoTailsOverlay(player_t *player, mobj_t *tails)
} }
else else
{ {
if (tails->state != states+chosenstate) if (tails->state != &states[chosenstate])
{ {
if (states[chosenstate].sprite == SPR_PLAY) if (states[chosenstate].sprite == SPR_PLAY)
tails->sprite2 = P_GetSkinSprite2(((skin_t *)tails->skin), (states[chosenstate].frame & FF_FRAMEMASK), player); tails->sprite2 = P_GetSkinSprite2(((skin_t *)tails->skin), P_GetStateSprite2(&states[chosenstate]), player);
P_SetMobjState(tails, chosenstate); P_SetMobjState(tails, chosenstate);
} }
} }

View file

@ -35,30 +35,87 @@
INT32 numskins = 0; INT32 numskins = 0;
skin_t **skins = NULL; skin_t **skins = NULL;
// // Gets the animation ID of a state
// P_GetSkinSprite2 UINT16 P_GetStateSprite2(state_t *state)
// For non-super players, tries each sprite2's immediate predecessor until it finds one with a number of frames or ends up at standing.
// For super players, does the same as above - but tries the super equivalent for each sprite2 before the non-super version.
//
UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player)
{ {
UINT8 super = 0, i = 0; if (state->sprite2)
return state->sprite2;
else
{
// Transform the state frame into an animation ID
UINT32 stateframe = state->frame & FF_FRAMEMASK;
UINT16 spr2 = stateframe & ~FF_SPR2SUPER;
if (stateframe & FF_SPR2SUPER)
spr2 |= SPR2F_SUPER;
return spr2;
}
}
// Gets the starting frame of an animation
UINT16 P_GetSprite2StateFrame(state_t *state)
{
if (state->sprite2)
return state->frame & FF_FRAMEMASK;
else
return 0;
}
// Checks if a state should use the "super" variant of the animation
boolean P_IsStateSprite2Super(state_t *state)
{
if (state->sprite2)
{
if (state->sprite2 & SPR2F_SUPER)
return true;
}
else if (state->frame & FF_SPR2SUPER)
return true;
return false;
}
// Applies SPR2F_SUPER to an animation based on the actor's state
UINT16 P_ApplySuperFlagToSprite2(UINT16 spr2, mobj_t *mobj)
{
if (mobj->player)
{
if (mobj->player->charflags & SF_NOSUPERSPRITES || (mobj->player->powers[pw_carry] == CR_NIGHTSMODE && (mobj->player->charflags & SF_NONIGHTSSUPER)))
spr2 &= ~SPR2F_SUPER;
else if (mobj->player->powers[pw_super] || (mobj->player->powers[pw_carry] == CR_NIGHTSMODE && (mobj->player->charflags & SF_SUPER)))
spr2 |= SPR2F_SUPER;
}
if (spr2 & SPR2F_SUPER)
{
if (mobj->eflags & MFE_FORCENOSUPER)
spr2 &= ~SPR2F_SUPER;
}
else if (mobj->eflags & MFE_FORCESUPER)
spr2 |= SPR2F_SUPER;
return spr2;
}
// For non-super players, this tries each sprite2's immediate predecessor until it finds one with a number of frames or ends up at standing.
// For super players, does the same as above - but tries the super equivalent for each sprite2 before the non-super version.
UINT16 P_GetSkinSprite2(skin_t *skin, UINT16 spr2, player_t *player)
{
UINT16 super = 0;
UINT8 i = 0;
if (!skin) if (!skin)
return 0; return 0;
if ((playersprite_t)(spr2 & ~FF_SPR2SUPER) >= free_spr2) while (!P_IsValidSprite2(skin, spr2)
return 0;
while (!skin->sprites[spr2].numframes
&& spr2 != SPR2_STND && spr2 != SPR2_STND
&& ++i < 32) // recursion limiter && ++i < 32) // recursion limiter
{ {
if (spr2 & FF_SPR2SUPER) if (spr2 & SPR2F_SUPER)
{ {
super = FF_SPR2SUPER; super = SPR2F_SUPER;
spr2 &= ~FF_SPR2SUPER; spr2 &= ~SPR2F_SUPER;
continue; continue;
} }
@ -92,6 +149,51 @@ UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player)
return spr2; return spr2;
} }
// Gets the spritedef of a skin animation
spritedef_t *P_GetSkinSpritedef(skin_t *skin, UINT16 spr2)
{
if (!skin)
return NULL;
boolean is_super = spr2 & SPR2F_SUPER;
spr2 &= SPR2F_MASK;
if (spr2 >= free_spr2)
return NULL;
if (is_super)
return &skin->super.sprites[spr2];
else
return &skin->sprites[spr2];
}
// Gets the spriteinfo of a skin animation
spriteinfo_t *P_GetSkinSpriteInfo(skin_t *skin, UINT16 spr2)
{
if (!skin)
return NULL;
boolean is_super = spr2 & SPR2F_SUPER;
spr2 &= SPR2F_MASK;
if (spr2 >= free_spr2)
return NULL;
if (is_super)
return &skin->super.sprinfo[spr2];
else
return &skin->sprinfo[spr2];
}
// Checks if a skin animation is valid
boolean P_IsValidSprite2(skin_t *skin, UINT16 spr2)
{
spritedef_t *sprdef = P_GetSkinSpritedef(skin, spr2);
return sprdef && sprdef->numframes;
}
static void Sk_SetDefaultValue(skin_t *skin) static void Sk_SetDefaultValue(skin_t *skin)
{ {
INT32 i; INT32 i;
@ -500,10 +602,10 @@ static UINT16 W_CheckForPatchSkinMarkerInPwad(UINT16 wadid, UINT16 startlump)
return INT16_MAX; // not found return INT16_MAX; // not found
} }
static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, skin_t *skin, UINT8 start_spr2) static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, skin_t *skin, UINT16 start_spr2)
{ {
UINT16 newlastlump; UINT16 newlastlump;
UINT8 sprite2; UINT16 sprite2;
*lump += 1; // start after S_SKIN *lump += 1; // start after S_SKIN
*lastlump = W_CheckNumForNamePwad("S_END",wadnum,*lump); // stop at S_END *lastlump = W_CheckNumForNamePwad("S_END",wadnum,*lump); // stop at S_END
@ -523,7 +625,7 @@ static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, ski
newlastlump++; newlastlump++;
// load all sprite sets we are aware of... for super! // load all sprite sets we are aware of... for super!
for (sprite2 = start_spr2; sprite2 < free_spr2; sprite2++) for (sprite2 = start_spr2; sprite2 < free_spr2; sprite2++)
R_AddSingleSpriteDef(spr2names[sprite2], &skin->sprites[FF_SPR2SUPER|sprite2], wadnum, newlastlump, *lastlump); R_AddSingleSpriteDef(spr2names[sprite2], &skin->super.sprites[sprite2], wadnum, newlastlump, *lastlump);
newlastlump--; newlastlump--;
*lastlump = newlastlump; // okay, make the normal sprite set loading end there *lastlump = newlastlump; // okay, make the normal sprite set loading end there

View file

@ -80,9 +80,14 @@ typedef struct
// specific sounds per skin // specific sounds per skin
sfxenum_t soundsid[NUMSKINSOUNDS]; // sound # in S_sfx table sfxenum_t soundsid[NUMSKINSOUNDS]; // sound # in S_sfx table
spritedef_t sprites[NUMPLAYERSPRITES];
spriteinfo_t sprinfo[NUMPLAYERSPRITES];
// contains super versions too // contains super versions too
spritedef_t sprites[NUMPLAYERSPRITES*2]; struct {
spriteinfo_t sprinfo[NUMPLAYERSPRITES*2]; spritedef_t sprites[NUMPLAYERSPRITES];
spriteinfo_t sprinfo[NUMPLAYERSPRITES];
} super;
} skin_t; } skin_t;
/// Externs /// Externs
@ -102,7 +107,14 @@ INT32 R_GetForcedSkin(INT32 playernum);
void R_AddSkins(UINT16 wadnum, boolean mainfile); void R_AddSkins(UINT16 wadnum, boolean mainfile);
void R_PatchSkins(UINT16 wadnum, boolean mainfile); void R_PatchSkins(UINT16 wadnum, boolean mainfile);
UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player); UINT16 P_GetStateSprite2(state_t *state);
UINT16 P_GetSprite2StateFrame(state_t *state);
UINT16 P_GetSkinSprite2(skin_t *skin, UINT16 spr2, player_t *player);
UINT16 P_ApplySuperFlagToSprite2(UINT16 spr2, mobj_t *mobj);
spritedef_t *P_GetSkinSpritedef(skin_t *skin, UINT16 spr2);
spriteinfo_t *P_GetSkinSpriteInfo(skin_t *skin, UINT16 spr2);
boolean P_IsValidSprite2(skin_t *skin, UINT16 spr2);
boolean P_IsStateSprite2Super(state_t *state);
void R_RefreshSprite2(void); void R_RefreshSprite2(void);

View file

@ -1588,20 +1588,22 @@ static void R_ProjectSprite(mobj_t *thing)
// decide which patch to use for sprite relative to player // decide which patch to use for sprite relative to player
#ifdef RANGECHECK #ifdef RANGECHECK
if ((size_t)(thing->sprite) >= numsprites) if ((size_t)(thing->sprite) >= numsprites)
I_Error("R_ProjectSprite: invalid sprite number %d ", thing->sprite); I_Error("R_ProjectSprite: invalid sprite number %d", thing->sprite);
#endif #endif
frame = thing->frame&FF_FRAMEMASK; frame = thing->frame & FF_FRAMEMASK;
//Fab : 02-08-98: 'skin' override spritedef currently used for skin //Fab : 02-08-98: 'skin' override spritedef currently used for skin
if (thing->skin && thing->sprite == SPR_PLAY) if (thing->skin && thing->sprite == SPR_PLAY)
{ {
sprdef = &((skin_t *)thing->skin)->sprites[thing->sprite2]; sprdef = P_GetSkinSpritedef(thing->skin, thing->sprite2);
#ifdef ROTSPRITE #ifdef ROTSPRITE
sprinfo = &((skin_t *)thing->skin)->sprinfo[thing->sprite2]; sprinfo = P_GetSkinSpriteInfo(thing->skin, thing->sprite2);
#endif #endif
if (frame >= sprdef->numframes) {
CONS_Alert(CONS_ERROR, M_GetText("R_ProjectSprite: invalid skins[\"%s\"].sprites[%sSPR2_%s] frame %s\n"), ((skin_t *)thing->skin)->name, ((thing->sprite2 & FF_SPR2SUPER) ? "FF_SPR2SUPER|": ""), spr2names[(thing->sprite2 & ~FF_SPR2SUPER)], sizeu5(frame)); if (frame >= sprdef->numframes)
{
CONS_Alert(CONS_ERROR, M_GetText("R_ProjectSprite: invalid skins[\"%s\"].sprites[SPR2_%s] %sframe %s\n"), ((skin_t *)thing->skin)->name, spr2names[thing->sprite2 & SPR2F_MASK], (thing->sprite2 & SPR2F_SUPER) ? "super ": "", sizeu5(frame));
thing->sprite = states[S_UNKNOWN].sprite; thing->sprite = states[S_UNKNOWN].sprite;
thing->frame = states[S_UNKNOWN].frame; thing->frame = states[S_UNKNOWN].frame;
sprdef = &sprites[thing->sprite]; sprdef = &sprites[thing->sprite];

View file

@ -371,9 +371,11 @@ void ST_LoadFaceGraphics(INT32 skinnum)
spritedef_t *sprdef = &skins[skinnum]->sprites[SPR2_XTRA]; spritedef_t *sprdef = &skins[skinnum]->sprites[SPR2_XTRA];
spriteframe_t *sprframe = &sprdef->spriteframes[XTRA_LIFEPIC]; spriteframe_t *sprframe = &sprdef->spriteframes[XTRA_LIFEPIC];
faceprefix[skinnum] = W_CachePatchNum(sprframe->lumppat[0], PU_HUDGFX); faceprefix[skinnum] = W_CachePatchNum(sprframe->lumppat[0], PU_HUDGFX);
if (skins[skinnum]->sprites[(SPR2_XTRA|FF_SPR2SUPER)].numframes > XTRA_LIFEPIC)
spritedef_t *super_sprdef = P_GetSkinSpritedef(skins[skinnum], SPR2_XTRA|SPR2F_SUPER);
if (super_sprdef->numframes > XTRA_LIFEPIC)
{ {
sprdef = &skins[skinnum]->sprites[SPR2_XTRA|FF_SPR2SUPER]; sprdef = super_sprdef;
sprframe = &sprdef->spriteframes[0]; sprframe = &sprdef->spriteframes[0];
superprefix[skinnum] = W_CachePatchNum(sprframe->lumppat[0], PU_HUDGFX); superprefix[skinnum] = W_CachePatchNum(sprframe->lumppat[0], PU_HUDGFX);
} }
@ -507,7 +509,7 @@ static void ST_DrawNightsOverlayNum(fixed_t x /* right border */, fixed_t y, fix
static void ST_drawDebugInfo(void) static void ST_drawDebugInfo(void)
{ {
INT32 height = 0, h = 8, w = 18, lowh; INT32 height = 0, h = 8, w = 18, lowh;
void (*textfunc)(INT32, INT32, INT32, const char *); fixed_t textscale = FRACUNIT/2;
if (!(stplyr->mo && cv_debug)) if (!(stplyr->mo && cv_debug))
return; return;
@ -516,12 +518,12 @@ static void ST_drawDebugInfo(void)
if ((moviemode == MM_GIF && cv_gif_downscale.value) || vid.dup == 1) if ((moviemode == MM_GIF && cv_gif_downscale.value) || vid.dup == 1)
{ {
textfunc = V_DrawRightAlignedString; textscale = FRACUNIT;
lowh = ((vid.height/vid.dup) - 16); lowh = ((vid.height/vid.dup) - 16);
} }
else else
{ {
textfunc = V_DrawRightAlignedSmallString; textscale = FRACUNIT/2;
h /= 2; h /= 2;
w /= 2; w /= 2;
lowh = 0; lowh = 0;
@ -532,10 +534,10 @@ static void ST_drawDebugInfo(void)
V_DrawRightAlignedThinString(320, 8+lowh, VFLAGS|V_REDMAP, "SOME INFO NOT VISIBLE");\ V_DrawRightAlignedThinString(320, 8+lowh, VFLAGS|V_REDMAP, "SOME INFO NOT VISIBLE");\
return;\ return;\
}\ }\
textfunc(320, height, VFLAGS, str);\ V_DrawAlignedFontString(320, height, VFLAGS, textscale, textscale, str, hu_font, alignright);\
height += h; height += h;
#define V_DrawDebugFlag(f, str) textfunc(width, height, VFLAGS|f, str);\ #define V_DrawDebugFlag(f, str) V_DrawAlignedFontString(width, height, VFLAGS|f, textscale, textscale, str, hu_font, alignright);\
width -= w width -= w
if (cv_debug & DBG_MEMORY) if (cv_debug & DBG_MEMORY)
@ -1551,13 +1553,16 @@ static void ST_drawPowerupHUD(void)
{ {
shieldoffs[q] = ICONSEP; shieldoffs[q] = ICONSEP;
if ((stplyr->powers[pw_shield] & SH_NOSTACK & ~SH_FORCEHP) == SH_FORCE) if ((stplyr->powers[pw_shield] & SH_NOSTACK & ~SH_FORCEHP) == SH_FORCE
&& (stplyr->powers[pw_shield] & SH_FORCEHP) > 0) // Special handling for >1HP Force Shields
{ {
UINT8 i, max = (stplyr->powers[pw_shield] & SH_FORCEHP); UINT8 max = (stplyr->powers[pw_shield] & SH_FORCEHP);
for (i = 0; i <= max; i++)
{ V_DrawSmallScaledPatch(offs, hudinfo[HUD_POWERUPS].y, V_PERPLAYER|hudinfo[HUD_POWERUPS].f|V_HUDTRANSHALF, forceshield);
V_DrawSmallScaledPatch(offs-(i<<1), hudinfo[HUD_POWERUPS].y-(i<<1), (V_PERPLAYER|hudinfo[HUD_POWERUPS].f)|((i == max) ? V_HUDTRANS : V_HUDTRANSHALF), forceshield); V_DrawSmallScaledPatch(offs-2, hudinfo[HUD_POWERUPS].y-2, V_PERPLAYER|hudinfo[HUD_POWERUPS].f|V_HUDTRANS, forceshield);
}
if (max > 1) // if the shield has more than 2 hits, show the extra n hits as "+n"
V_DrawRightAlignedThinString(offs+16, hudinfo[HUD_POWERUPS].y, V_PERPLAYER|hudinfo[HUD_POWERUPS].f|V_HUDTRANS, va("+%d", max - 1));
} }
else else
{ {
@ -1567,6 +1572,7 @@ static void ST_drawPowerupHUD(void)
case SH_ELEMENTAL: p = watershield; break; case SH_ELEMENTAL: p = watershield; break;
case SH_ARMAGEDDON: p = bombshield; break; case SH_ARMAGEDDON: p = bombshield; break;
case SH_ATTRACT: p = ringshield; break; case SH_ATTRACT: p = ringshield; break;
case SH_FORCE: p = forceshield; break;
case SH_PITY: p = pityshield; break; case SH_PITY: p = pityshield; break;
case SH_PINK: p = pinkshield; break; case SH_PINK: p = pinkshield; break;
case SH_FLAMEAURA: p = flameshield; break; case SH_FLAMEAURA: p = flameshield; break;

View file

@ -68,3 +68,27 @@ int endswith(const char *base, const char *tag)
return !memcmp(&base[base_length - tag_length], tag, tag_length); return !memcmp(&base[base_length - tag_length], tag, tag_length);
} }
// strtok version that only skips over one delimiter at a time
char *xstrtok(char *line, const char *delims)
{
static char *saveline = NULL;
char *p;
if(line != NULL)
saveline = line;
// see if we have reached the end of the line
if(saveline == NULL || *saveline == '\0')
return NULL;
p = saveline; // save start of this token
saveline += strcspn(saveline, delims); // get the number of non-delims characters, go past delimiter
if(*saveline != '\0') // trash the delim if necessary
*saveline++ = '\0';
return p;
}

File diff suppressed because it is too large Load diff

View file

@ -17,6 +17,7 @@
#include "doomdef.h" #include "doomdef.h"
#include "doomtype.h" #include "doomtype.h"
#include "r_defs.h" #include "r_defs.h"
#include "hu_stuff.h" //font arrays
// //
// VIDEO // VIDEO
@ -191,86 +192,93 @@ void V_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c, UINT16 color, U
void V_DrawFadeConsBack(INT32 plines); void V_DrawFadeConsBack(INT32 plines);
void V_DrawPromptBack(INT32 boxheight, INT32 color); void V_DrawPromptBack(INT32 boxheight, INT32 color);
// draw a single character
void V_DrawCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed);
// draw a single character, but for the chat
void V_DrawChatCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed, UINT8 *colormap);
UINT8 *V_GetStringColormap(INT32 colorflags); UINT8 *V_GetStringColormap(INT32 colorflags);
void V_DrawLevelTitle(INT32 x, INT32 y, INT32 option, const char *string); // Generalized character drawing function, combining console & chat functionality with a specified font.
void V_DrawFontCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed, fixed_t scale, UINT8 *colormap, fontdef_t font);
#define V_DrawCharacter(x,y,c,l) V_DrawFontCharacter(x,y,c,l,FRACUNIT,NULL,hu_font)
#define V_DrawChatCharacter(x,y,c,l,cm) V_DrawFontCharacter(x,y,c,l,FRACUNIT/2,cm,hu_font)
// wordwrap a string using the hu_font // Precompile a wordwrapped string to any given width, using a specified font.
char *V_WordWrap(INT32 x, INT32 w, INT32 option, const char *string); char *V_FontWordWrap(INT32 x, INT32 w, INT32 option, fixed_t scale, const char *string, fontdef_t font);
UINT8 *V_GetStringColormap(INT32 colorflags); #define V_WordWrap(x,w,o,str) V_FontWordWrap(x, w, o, FRACUNIT, str, hu_font)
#define V_ChatWordWrap(x,w,o,str) V_FontWordWrap(x, w, o, FRACUNIT/2, str, hu_font)
enum string_align {
alignleft = 0,
aligncenter,
alignright
};
// Draw a string, using a supplied font and scale.
void V_DrawFontString(INT32 x, INT32 y, INT32 option, fixed_t pscale, fixed_t vscale, const char *string, fontdef_t font);
void V_DrawAlignedFontString(INT32 x, INT32 y, INT32 option, fixed_t pscale, fixed_t vscale, const char *string, fontdef_t font, enum string_align align);
// Draw a string, using a supplied font and scale, at fixed_t coordinates.
void V_DrawFontStringAtFixed(fixed_t x, fixed_t y, INT32 option, fixed_t pscale, fixed_t vscale, const char *string, fontdef_t font);
void V_DrawAlignedFontStringAtFixed(fixed_t x, fixed_t y, INT32 option, fixed_t pscale, fixed_t vscale, const char *string, fontdef_t font, enum string_align align);
// Defines for old string drawers.
// draw a string using the hu_font // draw a string using the hu_font
void V_DrawString(INT32 x, INT32 y, INT32 option, const char *string); #define V_DrawString(x,y,o,str) V_DrawFontString(x,y,o,FRACUNIT,FRACUNIT,str,hu_font)
void V_DrawCenteredString(INT32 x, INT32 y, INT32 option, const char *string); #define V_DrawCenteredString(x,y,o,str) V_DrawAlignedFontString(x,y,o,FRACUNIT,FRACUNIT,str,hu_font,aligncenter)
void V_DrawRightAlignedString(INT32 x, INT32 y, INT32 option, const char *string); #define V_DrawRightAlignedString(x,y,o,str) V_DrawAlignedFontString(x,y,o,FRACUNIT,FRACUNIT,str,hu_font,alignright)
// draw a string using the hu_font, 0.5x scale // draw a string using the hu_font, 0.5x scale
void V_DrawSmallString(INT32 x, INT32 y, INT32 option, const char *string); #define V_DrawSmallString(x,y,o,str) V_DrawFontString(x,y,o,FRACUNIT/2,FRACUNIT/2,str,hu_font)
void V_DrawCenteredSmallString(INT32 x, INT32 y, INT32 option, const char *string); #define V_DrawCenteredSmallString(x,y,o,str) V_DrawAlignedFontString(x,y,o,FRACUNIT/2,FRACUNIT/2,str,hu_font,aligncenter)
void V_DrawRightAlignedSmallString(INT32 x, INT32 y, INT32 option, const char *string); #define V_DrawRightAlignedSmallString(x,y,o,str) V_DrawAlignedFontString(x,y,o,FRACUNIT/2,FRACUNIT/2,str,hu_font,alignright)
// Write a string using the tny_font
// draw a string using the tny_font #define V_DrawThinString(x,y,o,str) V_DrawFontString(x,y,o,FRACUNIT,FRACUNIT,str,tny_font)
void V_DrawThinString(INT32 x, INT32 y, INT32 option, const char *string); #define V_DrawCenteredThinString(x,y,o,str) V_DrawAlignedFontString(x,y,o,FRACUNIT,FRACUNIT,str,tny_font,aligncenter)
void V_DrawCenteredThinString(INT32 x, INT32 y, INT32 option, const char *string); #define V_DrawRightAlignedThinString(x,y,o,str) V_DrawAlignedFontString(x,y,o,FRACUNIT,FRACUNIT,str,tny_font,alignright)
void V_DrawRightAlignedThinString(INT32 x, INT32 y, INT32 option, const char *string);
// draw a string using the tny_font, 0.5x scale // draw a string using the tny_font, 0.5x scale
void V_DrawSmallThinString(INT32 x, INT32 y, INT32 option, const char *string); #define V_DrawSmallThinString(x,y,o,str) V_DrawFontString(x,y,o,FRACUNIT/2,FRACUNIT/2,str,tny_font)
void V_DrawCenteredSmallThinString(INT32 x, INT32 y, INT32 option, const char *string); #define V_DrawCenteredSmallThinString(x,y,o,str) V_DrawAlignedFontString(x,y,o,FRACUNIT/2,FRACUNIT/2,str,tny_font,aligncenter)
void V_DrawRightAlignedSmallThinString(INT32 x, INT32 y, INT32 option, const char *string); #define V_DrawRightAlignedSmallThinString(x,y,o,str) V_DrawAlignedFontString(x,y,o,FRACUNIT/2,FRACUNIT/2,str,tny_font,alignright)
// draw a string using the hu_font at fixed_t coordinates // draw a string using the hu_font at fixed_t coordinates
void V_DrawStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string); #define V_DrawStringAtFixed(x,y,o,str) V_DrawFontStringAtFixed(x,y,o,FRACUNIT,FRACUNIT,str,hu_font)
void V_DrawCenteredStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string); #define V_DrawCenteredStringAtFixed(x,y,o,str) V_DrawAlignedFontStringAtFixed(x,y,o,FRACUNIT,FRACUNIT,str,hu_font,aligncenter)
void V_DrawRightAlignedStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string); #define V_DrawRightAlignedStringAtFixed(x,y,o,str) V_DrawAlignedFontStringAtFixed(x,y,o,FRACUNIT,FRACUNIT,str,hu_font,alignright)
// draw a string using the hu_font at fixed_t coordinates, 0.5x scale // draw a string using the hu_font at fixed_t coordinates, 0.5x scale
void V_DrawSmallStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string); #define V_DrawSmallStringAtFixed(x,y,o,str) V_DrawFontStringAtFixed(x,y,o,FRACUNIT/2,FRACUNIT/2,str,hu_font)
void V_DrawCenteredSmallStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string); #define V_DrawCenteredSmallStringAtFixed(x,y,o,str) V_DrawAlignedFontStringAtFixed(x,y,o,FRACUNIT/2,FRACUNIT/2,str,hu_font,aligncenter)
void V_DrawRightAlignedSmallStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string); #define V_DrawRightAlignedSmallStringAtFixed(x,y,o,str) V_DrawAlignedFontStringAtFixed(x,y,o,FRACUNIT/2,FRACUNIT/2,str,hu_font,alignright)
// draw a string using the tny_font at fixed_t coordinates // draw a string using the tny_font at fixed_t coordinates
void V_DrawThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string); #define V_DrawThinStringAtFixed(x,y,o,str) V_DrawFontStringAtFixed(x,y,o,FRACUNIT,FRACUNIT,str,tny_font)
void V_DrawCenteredThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string); #define V_DrawCenteredThinStringAtFixed(x,y,o,str) V_DrawAlignedFontStringAtFixed(x,y,o,FRACUNIT,FRACUNIT,str,tny_font,aligncenter)
void V_DrawRightAlignedThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string); #define V_DrawRightAlignedThinStringAtFixed(x,y,o,str) V_DrawAlignedFontStringAtFixed(x,y,o,FRACUNIT,FRACUNIT,str,tny_font,alignright)
// draw a string using the tny_font at fixed_t coordinates, 0.5x scale // draw a string using the tny_font at fixed_t coordinates, 0.5x scale
void V_DrawSmallThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string); #define V_DrawSmallThinStringAtFixed(x,y,o,str) V_DrawFontStringAtFixed(x,y,o,FRACUNIT/2,FRACUNIT/2,str,tny_font)
void V_DrawCenteredSmallThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string); #define V_DrawCenteredSmallThinStringAtFixed(x,y,o,str) V_DrawAlignedFontStringAtFixed(x,y,o,FRACUNIT/2,FRACUNIT/2,str,tny_font,aligncenter)
void V_DrawRightAlignedSmallThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string); #define V_DrawRightAlignedSmallThinStringAtFixed(x,y,o,str) V_DrawAlignedFontStringAtFixed(x,y,o,FRACUNIT/2,FRACUNIT/2,str,tny_font,alignright)
// draw a string using the credit font
#define V_DrawCreditString(x,y,o,str) V_DrawFontStringAtFixed(x,y,o,FRACUNIT,FRACUNIT,str,cred_font)
// draw a string using the level title font
#define V_DrawLevelTitle(x,y,o,str) V_DrawFontString(x,y,o|V_ALLOWLOWERCASE,FRACUNIT,FRACUNIT,str,lt_font)
// Draw tall nums, used for menu, HUD, intermission // Draw tall nums, used for menu, HUD, intermission
void V_DrawTallNum(INT32 x, INT32 y, INT32 flags, INT32 num); void V_DrawTallNum(INT32 x, INT32 y, INT32 flags, INT32 num);
void V_DrawPaddedTallNum(INT32 x, INT32 y, INT32 flags, INT32 num, INT32 digits); void V_DrawPaddedTallNum(INT32 x, INT32 y, INT32 flags, INT32 num, INT32 digits);
void V_DrawLevelActNum(INT32 x, INT32 y, INT32 flags, UINT8 num); void V_DrawLevelActNum(INT32 x, INT32 y, INT32 flags, UINT8 num);
// Find string width from lt_font chars
INT32 V_LevelNameWidth(const char *string);
INT32 V_LevelNameHeight(const char *string);
INT16 V_LevelActNumWidth(UINT8 num); // act number width INT16 V_LevelActNumWidth(UINT8 num); // act number width
void V_DrawCreditString(fixed_t x, fixed_t y, INT32 option, const char *string);
INT32 V_CreditStringWidth(const char *string);
// Draw a string using the nt_font // Draw a string using the nt_font
void V_DrawNameTag(INT32 x, INT32 y, INT32 option, fixed_t scale, UINT8 *basecolormap, UINT8 *outlinecolormap, const char *string); void V_DrawNameTag(INT32 x, INT32 y, INT32 option, fixed_t scale, UINT8 *basecolormap, UINT8 *outlinecolormap, const char *string);
INT32 V_CountNameTagLines(const char *string); INT32 V_CountNameTagLines(const char *string);
INT32 V_NameTagWidth(const char *string);
// Find string width from hu_font chars // Find string width or height from supplied font chars
INT32 V_StringWidth(const char *string, INT32 option); INT32 V_FontStringWidth(const char *string, INT32 option, fontdef_t font);
// Find string width from hu_font chars, 0.5x scale INT32 V_FontStringHeight(const char *string, INT32 option, fontdef_t font);
INT32 V_SmallStringWidth(const char *string, INT32 option);
// Find string width from tny_font chars // Defines for old string width functions.
INT32 V_ThinStringWidth(const char *string, INT32 option); #define V_StringWidth(str,o) V_FontStringWidth(str,o,hu_font)
// Find string width from tny_font chars, 0.5x scale #define V_SmallStringWidth(str,o) V_FontStringWidth(str,o,hu_font)/2
INT32 V_SmallThinStringWidth(const char *string, INT32 option); #define V_ThinStringWidth(str,o) V_FontStringWidth(str,o,tny_font)
#define V_SmallThinStringWidth(str,o) V_FontStringWidth(str,o,tny_font)/2
#define V_CreditStringWidth(str) V_FontStringWidth(str,0,cred_font)
#define V_NameTagWidth(str) V_FontStringWidth(str,0,ntb_font)
#define V_LevelNameWidth(str) V_FontStringWidth(str,V_ALLOWLOWERCASE,lt_font)
#define V_LevelNameHeight(str) V_FontStringHeight(str,0,lt_font)
#define V_StringHeight(str,o) V_FontStringHeight(str,o,hu_font)
void V_DoPostProcessor(INT32 view, postimg_t type, INT32 param); void V_DoPostProcessor(INT32 view, postimg_t type, INT32 param);