LunaCON: proper handling of dynamic remappings with weapon defaults.

That is, the gamevars named WEAPONx_* in CON will now have the remapped value
if they were not overridden from CON ('gamevar' at file scope).
For C-CON, everything except signaling an override from the CON parser is in
place.

git-svn-id: https://svn.eduke32.com/eduke32@3848 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
helixhorned 2013-06-02 14:07:56 +00:00
parent 882eb4cb8b
commit 185597d3b3
8 changed files with 88 additions and 19 deletions

View file

@ -10671,6 +10671,9 @@ static void G_Startup(void)
G_InitDynamicTiles();
G_InitDynamicSounds();
// These depend on having the dynamic tile and/or sound mappings set up:
Gv_FinalizeWeaponDefaults();
G_PostCreateGameState();
if (g_netServer || ud.multimode > 1) G_CheckGametype();
@ -10920,11 +10923,11 @@ static int32_t check_filename_casing(void)
const char *g_sizes_of_what[] = {
"sectortype", "walltype", "spritetype", "spriteext_t",
"actor_t", "DukePlayer_t", "playerdata_t",
"user_defs", "tiledata_t" };
"user_defs", "tiledata_t", "weapondata_t" };
int32_t g_sizes_of[] = {
sizeof(sectortype), sizeof(walltype), sizeof(spritetype), sizeof(spriteext_t),
sizeof(actor_t), sizeof(DukePlayer_t), sizeof(playerdata_t),
sizeof(user_defs), sizeof(tiledata_t) };
sizeof(user_defs), sizeof(tiledata_t), sizeof(weapondata_t) };
DukePlayer_t *g_player_ps[MAXPLAYERS];
#endif

View file

