Read-only mapthing_t

Map things are writeable in Lua, which I am pretty certain is a mistake because mapthings are not sent over the network at all. I considered making them net-synced (it would be relatively easy), but it also aligns with another, more "philosophical" issue: Doom generally copies over properties from mapthing_t into mobj_t, and then only refers to it again when needing to respawn an object -- mapthing_t is not really intended to be referred to very often at runtime. At best it's slightly annoying since some objects rely on a spawnpoint for behavior changes, at worst it may make ACS more confusing in the future since Thing and Mobj tags are mixed together or less useful since they wouldn't be able to modify behaviors of objects that are based on args.

So I decided to solve these two issues at the same time; just treat mapthing_t as something to copy values from, like OG Doom does it. This basically just means that special and args are also part of the mobj now instead of the mapthing, which should fill any desire to edit this stuff from Lua, and reduces the number of instances where objects need to check for their spawnpoint to function properly.
This commit is contained in:
Sally Coolatta 2023-05-25 14:40:55 -04:00
parent a8e122c36b
commit 9d80323a3a
22 changed files with 397 additions and 330 deletions

View file

@ -271,7 +271,7 @@ bool Environment::checkTag(ACSVM::Word type, ACSVM::Word tag)
case ACS_TAGTYPE_CAMERA:
{
const mobj_t *camera = P_FindObjectTypeFromTag(MT_ALTVIEWMAN, tag);
if (camera == nullptr || camera->spawnpoint == nullptr)
if (camera == nullptr)
{
return true;
}

View file

@ -6480,11 +6480,6 @@ struct int_const_s const INT_CONST[] = {
{"PA_DRIFT",PA_DRIFT},
{"PA_HURT",PA_HURT},
// Got Flags, for player->gotflag!
// Used to be MF_ for some stupid reason, now they're GF_ to stop them looking like mobjflags
{"GF_REDFLAG",GF_REDFLAG},
{"GF_BLUEFLAG",GF_BLUEFLAG},
// Customisable sounds for Skins, from sounds.h
{"SKSSPIN",SKSSPIN},
{"SKSPUTPUT",SKSPUTPUT},

View file

@ -261,7 +261,7 @@ struct mapthing_t
UINT16 options;
INT16 z;
UINT8 extrainfo;
taglist_t tags;
mtag_t tid;
fixed_t scale;
INT16 special;
INT32 args[NUMMAPTHINGARGS];

View file

@ -320,10 +320,6 @@ extern UINT8 skipstats;
// Fun extra stuff
extern INT16 lastmap; // Last level you were at (returning from special stages).
extern mobj_t *redflag, *blueflag; // Pointers to physical flags
extern mapthing_t *rflagpoint, *bflagpoint; // Pointers to the flag spawn locations
#define GF_REDFLAG 1
#define GF_BLUEFLAG 2
// A single point in space.
struct mappoint_t

View file

@ -186,13 +186,6 @@ textprompt_t *textprompts[MAX_PROMPTS];
INT16 nextmapoverride;
UINT8 skipstats;
// Pointers to each CTF flag
mobj_t *redflag;
mobj_t *blueflag;
// Pointers to CTF spawn location
mapthing_t *rflagpoint;
mapthing_t *bflagpoint;
quake_t *g_quakes = NULL;
// Map Header Information

View file

@ -101,7 +101,11 @@ enum mobj_e {
mobj_sprzoff,
mobj_hitlag,
mobj_waterskip,
mobj_dispoffset
mobj_dispoffset,
mobj_tid,
mobj_special,
mobj_args,
mobj_stringargs
};
static const char *const mobj_opt[] = {
@ -184,6 +188,10 @@ static const char *const mobj_opt[] = {
"hitlag",
"waterskip",
"dispoffset",
"tid",
"special",
"args",
"stringargs",
NULL};
#define UNIMPLEMENTED luaL_error(L, LUA_QL("mobj_t") " field " LUA_QS " is not implemented for Lua and cannot be accessed.", mobj_opt[field])
@ -468,6 +476,18 @@ static int mobj_get(lua_State *L)
case mobj_dispoffset:
lua_pushinteger(L, mo->dispoffset);
break;
case mobj_tid:
lua_pushinteger(L, mo->tid);
break;
case mobj_special:
lua_pushinteger(L, mo->special);
break;
case mobj_args:
LUA_PushUserdata(L, mo->args, META_THINGARGS);
break;
case mobj_stringargs:
LUA_PushUserdata(L, mo->stringargs, META_THINGSTRINGARGS);
break;
default: // extra custom variables in Lua memory
lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS);
I_Assert(lua_istable(L, -1));
@ -846,6 +866,16 @@ static int mobj_set(lua_State *L)
case mobj_dispoffset:
mo->dispoffset = luaL_checkinteger(L, 3);
break;
case mobj_tid:
P_SetThingTID(mo, luaL_checkinteger(L, 3));
break;
case mobj_special:
mo->special = luaL_checkinteger(L, 3);
break;
case mobj_args:
return NOSET;
case mobj_stringargs:
return NOSET;
default:
lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS);
I_Assert(lua_istable(L, -1));
@ -949,13 +979,8 @@ static int mapthing_get(lua_State *L)
number = mt->z;
else if(fastcmp(field,"extrainfo"))
number = mt->extrainfo;
else if(fastcmp(field,"tag"))
number = Tag_FGet(&mt->tags);
else if(fastcmp(field,"taglist"))
{
LUA_PushUserdata(L, &mt->tags, META_TAGLIST);
return 1;
}
else if(fastcmp(field,"tid"))
number = mt->tid;
else if(fastcmp(field,"special"))
number = mt->special;
else if(fastcmp(field,"args"))
@ -980,62 +1005,6 @@ static int mapthing_get(lua_State *L)
return 1;
}
static int mapthing_set(lua_State *L)
{
mapthing_t *mt = *((mapthing_t **)luaL_checkudata(L, 1, META_MAPTHING));
const char *field = luaL_checkstring(L, 2);
if (!mt)
return luaL_error(L, "accessed mapthing_t doesn't exist anymore.");
if (hud_running)
return luaL_error(L, "Do not alter mapthing_t in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter mapthing_t in CMD building code!");
if(fastcmp(field,"x"))
mt->x = (INT16)luaL_checkinteger(L, 3);
else if(fastcmp(field,"y"))
mt->y = (INT16)luaL_checkinteger(L, 3);
else if(fastcmp(field,"angle"))
mt->angle = (INT16)luaL_checkinteger(L, 3);
else if(fastcmp(field,"pitch"))
mt->pitch = (INT16)luaL_checkinteger(L, 3);
else if(fastcmp(field,"roll"))
mt->roll = (INT16)luaL_checkinteger(L, 3);
else if(fastcmp(field,"type"))
mt->type = (UINT16)luaL_checkinteger(L, 3);
else if(fastcmp(field,"options"))
mt->options = (UINT16)luaL_checkinteger(L, 3);
else if(fastcmp(field,"scale"))
mt->scale = luaL_checkfixed(L, 3);
else if(fastcmp(field,"z"))
mt->z = (INT16)luaL_checkinteger(L, 3);
else if(fastcmp(field,"extrainfo"))
{
INT32 extrainfo = luaL_checkinteger(L, 3);
if (extrainfo & ~15)
return luaL_error(L, "mapthing_t extrainfo set %d out of range (%d - %d)", extrainfo, 0, 15);
mt->extrainfo = (UINT8)extrainfo;
}
else if (fastcmp(field,"tag"))
Tag_FSet(&mt->tags, (INT16)luaL_checkinteger(L, 3));
else if (fastcmp(field,"taglist"))
return LUA_ErrSetDirectly(L, "mapthing_t", "taglist");
else if (fastcmp(field,"special"))
{
// Can't change mapthing args (yet?), so let's not allow changing special either.
//mt->special = (INT16)luaL_checkinteger(L, 3);
return LUA_ErrSetDirectly(L, "mapthing_t", "special");
}
else if(fastcmp(field,"mobj"))
mt->mobj = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
else
return luaL_error(L, LUA_QL("mapthing_t") " has no field named " LUA_QS, field);
return 0;
}
static int mapthing_num(lua_State *L)
{
mapthing_t *mt = *((mapthing_t **)luaL_checkudata(L, 1, META_MAPTHING));
@ -1065,6 +1034,7 @@ static int lib_iterateMapthings(lua_State *L)
static int lib_getMapthing(lua_State *L)
{
const char *field;
INLEVEL
if (lua_isnumber(L, 2))
{
@ -1074,6 +1044,13 @@ static int lib_getMapthing(lua_State *L)
LUA_PushUserdata(L, &mapthings[i], META_MAPTHING);
return 1;
}
field = luaL_checkstring(L, 2);
if (fastcmp(field,"iterate"))
{
lua_pushcfunction(L, lib_iterateMapthings);
return 1;
}
return 0;
}
@ -1113,20 +1090,19 @@ int LUA_MobjLib(lua_State *L)
lua_pushcfunction(L, mapthing_get);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, mapthing_set);
lua_setfield(L, -2, "__newindex");
lua_pushcfunction(L, mapthing_num);
lua_setfield(L, -2, "__len");
lua_pop(L,1);
LUA_PushTaggableObjectArray(L, "mapthings",
lib_iterateMapthings,
lib_getMapthing,
lib_nummapthings,
tags_mapthings,
&nummapthings, &mapthings,
sizeof (mapthing_t), META_MAPTHING);
lua_newuserdata(L, 0);
lua_createtable(L, 0, 2);
lua_pushcfunction(L, lib_getMapthing);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, lib_nummapthings);
lua_setfield(L, -2, "__len");
lua_setmetatable(L, -2);
lua_setglobal(L, "mapthings");
return 0;
}

