Skip to content

Commit

Permalink
Scripting|Doom|Heretic|Hexen: Added Thing "On death" script
Browse files Browse the repository at this point in the history
IssueID #2374
  • Loading branch information
skyjake committed Dec 21, 2019
1 parent 99f9925 commit 977df19
Show file tree
Hide file tree
Showing 9 changed files with 63 additions and 8 deletions.
2 changes: 2 additions & 0 deletions doomsday/apps/libdoomsday/include/doomsday/world/thinker.h
Expand Up @@ -48,6 +48,8 @@ typedef struct thinker_s {
#define THINKER_DATA(thinker, T) (reinterpret_cast<Thinker::IData *>((thinker).d)->as<T>())
#define THINKER_DATA_MAYBE(thinker, T) (de::maybeAs<T>(reinterpret_cast<Thinker::IData *>((thinker).d)))

#define THINKER_NS(thinker) (THINKER_DATA((thinker), ThinkerData).objectNamespace())

#ifdef __cplusplus
extern "C" {
#endif
Expand Down
1 change: 1 addition & 0 deletions doomsday/apps/libdoomsday/src/defs/dedparser.cpp
Expand Up @@ -1265,6 +1265,7 @@ DENG2_PIMPL(DEDParser)
RV_INT_ELEM("Misc4", (*mo)["misc"], 3)

RV_STR("On touch", (*mo)["onTouch"]) // script function (MF_SPECIAL)
RV_STR("On death", (*mo)["onDeath"]) // script function

RV_END
CHECKSC;
Expand Down
1 change: 1 addition & 0 deletions doomsday/apps/libdoomsday/src/defs/thing.cpp
Expand Up @@ -44,6 +44,7 @@ void Thing::resetToDefaults()
def().addNumber("mass", 0);
def().addNumber("damage", 0);
def().addText ("onTouch", ""); // script function to call when touching a special thing
def().addText ("onDeath", ""); // script function to call when thing is killed
def().addArray ("flags").array().addMany(NUM_MOBJ_FLAGS, 0);
def().addArray ("misc").array().addMany(NUM_MOBJ_MISC, 0);
}
Expand Down
2 changes: 1 addition & 1 deletion doomsday/apps/libdoomsday/src/doomsdayapp_bindings.cpp
Expand Up @@ -57,7 +57,7 @@ static Value *Function_Player_Thing(Context &ctx, const Function::ArgumentValues
const int plrNum = playerIndex(ctx);
if (const mobj_t *mo = DoomsdayApp::players().at(plrNum).publicData().mo)
{
return new RecordValue(THINKER_DATA(mo->thinker, ThinkerData).objectNamespace());
return new RecordValue(THINKER_NS(mo->thinker));
}
return nullptr;
}
Expand Down
4 changes: 3 additions & 1 deletion doomsday/apps/plugins/common/include/mobj.h
Expand Up @@ -236,6 +236,8 @@ enum mobjtouchresult_e {
MTR_DESTROY
};

void Mobj_RunScriptOnDeath(mobj_t *mob, mobj_t *killer);

/**
* Called when @a toucher comes into contact with special thing @a special that has a
* custom scripted touch action.
Expand All @@ -247,7 +249,7 @@ enum mobjtouchresult_e {
* @return @c true if a scripted action is defined for the object. In this case, @a result
* will contain a valid value afterwards.
*/
dd_bool Mobj_TouchSpecialScriptedThing(mobj_t *mob, mobj_t *special, enum mobjtouchresult_e *result);
dd_bool Mobj_RunScriptOnTouch(mobj_t *mob, mobj_t *special, enum mobjtouchresult_e *result);

#ifdef __cplusplus
} // extern "C"
Expand Down
49 changes: 46 additions & 3 deletions doomsday/apps/plugins/common/src/world/mobj.cpp
Expand Up @@ -1154,17 +1154,59 @@ void Mobj_RestoreObjectState(mobj_t *mob, de::Info::BlockElement const &state)
#endif
}

