A lot of CON rewrites/optimizations. Converts projectile system to dynamic allocation, saving a bunch of memory (something like sizeof(projectile_t) * MAXTILES * 2). This commit also contains changes that reduce overhead for CON commands that take a lot of parameters, by way of adding a Gv_GetManyVars() to replace long strings of subsequent calls to Gv_GetVarX().

Savegame version has been bumped due to the projectile changes. There is no way this commit doesn't cause at least one bug, so DONT_BUILD. ;)

git-svn-id: https://svn.eduke32.com/eduke32@5080 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
terminx 2015-03-24 00:40:55 +00:00
parent 9cb68410a0
commit c9ce545ab8
15 changed files with 818 additions and 587 deletions

View file

@ -240,7 +240,8 @@ typedef struct {
int32_t cacherange; // formerly SpriteCache int32_t cacherange; // formerly SpriteCache
// todo: make this a pointer and allocate at runtime // todo: make this a pointer and allocate at runtime
projectile_t defproj; projectile_t *proj;
projectile_t *defproj;
} tiledata_t; } tiledata_t;

View file

@ -55,10 +55,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
// increase by 3, because atomic GRP adds 1, and Shareware adds 2 // increase by 3, because atomic GRP adds 1, and Shareware adds 2
#ifdef LUNATIC #ifdef LUNATIC
// Lunatic // Lunatic
# define BYTEVERSION_JF 297 # define BYTEVERSION_JF 300
#else #else
// Non-Lua build // Non-Lua build
# define BYTEVERSION_JF 297 # define BYTEVERSION_JF 300
#endif #endif
//#define BYTEVERSION_13 27 //#define BYTEVERSION_13 27

View file

