raze-gles/source/build/src/mhk.cpp
Christoph Oelckers 8114309e89 - compat.h cleanup.
* use static_assert directly. Raze is C++17, no need for that macro shit.
* removed CONSTEXPR - I seriously fail to see the use here, many of the functions marked as CONSTEXPR cannot possibly even be constant evaluated so the declaration makes no sense. Removed most of these and replaced the valid ones with the official constexpr keyword.
* got rid of EDUKE_PREDICT_FALSE - this makes zero sense in script parsing code, at best it will save a few microseconds. Clean code wins.
* replaced Blrintf with xs_CRoundToInt. Shitty name is shitty name, even if derived from POSIX.
* replaced Bstr*casecmp with str*icmp. As these get defined in the CMake project based on actual compiler checks they are preferable here.
* removed lots of other stuff that is not needed with a minimum compiler requirement of C++17.
2020-09-04 21:24:48 +02:00

444 lines
14 KiB
C++

#include "compat.h"
#include "build.h"
#include "scriptfile.h"
#include "printf.h"
usermaphack_t g_loadedMapHack; // used only for the MD4 part
int compare_usermaphacks(const void *a, const void *b)
{
return memcmp(((usermaphack_t const *) a)->md4, ((usermaphack_t const *) b)->md4, 16);
}
usermaphack_t *usermaphacks;
int32_t num_usermaphacks;
#ifdef POLYMER
static int16_t maphacklightcnt=0;
static int16_t maphacklight[PR_MAXLIGHTS];
void engineClearLightsFromMHK()
{
int32_t i;
for (i=0; i<maphacklightcnt; i++)
{
if (maphacklight[i] >= 0)
polymer_deletelight(maphacklight[i]);
maphacklight[i] = -1;
}
maphacklightcnt = 0;
}
#else
void engineClearLightsFromMHK() {}
#endif
//
// loadmaphack
//
int32_t engineLoadMHK(const char *filename)
{
enum
{
T_SPRITE = 0,
T_ANGOFF,
T_NOMODEL,
T_NOANIM,
T_PITCH,
T_ROLL,
T_MDPIVOTXOFF,
T_MDPIVOTYOFF,
T_MDPIVOTZOFF,
T_MDPOSITIONXOFF,
T_MDPOSITIONYOFF,
T_MDPOSITIONZOFF,
T_AWAY1,
T_AWAY2,
T_MHKRESET,
T_LIGHT,
};
static struct { const char *text; int32_t tokenid; } legaltokens [] =
{
{ "sprite", T_SPRITE },
{ "angleoff", T_ANGOFF },
{ "angoff", T_ANGOFF },
{ "notmd2", T_NOMODEL },
{ "notmd3", T_NOMODEL },
{ "notmd", T_NOMODEL },
{ "nomd2anim", T_NOANIM },
{ "nomd3anim", T_NOANIM },
{ "nomdanim", T_NOANIM },
{ "pitch", T_PITCH },
{ "roll", T_ROLL },
{ "mdxoff", T_MDPIVOTXOFF },
{ "mdyoff", T_MDPIVOTYOFF },
{ "mdzoff", T_MDPIVOTZOFF },
{ "mdpivxoff", T_MDPIVOTXOFF },
{ "mdpivyoff", T_MDPIVOTYOFF },
{ "mdpivzoff", T_MDPIVOTZOFF },
{ "mdpivotxoff", T_MDPIVOTXOFF },
{ "mdpivotyoff", T_MDPIVOTYOFF },
{ "mdpivotzoff", T_MDPIVOTZOFF },
{ "mdposxoff", T_MDPOSITIONXOFF },
{ "mdposyoff", T_MDPOSITIONYOFF },
{ "mdposzoff", T_MDPOSITIONZOFF },
{ "mdpositionxoff", T_MDPOSITIONXOFF },
{ "mdpositionyoff", T_MDPOSITIONYOFF },
{ "mdpositionzoff", T_MDPOSITIONZOFF },
{ "away1", T_AWAY1 },
{ "away2", T_AWAY2 },
{ "mhkreset", T_MHKRESET },
{ "light", T_LIGHT },
{ NULL, -1 }
};
scriptfile *script = NULL;
char *tok, *cmdtokptr;
int32_t i;
int32_t whichsprite = -1;
static char fn[BMAX_PATH];
#ifdef POLYMER
int32_t toomanylights = 0;
engineClearLightsFromMHK();
#endif
if (filename)
{
Bmemset(spriteext, 0, sizeof(spriteext_t) * MAXSPRITES);
Bmemset(spritesmooth, 0, sizeof(spritesmooth_t) *(MAXSPRITES+MAXUNIQHUDID));
Bstrcpy(fn, filename);
script = scriptfile_fromfile(filename);
}
else if (fn[0])
{
// re-load
// XXX: what if we changed between levels? Could a wrong maphack be loaded?
script = scriptfile_fromfile(fn);
}
if (!script)
{
fn[0] = 0;
return -1;
}
while (1)
{
tok = scriptfile_gettoken(script);
if (!tok) break;
for (i=0; legaltokens[i].text; i++) if (!stricmp(tok, legaltokens[i].text)) break;
cmdtokptr = script->ltextptr;
if (!filename && legaltokens[i].tokenid != T_LIGHT) continue;
switch (legaltokens[i].tokenid)
{
case T_SPRITE: // sprite <xx>
if (scriptfile_getnumber(script, &whichsprite)) break;
if ((unsigned) whichsprite >= (unsigned) MAXSPRITES)
{
// sprite number out of range
Printf("Sprite number out of range 0-%d on line %s:%d\n",
MAXSPRITES-1, script->filename, scriptfile_getlinum(script, cmdtokptr));
whichsprite = -1;
break;
}
break;
case T_ANGOFF: // angoff <xx>
{
int32_t ang;
if (scriptfile_getnumber(script, &ang)) break;
if (whichsprite < 0)
{
// no sprite directive preceeding
Printf("Ignoring angle offset directive because of absent/invalid sprite number on line %s:%d\n",
script->filename, scriptfile_getlinum(script, cmdtokptr));
break;
}
spriteext[whichsprite].angoff = (int16_t) ang;
}
break;
case T_NOMODEL: // notmd
if (whichsprite < 0)
{
// no sprite directive preceeding
Printf("Ignoring not-MD2/MD3 directive because of absent/invalid sprite number on line %s:%d\n",
script->filename, scriptfile_getlinum(script, cmdtokptr));
break;
}
spriteext[whichsprite].flags |= SPREXT_NOTMD;
break;
case T_NOANIM: // nomdanim
if (whichsprite < 0)
{
// no sprite directive preceeding
Printf("Ignoring no-MD2/MD3-anim directive because of absent/invalid sprite number on line %s:%d\n",
script->filename, scriptfile_getlinum(script, cmdtokptr));
break;
}
spriteext[whichsprite].flags |= SPREXT_NOMDANIM;
break;
case T_PITCH: // pitch <xx>
{
int32_t pitch;
if (scriptfile_getnumber(script, &pitch)) break;
if (whichsprite < 0)
{
// no sprite directive preceeding
Printf("Ignoring pitch directive because of absent/invalid sprite number on line %s:%d\n",
script->filename, scriptfile_getlinum(script, cmdtokptr));
break;
}
spriteext[whichsprite].pitch = (int16_t) pitch;
}
break;
case T_ROLL: // roll <xx>
{
int32_t roll;
if (scriptfile_getnumber(script, &roll)) break;
if (whichsprite < 0)
{
// no sprite directive preceeding
Printf("Ignoring roll directive because of absent/invalid sprite number on line %s:%d\n",
script->filename, scriptfile_getlinum(script, cmdtokptr));
break;
}
spriteext[whichsprite].roll = (int16_t) roll;
}
break;
case T_MDPIVOTXOFF: // mdpivxoff <xx>
{
int32_t i;
if (scriptfile_getnumber(script, &i)) break;
if (whichsprite < 0)
{
// no sprite directive preceeding
Printf("Ignoring mdxoff/mdpivxoff directive because of absent/invalid sprite number on line %s:%d\n",
script->filename, scriptfile_getlinum(script, cmdtokptr));
break;
}
spriteext[whichsprite].pivot_offset.x = i;
}
break;
case T_MDPIVOTYOFF: // mdpivyoff <xx>
{
int32_t i;
if (scriptfile_getnumber(script, &i)) break;
if (whichsprite < 0)
{
// no sprite directive preceeding
Printf("Ignoring mdyoff/mdpivyoff directive because of absent/invalid sprite number on line %s:%d\n",
script->filename, scriptfile_getlinum(script, cmdtokptr));
break;
}
spriteext[whichsprite].pivot_offset.y = i;
}
break;
case T_MDPIVOTZOFF: // mdpivzoff <xx>
{
int32_t i;
if (scriptfile_getnumber(script, &i)) break;
if (whichsprite < 0)
{
// no sprite directive preceeding
Printf("Ignoring mdzoff/mdpivzoff directive because of absent/invalid sprite number on line %s:%d\n",
script->filename, scriptfile_getlinum(script, cmdtokptr));
break;
}
spriteext[whichsprite].pivot_offset.z = i;
}
break;
case T_MDPOSITIONXOFF: // mdposxoff <xx>
{
int32_t i;
if (scriptfile_getnumber(script, &i)) break;
if (whichsprite < 0)
{
// no sprite directive preceeding
Printf("Ignoring mdposxoff directive because of absent/invalid sprite number on line %s:%d\n",
script->filename, scriptfile_getlinum(script, cmdtokptr));
break;
}
spriteext[whichsprite].position_offset.x = i;
}
break;
case T_MDPOSITIONYOFF: // mdposyoff <xx>
{
int32_t i;
if (scriptfile_getnumber(script, &i)) break;
if (whichsprite < 0)
{
// no sprite directive preceeding
Printf("Ignoring mdposyoff directive because of absent/invalid sprite number on line %s:%d\n",
script->filename, scriptfile_getlinum(script, cmdtokptr));
break;
}
spriteext[whichsprite].position_offset.y = i;
}
break;
case T_MDPOSITIONZOFF: // mdposzoff <xx>
{
int32_t i;
if (scriptfile_getnumber(script, &i)) break;
if (whichsprite < 0)
{
// no sprite directive preceeding
Printf("Ignoring mdposzoff directive because of absent/invalid sprite number on line %s:%d\n",
script->filename, scriptfile_getlinum(script, cmdtokptr));
break;
}
spriteext[whichsprite].position_offset.z = i;
}
break;
case T_AWAY1: // away1
if (whichsprite < 0)
{
// no sprite directive preceeding
Printf("Ignoring moving away directive because of absent/invalid sprite number on line %s:%d\n",
script->filename, scriptfile_getlinum(script, cmdtokptr));
break;
}
spriteext[whichsprite].flags |= SPREXT_AWAY1;
break;
case T_AWAY2: // away2
if (whichsprite < 0)
{
// no sprite directive preceeding
Printf("Ignoring moving away directive because of absent/invalid sprite number on line %s:%d\n",
script->filename, scriptfile_getlinum(script, cmdtokptr));
break;
}
spriteext[whichsprite].flags |= SPREXT_AWAY2;
break;
case T_MHKRESET: // mhkreset
{
if (whichsprite < 0)
{
// no sprite directive preceeding
Printf("Ignoring mhkreset directive because of absent/invalid sprite number on line %s:%d\n",
script->filename, scriptfile_getlinum(script, cmdtokptr));
break;
}
auto pSpriteExt = &spriteext[whichsprite];
pSpriteExt->angoff = 0;
pSpriteExt->flags &= ~(SPREXT_NOTMD|SPREXT_NOMDANIM|SPREXT_AWAY1|SPREXT_AWAY2);
pSpriteExt->pitch = 0;
pSpriteExt->roll = 0;
pSpriteExt->pivot_offset = {};
pSpriteExt->position_offset = {};
break;
}
#ifdef POLYMER
case T_LIGHT: // light sector x y z range r g b radius faderadius angle horiz minshade maxshade priority tilenum
{
int32_t value;
int16_t lightid;
#pragma pack(push,1)
_prlight light;
#pragma pack(pop)
if (toomanylights)
break; // ignore further light defs
scriptfile_getnumber(script, &value);
light.sector = value;
scriptfile_getnumber(script, &value);
light.x = value;
scriptfile_getnumber(script, &value);
light.y = value;
scriptfile_getnumber(script, &value);
light.z = value;
scriptfile_getnumber(script, &value);
light.range = value;
scriptfile_getnumber(script, &value);
light.color[0] = value;
scriptfile_getnumber(script, &value);
light.color[1] = value;
scriptfile_getnumber(script, &value);
light.color[2] = value;
scriptfile_getnumber(script, &value);
light.radius = value;
scriptfile_getnumber(script, &value);
light.faderadius = value;
scriptfile_getnumber(script, &value);
light.angle = value;
scriptfile_getnumber(script, &value);
light.horiz = value;
scriptfile_getnumber(script, &value);
light.minshade = value;
scriptfile_getnumber(script, &value);
light.maxshade = value;
scriptfile_getnumber(script, &value);
light.priority = value;
scriptfile_getsymbol(script, &value);
light.tilenum = value;
light.publicflags.emitshadow = 1;
light.publicflags.negative = 0;
if (videoGetRenderMode() == REND_POLYMER)
{
if (maphacklightcnt == PR_MAXLIGHTS)
{
Printf("warning: max light count %d exceeded, "
"ignoring further light defs\n", PR_MAXLIGHTS);
toomanylights = 1;
break;
}
lightid = polymer_addlight(&light);
if (lightid>=0)
maphacklight[maphacklightcnt++] = lightid;
}
break;
}
#endif // POLYMER
default:
// unrecognised token
break;
}
}
scriptfile_close(script);
return 0;
}
// taken out of the game modules - this code was repeated in all of them.
static int G_TryMapHack(const char* mhkfile)
{
int const failure = engineLoadMHK(mhkfile);
if (!failure)
Printf("Loaded map hack file \"%s\"\n", mhkfile);
return failure;
}
void G_LoadMapHack(const char* filename)
{
FString hack = StripExtension(filename) + ".mhk";
if (G_TryMapHack(hack) && usermaphacks != NULL)
{
auto pMapInfo = (usermaphack_t*)bsearch(&g_loadedMapHack, usermaphacks, num_usermaphacks,
sizeof(usermaphack_t), compare_usermaphacks);
if (pMapInfo)
G_TryMapHack(pMapInfo->mhkfile);
}
}