@ -1067,6 +1067,12 @@ void Gv_ResetSystemDefaults(void)
//AddLog("EOF:ResetWeaponDefaults");
}
// Will set members that were overridden at CON translation time to 1.
// For example, if
// gamevar WEAPON1_SHOOTS 2200 GAMEVAR_PERPLAYER
// was specified at file scope, g_weaponOverridden[1].Shoots will be 1.
weapondata_t g_weaponOverridden[MAX_WEAPONS];
static weapondata_t weapondefaults[MAX_WEAPONS] = {
/*
WorksLike, Clip, Reload, FireDelay, TotalTime, HoldDelay,
@ -1199,6 +1205,9 @@ static int32_t G_StaticToDynamicSound(int32_t sound)
}
}
// Initialize WEAPONx_* gamevars. Since for Lunatic, they reside on the C side,
// they're set directly. In C-CON, a new CON variable is defined together with
// its initial value.
#ifdef LUNATIC
# define ADDWEAPONVAR(Weapidx, Membname) do { \
int32_t j; \
@ -1213,6 +1222,54 @@ static int32_t G_StaticToDynamicSound(int32_t sound)
} while (0)
#endif
// After CON translation, get not-overridden members from weapondefaults[] back
// into the live arrays! (That is, g_playerWeapon[][] for Lunatic, WEAPONx_*
// gamevars on the CON side in C-CON.)
#ifdef LUNATIC
# define POSTADDWEAPONVAR(Weapidx, Membname) ADDWEAPONVAR(Weapidx, Membname)
#else
// NYI
# define POSTADDWEAPONVAR(Weapidx, Membname) do {} while (0)
#endif
// Finish a default weapon member after CON translation. If it was not
// overridden from CON itself (see example at g_weaponOverridden[]), we set
// both the weapondefaults[] entry (probably dead by now) and the live value.
#define FINISH_WEAPON_DEFAULT_X(What, i, Membname) do { \
if (!g_weaponOverridden[i].Membname) \
{ \
weapondefaults[i].Membname = G_StaticToDynamic##What(weapondefaults[i].Membname); \
POSTADDWEAPONVAR(i, Membname); \
} \
} while (0)
#define FINISH_WEAPON_DEFAULT_TILE(i, Membname) FINISH_WEAPON_DEFAULT_X(Tile, i, Membname)
#define FINISH_WEAPON_DEFAULT_SOUND(i, Membname) FINISH_WEAPON_DEFAULT_X(Sound, i, Membname)
// Process the dynamic {tile,sound} mappings after CON has been translated.
// We cannot do this before, because the dynamic maps are not yet set up then.
void Gv_FinalizeWeaponDefaults(void)
{
int32_t i;
for (i=0; i<MAX_WEAPONS; i++)
{
FINISH_WEAPON_DEFAULT_TILE(i, Shoots);
FINISH_WEAPON_DEFAULT_TILE(i, Spawn);
FINISH_WEAPON_DEFAULT_SOUND(i, InitialSound);
FINISH_WEAPON_DEFAULT_SOUND(i, FireSound);
FINISH_WEAPON_DEFAULT_SOUND(i, ReloadSound1);
FINISH_WEAPON_DEFAULT_SOUND(i, Sound2Sound);
FINISH_WEAPON_DEFAULT_SOUND(i, ReloadSound2);
FINISH_WEAPON_DEFAULT_SOUND(i, SelectSound);
}
}
#undef FINISH_WEAPON_DEFAULT_SOUND
#undef FINISH_WEAPON_DEFAULT_TILE
#undef FINISH_WEAPON_DEFAULT_X
#undef POSTADDWEAPONVAR
static void Gv_AddSystemVars(void)
{
// only call ONCE
@ -1235,20 +1292,8 @@ static void Gv_AddSystemVars(void)
weapondefaults[GROW_WEAPON].FireSound = 0;
}
//AddLog("Gv_AddSystemVars");
for (i=0; i<MAX_WEAPONS; i++)
{
weapondefaults[i].Shoots = G_StaticToDynamicTile(weapondefaults[i].Shoots);
weapondefaults[i].Spawn = G_StaticToDynamicTile(weapondefaults[i].Spawn);
weapondefaults[i].InitialSound = G_StaticToDynamicSound(weapondefaults[i].InitialSound);
weapondefaults[i].FireSound = G_StaticToDynamicSound(weapondefaults[i].FireSound);
weapondefaults[i].ReloadSound1 = G_StaticToDynamicSound(weapondefaults[i].ReloadSound1);
weapondefaults[i].Sound2Sound = G_StaticToDynamicSound(weapondefaults[i].Sound2Sound);
weapondefaults[i].ReloadSound2 = G_StaticToDynamicSound(weapondefaults[i].ReloadSound2);
weapondefaults[i].SelectSound = G_StaticToDynamicSound(weapondefaults[i].SelectSound);
ADDWEAPONVAR(i, WorksLike);
ADDWEAPONVAR(i, Clip);
ADDWEAPONVAR(i, Reload);
@ -1403,6 +1448,8 @@ static void Gv_AddSystemVars(void)
#endif
}
#undef ADDWEAPONVAR
void Gv_Init(void)
{
// only call ONCE

View file

@ -118,6 +118,7 @@ LUNATIC_CB void (*A_ResetVars)(int32_t iActor);
void Gv_ResetSystemDefaults(void);
void Gv_Init(void);
void Gv_FinalizeWeaponDefaults(void);
#if !defined LUNATIC
#define GV_VAROP(func, operator) static inline void __fastcall func(register int32_t id, register int32_t lValue) \

View file

@ -589,6 +589,7 @@ user_defs ud;
playerdata_t g_player[MAXPLAYERS];
DukePlayer_t *g_player_ps[MAXPLAYERS];
weapondata_t g_playerWeapon[MAXPLAYERS][MAX_WEAPONS];
weapondata_t g_weaponOverridden[MAX_WEAPONS];
tiledata_t g_tile[MAXTILES];
projectile_t ProjectileData[MAXTILES];
projectile_t SpriteProjectile[MAXSPRITES];
@ -705,7 +706,7 @@ string.dump = nil
-- sanity-check struct type sizes
local good = true
for i=0,8 do
for i=0,9 do
local what = ffi.string(ffiC.g_sizes_of_what[i])
local fsz = ffi.sizeof(what)
local csz = ffiC.g_sizes_of[i]
@ -1058,12 +1059,16 @@ local weapondata_mt = {
end,
__newindex = function(wd, member, val)
-- Set to 'true' if we set a tile or sound member.
local didit = false
if (string.match(member, "sound")) then
if (val < 0) then
val = 0 -- Set to 0 if oob (e.g. CrackDown).
else
check_sound_idx(val)
end
didit = true
elseif (member=="workslike") then
check_weapon_idx(val)
elseif (member=="spawn" or member=="shoots") then
@ -1075,9 +1080,22 @@ local weapondata_mt = {
else
check_tile_idx(val)
end
didit = true
end
ffi.cast(weapondata_ptr_ct, wd)[0][member] = val
if (didit and ffiC.g_elCallDepth==0) then
-- Signal that we overrode this member at CON translation time.
-- Get weapon index as pointer difference first. PLAYER_0.
local wi = ffi.cast(weapondata_ptr_ct, wd)-ffi.cast(weapondata_ptr_ct, ffiC.g_playerWeapon[0][0])
assert(not (wi >= ffiC.MAX_WEAPONS+0ULL))
-- Set g_weaponOverridden[wi][member], but without invoking
-- weapondata_t's __newindex metamethod (i.e. us)!
ffi.cast(weapondata_ptr_ct, ffiC.g_weaponOverridden[wi])[member] = 1
end
end,
}
ffi.metatype("weapondata_t", weapondata_mt)

View file

@ -16,7 +16,7 @@ local bit = require("bit")
-- 2: disable JIT compilation
-- 4: load LuaJIT's 'v' module, printing trace info
-- 8: load LuaJIT's 'dump' module, printing generated IR/machine code
ffi.cdef "enum { _DEBUG_LUNATIC=2 }"
ffi.cdef "enum { _DEBUG_LUNATIC=1 }"
if (bit.band(ffiC._DEBUG_LUNATIC, 2)~=0) then
require("jit").off()

View file

@ -124,6 +124,7 @@ C_DefineSkillName;
C_DefineLevelName;
C_DefineProjectile;
C_DefineGameFuncName;
C_DefineGameType;
C_SetDefName;
SCRIPT_GetNumber;
@ -135,6 +136,7 @@ ud;
g_player;
g_player_ps;
g_playerWeapon;
g_weaponOverridden;
g_tile;
ProjectileData;
SpriteProjectile;

View file

@ -1222,7 +1222,7 @@ function Cmd.gamevar(identifier, initval, flags)
-- Emit code to set the variable at Lua parse time.
if (bit.band(oflags, GVFLAG.PERPLAYER) ~= 0) then
-- Replace player index by 0.
-- Replace player index by 0. PLAYER_0.
-- TODO_MP: init for all players.
local pvar, numrepls = ogv.name:gsub("_pli", "0")
assert(numrepls>=1)

View file

@ -518,8 +518,6 @@ static void Gv_AddSystemVars(void)
// only call ONCE
int32_t hlcnt_id, hlscnt_id;
//AddLog("Gv_AddSystemVars");
// special vars for struct access
// MUST be at top and in this order!!!
Gv_NewVar("sprite", -1, GAMEVAR_READONLY | GAMEVAR_SYSTEM | GAMEVAR_SPECIAL);