@ -1703,7 +1703,7 @@ static void G_DrawWeapAmounts(const DukePlayer_t *p,int32_t x,int32_t y,int32_t
} }
// yofs: in hud_scale-independent, (<<16)-scaled, 0-200-normalized y coords. // yofs: in hud_scale-independent, (<<16)-scaled, 0-200-normalized y coords.
static void G_DrawDigiNum_(int32_t x, int32_t yofs, int32_t y, int32_t n, char s, int32_t cs) static inline void G_DrawDigiNum_(int32_t x, int32_t yofs, int32_t y, int32_t n, char s, int32_t cs)
{ {
if (!(cs & ROTATESPRITE_FULL16)) if (!(cs & ROTATESPRITE_FULL16))
{ {

View file

@ -2316,73 +2316,92 @@ LUNATIC_EXTERN int32_t C_SetDefName(const char *name)
return (g_defNamePtr==NULL); return (g_defNamePtr==NULL);
} }
defaultprojectile_t DefaultProjectile;
int32_t g_numProjectiles = 0;
EDUKE32_STATIC_ASSERT(sizeof(projectile_t) == sizeof(DefaultProjectile));
LUNATIC_EXTERN void C_DefineProjectile(int32_t j, int32_t what, int32_t val) LUNATIC_EXTERN void C_DefineProjectile(int32_t j, int32_t what, int32_t val)
{ {
if (g_tile[j].proj == NULL)
{
g_tile[j].proj = (projectile_t *) Xmalloc(sizeof(projectile_t));
*g_tile[j].proj = *(projectile_t *)&DefaultProjectile;
g_numProjectiles += 2;
}
projectile_t * const proj = g_tile[j].proj;
switch (what) switch (what)
{ {
case PROJ_WORKSLIKE: case PROJ_WORKSLIKE:
g_tile[j].defproj.workslike = ProjectileData[j].workslike = val; break; proj->workslike = val; break;
case PROJ_SPAWNS: case PROJ_SPAWNS:
g_tile[j].defproj.spawns = ProjectileData[j].spawns = val; break; proj->spawns = val; break;
case PROJ_SXREPEAT: case PROJ_SXREPEAT:
g_tile[j].defproj.sxrepeat = ProjectileData[j].sxrepeat = val; break; proj->sxrepeat = val; break;
case PROJ_SYREPEAT: case PROJ_SYREPEAT:
g_tile[j].defproj.syrepeat = ProjectileData[j].syrepeat = val; break; proj->syrepeat = val; break;
case PROJ_SOUND: case PROJ_SOUND:
g_tile[j].defproj.sound = ProjectileData[j].sound = val; break; proj->sound = val; break;
case PROJ_ISOUND: case PROJ_ISOUND:
g_tile[j].defproj.isound = ProjectileData[j].isound = val; break; proj->isound = val; break;
case PROJ_VEL: case PROJ_VEL:
g_tile[j].defproj.vel = ProjectileData[j].vel = val; break; proj->vel = val; break;
case PROJ_EXTRA: case PROJ_EXTRA:
g_tile[j].defproj.extra = ProjectileData[j].extra = val; break; proj->extra = val; break;
case PROJ_DECAL: case PROJ_DECAL:
g_tile[j].defproj.decal = ProjectileData[j].decal = val; break; proj->decal = val; break;
case PROJ_TRAIL: case PROJ_TRAIL:
g_tile[j].defproj.trail = ProjectileData[j].trail = val; break; proj->trail = val; break;
case PROJ_TXREPEAT: case PROJ_TXREPEAT:
g_tile[j].defproj.txrepeat = ProjectileData[j].txrepeat = val; break; proj->txrepeat = val; break;
case PROJ_TYREPEAT: case PROJ_TYREPEAT:
g_tile[j].defproj.tyrepeat = ProjectileData[j].tyrepeat = val; break; proj->tyrepeat = val; break;
case PROJ_TOFFSET: case PROJ_TOFFSET:
g_tile[j].defproj.toffset = ProjectileData[j].toffset = val; break; proj->toffset = val; break;
case PROJ_TNUM: case PROJ_TNUM:
g_tile[j].defproj.tnum = ProjectileData[j].tnum = val; break; proj->tnum = val; break;
case PROJ_DROP: case PROJ_DROP:
g_tile[j].defproj.drop = ProjectileData[j].drop = val; break; proj->drop = val; break;
case PROJ_CSTAT: case PROJ_CSTAT:
g_tile[j].defproj.cstat = ProjectileData[j].cstat = val; break; proj->cstat = val; break;
case PROJ_CLIPDIST: case PROJ_CLIPDIST:
g_tile[j].defproj.clipdist = ProjectileData[j].clipdist = val; break; proj->clipdist = val; break;
case PROJ_SHADE: case PROJ_SHADE:
g_tile[j].defproj.shade = ProjectileData[j].shade = val; break; proj->shade = val; break;
case PROJ_XREPEAT: case PROJ_XREPEAT:
g_tile[j].defproj.xrepeat = ProjectileData[j].xrepeat = val; break; proj->xrepeat = val; break;
case PROJ_YREPEAT: case PROJ_YREPEAT:
g_tile[j].defproj.yrepeat = ProjectileData[j].yrepeat = val; break; proj->yrepeat = val; break;
case PROJ_PAL: case PROJ_PAL:
g_tile[j].defproj.pal = ProjectileData[j].pal = val; break; proj->pal = val; break;
case PROJ_EXTRA_RAND: case PROJ_EXTRA_RAND:
g_tile[j].defproj.extra_rand = ProjectileData[j].extra_rand = val; break; proj->extra_rand = val; break;
case PROJ_HITRADIUS: case PROJ_HITRADIUS:
g_tile[j].defproj.hitradius = ProjectileData[j].hitradius = val; break; proj->hitradius = val; break;
case PROJ_MOVECNT: case PROJ_MOVECNT:
g_tile[j].defproj.movecnt = ProjectileData[j].movecnt = val; break; proj->movecnt = val; break;
case PROJ_OFFSET: case PROJ_OFFSET:
g_tile[j].defproj.offset = ProjectileData[j].offset = val; break; proj->offset = val; break;
case PROJ_BOUNCES: case PROJ_BOUNCES:
g_tile[j].defproj.bounces = ProjectileData[j].bounces = val; break; proj->bounces = val; break;
case PROJ_BSOUND: case PROJ_BSOUND:
g_tile[j].defproj.bsound = ProjectileData[j].bsound = val; break; proj->bsound = val; break;
case PROJ_RANGE: case PROJ_RANGE:
g_tile[j].defproj.range = ProjectileData[j].range = val; break; proj->range = val; break;
case PROJ_FLASH_COLOR: case PROJ_FLASH_COLOR:
g_tile[j].defproj.flashcolor = ProjectileData[j].flashcolor = val; break; proj->flashcolor = val; break;
case PROJ_USERDATA: case PROJ_USERDATA:
g_tile[j].defproj.userdata = ProjectileData[j].userdata = val; break; proj->userdata = val; break;
default: break; default: break;
} }
if (g_tile[j].defproj == NULL)
g_tile[j].defproj = (projectile_t *)Xmalloc(sizeof(projectile_t));
*g_tile[j].defproj = *proj;
g_tile[j].flags |= SFLAG_PROJECTILE; g_tile[j].flags |= SFLAG_PROJECTILE;
} }
@ -6258,38 +6277,22 @@ static void C_AddDefaultDefinitions(void)
void C_InitProjectiles(void) void C_InitProjectiles(void)
{ {
int32_t i; defaultprojectile_t const Projectile =
typedef struct
{ {
int32_t workslike, cstat; // 8b 1, -1, 2048, 0, 0, (int16_t) SMALLSMOKE, -1, -1, 600, (int16_t) BULLETHOLE, -1, 0, 0, 448,
int32_t hitradius, range, flashcolor; // 12b (int16_t) g_numFreezeBounces, (int16_t) PIPEBOMB_BOUNCE, 1, 100, -1, -1, -1, -1, -1, -96, 18, 18,
int16_t spawns, sound, isound, vel; // 8b 0, 1, 32, { 0, 0 }, 0,
int16_t decal, trail, tnum, drop; // 8b
int16_t offset, bounces, bsound; // 6b
int16_t toffset; // 2b
int16_t extra, extra_rand; // 4b
int8_t sxrepeat, syrepeat, txrepeat, tyrepeat; // 4b
int8_t shade, xrepeat, yrepeat, pal; // 4b
int8_t movecnt; // 1b
uint8_t clipdist; // 1b
int8_t filler[2]; // 2b
int32_t userdata; // 4b
} defaultprojectile_t;
defaultprojectile_t DefaultProjectile =
{
1, -1, 2048, 0, 0, (int16_t)SMALLSMOKE, -1, -1, 600, (int16_t)BULLETHOLE, -1, 0, 0, 448,
(int16_t)g_numFreezeBounces, (int16_t)PIPEBOMB_BOUNCE, 1, 100, -1, -1, -1, -1, -1, -96, 18, 18,
0, 1, 32, {0,0}, 0,
}; };
EDUKE32_STATIC_ASSERT(sizeof(projectile_t) == sizeof(DefaultProjectile)); DefaultProjectile = Projectile;
for (i=MAXTILES-1; i>=0; i--) for (int i=MAXTILES-1; i>=0; i--)
{ {
Bmemcpy(&ProjectileData[i], &DefaultProjectile, sizeof(projectile_t)); if (g_tile[i].proj)
Bmemcpy(&g_tile[i].defproj, &DefaultProjectile, sizeof(projectile_t)); *g_tile[i].proj = *(projectile_t *)&DefaultProjectile;
if (g_tile[i].defproj)
*g_tile[i].defproj = *(projectile_t *)&DefaultProjectile;
} }
} }

View file

@ -94,10 +94,30 @@ extern const memberlabel_t InputLabels[];
extern const memberlabel_t TsprLabels[]; extern const memberlabel_t TsprLabels[];
#endif #endif
typedef struct
{
int32_t workslike, cstat; // 8b
int32_t hitradius, range, flashcolor; // 12b
int16_t spawns, sound, isound, vel; // 8b
int16_t decal, trail, tnum, drop; // 8b
int16_t offset, bounces, bsound; // 6b
int16_t toffset; // 2b
int16_t extra, extra_rand; // 4b
int8_t sxrepeat, syrepeat, txrepeat, tyrepeat; // 4b
int8_t shade, xrepeat, yrepeat, pal; // 4b
int8_t movecnt; // 1b
uint8_t clipdist; // 1b
int8_t filler[2]; // 2b
int32_t userdata; // 4b
} defaultprojectile_t;
extern defaultprojectile_t DefaultProjectile;
int32_t C_AllocQuote(int32_t qnum); int32_t C_AllocQuote(int32_t qnum);
void C_InitQuotes(void); void C_InitQuotes(void);
void C_InitProjectiles(void); void C_InitProjectiles(void);
extern int32_t g_numProjectiles;
typedef struct { typedef struct {
int g_i, g_p, g_x; int g_i, g_p, g_x;
int32_t *g_t; int32_t *g_t;

File diff suppressed because it is too large Load diff

View file

@ -100,7 +100,7 @@ void G_GetTimeDate(int32_t *vals);
int32_t G_StartTrack(int32_t level); int32_t G_StartTrack(int32_t level);
int32_t A_Dodge(spritetype *s); int32_t A_Dodge(spritetype *s);
#ifdef LUNATIC #ifdef LUNATIC
void G_ShowView(int32_t x, int32_t y, int32_t z, int32_t a, int32_t horiz, int32_t sect, void G_ShowView(vec3_t vec, int32_t a, int32_t horiz, int32_t sect,
int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t unbiasedp); int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t unbiasedp);
void P_AddWeaponMaybeSwitchI(int32_t snum, int32_t weap); void P_AddWeaponMaybeSwitchI(int32_t snum, int32_t weap);
void VM_FallSprite(int32_t i); void VM_FallSprite(int32_t i);

View file

@ -1239,6 +1239,8 @@ badtspr:
static void __fastcall VM_AccessProjectile(int32_t iSet, int32_t lVar1, int32_t lLabelID, int32_t lVar2) static void __fastcall VM_AccessProjectile(int32_t iSet, int32_t lVar1, int32_t lLabelID, int32_t lVar2)
{ {
projectile_t * const proj = g_tile[lVar1].proj;
if (EDUKE32_PREDICT_FALSE((unsigned)lVar1 >= MAXTILES)) if (EDUKE32_PREDICT_FALSE((unsigned)lVar1 >= MAXTILES))
goto badtile; goto badtile;
@ -1248,72 +1250,72 @@ static void __fastcall VM_AccessProjectile(int32_t iSet, int32_t lVar1, int32_t
switch (lLabelID) switch (lLabelID)
{ {
case PROJ_WORKSLIKE: ProjectileData[lVar1].workslike = iSet; break; case PROJ_WORKSLIKE: proj->workslike = iSet; break;
case PROJ_SPAWNS: ProjectileData[lVar1].spawns = iSet; break; case PROJ_SPAWNS: proj->spawns = iSet; break;
case PROJ_SXREPEAT: ProjectileData[lVar1].sxrepeat = iSet; break; case PROJ_SXREPEAT: proj->sxrepeat = iSet; break;
case PROJ_SYREPEAT: ProjectileData[lVar1].syrepeat = iSet; break; case PROJ_SYREPEAT: proj->syrepeat = iSet; break;
case PROJ_SOUND: ProjectileData[lVar1].sound = iSet; break; case PROJ_SOUND: proj->sound = iSet; break;
case PROJ_ISOUND: ProjectileData[lVar1].isound = iSet; break; case PROJ_ISOUND: proj->isound = iSet; break;
case PROJ_VEL: ProjectileData[lVar1].vel = iSet; break; case PROJ_VEL: proj->vel = iSet; break;
case PROJ_EXTRA: ProjectileData[lVar1].extra = iSet; break; case PROJ_EXTRA: proj->extra = iSet; break;
case PROJ_DECAL: ProjectileData[lVar1].decal = iSet; break; case PROJ_DECAL: proj->decal = iSet; break;
case PROJ_TRAIL: ProjectileData[lVar1].trail = iSet; break; case PROJ_TRAIL: proj->trail = iSet; break;
case PROJ_TXREPEAT: ProjectileData[lVar1].txrepeat = iSet; break; case PROJ_TXREPEAT: proj->txrepeat = iSet; break;
case PROJ_TYREPEAT: ProjectileData[lVar1].tyrepeat = iSet; break; case PROJ_TYREPEAT: proj->tyrepeat = iSet; break;
case PROJ_TOFFSET: ProjectileData[lVar1].toffset = iSet; break; case PROJ_TOFFSET: proj->toffset = iSet; break;
case PROJ_TNUM: ProjectileData[lVar1].tnum = iSet; break; case PROJ_TNUM: proj->tnum = iSet; break;
case PROJ_DROP: ProjectileData[lVar1].drop = iSet; break; case PROJ_DROP: proj->drop = iSet; break;
case PROJ_CSTAT: ProjectileData[lVar1].cstat = iSet; break; case PROJ_CSTAT: proj->cstat = iSet; break;
case PROJ_CLIPDIST: ProjectileData[lVar1].clipdist = iSet; break; case PROJ_CLIPDIST: proj->clipdist = iSet; break;
case PROJ_SHADE: ProjectileData[lVar1].shade = iSet; break; case PROJ_SHADE: proj->shade = iSet; break;
case PROJ_XREPEAT: ProjectileData[lVar1].xrepeat = iSet; break; case PROJ_XREPEAT: proj->xrepeat = iSet; break;
case PROJ_YREPEAT: ProjectileData[lVar1].yrepeat = iSet; break; case PROJ_YREPEAT: proj->yrepeat = iSet; break;
case PROJ_PAL: ProjectileData[lVar1].pal = iSet; break; case PROJ_PAL: proj->pal = iSet; break;
case PROJ_EXTRA_RAND: ProjectileData[lVar1].extra_rand = iSet; break; case PROJ_EXTRA_RAND: proj->extra_rand = iSet; break;
case PROJ_HITRADIUS: ProjectileData[lVar1].hitradius = iSet; break; case PROJ_HITRADIUS: proj->hitradius = iSet; break;
case PROJ_MOVECNT: ProjectileData[lVar1].movecnt = iSet; break; case PROJ_MOVECNT: proj->movecnt = iSet; break;
case PROJ_OFFSET: ProjectileData[lVar1].offset = iSet; break; case PROJ_OFFSET: proj->offset = iSet; break;
case PROJ_BOUNCES: ProjectileData[lVar1].bounces = iSet; break; case PROJ_BOUNCES: proj->bounces = iSet; break;
case PROJ_BSOUND: ProjectileData[lVar1].bsound = iSet; break; case PROJ_BSOUND: proj->bsound = iSet; break;
case PROJ_RANGE: ProjectileData[lVar1].range = iSet; break; case PROJ_RANGE: proj->range = iSet; break;
case PROJ_FLASH_COLOR: ProjectileData[lVar1].flashcolor = iSet; break; case PROJ_FLASH_COLOR: proj->flashcolor = iSet; break;
case PROJ_USERDATA: ProjectileData[lVar1].userdata = iSet; break; case PROJ_USERDATA: proj->userdata = iSet; break;
} }
} }
else else
{ {
switch (lLabelID) switch (lLabelID)
{ {
case PROJ_WORKSLIKE: iSet = ProjectileData[lVar1].workslike; break; case PROJ_WORKSLIKE: iSet = proj->workslike; break;
case PROJ_SPAWNS: iSet = ProjectileData[lVar1].spawns; break; case PROJ_SPAWNS: iSet = proj->spawns; break;
case PROJ_SXREPEAT: iSet = ProjectileData[lVar1].sxrepeat; break; case PROJ_SXREPEAT: iSet = proj->sxrepeat; break;
case PROJ_SYREPEAT: iSet = ProjectileData[lVar1].syrepeat; break; case PROJ_SYREPEAT: iSet = proj->syrepeat; break;
case PROJ_SOUND: iSet = ProjectileData[lVar1].sound; break; case PROJ_SOUND: iSet = proj->sound; break;
case PROJ_ISOUND: iSet = ProjectileData[lVar1].isound; break; case PROJ_ISOUND: iSet = proj->isound; break;
case PROJ_VEL: iSet = ProjectileData[lVar1].vel; break; case PROJ_VEL: iSet = proj->vel; break;
case PROJ_EXTRA: iSet = ProjectileData[lVar1].extra; break; case PROJ_EXTRA: iSet = proj->extra; break;
case PROJ_DECAL: iSet = ProjectileData[lVar1].decal; break; case PROJ_DECAL: iSet = proj->decal; break;
case PROJ_TRAIL: iSet = ProjectileData[lVar1].trail; break; case PROJ_TRAIL: iSet = proj->trail; break;
case PROJ_TXREPEAT: iSet = ProjectileData[lVar1].txrepeat; break; case PROJ_TXREPEAT: iSet = proj->txrepeat; break;
case PROJ_TYREPEAT: iSet = ProjectileData[lVar1].tyrepeat; break; case PROJ_TYREPEAT: iSet = proj->tyrepeat; break;
case PROJ_TOFFSET: iSet = ProjectileData[lVar1].toffset; break; case PROJ_TOFFSET: iSet = proj->toffset; break;
case PROJ_TNUM: iSet = ProjectileData[lVar1].tnum; break; case PROJ_TNUM: iSet = proj->tnum; break;
case PROJ_DROP: iSet = ProjectileData[lVar1].drop; break; case PROJ_DROP: iSet = proj->drop; break;
case PROJ_CSTAT: iSet = ProjectileData[lVar1].cstat; break; case PROJ_CSTAT: iSet = proj->cstat; break;
case PROJ_CLIPDIST: iSet = ProjectileData[lVar1].clipdist; break; case PROJ_CLIPDIST: iSet = proj->clipdist; break;
case PROJ_SHADE: iSet = ProjectileData[lVar1].shade; break; case PROJ_SHADE: iSet = proj->shade; break;
case PROJ_XREPEAT: iSet = ProjectileData[lVar1].xrepeat; break; case PROJ_XREPEAT: iSet = proj->xrepeat; break;
case PROJ_YREPEAT: iSet = ProjectileData[lVar1].yrepeat; break; case PROJ_YREPEAT: iSet = proj->yrepeat; break;
case PROJ_PAL: iSet = ProjectileData[lVar1].pal; break; case PROJ_PAL: iSet = proj->pal; break;
case PROJ_EXTRA_RAND: iSet = ProjectileData[lVar1].extra_rand; break; case PROJ_EXTRA_RAND: iSet = proj->extra_rand; break;
case PROJ_HITRADIUS: iSet = ProjectileData[lVar1].hitradius; break; case PROJ_HITRADIUS: iSet = proj->hitradius; break;
case PROJ_MOVECNT: iSet = ProjectileData[lVar1].movecnt; break; case PROJ_MOVECNT: iSet = proj->movecnt; break;
case PROJ_OFFSET: iSet = ProjectileData[lVar1].offset; break; case PROJ_OFFSET: iSet = proj->offset; break;
case PROJ_BOUNCES: iSet = ProjectileData[lVar1].bounces; break; case PROJ_BOUNCES: iSet = proj->bounces; break;
case PROJ_BSOUND: iSet = ProjectileData[lVar1].bsound; break; case PROJ_BSOUND: iSet = proj->bsound; break;
case PROJ_RANGE: iSet = ProjectileData[lVar1].range; break; case PROJ_RANGE: iSet = proj->range; break;
case PROJ_FLASH_COLOR: iSet = ProjectileData[lVar1].flashcolor; break; case PROJ_FLASH_COLOR: iSet = proj->flashcolor; break;
case PROJ_USERDATA: iSet = ProjectileData[lVar1].userdata; break; case PROJ_USERDATA: iSet = proj->userdata; break;
default: iSet = -1; break; default: iSet = -1; break;
} }
@ -1323,7 +1325,7 @@ static void __fastcall VM_AccessProjectile(int32_t iSet, int32_t lVar1, int32_t
return; return;
badtile: badtile:
CON_ERRPRINTF("invalid tile (%d)\n", lVar1); CON_ERRPRINTF("invalid projectile (%d)\n", lVar1);
insptr += (lVar2 == MAXGAMEVARS); insptr += (lVar2 == MAXGAMEVARS);
return; return;
} }

View file

@ -752,10 +752,9 @@ badwall:
void __fastcall Gv_SetVar(int32_t const id, int32_t const lValue, int32_t const iActor, int32_t const iPlayer) void __fastcall Gv_SetVar(int32_t const id, int32_t const lValue, int32_t const iActor, int32_t const iPlayer)
{ {
if (EDUKE32_PREDICT_FALSE((unsigned)id >= (unsigned)g_gameVarCount)) goto badvarid; int const f = aGameVars[id].dwFlags & (GAMEVAR_USER_MASK|GAMEVAR_PTR_MASK);
int f; if (EDUKE32_PREDICT_FALSE((unsigned)id >= (unsigned)g_gameVarCount)) goto badvarid;
f = aGameVars[id].dwFlags & (GAMEVAR_USER_MASK|GAMEVAR_PTR_MASK);
if (!f) aGameVars[id].val.lValue=lValue; if (!f) aGameVars[id].val.lValue=lValue;
else if (f == GAMEVAR_PERPLAYER) else if (f == GAMEVAR_PERPLAYER)
@ -809,6 +808,116 @@ static const char *gvxerrs[] = {
"Gv_GetVarX(): invalid array index", "Gv_GetVarX(): invalid array index",
}; };
int32_t __fastcall Gv_GetSpecialVarX(int32_t id)
{
int rv = -1;
if (id & (MAXGAMEVARS << 2)) // array
{
int const index = Gv_GetVarX(*insptr++);
id &= (MAXGAMEVARS - 1); // ~((MAXGAMEVARS<<2)|(MAXGAMEVARS<<1));
int const siz = (aGameArrays[id].dwFlags & GAMEARRAY_VARSIZE) ?
Gv_GetVarX(aGameArrays[id].size) : aGameArrays[id].size;
if (EDUKE32_PREDICT_FALSE((unsigned) index >= (unsigned) siz))
{
CON_ERRPRINTF("%s %s[%d]\n", gvxerrs[GVX_BADINDEX], aGameArrays[id].szLabel, index);
return -1;
}
switch (aGameArrays[id].dwFlags & GAMEARRAY_TYPE_MASK)
{
case 0: rv = (aGameArrays[id].plValues)[index]; break;
case GAMEARRAY_OFINT: rv = ((int32_t *) aGameArrays[id].plValues)[index]; break;
case GAMEARRAY_OFSHORT: rv = ((int16_t *) aGameArrays[id].plValues)[index]; break;
case GAMEARRAY_OFCHAR: rv = ((uint8_t *) aGameArrays[id].plValues)[index]; break;
}
}
else if (id & (MAXGAMEVARS << 3)) // struct shortcut vars
{
int indexvar = *insptr;
int index = Gv_GetVarX(*insptr++);
switch ((id & (MAXGAMEVARS - 1)) - g_iSpriteVarID)
{
case 0: // if (id == g_iSpriteVarID)
{
int const label = *insptr++;
/*OSD_Printf("%d %d %d\n",__LINE__,index,label);*/
indexvar = (EDUKE32_PREDICT_FALSE(ActorLabels[label].flags & LABEL_HASPARM2)) ?
Gv_GetVarX(*insptr++) : 0;
if (EDUKE32_PREDICT_FALSE((unsigned) index >= MAXSPRITES))
{
id = index;
CON_ERRPRINTF("%s %d\n", gvxerrs[GVX_BADSPRITE], id);
return -1;
}
rv = VM_AccessSpriteX(index, label, indexvar);
break;
}
case 3: // else if (id == g_iPlayerVarID)
{
int const label = *insptr++;
if (indexvar == g_iThisActorID)
index = vm.g_p;
indexvar = (EDUKE32_PREDICT_FALSE(PlayerLabels[label].flags & LABEL_HASPARM2)) ?
Gv_GetVarX(*insptr++) : 0;
if (EDUKE32_PREDICT_FALSE((unsigned) index >= MAXPLAYERS))
{
id = index;
CON_ERRPRINTF("%s %d\n", gvxerrs[GVX_BADPLAYER], id);
return -1;
}
rv = VM_AccessPlayerX(index, label, indexvar);
break;
}
case 4: // else if (id == g_iActorVarID)
rv = Gv_GetVar(*insptr++, index, vm.g_p);
break;
case 1: // else if (id == g_iSectorVarID)
if (indexvar == g_iThisActorID)
index = sprite[vm.g_i].sectnum;
if (EDUKE32_PREDICT_FALSE((unsigned) index >= MAXSECTORS))
{
id = index;
insptr++;
CON_ERRPRINTF("%s %d\n", gvxerrs[GVX_BADSECTOR], id);
return -1;
}
rv = VM_AccessSectorX(index, *insptr++);
break;
case 2: // else if (id == g_iWallVarID)
if (EDUKE32_PREDICT_FALSE((unsigned) index >= MAXWALLS))
{
id = index;
insptr++;
CON_ERRPRINTF("%s %d\n", gvxerrs[GVX_BADWALL], id);
return -1;
}
rv = VM_AccessWallX(index, *insptr++);
break;
default: EDUKE32_UNREACHABLE_SECTION(return -1);
}
}
return rv;
}
int32_t __fastcall Gv_GetVarX(int32_t id) int32_t __fastcall Gv_GetVarX(int32_t id)
{ {
if (id == g_iThisActorID) if (id == g_iThisActorID)
@ -821,7 +930,7 @@ int32_t __fastcall Gv_GetVarX(int32_t id)
int rv = -1; int rv = -1;
if (EDUKE32_PREDICT_FALSE(id >= g_gameVarCount && negateResult == 0)) if (EDUKE32_PREDICT_FALSE(id >= g_gameVarCount && negateResult == 0))
goto nastyhacks; rv = Gv_GetSpecialVarX(id);
else else
{ {
id &= MAXGAMEVARS-1; id &= MAXGAMEVARS-1;
@ -847,121 +956,70 @@ int32_t __fastcall Gv_GetVarX(int32_t id)
rv = (*((uint8_t *) aGameVars[id].val.lValue)); break; rv = (*((uint8_t *) aGameVars[id].val.lValue)); break;
} }
return (rv ^ -negateResult) + negateResult;
}
nastyhacks:
if (id & (MAXGAMEVARS << 2)) // array
{
int const index = Gv_GetVarX(*insptr++);
id &= (MAXGAMEVARS - 1); // ~((MAXGAMEVARS<<2)|(MAXGAMEVARS<<1));
int const siz = (aGameArrays[id].dwFlags & GAMEARRAY_VARSIZE) ?
Gv_GetVarX(aGameArrays[id].size) : aGameArrays[id].size;
if (EDUKE32_PREDICT_FALSE((unsigned)index >= (unsigned)siz))
{
CON_ERRPRINTF("%s %s[%d]\n", gvxerrs[GVX_BADINDEX], aGameArrays[id].szLabel, index);
return -1;
}
switch (aGameArrays[id].dwFlags & GAMEARRAY_TYPE_MASK)
{
case 0: rv = (aGameArrays[id].plValues)[index]; break;
case GAMEARRAY_OFINT: rv = ((int32_t *)aGameArrays[id].plValues)[index]; break;
case GAMEARRAY_OFSHORT: rv = ((int16_t *)aGameArrays[id].plValues)[index]; break;
case GAMEARRAY_OFCHAR: rv = ((uint8_t *)aGameArrays[id].plValues)[index]; break;
}
}
else if (id & (MAXGAMEVARS << 3)) // struct shortcut vars
{
int indexvar = *insptr;
int index = Gv_GetVarX(*insptr++);
switch ((id & (MAXGAMEVARS - 1)) - g_iSpriteVarID)
{
case 0: // if (id == g_iSpriteVarID)
{
int const label = *insptr++;
/*OSD_Printf("%d %d %d\n",__LINE__,index,label);*/
indexvar = (EDUKE32_PREDICT_FALSE(ActorLabels[label].flags & LABEL_HASPARM2)) ?
Gv_GetVarX(*insptr++) : 0;
if (EDUKE32_PREDICT_FALSE((unsigned)index >= MAXSPRITES))
{
id = index;
CON_ERRPRINTF("%s %d\n", gvxerrs[GVX_BADSPRITE], id);
return -1;
}
rv = VM_AccessSpriteX(index, label, indexvar);
break;
}
case 3: // else if (id == g_iPlayerVarID)
{
int const label = *insptr++;
if (indexvar == g_iThisActorID)
index = vm.g_p;
indexvar = (EDUKE32_PREDICT_FALSE(PlayerLabels[label].flags & LABEL_HASPARM2)) ?
Gv_GetVarX(*insptr++) : 0;
if (EDUKE32_PREDICT_FALSE((unsigned)index >= MAXPLAYERS))
{
id = index;
CON_ERRPRINTF("%s %d\n", gvxerrs[GVX_BADPLAYER], id);
return -1;
}
rv = VM_AccessPlayerX(index, label, indexvar);
break;
}
case 4: // else if (id == g_iActorVarID)
rv = Gv_GetVar(*insptr++, index, vm.g_p);
break;
case 1: // else if (id == g_iSectorVarID)
if (indexvar == g_iThisActorID)
index = sprite[vm.g_i].sectnum;
if (EDUKE32_PREDICT_FALSE((unsigned)index >= MAXSECTORS))
{
id = index;
insptr++;
CON_ERRPRINTF("%s %d\n", gvxerrs[GVX_BADSECTOR], id);
return -1;
}
rv = VM_AccessSectorX(index, *insptr++);
break;
case 2: // else if (id == g_iWallVarID)
if (EDUKE32_PREDICT_FALSE((unsigned)index >= MAXWALLS))
{
id = index;
insptr++;
CON_ERRPRINTF("%s %d\n", gvxerrs[GVX_BADWALL], id);
return -1;
}
rv = VM_AccessWallX(index, *insptr++);
break;
default: EDUKE32_UNREACHABLE_SECTION(return -1);
}
} }
return (rv ^ -negateResult) + negateResult; return (rv ^ -negateResult) + negateResult;
perr: perr:
id = vm.g_p; CON_ERRPRINTF("%s %d\n", gvxerrs[GVX_BADPLAYER], vm.g_p);
CON_ERRPRINTF("%s %d\n", gvxerrs[GVX_BADPLAYER], id);
return -1; return -1;
} }
void __fastcall Gv_GetManyVars(int32_t const count, int32_t * const rv)
{
for (int j = 0; j < count; ++j)
{
int id = *insptr++;
if (id == g_iThisActorID)
{
rv[j] = vm.g_i;
continue;
}
if (id == MAXGAMEVARS)
{
rv[j] = *insptr++;
continue;
}
int const negateResult = !!(id & (MAXGAMEVARS << 1));
if (EDUKE32_PREDICT_FALSE(id >= g_gameVarCount && negateResult == 0))
{
rv[j] = Gv_GetSpecialVarX(id);
continue;
}
id &= MAXGAMEVARS - 1;
int const f = aGameVars[id].dwFlags & (GAMEVAR_USER_MASK | GAMEVAR_PTR_MASK);
int val = aGameVars[id].val.lValue;
if (f == GAMEVAR_PERPLAYER)
{
if (EDUKE32_PREDICT_FALSE((unsigned)vm.g_p >= MAXPLAYERS))
goto perr;
val = aGameVars[id].val.plValues[vm.g_p];
}
else if (f == GAMEVAR_PERACTOR)
val = aGameVars[id].val.plValues[vm.g_i];
else
switch (f)
{
case GAMEVAR_INTPTR: val = (*((int32_t *)aGameVars[id].val.lValue)); break;
case GAMEVAR_SHORTPTR: val = (*((int16_t *)aGameVars[id].val.lValue)); break;
case GAMEVAR_CHARPTR: val = (*((uint8_t *)aGameVars[id].val.lValue)); break;
}
rv[j] = (val ^ -negateResult) + negateResult;
continue;
perr:
CON_ERRPRINTF("%s %d\n", gvxerrs[GVX_BADPLAYER], vm.g_p);
}
}
void __fastcall Gv_SetVarX(int32_t const id, int32_t const lValue) void __fastcall Gv_SetVarX(int32_t const id, int32_t const lValue)
{ {
int const f = aGameVars[id].dwFlags & (GAMEVAR_USER_MASK|GAMEVAR_PTR_MASK); int const f = aGameVars[id].dwFlags & (GAMEVAR_USER_MASK|GAMEVAR_PTR_MASK);
@ -1090,7 +1148,8 @@ void Gv_ResetSystemDefaults(void)
#endif #endif
for (int i = 0; i <= MAXTILES - 1; i++) for (int i = 0; i <= MAXTILES - 1; i++)
Bmemcpy(&ProjectileData[i], &g_tile[i].defproj, sizeof(projectile_t)); if (g_tile[i].defproj)
*g_tile[i].proj = *g_tile[i].defproj;
#ifndef LUNATIC #ifndef LUNATIC
int i; int i;

View file

@ -103,6 +103,7 @@ extern int32_t g_gameArrayCount;
int32_t __fastcall Gv_GetVar(int32_t id, int32_t iActor, int32_t iPlayer); int32_t __fastcall Gv_GetVar(int32_t id, int32_t iActor, int32_t iPlayer);
void __fastcall Gv_SetVar(int32_t const id, int32_t const lValue, int32_t const iActor, int32_t const iPlayer); void __fastcall Gv_SetVar(int32_t const id, int32_t const lValue, int32_t const iActor, int32_t const iPlayer);
int32_t __fastcall Gv_GetVarX(int32_t id); int32_t __fastcall Gv_GetVarX(int32_t id);
void __fastcall Gv_GetManyVars(int32_t const count, int32_t * const rv);
void __fastcall Gv_SetVarX(int32_t const id, int32_t const lValue); void __fastcall Gv_SetVarX(int32_t const id, int32_t const lValue);
int32_t Gv_GetVarByLabel(const char *szGameLabel,int32_t const lDefault,int32_t const iActor,int32_t const iPlayer); int32_t Gv_GetVarByLabel(const char *szGameLabel,int32_t const lDefault,int32_t const iActor,int32_t const iPlayer);

View file

@ -128,7 +128,6 @@ G_EXTERN playerspawn_t g_playerSpawnPoints[MAXPLAYERS];
G_EXTERN input_t inputfifo[MOVEFIFOSIZ][MAXPLAYERS]; G_EXTERN input_t inputfifo[MOVEFIFOSIZ][MAXPLAYERS];
#pragma pack(pop) #pragma pack(pop)
G_EXTERN projectile_t ProjectileData[MAXTILES];
G_EXTERN projectile_t SpriteProjectile[MAXSPRITES]; G_EXTERN projectile_t SpriteProjectile[MAXSPRITES];
G_EXTERN sound_t g_sounds[MAXSOUNDS]; G_EXTERN sound_t g_sounds[MAXSOUNDS];
G_EXTERN uint32_t everyothertime; G_EXTERN uint32_t everyothertime;

View file

@ -1041,7 +1041,9 @@ function _showview(x, y, z, a, horiz, sect, x1, y1, x2, y2, unbiasedp)
error("invalid coordinates "..str, 2) error("invalid coordinates "..str, 2)
end end
CF.G_ShowView(x, y, z, a, horiz, sect, x1, y1, x2, y2, unbiasedp); local pos = vec3(x, y, z)
CF.G_ShowView(pos, a, horiz, sect, x1, y1, x2, y2, unbiasedp);
end end

View file

@ -368,7 +368,7 @@ extern int32_t A_InsertSprite(int32_t whatsect,int32_t s_x,int32_t s_y,int32_t s
extern void A_AddToDeleteQueue(int32_t i); extern void A_AddToDeleteQueue(int32_t i);
extern int32_t A_PlaySound(uint32_t num, int32_t i); extern int32_t A_PlaySound(uint32_t num, int32_t i);
extern void A_DeleteSprite(int32_t s); extern void A_DeleteSprite(int32_t s);
extern void G_ShowView(int32_t x, int32_t y, int32_t z, int32_t a, int32_t horiz, int32_t sect, extern void G_ShowView(vec3_t vec, int32_t a, int32_t horiz, int32_t sect,
int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t unbiasedp); int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t unbiasedp);
extern void G_GameExit(const char *msg); extern void G_GameExit(const char *msg);
#ifdef __cplusplus #ifdef __cplusplus
@ -420,7 +420,7 @@ DEFINE_VOID_CFUNC(A_AddToDeleteQueue, ONE_ARG)
DEFINE_RET_CFUNC(A_PlaySound, TWO_ARGS) DEFINE_RET_CFUNC(A_PlaySound, TWO_ARGS)
DEFINE_VOID_CFUNC(A_DeleteSprite, ONE_ARG) DEFINE_VOID_CFUNC(A_DeleteSprite, ONE_ARG)
DEFINE_VOID_CFUNC(G_ShowView, LARG(1), LARG(2), LARG(3), LARG(4), LARG(5), LARG(6), DEFINE_VOID_CFUNC(G_ShowView, LARG(1), LARG(2), LARG(3), LARG(4), LARG(5), LARG(6),
LARG(7), LARG(8), LARG(9), LARG(10), LARG(11)) LARG(7), LARG(8), LARG(9))
#define CFUNC_REG(Name) { #Name, Name##_CF } #define CFUNC_REG(Name) { #Name, Name##_CF }

View file

@ -136,6 +136,11 @@ static void A_DoWaterTracers(int32_t x1,int32_t y1,int32_t z1,int32_t x2,int32_t
} }
} }
static inline projectile_t * Proj_GetProjectile(int tile)
{
return ((unsigned)tile < MAXTILES && g_tile[tile].proj) ? g_tile[tile].proj : (projectile_t *) &DefaultProjectile;
}
static void A_HitscanProjTrail(const vec3_t *sv, const vec3_t *dv, int32_t ang, int32_t atwith) static void A_HitscanProjTrail(const vec3_t *sv, const vec3_t *dv, int32_t ang, int32_t atwith)
{ {
int32_t n, j, i; int32_t n, j, i;
@ -143,7 +148,7 @@ static void A_HitscanProjTrail(const vec3_t *sv, const vec3_t *dv, int32_t ang,
vec3_t srcvect; vec3_t srcvect;
vec3_t destvect; vec3_t destvect;
const projectile_t *const proj = &ProjectileData[atwith]; const projectile_t *const proj = Proj_GetProjectile(atwith);
Bmemcpy(&destvect, dv, sizeof(vec3_t)); Bmemcpy(&destvect, dv, sizeof(vec3_t));
@ -212,7 +217,7 @@ static int32_t A_FindTargetSprite(const spritetype *s, int32_t aang, int32_t atw
if (g_player[snum].ps->auto_aim == 2) if (g_player[snum].ps->auto_aim == 2)
{ {
if (A_CheckSpriteTileFlags(atwith,SFLAG_PROJECTILE) && (ProjectileData[atwith].workslike & PROJECTILE_RPG)) if (A_CheckSpriteTileFlags(atwith,SFLAG_PROJECTILE) && (Proj_GetProjectile(atwith)->workslike & PROJECTILE_RPG))
return -1; return -1;
switch (DYNAMICTILEMAP(atwith)) switch (DYNAMICTILEMAP(atwith))
@ -390,7 +395,8 @@ static int32_t GetAutoAimAngle(int32_t i, int32_t p, int32_t atwith,
static void Proj_MaybeSpawn(int32_t k, int32_t atwith, const hitdata_t *hit) static void Proj_MaybeSpawn(int32_t k, int32_t atwith, const hitdata_t *hit)
{ {
// atwith < 0 is for hard-coded projectiles // atwith < 0 is for hard-coded projectiles
int32_t spawntile = atwith < 0 ? -atwith : ProjectileData[atwith].spawns; projectile_t * const proj = Proj_GetProjectile(atwith);
int32_t spawntile = atwith < 0 ? -atwith : proj->spawns;
if (spawntile >= 0) if (spawntile >= 0)
{ {
@ -398,10 +404,10 @@ static void Proj_MaybeSpawn(int32_t k, int32_t atwith, const hitdata_t *hit)
if (atwith >= 0) if (atwith >= 0)
{ {
if (ProjectileData[atwith].sxrepeat > 4) if (proj->sxrepeat > 4)
sprite[wh].xrepeat = ProjectileData[atwith].sxrepeat; sprite[wh].xrepeat = proj->sxrepeat;
if (ProjectileData[atwith].syrepeat > 4) if (proj->syrepeat > 4)
sprite[wh].yrepeat = ProjectileData[atwith].syrepeat; sprite[wh].yrepeat = proj->syrepeat;
} }
A_SetHitData(wh, hit); A_SetHitData(wh, hit);
@ -424,9 +430,10 @@ static int32_t Proj_InsertShotspark(const hitdata_t *hit, int32_t i, int32_t atw
static int32_t Proj_GetExtra(int32_t atwith) static int32_t Proj_GetExtra(int32_t atwith)
{ {
int32_t extra = ProjectileData[atwith].extra; projectile_t * const proj = Proj_GetProjectile(atwith);
if (ProjectileData[atwith].extra_rand > 0) int32_t extra = proj->extra;
extra += (krand()%ProjectileData[atwith].extra_rand); if (proj->extra_rand > 0)
extra += (krand() % proj->extra_rand);
return extra; return extra;
} }
@ -566,7 +573,7 @@ static int32_t Proj_DoHitscan(int32_t i, int32_t cstatmask,
static void Proj_DoRandDecalSize(int32_t spritenum, int32_t atwith) static void Proj_DoRandDecalSize(int32_t spritenum, int32_t atwith)
{ {
const projectile_t *const proj = &ProjectileData[atwith]; const projectile_t *const proj = Proj_GetProjectile(atwith);
if (proj->workslike & PROJECTILE_RANDDECALSIZE) if (proj->workslike & PROJECTILE_RANDDECALSIZE)
{ {
@ -811,7 +818,7 @@ static void Proj_HandleKnee(hitdata_t *hit, int32_t i, int32_t p, int32_t atwith
if (proj != NULL) if (proj != NULL)
{ {
// Custom projectiles. // Custom projectiles.
SpriteProjectile[j].workslike = ProjectileData[sprite[j].picnum].workslike; SpriteProjectile[j].workslike = Proj_GetProjectile(sprite[j].picnum)->workslike;
sprite[j].extra = proj->extra; sprite[j].extra = proj->extra;
} }
@ -858,7 +865,7 @@ static void Proj_HandleKnee(hitdata_t *hit, int32_t i, int32_t p, int32_t atwith
static int32_t A_ShootCustom(const int32_t i, const int32_t atwith, int16_t sa, vec3_t * const srcvect) static int32_t A_ShootCustom(const int32_t i, const int32_t atwith, int16_t sa, vec3_t * const srcvect)
{ {
/* Custom projectiles */ /* Custom projectiles */
projectile_t *const proj = &ProjectileData[atwith]; projectile_t *const proj = Proj_GetProjectile(atwith);
int32_t j, k = -1, l; int32_t j, k = -1, l;
int32_t vel, zvel = 0; int32_t vel, zvel = 0;
hitdata_t hit; hitdata_t hit;
@ -999,10 +1006,7 @@ static int32_t A_ShootCustom(const int32_t i, const int32_t atwith, int16_t sa,
if (proj->clipdist != 255) sprite[j].clipdist = proj->clipdist; if (proj->clipdist != 255) sprite[j].clipdist = proj->clipdist;
else sprite[j].clipdist = 40; else sprite[j].clipdist = 40;
{ SpriteProjectile[j] = *Proj_GetProjectile(sprite[j].picnum);
int32_t picnum = sprite[j].picnum; // why?
Bmemcpy(&SpriteProjectile[j], &ProjectileData[picnum], sizeof(projectile_t));
}
return j; return j;

View file

@ -959,6 +959,12 @@ static void sv_quoteredefload();
static void sv_postquoteredef(); static void sv_postquoteredef();
static void sv_restsave(); static void sv_restsave();
static void sv_restload(); static void sv_restload();
static void sv_preprojectilesave();
static void sv_postprojectilesave();
static void sv_preprojectileload();
static void sv_postprojectileload();
static projectile_t *ProjectileData;
#define SVARDATALEN \ #define SVARDATALEN \
((sizeof(g_player[0].user_name)+sizeof(g_player[0].pcolor)+sizeof(g_player[0].pteam) \ ((sizeof(g_player[0].user_name)+sizeof(g_player[0].pcolor)+sizeof(g_player[0].pteam) \
@ -1062,7 +1068,6 @@ static const dataspec_t svgm_secwsp[] =
{ DS_NOCHK, &g_mirrorSector[0], sizeof(g_mirrorSector[0]), ARRAY_SIZE(g_mirrorSector) }, { DS_NOCHK, &g_mirrorSector[0], sizeof(g_mirrorSector[0]), ARRAY_SIZE(g_mirrorSector) },
// projectiles // projectiles
{ 0, &SpriteProjectile[0], sizeof(projectile_t), MAXSPRITES }, { 0, &SpriteProjectile[0], sizeof(projectile_t), MAXSPRITES },
{ 0, &ProjectileData[0], sizeof(projectile_t), MAXTILES },
{ 0, &everyothertime, sizeof(everyothertime), 1 }, { 0, &everyothertime, sizeof(everyothertime), 1 },
{ DS_END, 0, 0, 0 } { DS_END, 0, 0, 0 }
}; };
@ -1078,6 +1083,11 @@ static const dataspec_t svgm_script[] =
{ DS_SAVEFN|DS_NOCHK, (void *)&sv_prescriptsave_once, 0, 1 }, { DS_SAVEFN|DS_NOCHK, (void *)&sv_prescriptsave_once, 0, 1 },
#endif #endif
{ DS_NOCHK, &g_tile[0], sizeof(tiledata_t), MAXTILES }, { DS_NOCHK, &g_tile[0], sizeof(tiledata_t), MAXTILES },
{ DS_SAVEFN, (void *) &sv_preprojectilesave, 0, 1 },
{ DS_LOADFN, (void *) &sv_preprojectileload, 0, 1 },
{ DS_DYNAMIC|DS_CNT(g_numProjectiles), &ProjectileData, sizeof(projectile_t), (intptr_t)&g_numProjectiles },
{ DS_SAVEFN, (void *) &sv_postprojectilesave, 0, 1 },
{ DS_LOADFN, (void *) &sv_postprojectileload, 0, 1 },
#if !defined LUNATIC #if !defined LUNATIC
{ DS_LOADFN|DS_NOCHK, (void *)&sv_prescriptload_once, 0, 1 }, { DS_LOADFN|DS_NOCHK, (void *)&sv_prescriptload_once, 0, 1 },
{ DS_DYNAMIC|DS_CNT(g_scriptSize)|DS_NOCHK, &script, sizeof(script[0]), (intptr_t)&g_scriptSize }, { DS_DYNAMIC|DS_CNT(g_scriptSize)|DS_NOCHK, &script, sizeof(script[0]), (intptr_t)&g_scriptSize },
@ -1711,6 +1721,59 @@ static void sv_quoteload()
} }
} }
} }
static void sv_preprojectilesave()
{
ProjectileData = (projectile_t *) Xrealloc(ProjectileData, sizeof(projectile_t) * g_numProjectiles);
int onumprojectiles = g_numProjectiles;
g_numProjectiles = 0;
for (int i=0; i<MAXTILES; i++)
{
if (g_tile[i].proj)
{
Bmemcpy(&ProjectileData[g_numProjectiles], g_tile[i].proj, sizeof(projectile_t));
Bmemcpy(&ProjectileData[g_numProjectiles+1], g_tile[i].defproj, sizeof(projectile_t));
g_numProjectiles += 2;
}
}
Bassert(g_numProjectiles == onumprojectiles);
}
static void sv_postprojectilesave()
{
// DO_FREE_AND_NULL(ProjectileData);
}
static void sv_preprojectileload()
{
ProjectileData = (projectile_t *) Xrealloc(ProjectileData, sizeof(projectile_t) * g_numProjectiles);
}
static void sv_postprojectileload()
{
int onumprojectiles = g_numProjectiles;
g_numProjectiles = 0;
for (int i=0; i<MAXTILES; i++)
{
if (g_tile[i].proj)
{
g_tile[i].proj = (projectile_t *) Xmalloc(sizeof(projectile_t));
g_tile[i].defproj = (projectile_t *) Xmalloc(sizeof(projectile_t));
Bmemcpy(g_tile[i].proj, &ProjectileData[g_numProjectiles], sizeof(projectile_t));
Bmemcpy(g_tile[i].defproj, &ProjectileData[g_numProjectiles+1], sizeof(projectile_t));
g_numProjectiles += 2;
}
}
Bassert(g_numProjectiles == onumprojectiles);
// DO_FREE_AND_NULL(ProjectileData);
}
static void sv_prequoteredef() static void sv_prequoteredef()
{ {
// "+1" needed for dfwrite which doesn't handle the src==NULL && cnt==0 case // "+1" needed for dfwrite which doesn't handle the src==NULL && cnt==0 case