View file

@ -902,7 +902,6 @@ void LUA_InvalidateMapthings(void)
for (i = 0; i < nummapthings; i++)
{
LUA_InvalidateUserdata(&mapthings[i]);
LUA_InvalidateUserdata(&mapthings[i].tags);
LUA_InvalidateUserdata(mapthings[i].args);
LUA_InvalidateUserdata(mapthings[i].stringargs);
}

View file

@ -178,10 +178,8 @@ Obj_InitLoopEndpoint
void
Obj_InitLoopCenter (mobj_t *center)
{
const mapthing_t *mt = center->spawnpoint;
center_max_revolution(center) = mt->args[1] * FRACUNIT / 360;
center_set_flip(center, mt->args[0]);
center_max_revolution(center) = center->args[1] * FRACUNIT / 360;
center_set_flip(center, center->args[0]);
}
void

View file

@ -3435,8 +3435,7 @@ static void P_DoBossVictory(mobj_t *mo)
}
// victory!
if (mo->spawnpoint)
P_LinedefExecute(mo->spawnpoint->args[3], mo, NULL);
P_LinedefExecute(mo->args[3], mo, NULL);
if (stoppedclock && modeattacking) // if you're just time attacking, skip making the capsule appear since you don't need to step on it anyways.
return;
@ -3460,7 +3459,7 @@ static void P_DoBossVictory(mobj_t *mo)
static void P_DoBossDefaultDeath(mobj_t *mo)
{
INT32 bossid = (mo->spawnpoint ? mo->spawnpoint->args[0] : 0);
INT32 bossid = mo->args[0];
// Stop exploding and prepare to run.
P_SetMobjState(mo, mo->info->xdeathstate);
@ -3505,8 +3504,7 @@ void A_BossDeath(mobj_t *mo)
if (LUA_CallAction(A_BOSSDEATH, mo))
return;
if (mo->spawnpoint)
P_LinedefExecute(mo->spawnpoint->args[2], mo, NULL);
P_LinedefExecute(mo->args[2], mo, NULL);
mo->health = 0;
// Boss is dead (but not necessarily fleeing...)
@ -4076,8 +4074,8 @@ void A_FishJump(mobj_t *actor)
jumpval = locvar1;
else
{
if (actor->spawnpoint && actor->spawnpoint->args[0])
jumpval = actor->spawnpoint->args[0];
if (actor->args[0])
jumpval = actor->args[0];
else
jumpval = 44;
}
@ -5086,29 +5084,26 @@ void A_RockSpawn(mobj_t *actor)
if (LUA_CallAction(A_ROCKSPAWN, actor))
return;
if (!actor->spawnpoint)
return;
type = actor->spawnpoint->stringargs[0] ? get_number(actor->spawnpoint->stringargs[0]) : MT_ROCKCRUMBLE1;
type = actor->stringargs[0] ? get_number(actor->stringargs[0]) : MT_ROCKCRUMBLE1;
if (type < MT_NULL || type >= NUMMOBJTYPES)
{
CONS_Debug(DBG_GAMELOGIC, "A_RockSpawn: Invalid mobj type %s!\n", actor->spawnpoint->stringargs[0]);
CONS_Debug(DBG_GAMELOGIC, "A_RockSpawn: Invalid mobj type %s!\n", actor->stringargs[0]);
return;
}
dist = max(actor->spawnpoint->args[0] << (FRACBITS - 4), 1);
if (actor->spawnpoint->args[2])
dist = max(actor->args[0] << (FRACBITS - 4), 1);
if (actor->args[2])
dist += P_RandomByte(PR_UNDEFINED) * (FRACUNIT/32); // random oomph
mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_FALLINGROCK);
P_SetMobjState(mo, mobjinfo[type].spawnstate);
mo->angle = FixedAngle(actor->spawnpoint->angle << FRACBITS);
mo->angle = actor->angle;
P_InstaThrust(mo, mo->angle, dist);
mo->momz = dist;
var1 = actor->spawnpoint->args[1];
var1 = actor->args[1];
A_SetTics(actor);
}
@ -5770,8 +5765,7 @@ void A_Boss1Chase(mobj_t *actor)
}
else
{
if (actor->spawnpoint)
P_LinedefExecute(actor->spawnpoint->args[4], actor, NULL);
P_LinedefExecute(actor->args[4], actor, NULL);
P_SetMobjState(actor, actor->info->raisestate);
}
@ -6468,7 +6462,7 @@ void A_GuardChase(mobj_t *actor)
false, NULL)
&& speed > 0) // can't be the same check as previous so that P_TryMove gets to happen.
{
INT32 direction = actor->spawnpoint ? actor->spawnpoint->args[0] : TMGD_BACK;
INT32 direction = actor->args[0];
switch (direction)
{
@ -6903,16 +6897,13 @@ void A_LinedefExecuteFromArg(mobj_t *actor)
if (LUA_CallAction(A_LINEDEFEXECUTEFROMARG, actor))
return;
if (!actor->spawnpoint)
return;
if (locvar1 < 0 || locvar1 > NUMMAPTHINGARGS)
{
CONS_Debug(DBG_GAMELOGIC, "A_LinedefExecuteFromArg: Invalid mapthing arg %d\n", locvar1);
return;
}
tagnum = actor->spawnpoint->args[locvar1];
tagnum = actor->args[locvar1];
CONS_Debug(DBG_GAMELOGIC, "A_LinedefExecuteFromArg: Running mobjtype %d's sector with tag %d\n", actor->type, tagnum);
@ -7909,15 +7900,32 @@ void A_StateRangeByParameter(mobj_t *actor)
{
INT32 locvar1 = var1;
INT32 locvar2 = var2;
UINT8 parameter = (actor->spawnpoint ? actor->spawnpoint->extrainfo : 0);
UINT8 parameter = 0;
INT32 range = 0;
if (LUA_CallAction(A_STATERANGEBYPARAMETER, actor))
{
return;
}
if (locvar2 - locvar1 < 0)
return; // invalid range
if (udmf)
{
parameter = actor->args[0];
}
else if (actor->spawnpoint != NULL)
{
// binary format backwards compatibility
parameter = actor->spawnpoint->extrainfo;
}
P_SetMobjState(actor, locvar1 + (parameter % (1 + locvar2 - locvar1)));
range = locvar2 - locvar1;
if (range < 0)
{
CONS_Debug(DBG_GAMELOGIC, "A_StateRangeByParameter: invalid range %d (var1: %d, var2: %d)\n", range, locvar1, locvar2);
return;
}
P_SetMobjState(actor, locvar1 + (parameter % (range + 1)));
}
// Function: A_DualAction
@ -10317,17 +10325,13 @@ void P_InternalFlickySetColor(mobj_t *actor, UINT8 color)
//
// Description: Place flickies in-level.
//
// var1:
// Lower 16 bits = if 0, spawns random flicky based on level header. Else, spawns the designated thing type.
// Bits 17-20 = Flicky color, up to 15. Applies to fish.
// Bit 21 = Flag TMFF_AIMLESS (see below)
// Bit 22 = Flag TMFF_STATIONARY (see below)
// Bit 23 = Flag TMFF_HOP (see below)
//
// If actor is placed from a spawnpoint (map Thing), the Thing's properties take precedence.
//
// var1 = if 0, spawns random flicky based on level header. Else, spawns the designated thing type.
// var2 = maximum default distance away from spawn the flickies are allowed to travel. If args[0] != 0, then that's the radius.
//
// args[0] = Flicky radius
// args[1] = Behavior flags (see the list below)
// args[2] = Flicky color, up to 15. Applies to fish.
//
// If TMFF_AIMLESS (MF_SLIDEME): is flagged, Flickies move aimlessly. Else, orbit around the target.
// If TMFF_STATIONARY (MF_GRENADEBOUNCE): Flickies stand in-place without gravity (unless they hop, then gravity is applied.)
// If TMFF_HOP (MF_NOCLIPTHING): is flagged, Flickies hop.
@ -10336,51 +10340,31 @@ void A_FlickyCenter(mobj_t *actor)
{
INT32 locvar1 = var1;
INT32 locvar2 = var2;
UINT16 flickytype = (locvar1 & 0xFFFF);
UINT8 flickycolor = ((locvar1 >> 16) & 0xFF);
UINT8 flickyflags = ((locvar1 >> 20) & 0xF);
fixed_t homeRadius = INT32_MAX;
if (LUA_CallAction(A_FLICKYCENTER, actor))
return;
homeRadius = locvar2 ? FixedMul(abs(locvar2), actor->scale) : 384*actor->scale;
if (!actor->tracer)
{
mobj_t *flicky = P_InternalFlickySpawn(actor, locvar1, 1, false, 0);
P_SetTarget(&flicky->target, actor);
P_SetTarget(&actor->tracer, flicky);
if (actor->spawnpoint)
{
actor->flags &= ~(MF_SLIDEME|MF_GRENADEBOUNCE|MF_NOCLIPTHING);
if (actor->spawnpoint->args[1] & TMFF_AIMLESS)
actor->flags |= MF_SLIDEME;
if (actor->spawnpoint->args[1] & TMFF_STATIONARY)
actor->flags |= MF_GRENADEBOUNCE;
if (actor->spawnpoint->args[1] & TMFF_HOP)
actor->flags |= MF_NOCLIPTHING;
actor->extravalue1 = actor->spawnpoint->args[0] ? abs(actor->spawnpoint->args[0])*FRACUNIT
: locvar2 ? abs(locvar2) : 384*FRACUNIT;
actor->extravalue2 = actor->spawnpoint->args[2];
actor->friction = actor->spawnpoint->x*FRACUNIT;
actor->movefactor = actor->spawnpoint->y*FRACUNIT;
actor->watertop = actor->spawnpoint->z*FRACUNIT;
}
else
{
actor->flags &= ~(MF_SLIDEME|MF_GRENADEBOUNCE|MF_NOCLIPTHING);
if (flickyflags & TMFF_AIMLESS)
actor->flags |= MF_SLIDEME;
if (flickyflags & TMFF_STATIONARY)
actor->flags |= MF_GRENADEBOUNCE;
if (flickyflags & TMFF_HOP)
actor->flags |= MF_NOCLIPTHING;
actor->extravalue1 = abs(locvar2);
actor->extravalue2 = flickycolor;
actor->friction = actor->x;
actor->movefactor = actor->y;
actor->watertop = actor->z;
locvar1 = flickytype;
}
actor->flags &= ~(MF_SLIDEME|MF_GRENADEBOUNCE|MF_NOCLIPTHING);
if (actor->args[1] & TMFF_AIMLESS)
actor->flags |= MF_SLIDEME;
if (actor->args[1] & TMFF_STATIONARY)
actor->flags |= MF_GRENADEBOUNCE;
if (actor->args[1] & TMFF_HOP)
actor->flags |= MF_NOCLIPTHING;
actor->extravalue1 = actor->args[0] ? abs(actor->args[0])*actor->scale : homeRadius;
actor->extravalue2 = actor->args[2];
actor->friction = actor->x;
actor->movefactor = actor->y;
actor->watertop = actor->z;
if (actor->flags & MF_GRENADEBOUNCE) // in-place
actor->tracer->fuse = 0;
@ -10408,7 +10392,7 @@ void A_FlickyCenter(mobj_t *actor)
// Impose default home radius if flicky orbits around player
if (!actor->extravalue1)
actor->extravalue1 = locvar2 ? abs(locvar2) : 384 * FRACUNIT;
actor->extravalue1 = homeRadius;
P_LookForPlayers(actor, true, false, actor->extravalue1);
@ -11298,7 +11282,7 @@ void A_Boss5FindWaypoint(mobj_t *actor)
INT32 locvar1 = var1;
boolean avoidcenter;
INT32 i;
INT32 bossid = (actor->spawnpoint ? actor->spawnpoint->args[0] : 0);
INT32 bossid = actor->args[0];
if (LUA_CallAction(A_BOSS5FINDWAYPOINT, actor))
return;
@ -12681,8 +12665,7 @@ void A_SpawnPterabytes(mobj_t *actor)
if (LUA_CallAction(A_SPAWNPTERABYTES, actor))
return;
if (actor->spawnpoint)
amount = min(1, actor->spawnpoint->args[0]);
amount = min(1, actor->args[0]);
interval = FixedAngle(FRACUNIT*360/amount);
@ -13370,11 +13353,11 @@ void A_MayonakaArrow(mobj_t *actor)
if (LUA_CallAction(A_MAYONAKAARROW, (actor)))
return;
iswarning = (actor->spawnpoint->args[0] == TMMA_WARN); // is our object a warning sign?
iswarning = (actor->args[0] == TMMA_WARN); // is our object a warning sign?
// "animtimer" is replaced by "extravalue1" here.
actor->extravalue1 = ((actor->extravalue1) ? (actor->extravalue1+1) : (P_RandomRange(PR_DECORATION, 0, (iswarning) ? (TICRATE/2) : TICRATE*3)));
flip = ((actor->spawnpoint->args[0] == TMMA_FLIP) ? (3) : (0)); // flip adds 3 frames, which is the flipped version of the sign.
flip = ((actor->args[0] == TMMA_FLIP) ? (3) : (0)); // flip adds 3 frames, which is the flipped version of the sign.
// special warning behavior:
if (iswarning)
flip = 6;

View file

@ -547,7 +547,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
return;
case MT_STARPOST:
P_TouchStarPost(special, player, special->spawnpoint && special->spawnpoint->args[1]);
P_TouchStarPost(special, player, special->args[1]);
return;
case MT_BIGTUMBLEWEED:

View file

@ -608,6 +608,8 @@ void P_SetThingTID(mobj_t *mo, mtag_t tid);
void P_RemoveThingTID(mobj_t *mo);
mobj_t *P_FindMobjFromTID(mtag_t tid, mobj_t *i, mobj_t *activator);
void P_DeleteMobjStringArgs(mobj_t *mobj);
#ifdef __cplusplus
} // extern "C"
#endif

View file

@ -528,7 +528,7 @@ static void P_DoFanAndGasJet(mobj_t *spring, mobj_t *object)
if (object->eflags & MFE_SPRUNG)
break;
if (spring->spawnpoint && spring->spawnpoint->args[1])
if (spring->args[1])
{
if (object->player)
{

View file

@ -4420,7 +4420,7 @@ static void P_RefreshItemCapsuleParts(mobj_t *mobj)
color = SKINCOLOR_GOLD;
newRenderFlags |= RF_SEMIBRIGHT;
}
else if (mobj->spawnpoint && (mobj->spawnpoint->args[2] & TMICF_INVERTTIMEATTACK))
else if (mobj->args[2] & TMICF_INVERTTIMEATTACK)
color = SKINCOLOR_SAPPHIRE;
else if (itemType == KITEM_SPB)
color = SKINCOLOR_JET;
@ -6511,7 +6511,7 @@ static void P_MobjSceneryThink(mobj_t *mobj)
if (!(leveltime % 10))
{
mobj_t *smok = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_PETSMOKE);
if (mobj->spawnpoint && mobj->spawnpoint->args[0])
if (mobj->args[0])
P_SetMobjStateNF(smok, smok->info->painstate); // same function, diff sprite
}
break;
@ -9638,7 +9638,7 @@ static boolean P_FuseThink(mobj_t *mobj)
case MT_SPIKE:
case MT_WALLSPIKE:
P_SetMobjState(mobj, mobj->state->nextstate);
mobj->fuse = mobj->spawnpoint ? mobj->spawnpoint->args[0] : mobj->info->speed;
mobj->fuse = mobj->args[0];
break;
case MT_LAVAFALL:
if (mobj->state - states == S_LAVAFALL_DORMANT)
@ -9764,7 +9764,7 @@ void P_MobjThinker(mobj_t *mobj)
if (mobj->flags & MF_NOTHINK)
return;
if ((mobj->flags & MF_BOSS) && mobj->spawnpoint && (bossdisabled & (1<<mobj->spawnpoint->args[0])))
if ((mobj->flags & MF_BOSS) && (bossdisabled & (1 << mobj->args[0])))
return;
mobj->flags2 &= ~(MF2_ALREADYHIT);
@ -11123,6 +11123,7 @@ void P_RemoveMobj(mobj_t *mobj)
P_SetTarget(&mobj->itnext, NULL);
P_RemoveThingTID(mobj);
P_DeleteMobjStringArgs(mobj);
R_RemoveMobjInterpolator(mobj);
// free block
@ -11209,6 +11210,8 @@ void P_RemoveSavegameMobj(mobj_t *mobj)
// stop any playing sound
S_StopSound(mobj);
P_DeleteMobjStringArgs(mobj);
R_RemoveMobjInterpolator(mobj);
// free block
@ -12175,7 +12178,7 @@ static boolean P_SetupEmblem(mapthing_t *mthing, mobj_t *mobj)
INT32 j;
emblem_t* emblem = M_GetLevelEmblems(gamemap);
skincolornum_t emcolor;
INT16 tagnum = Tag_FGet(&mthing->tags);
INT16 tagnum = mthing->tid;
while (emblem)
{
@ -12653,7 +12656,7 @@ static mobj_t *P_MakeSoftwareCorona(mobj_t *mo, INT32 height)
void P_InitSkyboxPoint(mobj_t *mobj, mapthing_t *mthing)
{
mtag_t tag = Tag_FGet(&mthing->tags);
mtag_t tag = mthing->tid;
if (tag < 0 || tag > 15)
{
CONS_Debug(DBG_GAMELOGIC, "P_InitSkyboxPoint: Skybox ID %d of mapthing %s is not between 0 and 15!\n", tag, sizeu1((size_t)(mthing - mapthings)));
@ -12807,10 +12810,6 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean
if (!P_SetupParticleGen(mthing, mobj))
return false;
break;
case MT_ROCKSPAWNER:
mobj->threshold = mthing->angle;
mobj->movecount = mthing->extrainfo;
break;
case MT_TUBEWAYPOINT:
{
UINT8 sequence = mthing->args[0];
@ -12969,20 +12968,12 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean
mobj->flags2 |= MF2_AMBUSH;
}
break;
case MT_REDFLAG:
redflag = mobj;
rflagpoint = mobj->spawnpoint;
break;
case MT_BLUEFLAG:
blueflag = mobj;
bflagpoint = mobj->spawnpoint;
break;
// SRB2Kart
case MT_WAYPOINT:
{
const fixed_t mobjscale =
mapheaderinfo[gamemap-1]->default_waypoint_radius;
mtag_t tag = Tag_FGet(&mthing->tags);
mtag_t tag = mthing->tid;
if (mthing->args[1] > 0)
mobj->radius = (mthing->args[1]) * FRACUNIT;
@ -13145,8 +13136,8 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean
{
fixed_t top = mobj->z;
UINT8 i;
UINT8 locnumsegs = (mthing->extrainfo)+2;
UINT8 numleaves = max(3, (abs(mthing->angle+1) % 6) + 3);
UINT8 locnumsegs = abs(mthing->args[0])+2;
UINT8 numleaves = max(3, (abs(mthing->args[1])+1 % 6) + 3);
mobj_t *coconut;
// Spawn tree segments
@ -13360,6 +13351,7 @@ static mobj_t *P_SpawnMobjFromMapThing(mapthing_t *mthing, fixed_t x, fixed_t y,
{
mobj_t *mobj = NULL;
boolean doangle = true;
size_t arg = SIZE_MAX;
mobj = P_SpawnMobj(x, y, z, i);
mobj->spawnpoint = mthing;
@ -13393,7 +13385,34 @@ static mobj_t *P_SpawnMobjFromMapThing(mapthing_t *mthing, fixed_t x, fixed_t y,
mobj->pitch = FixedAngle(mthing->pitch << FRACBITS);
mobj->roll = FixedAngle(mthing->roll << FRACBITS);
P_SetThingTID(mobj, Tag_FGet(&mthing->tags));
P_SetThingTID(mobj, mthing->tid);
mobj->special = mthing->special;
for (arg = 0; arg < NUMMAPTHINGARGS; arg++)
{
mobj->args[arg] = mthing->args[arg];
}
for (arg = 0; arg < NUMMAPTHINGSTRINGARGS; arg++)
{
size_t len = 0;
if (mthing->stringargs[arg])
{
len = strlen(mthing->stringargs[arg]);
}
if (len == 0)
{
Z_Free(mobj->stringargs[arg]);
mobj->stringargs[arg] = NULL;
continue;
}
mobj->stringargs[arg] = Z_Realloc(mobj->stringargs[arg], len + 1, PU_LEVEL, NULL);
M_Memcpy(mobj->stringargs[arg], mthing->stringargs[arg], len + 1);
}
mthing->mobj = mobj;
@ -13593,7 +13612,7 @@ static void P_SpawnItemRow(mapthing_t *mthing, mobjtype_t *itemtypes, UINT8 numi
{
const fixed_t length = (numitems - 1) * horizontalspacing / 2;
mobj_t *loopcenter = Obj_FindLoopCenter(Tag_FGet(&mthing->tags));
mobj_t *loopcenter = Obj_FindLoopCenter(mthing->tid);
// Spawn the anchor at the middle point of the line
loopanchor = P_SpawnMobjFromMapThing(&dummything,
@ -14425,3 +14444,14 @@ mobj_t *P_FindMobjFromTID(mtag_t tid, mobj_t *i, mobj_t *activator)
return i;
}
void P_DeleteMobjStringArgs(mobj_t *mobj)
{
size_t i = SIZE_MAX;
for (i = 0; i < NUMMAPTHINGSTRINGARGS; i++)
{
Z_Free(mobj->stringargs[i]);
mobj->stringargs[i] = NULL;
}
}

View file

@ -425,6 +425,10 @@ struct mobj_t
INT32 dispoffset;
INT16 special;
INT32 args[NUMMAPTHINGARGS];
char *stringargs[NUMMAPTHINGSTRINGARGS];
// WARNING: New fields must be added separately to savegame and Lua.
};

View file

@ -558,7 +558,7 @@ static void Polyobj_moveToSpawnSpot(mapthing_t *anchor)
polyobj_t *po;
vertex_t dist, sspot;
size_t i;
mtag_t tag = Tag_FGet(&anchor->tags);
mtag_t tag = anchor->tid;
if (!(po = Polyobj_GetForNum(tag)))
{
@ -1351,7 +1351,7 @@ void Polyobj_InitLevel(void)
{
qitem = (mobjqitem_t *)M_QueueIterator(&spawnqueue);
Polyobj_spawnPolyObj(i, qitem->mo, Tag_FGet(&qitem->mo->spawnpoint->tags));
Polyobj_spawnPolyObj(i, qitem->mo, qitem->mo->spawnpoint->tid);
}
// move polyobjects to spawn points

View file

@ -2135,6 +2135,31 @@ static void P_NetUnArchiveWorld(savebuffer_t *save)
// Thinkers
//
static boolean P_ThingArgsEqual(const mobj_t *mobj, const mapthing_t *mapthing)
{
UINT8 i;
for (i = 0; i < NUMMAPTHINGARGS; i++)
if (mobj->args[i] != mapthing->args[i])
return false;
return true;
}
static boolean P_ThingStringArgsEqual(const mobj_t *mobj, const mapthing_t *mapthing)
{
UINT8 i;
for (i = 0; i < NUMMAPTHINGSTRINGARGS; i++)
{
if (!mobj->stringargs[i])
return !mapthing->stringargs[i];
if (strcmp(mobj->stringargs[i], mapthing->stringargs[i]))
return false;
}
return true;
}
typedef enum
{
MD_SPAWNPOINT = 1,
@ -2166,8 +2191,8 @@ typedef enum
MD_WATERBOTTOM = 1<<26,
MD_SCALE = 1<<27,
MD_DSCALE = 1<<28,
MD_BLUEFLAG = 1<<29,
MD_REDFLAG = 1<<30,
MD_ARGS = 1<<29,
MD_STRINGARGS = 1<<30,
MD_MORE = (INT32)(1U<<31)
} mobj_diff_t;
@ -2191,10 +2216,10 @@ typedef enum
MD2_SHADOWSCALE = 1<<15,
MD2_RENDERFLAGS = 1<<16,
MD2_TID = 1<<17,
MD2_SPRITEXSCALE = 1<<18,
MD2_SPRITEYSCALE = 1<<19,
MD2_SPRITEXOFFSET = 1<<20,
MD2_SPRITEYOFFSET = 1<<21,
MD2_SPRITESCALE = 1<<18,
MD2_SPRITEOFFSET = 1<<19,
MD2_WORLDOFFSET = 1<<20,
MD2_SPECIAL = 1<<21,
MD2_FLOORSPRITESLOPE = 1<<22,
MD2_DISPOFFSET = 1<<23,
MD2_HITLAG = 1<<24,
@ -2287,6 +2312,7 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8
const mobj_t *mobj = (const mobj_t *)th;
UINT32 diff;
UINT32 diff2;
size_t j;
// Ignore stationary hoops - these will be respawned from mapthings.
if (mobj->type == MT_HOOP)
@ -2318,9 +2344,44 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8
if (mobj->info->doomednum != mobj->spawnpoint->type)
diff |= MD_TYPE;
if (!P_ThingArgsEqual(mobj, mobj->spawnpoint))
diff |= MD_ARGS;
if (!P_ThingStringArgsEqual(mobj, mobj->spawnpoint))
diff |= MD_STRINGARGS;
if (mobj->special != mobj->spawnpoint->type)
diff2 |= MD2_SPECIAL;
}
else
diff = MD_POS | MD_TYPE; // not a map spawned thing so make it from scratch
{
// not a map spawned thing, so make it from scratch
diff = MD_POS | MD_TYPE;
for (j = 0; j < NUMMAPTHINGARGS; j++)
{
if (mobj->args[j] != 0)
{
diff |= MD_ARGS;
break;
}
}
for (j = 0; j < NUMMAPTHINGSTRINGARGS; j++)
{
if (mobj->stringargs[j] != NULL)
{
diff |= MD_STRINGARGS;
break;
}
}
if (mobj->special != 0)
{
diff2 |= MD2_SPECIAL;
}
}
diff2 = 0;
@ -2355,7 +2416,6 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8
diff |= MD_EFLAGS;
if (mobj->player)
diff |= MD_PLAYER;
if (mobj->movedir)
diff |= MD_MOVEDIR;
if (mobj->movecount)
@ -2384,12 +2444,6 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8
diff |= MD_DSCALE;
if (mobj->scalespeed != mapobjectscale/12)
diff2 |= MD2_SCALESPEED;
if (mobj == redflag)
diff |= MD_REDFLAG;
if (mobj == blueflag)
diff |= MD_BLUEFLAG;
if (mobj->cusval)
diff2 |= MD2_CUSVAL;
if (mobj->cvmem)
@ -2424,14 +2478,12 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8
diff2 |= MD2_RENDERFLAGS;
if (mobj->tid != 0)
diff2 |= MD2_TID;
if (mobj->spritexscale != FRACUNIT)
diff2 |= MD2_SPRITEXSCALE;
if (mobj->spriteyscale != FRACUNIT)
diff2 |= MD2_SPRITEYSCALE;
if (mobj->spritexoffset)
diff2 |= MD2_SPRITEXOFFSET;
if (mobj->spriteyoffset)
diff2 |= MD2_SPRITEYOFFSET;
if (mobj->spritexscale != FRACUNIT || mobj->spriteyscale != FRACUNIT)
diff2 |= MD2_SPRITESCALE;
if (mobj->spritexoffset || mobj->spriteyoffset)
diff2 |= MD2_SPRITEOFFSET;
if (mobj->sprxoff || mobj->spryoff || mobj->sprzoff)
diff2 |= MD2_WORLDOFFSET;
if (mobj->floorspriteslope)
{
pslope_t *slope = mobj->floorspriteslope;
@ -2577,6 +2629,29 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8
WRITEFIXED(save->p, mobj->destscale);
if (diff2 & MD2_SCALESPEED)
WRITEFIXED(save->p, mobj->scalespeed);
if (diff & MD_ARGS)
{
for (j = 0; j < NUMMAPTHINGARGS; j++)
WRITEINT32(save->p, mobj->args[j]);
}
if (diff & MD_STRINGARGS)
{
for (j = 0; j < NUMMAPTHINGSTRINGARGS; j++)
{
size_t len, k;
if (!mobj->stringargs[j])
{
WRITEINT32(save->p, 0);
continue;
}
len = strlen(mobj->stringargs[j]);
WRITEINT32(save->p, len);
for (k = 0; k < len; k++)
WRITECHAR(save->p, mobj->stringargs[j][k]);
}
}
if (diff2 & MD2_CUSVAL)
WRITEINT32(save->p, mobj->cusval);
if (diff2 & MD2_CVMEM)
@ -2624,14 +2699,24 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8
}
if (diff2 & MD2_TID)
WRITEINT16(save->p, mobj->tid);
if (diff2 & MD2_SPRITEXSCALE)
if (diff2 & MD2_SPRITESCALE)
{
WRITEFIXED(save->p, mobj->spritexscale);
if (diff2 & MD2_SPRITEYSCALE)
WRITEFIXED(save->p, mobj->spriteyscale);
if (diff2 & MD2_SPRITEXOFFSET)
}
if (diff2 & MD2_SPRITEOFFSET)
{
WRITEFIXED(save->p, mobj->spritexoffset);
if (diff2 & MD2_SPRITEYOFFSET)
WRITEFIXED(save->p, mobj->spriteyoffset);
}
if (diff2 & MD2_WORLDOFFSET)
{
WRITEFIXED(save->p, mobj->sprxoff);
WRITEFIXED(save->p, mobj->spryoff);
WRITEFIXED(save->p, mobj->sprzoff);
}
if (diff2 & MD2_SPECIAL)
WRITEINT16(save->p, mobj->special);
if (diff2 & MD2_FLOORSPRITESLOPE)
{
pslope_t *slope = mobj->floorspriteslope;
@ -3549,6 +3634,7 @@ static thinker_t* LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker)
INT32 i;
fixed_t z, floorz, ceilingz;
ffloor_t *floorrover = NULL, *ceilingrover = NULL;
size_t j;
diff = READUINT32(save->p);
if (diff & MD_MORE)
@ -3742,6 +3828,31 @@ static thinker_t* LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker)
mobj->scalespeed = READFIXED(save->p);
else
mobj->scalespeed = mapobjectscale/12;
if (diff & MD_ARGS)
{
for (j = 0; j < NUMMAPTHINGARGS; j++)
mobj->args[j] = READINT32(save->p);
}
if (diff & MD_STRINGARGS)
{
for (j = 0; j < NUMMAPTHINGSTRINGARGS; j++)
{
size_t len = READINT32(save->p);
size_t k;
if (!len)
{
Z_Free(mobj->stringargs[j]);
mobj->stringargs[j] = NULL;
continue;
}
mobj->stringargs[j] = Z_Realloc(mobj->stringargs[j], len + 1, PU_LEVEL, NULL);
for (k = 0; k < len; k++)
mobj->stringargs[j][k] = READCHAR(save->p);
mobj->stringargs[j][len] = '\0';
}
}
if (diff2 & MD2_CUSVAL)
mobj->cusval = READINT32(save->p);
if (diff2 & MD2_CVMEM)
@ -3777,18 +3888,38 @@ static thinker_t* LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker)
mobj->renderflags = READUINT32(save->p);
if (diff2 & MD2_TID)
P_SetThingTID(mobj, READINT16(save->p));
if (diff2 & MD2_SPRITEXSCALE)
if (diff2 & MD2_SPRITESCALE)
{
mobj->spritexscale = READFIXED(save->p);
else
mobj->spritexscale = FRACUNIT;
if (diff2 & MD2_SPRITEYSCALE)
mobj->spriteyscale = READFIXED(save->p);
}
else
mobj->spriteyscale = FRACUNIT;
if (diff2 & MD2_SPRITEXOFFSET)
{
mobj->spritexscale = mobj->spriteyscale = FRACUNIT;
}
if (diff2 & MD2_SPRITEOFFSET)
{
mobj->spritexoffset = READFIXED(save->p);
if (diff2 & MD2_SPRITEYOFFSET)
mobj->spriteyoffset = READFIXED(save->p);
}
else
{
mobj->spritexoffset = mobj->spriteyoffset = 0;
}
if (diff2 & MD2_WORLDOFFSET)
{
mobj->sprxoff = READFIXED(save->p);
mobj->spryoff = READFIXED(save->p);
mobj->sprzoff = READFIXED(save->p);
}
else
{
mobj->sprxoff = mobj->spryoff = mobj->sprzoff = 0;
}
if (diff2 & MD2_SPECIAL)
{
mobj->special = READINT16(save->p);
}
if (diff2 & MD2_FLOORSPRITESLOPE)
{
pslope_t *slope = (pslope_t *)P_CreateFloorSpriteSlope(mobj);
@ -3836,17 +3967,6 @@ static thinker_t* LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker)
mobj->terrain = NULL;
}
if (diff & MD_REDFLAG)
{
redflag = mobj;
rflagpoint = mobj->spawnpoint;
}
if (diff & MD_BLUEFLAG)
{
blueflag = mobj;
bflagpoint = mobj->spawnpoint;
}
// set sprev, snext, bprev, bnext, subsector
P_SetThingPosition(mobj);

View file

@ -714,7 +714,7 @@ static int cmp_loopends(const void *a, const void *b)
// weighted sorting; tag takes precedence over type
return
intsign(Tag_FGet(&mt1->tags) - Tag_FGet(&mt2->tags)) * 2 +
intsign(mt1->tid - mt2->tid) * 2 +
intsign(mt1->args[0] - mt2->args[0]);
}
@ -793,7 +793,7 @@ static void P_SpawnMapThings(boolean spawnemblems)
*mt1 = loopends[i - 1],
*mt2 = loopends[i];
if (Tag_FGet(&mt1->tags) == Tag_FGet(&mt2->tags) &&
if (mt1->tid == mt2->tid &&
mt1->args[0] == mt2->args[0])
{
P_SpawnItemLine(mt1, mt2);
@ -1305,7 +1305,7 @@ static void P_LoadThings(UINT8 *data)
mt->type = READUINT16(data);
mt->options = READUINT16(data);
mt->extrainfo = (UINT8)(mt->type >> 12);
Tag_FSet(&mt->tags, 0);
mt->tid = 0;
mt->scale = FRACUNIT;
memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args));
memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs));
@ -1870,17 +1870,7 @@ static void ParseTextmapLinedefParameter(UINT32 i, const char *param, const char
static void ParseTextmapThingParameter(UINT32 i, const char *param, const char *val)
{
if (fastcmp(param, "id"))
Tag_FSet(&mapthings[i].tags, atol(val));
else if (fastcmp(param, "moreids"))
{
const char* id = val;
while (id)
{
Tag_Add(&mapthings[i].tags, atol(id));
if ((id = strchr(id, ' ')))
id++;
}
}
mapthings[i].tid = atol(val);
else if (fastcmp(param, "x"))
mapthings[i].x = atol(val);
else if (fastcmp(param, "y"))
@ -2063,9 +2053,6 @@ static void P_WriteTextmap(void)
for (i = 0; i < nummapthings; i++)
{
if (mapthings[i].tags.count)
wmapthings[i].tags.tags = memcpy(Z_Malloc(mapthings[i].tags.count * sizeof(mtag_t), PU_LEVEL, NULL), mapthings[i].tags.tags, mapthings[i].tags.count * sizeof(mtag_t));
if (mapthings[i].user.length)
{
wmapthings[i].user.properties = memcpy(
@ -2232,7 +2219,7 @@ static void P_WriteTextmap(void)
CONS_Alert(CONS_WARNING, M_GetText("No unused tag found. Linedef %s with type 412 cannot be converted.\n"), sizeu1(i));
break;
}
Tag_Add(&specialthings[s].teleport->tags, freetag);
specialthings[s].teleport->tid = freetag;
wlines[i].args[0] = freetag;
freetag = Tag_NextUnused(freetag);
break;
@ -2246,7 +2233,7 @@ static void P_WriteTextmap(void)
CONS_Alert(CONS_WARNING, M_GetText("No unused tag found. Linedef %s with type 422 cannot be converted.\n"), sizeu1(i));
break;
}
Tag_Add(&specialthings[s].altview->tags, freetag);
specialthings[s].altview->tid = freetag;
wlines[i].args[0] = freetag;
specialthings[s].altview->pitch = wlines[i].args[2];
freetag = Tag_NextUnused(freetag);
@ -2271,7 +2258,7 @@ static void P_WriteTextmap(void)
CONS_Alert(CONS_WARNING, M_GetText("No unused tag found. Linedef %s with type 457 cannot be converted.\n"), sizeu1(i));
break;
}
Tag_Add(&specialthings[s].angleanchor->tags, freetag);
specialthings[s].angleanchor->tid = freetag;
wlines[i].args[0] = freetag;
freetag = Tag_NextUnused(freetag);
break;
@ -2370,20 +2357,8 @@ static void P_WriteTextmap(void)
{
fprintf(f, "thing // %s\n", sizeu1(i));
fprintf(f, "{\n");
firsttag = Tag_FGet(&wmapthings[i].tags);
if (firsttag != 0)
fprintf(f, "id = %d;\n", firsttag);
if (wmapthings[i].tags.count > 1)
{
fprintf(f, "moreids = \"");
for (j = 1; j < wmapthings[i].tags.count; j++)
{
if (j > 1)
fprintf(f, " ");
fprintf(f, "%d", wmapthings[i].tags.tags[j]);
}
fprintf(f, "\";\n");
}
if (wmapthings[i].tid != 0)
fprintf(f, "id = %d;\n", wmapthings[i].tid);
fprintf(f, "x = %d;\n", wmapthings[i].x);
fprintf(f, "y = %d;\n", wmapthings[i].y);
if (wmapthings[i].z != 0)
@ -2833,9 +2808,6 @@ static void P_WriteTextmap(void)
for (i = 0; i < nummapthings; i++)
{
if (wmapthings[i].tags.count)
Z_Free(wmapthings[i].tags.tags);
if (wmapthings[i].user.length)
Z_Free(wmapthings[i].user.properties);
}
@ -3045,7 +3017,7 @@ static void P_LoadTextmap(void)
mt->options = 0;
mt->z = 0;
mt->extrainfo = 0;
Tag_FSet(&mt->tags, 0);
mt->tid = 0;
mt->scale = FRACUNIT;
memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args));
memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs));
@ -4304,7 +4276,7 @@ static void P_AddBinaryMapTags(void)
case 760:
case 761:
case 762:
Tag_FSet(&mapthings[i].tags, mapthings[i].angle);
mapthings[i].tid = mapthings[i].angle;
break;
case 290:
case 292:
@ -4312,7 +4284,7 @@ static void P_AddBinaryMapTags(void)
case 780:
case 2020: // MT_LOOPENDPOINT
case 2021: // MT_LOOPCENTERPOINT
Tag_FSet(&mapthings[i].tags, mapthings[i].extrainfo);
mapthings[i].tid = mapthings[i].extrainfo;
break;
default:
break;
@ -6837,9 +6809,8 @@ static void P_ConvertBinaryThingTypes(void)
{
INT32 check = -1;
INT32 firstline = -1;
mtag_t tag = Tag_FGet(&mapthings[i].tags);
TAG_ITER_LINES(tag, check)
TAG_ITER_LINES(mapthings[i].tid, check)
{
if (lines[check].special == 20)
{
@ -7058,7 +7029,7 @@ static void P_ConvertBinaryThingTypes(void)
{
INT32 firstline = Tag_FindLineSpecial(2000, (INT16)mapthings[i].angle);
Tag_FSet(&mapthings[i].tags, mapthings[i].angle);
mapthings[i].tid = mapthings[i].angle;
mapthings[i].args[0] = mapthings[i].z;
mapthings[i].z = 0;
@ -7135,6 +7106,10 @@ static void P_ConvertBinaryThingTypes(void)
case 2050: // MT_DUELBOMB
mapthings[i].args[1] = !!(mapthings[i].options & MTF_AMBUSH);
break;
case 1950: // MT_AAZTREE_HELPER
mapthings[i].args[0] = mapthings[i].extrainfo;
mapthings[i].args[1] = mapthings[i].angle;
break;
case 2333: // MT_BATTLECAPSULE
mapthings[i].args[0] = mapthings[i].extrainfo;
mapthings[i].args[1] = mapthings[i].angle;
@ -7160,7 +7135,7 @@ static void P_ConvertBinaryThingTypes(void)
break;
case FLOOR_SLOPE_THING:
case CEILING_SLOPE_THING:
Tag_FSet(&mapthings[i].tags, mapthings[i].extrainfo);
mapthings[i].tid = mapthings[i].extrainfo;
break;
default:
break;
@ -7376,10 +7351,6 @@ static void P_InitLevelSettings(void)
// emerald hunt
hunt1 = hunt2 = hunt3 = NULL;
// clear ctf pointers
redflag = blueflag = NULL;
rflagpoint = bflagpoint = NULL;
// circuit, race and competition stuff
numstarposts = 0;
timeinmap = 0;

View file

@ -624,11 +624,11 @@ static pslope_t *MakeViaMapthings(INT16 tag1, INT16 tag2, INT16 tag3, UINT8 flag
if (mt->type != 750) // Haha, I'm hijacking the old Chaos Spawn thingtype for something!
continue;
if (!vertices[0] && Tag_Find(&mt->tags, tag1))
if (!vertices[0] && mt->tid == tag1)
vertices[0] = mt;
else if (!vertices[1] && Tag_Find(&mt->tags, tag2))
else if (!vertices[1] && mt->tid == tag2)
vertices[1] = mt;
else if (!vertices[2] && Tag_Find(&mt->tags, tag3))
else if (!vertices[2] && mt->tid == tag3)
vertices[2] = mt;
}

View file

@ -2338,7 +2338,6 @@ void P_PushSpecialLine(line_t *line, mobj_t *thing)
//
void P_ActivateThingSpecial(mobj_t *mo, mobj_t *source)
{
mapthing_t *mt = NULL;
player_t *player = NULL;
activator_t *activator = NULL;
@ -2348,13 +2347,6 @@ void P_ActivateThingSpecial(mobj_t *mo, mobj_t *source)
return;
}
mt = mo->spawnpoint;
if (mt == NULL)
{
// No mapthing to activate the special of.
return;
}
// Is this necessary? Probably not, but I hate
// spectators so I will manually ensure they
// can't impact the gamestate anyway.
@ -2374,7 +2366,7 @@ void P_ActivateThingSpecial(mobj_t *mo, mobj_t *source)
}
}
if (P_CanActivateSpecial(mt->special) == false)
if (P_CanActivateSpecial(mo->special) == false)
{
// No special to even activate.
return;
@ -2389,7 +2381,7 @@ void P_ActivateThingSpecial(mobj_t *mo, mobj_t *source)
activator->sector = source->subsector->sector;
}
P_ProcessSpecial(activator, mt->special, mt->args, mt->stringargs);
P_ProcessSpecial(activator, mo->special, mo->args, mo->stringargs);
P_SetTarget(&activator->mo, NULL);
Z_Free(activator);
@ -3041,7 +3033,7 @@ boolean P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, cha
}
newViewMobj = P_FindObjectTypeFromTag(MT_ALTVIEWMAN, args[0]);
if (newViewMobj == NULL || newViewMobj->spawnpoint == NULL)
if (newViewMobj == NULL)
{
return false;
}
@ -6308,7 +6300,7 @@ P_RaiseTaggedThingsToFakeFloor (
if (
(type == 0 || mthing->type == type) &&
(tag == 0 || udmf ? Tag_Find(&mthing->tags, tag) : mthing->angle == tag)
(tag == 0 || (udmf ? mthing->tid : mthing->angle) == tag)
){
if (( mo->flags2 & MF2_OBJECTFLIP ))
{

View file

@ -199,7 +199,7 @@ get_anchor
for (i = 0; i < list->count; ++i)
{
if (list->points[i] == v && Tag_FGet(&list->anchors[i]->tags) == tag)
if (list->points[i] == v && list->anchors[i]->tid == tag)
{
for (k = 0; k < 3; ++k)
{

View file

@ -25,7 +25,6 @@ size_t num_tags;
// in several taggroups at the same time. These are built on level load.
taggroup_t* tags_sectors[MAXTAGS + 1];
taggroup_t* tags_lines[MAXTAGS + 1];
taggroup_t* tags_mapthings[MAXTAGS + 1];
/// Adds a tag to a given element's taglist. It will not add a duplicate.
/// \warning This does not rebuild the global taggroups, which are used for iteration.
@ -247,8 +246,7 @@ static size_t total_elements_with_tag (const mtag_t tag)
return
(
Taggroup_Count(tags_sectors[tag]) +
Taggroup_Count(tags_lines[tag]) +
Taggroup_Count(tags_mapthings[tag])
Taggroup_Count(tags_lines[tag])
);
}
@ -309,12 +307,7 @@ static void Taglist_AddToLines (const mtag_t tag, const size_t itemid)
Taggroup_Add_Init(tags_lines, tag, itemid);
}
static void Taglist_AddToMapthings (const mtag_t tag, const size_t itemid)
{
Taggroup_Add_Init(tags_mapthings, tag, itemid);
}
/// After all taglists have been built for each element (sectors, lines, things),
/// After all taglists have been built for each element (sectors, lines),
/// the global taggroups, made for iteration, are built here.
void Taglist_InitGlobalTables(void)
{
@ -327,7 +320,6 @@ void Taglist_InitGlobalTables(void)
{
tags_sectors[i] = NULL;
tags_lines[i] = NULL;
tags_mapthings[i] = NULL;
}
for (i = 0; i < numsectors; i++)
{
@ -339,11 +331,6 @@ void Taglist_InitGlobalTables(void)
for (j = 0; j < lines[i].tags.count; j++)
Taglist_AddToLines(lines[i].tags.tags[j], i);
}
for (i = 0; i < nummapthings; i++)
{
for (j = 0; j < mapthings[i].tags.count; j++)
Taglist_AddToMapthings(mapthings[i].tags.tags[j], i);
}
}
// Iteration, ingame search.
@ -358,11 +345,6 @@ INT32 Tag_Iterate_Lines (const mtag_t tag, const size_t p)
return Taggroup_Iterate(tags_lines, numlines, tag, p);
}
INT32 Tag_Iterate_Things (const mtag_t tag, const size_t p)
{
return Taggroup_Iterate(tags_mapthings, nummapthings, tag, p);
}
INT32 Tag_FindLineSpecial(const INT16 special, const mtag_t tag)
{
size_t i;
@ -468,3 +450,30 @@ mtag_t Tag_NextUnused(mtag_t start)
return (mtag_t)MAXTAGS;
}
// This is no longer a tag list to maintain parity with mobjs,
// but it's convenient to keep it in this file anyway.
INT32 Tag_Iterate_Things (const mtag_t tag, const size_t p)
{
size_t i = SIZE_MAX;
if (tag == MTAG_GLOBAL)
{
if (p < nummapthings)
{
return p;
}
return -1;
}
for (i = p; i < nummapthings; i++)
{
if (mapthings[i].tid == tag)
{
return i;
}
}
return -1;
}

View file

@ -59,7 +59,6 @@ extern size_t num_tags;
extern taggroup_t* tags_sectors[];
extern taggroup_t* tags_lines[];
extern taggroup_t* tags_mapthings[];
void Taggroup_Add (taggroup_t *garray[], const mtag_t tag, size_t id);
void Taggroup_Remove (taggroup_t *garray[], const mtag_t tag, size_t id);