dd_bool Mobj_TouchSpecialScriptedThing(mobj_t *mob, mobj_t *special, enum mobjtouchresult_e *result)
void Mobj_RunScriptOnDeath(mobj_t *mob, mobj_t *killer)
{
using namespace de;

if (IS_NETWORK_CLIENT)
{
// Clients don't do this, only the server will.
return;
}

// Check Thing definition for an onDeath script.
const auto &thingDef = DED_Definitions()->things[mob->type];
if (const String onDeathSrc = thingDef.gets(QStringLiteral("onDeath")))
{
LOG_AS("Mobj_RunScriptOnDeath");

const auto &self = THINKER_NS(mob->thinker);

Record ns;
ns.add(QStringLiteral("self")).set(new RecordValue(self));
Variable &killerVar = ns.add(QStringLiteral("killer"));
if (killer)
{
killerVar.set(new RecordValue(THINKER_NS(killer->thinker)));
}
else
{
killerVar.set(new NoneValue);
}
Process proc(&ns);
Script script(onDeathSrc);
proc.run(script);
proc.execute();
}
}

dd_bool Mobj_RunScriptOnTouch(mobj_t *mob, mobj_t *special, enum mobjtouchresult_e *result)
{
using namespace de;

if (IS_NETWORK_CLIENT)
{
// Clients don't do this, only the server will.
return false;
}

// Check Thing definition for an onTouch script.
const auto &thingDef = DED_Definitions()->things[special->type];
if (const String onTouchSrc = thingDef.gets(QStringLiteral("onTouch")))
{
LOG_AS("Mobj_TouchSpecialScriptedThing");
LOG_AS("Mobj_RunScriptOnTouch");

const auto &self = THINKER_DATA(special->thinker, ThinkerData).objectNamespace();
const auto &self = THINKER_NS(special->thinker);

// We will make it seem like the special thing has a script function
// called "onTouch", even though we are only now parsing the script from
Expand All @@ -1177,6 +1219,7 @@ dd_bool Mobj_TouchSpecialScriptedThing(mobj_t *mob, mobj_t *special, enum mobjto
// the function. The function returns a code that tells what to do with the
// special item afterwards: "keep", "dormant", "hide", "destroy".

// We are interested in the return value, so make it a function that can be called.
String src = "def onTouch(toucher)\n";
src += onTouchSrc;
src += "\nend";
Expand Down
2 changes: 2 additions & 0 deletions doomsday/apps/plugins/doom/src/p_inter.c
Expand Up @@ -981,6 +981,8 @@ void P_KillMobj(mobj_t *source, mobj_t *target, dd_bool stomping)
target->corpseTics = 0;
target->height /= 2*2;

Mobj_RunScriptOnDeath(target, source);

if(source && source->player)
{
// Count for intermission.
Expand Down
5 changes: 4 additions & 1 deletion doomsday/apps/plugins/heretic/src/p_inter.c
Expand Up @@ -971,7 +971,7 @@ void P_TouchSpecialMobj(mobj_t *special, mobj_t *toucher)

player = toucher->player;

if (Mobj_TouchSpecialScriptedThing(toucher, special, &touchResult))
if (Mobj_RunScriptOnTouch(toucher, special, &touchResult))
{
switch (touchResult)
{
Expand Down Expand Up @@ -1058,6 +1058,9 @@ static void killMobj(mobj_t *source, mobj_t *target)
target->flags2 &= ~MF2_PASSMOBJ;
target->corpseTics = 0;
target->height /= 2*2;

Mobj_RunScriptOnDeath(target, source);

if(source && source->player)
{
if(target->flags & MF_COUNTKILL)
Expand Down
5 changes: 3 additions & 2 deletions doomsday/apps/plugins/hexen/src/p_inter.c
Expand Up @@ -1452,8 +1452,7 @@ void P_KillMobj(mobj_t *source, mobj_t *target)
target->flags2 &= ~MF2_PASSMOBJ;
target->height /= 2 * 2;

if((target->flags & MF_COUNTKILL || target->type == MT_ZBELL) &&
target->special)
if ((target->flags & MF_COUNTKILL || target->type == MT_ZBELL) && target->special)
{
// Initiate monster death actions.
if(target->type == MT_SORCBOSS)
Expand All @@ -1466,6 +1465,8 @@ void P_KillMobj(mobj_t *source, mobj_t *target)
}
}

Mobj_RunScriptOnDeath(target, source);

if(source && source->player)
{
// Check for frag changes.
Expand Down

0 comments on commit 977df19

Please sign in to comment.