- added helpers needed to run CON replacement code.

* killit must exit to the top level right away. Use an exception for this.
* two new flags to make checking easier.
* do not export killit_flag to scripting.
This commit is contained in:
Christoph Oelckers 2023-04-30 08:11:30 +02:00
parent 960e58cdf2
commit 21a37d2c07
5 changed files with 36 additions and 4 deletions

View file

@ -448,6 +448,8 @@ enum sflags4_t
{
SFLAG4_DOUBLEHITDAMAGE = 0x00000001,
SFLAG4_NODAMAGETURN = 0x00000002,
SFLAG4_CONOVERRIDE = 0x00000004, // this is strictly internal
SFLAG4_INRUNSTATE = 0x00000008, // exception throwing guard.
};
using EDukeFlags4 = TFlags<sflags4_t, uint32_t>;

View file

@ -498,7 +498,7 @@ void GameInterface::FinalizeSetup()
}
}
//ScriptCode[actinf.scriptaddress] = 0; // ignore strength values for hashing the script code. (later, we still need this.)
ScriptCode[actinf.scriptaddress] = 0; // ignore strength values for hashing the script code.
// todo: hash the entire script code and compare against precalculated value for the current game.
// If identical, remove all ScriptAddresses from the class list.

View file

@ -170,6 +170,18 @@ public:
using HitInfo = THitInfo<DDukeActor>;
using Collision = TCollision<DDukeActor>;
// This is to satisfy the CON-based requirement of 'killit' immediately aborting all script code execution.
class CDukeKillEvent : public std::exception
{
int Type_;
public:
CDukeKillEvent(int type): Type_(type) {}
int Type() const { return Type_; }
// to print a meaningful message if killit got called from the wrong place.
const char* what() const override { return "killit called from outside RunState!"; }
};
struct animwalltype
{
walltype* wall;

View file

@ -293,7 +293,7 @@ DEFINE_FIELD(DDukeActor, curAction)
DEFINE_FIELD(DDukeActor, curMove)
DEFINE_FIELD(DDukeActor, curAI)
DEFINE_FIELD(DDukeActor, actioncounter)
DEFINE_FIELD(DDukeActor, killit_flag)
//DEFINE_FIELD(DDukeActor, killit_flag)
void TickActor(DDukeActor*);
DEFINE_ACTION_FUNCTION(DDukeActor, Tick)
@ -604,7 +604,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(DDukeActor, badguy, badguy)
int duke_scripted(const DDukeActor* act)
{
return act->conInfo() != nullptr;
return act->conInfo() != nullptr || (act->flags4 & SFLAG4_CONOVERRIDE);
}
DEFINE_ACTION_FUNCTION_NATIVE(DDukeActor, scripted, duke_scripted)
@ -927,6 +927,23 @@ DEFINE_ACTION_FUNCTION_NATIVE(DDukeActor, subkill, subkill)
return 0;
}
DEFINE_ACTION_FUNCTION(DDukeActor, killit)
{
PARAM_SELF_PROLOGUE(DDukeActor);
if (self->flags4 & SFLAG4_INRUNSTATE)
{
// this has to be done the hard way. The original CON interpreter stops running commands once an actor is set to be killed.
// The only safe way to handle this in native code while exiting all nested functions is throwing an exception.
throw CDukeKillEvent(1);
}
else
{
// if it is something else than the currently ticked actor we can outright destroy it.
self->Destroy();
}
return 0;
}
//---------------------------------------------------------------------------
//
// DukePlayer

View file

@ -312,7 +312,7 @@ class DukeActor : CoreActor native
native ActorMove curMove;
native Name curAI;
native int16 actioncounter;
native uint8 killit_flag;
//native uint8 killit_flag;
// flags are implemented natively to avoid the prefixes.
@ -402,6 +402,7 @@ class DukeActor : CoreActor native
native double GetAmbientDist();
native void addkill();
native void subkill();
native void killit();