thinker_era
A first pass in attempts to fix crashes when ACS causes map changes. Frustratingly still got a crash, but I think this is definitely the right foundation to work with.
This commit is contained in:
parent
5f43f1c2cd
commit
bdc50487b7
5 changed files with 36 additions and 2 deletions
|
|
@ -330,7 +330,16 @@ ACSVM::Word Environment::callSpecImpl
|
|||
);
|
||||
|
||||
activator_t *activator = static_cast<activator_t *>(Z_Calloc(sizeof(activator_t), PU_LEVEL, nullptr));
|
||||
auto __ = srb2::finally([activator]() { Z_Free(activator); });
|
||||
auto __ = srb2::finally(
|
||||
[info, activator]()
|
||||
{
|
||||
if (info->thread_era == thinker_era)
|
||||
{
|
||||
P_SetTarget(&activator->mo, NULL);
|
||||
Z_Free(activator);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// This needs manually set, as ACS just uses indicies in the
|
||||
// compiled string table and not actual strings, and SRB2 has
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ enum acs_tagType_e
|
|||
class ThreadInfo : public ACSVM::ThreadInfo
|
||||
{
|
||||
public:
|
||||
UINT32 thread_era; // If equal to thinker_era, mobj pointers are safe.
|
||||
mobj_t *mo; // Object that activated this thread.
|
||||
line_t *line; // Linedef that activated this thread.
|
||||
UINT8 side; // Front / back side of said linedef.
|
||||
|
|
@ -75,6 +76,7 @@ public:
|
|||
bool fromLineSpecial; // Called from P_ProcessLineSpecial.
|
||||
|
||||
ThreadInfo() :
|
||||
thread_era { thinker_era },
|
||||
mo{ nullptr },
|
||||
line{ nullptr },
|
||||
side{ 0 },
|
||||
|
|
@ -85,6 +87,7 @@ public:
|
|||
}
|
||||
|
||||
ThreadInfo(const ThreadInfo &info) :
|
||||
thread_era { thinker_era },
|
||||
mo{ nullptr },
|
||||
line{ info.line },
|
||||
side{ info.side },
|
||||
|
|
@ -96,6 +99,7 @@ public:
|
|||
}
|
||||
|
||||
ThreadInfo(const activator_t *activator) :
|
||||
thread_era { thinker_era },
|
||||
mo{ nullptr },
|
||||
line{ activator->line },
|
||||
side{ activator->side },
|
||||
|
|
@ -108,11 +112,15 @@ public:
|
|||
|
||||
~ThreadInfo()
|
||||
{
|
||||
P_SetTarget(&mo, nullptr);
|
||||
if (thread_era == thinker_era)
|
||||
{
|
||||
P_SetTarget(&mo, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
ThreadInfo &operator = (const ThreadInfo &info)
|
||||
{
|
||||
thread_era = thinker_era;
|
||||
P_SetTarget(&mo, info.mo);
|
||||
line = info.line;
|
||||
side = info.side;
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ extern thinker_t thlist[];
|
|||
extern mobj_t *mobjcache;
|
||||
|
||||
void P_InitThinkers(void);
|
||||
void P_InvalidateThinkersWithoutInit(void);
|
||||
void P_AddThinker(const thinklistnum_t n, thinker_t *thinker);
|
||||
void P_RemoveThinker(thinker_t *thinker);
|
||||
void P_UnlinkThinker(thinker_t *thinker);
|
||||
|
|
|
|||
14
src/p_tick.c
14
src/p_tick.c
|
|
@ -41,6 +41,8 @@
|
|||
|
||||
tic_t leveltime;
|
||||
|
||||
UINT32 thinker_era = 0;
|
||||
|
||||
INT32 P_AltFlip(INT32 n, tic_t tics)
|
||||
{
|
||||
return leveltime % (2 * tics) < tics ? n : -(n);
|
||||
|
|
@ -201,8 +203,20 @@ void P_InitThinkers(void)
|
|||
boss3cap = NULL;
|
||||
waypointcap = NULL;
|
||||
kitemcap = NULL;
|
||||
P_InvalidateThinkersWithoutInit();
|
||||
for (i = 0; i < NUM_THINKERLISTS; i++)
|
||||
thlist[i].prev = thlist[i].next = &thlist[i];
|
||||
|
||||
iquehead = iquetail = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// P_InvalidateThinkersWithoutInit
|
||||
//
|
||||
|
||||
void P_InvalidateThinkersWithoutInit(void)
|
||||
{
|
||||
thinker_era++;
|
||||
}
|
||||
|
||||
// Adds a new thinker at the end of the list.
|
||||
|
|
|
|||
|
|
@ -34,6 +34,8 @@ void P_DoTeamscrambling(void);
|
|||
void P_RemoveThinkerDelayed(thinker_t *thinker); //killed
|
||||
mobj_t *P_SetTarget(mobj_t **mo, mobj_t *target); // killough 11/98
|
||||
|
||||
extern UINT32 thinker_era;
|
||||
|
||||
// Negate the value for tics
|
||||
INT32 P_AltFlip(INT32 value, tic_t tics);
|
||||
#define P_RandomFlip(value) P_AltFlip(value, 1)
|
||||
|
|
|
|||
Loading…
Reference in a new issue