diff --git a/src/g_doom/a_doommisc.cpp b/src/g_doom/a_doommisc.cpp index 9f31782951..1df9a4e7cd 100644 --- a/src/g_doom/a_doommisc.cpp +++ b/src/g_doom/a_doommisc.cpp @@ -24,7 +24,6 @@ // Include all the other Doom stuff here to reduce compile time #include "a_bossbrain.cpp" #include "a_doomweaps.cpp" -#include "a_lostsoul.cpp" #include "a_painelemental.cpp" #include "a_revenant.cpp" #include "a_scriptedmarine.cpp" diff --git a/src/g_doom/a_lostsoul.cpp b/src/g_doom/a_lostsoul.cpp deleted file mode 100644 index 1c33f47a7d..0000000000 --- a/src/g_doom/a_lostsoul.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* -#include "templates.h" -#include "actor.h" -#include "info.h" -#include "m_random.h" -#include "s_sound.h" -#include "p_local.h" -#include "p_enemy.h" -#include "gi.h" -#include "gstrings.h" -#include "a_action.h" -#include "vm.h" -*/ - - FRandom pr_oldsoul ("BetaLostSoul"); - -// -// SkullAttack -// Fly at the player like a missile. -// - -void A_SkullAttack(AActor *self, double speed) -{ - AActor *dest; - if (!self->target) - return; - - dest = self->target; - self->flags |= MF_SKULLFLY; - - S_Sound (self, CHAN_VOICE, self->AttackSound, 1, ATTN_NORM); - A_FaceTarget (self); - self->VelFromAngle(speed); - self->Vel.Z = (dest->Center() - self->Z()) / self->DistanceBySpeed(dest, speed); -} - -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SkullAttack) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_FLOAT_DEF(speed); - - if (speed <= 0) - speed = SKULLSPEED; - A_SkullAttack(self, speed); - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_BetaSkullAttack) -{ - PARAM_SELF_PROLOGUE(AActor); - - int damage; - if (!self || !self->target || self->target->GetSpecies() == self->GetSpecies()) - return 0; - S_Sound (self, CHAN_WEAPON, self->AttackSound, 1, ATTN_NORM); - A_FaceTarget(self); - damage = (pr_oldsoul()%8+1)*self->GetMissileDamage(0,1); - P_DamageMobj(self->target, self, self, damage, NAME_None); - return 0; -} - - - -//========================================================================== -// -// CVAR transsouls -// -// How translucent things drawn with STYLE_SoulTrans are. Normally, only -// Lost Souls have this render style, but a dehacked patch could give other -// things this style. Values less than 0.25 will automatically be set to -// 0.25 to ensure some degree of visibility. Likewise, values above 1.0 will -// be set to 1.0, because anything higher doesn't make sense. -// -//========================================================================== - -CUSTOM_CVAR (Float, transsouls, 0.75f, CVAR_ARCHIVE) -{ - if (self < 0.25f) - { - self = 0.25f; - } - else if (self > 1.f) - { - self = 1.f; - } -} diff --git a/src/g_doom/a_painelemental.cpp b/src/g_doom/a_painelemental.cpp index 09160ddeb6..f2db5a2402 100644 --- a/src/g_doom/a_painelemental.cpp +++ b/src/g_doom/a_painelemental.cpp @@ -21,7 +21,7 @@ enum PA_Flags // A_PainShootSkull // Spawn a lost soul and launch it at the target // -void A_PainShootSkull (AActor *self, DAngle Angle, PClassActor *spawntype, int flags = 0, int limit = -1) +void A_PainShootSkull (VMFrameStack *stack, AActor *self, DAngle Angle, PClassActor *spawntype, int flags = 0, int limit = -1) { AActor *other; double prestep; @@ -137,7 +137,10 @@ void A_PainShootSkull (AActor *self, DAngle Angle, PClassActor *spawntype, int f other->CopyFriendliness (self, !(flags & PAF_NOTARGET)); if (!(flags & PAF_NOSKULLATTACK)) - A_SkullAttack(other, SKULLSPEED); + { + DECLARE_VMFUNC(AActor, A_SkullAttack); + CallAction(stack, A_SkullAttack, other); + } } @@ -148,7 +151,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_PainShootSkull) PARAM_FLOAT(angle); PARAM_INT_DEF(flags); PARAM_INT_DEF(limit); - A_PainShootSkull(self, angle, spawntype, flags, limit); + A_PainShootSkull(stack, self, angle, spawntype, flags, limit); + return 0; } diff --git a/src/info.cpp b/src/info.cpp index 26bd306fa8..4705e0e533 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -68,7 +68,7 @@ cycle_t ActionCycles; void FState::SetAction(const char *name) { - ActionFunc = FindGlobalActionFunction(name)->Variants[0].Implementation; + ActionFunc = FindVMFunction(RUNTIME_CLASS(AActor), name); } bool FState::CallAction(AActor *self, AActor *stateowner, FStateParamInfo *info, FState **stateret) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 3ea4a25e19..d0c0af1f55 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -6445,6 +6445,12 @@ FName AActor::GetSpecies() return Species = thistype->TypeName; // [GZ] Speeds up future calls. } +DEFINE_ACTION_FUNCTION(AActor, GetSpecies) +{ + PARAM_SELF_PROLOGUE(AActor); + ACTION_RETURN_INT(self->GetSpecies()); +} + //========================================================================== // // AActor :: IsFriend @@ -6850,6 +6856,14 @@ DEFINE_ACTION_FUNCTION(AActor, VelFromAngle) return 0; } +DEFINE_ACTION_FUNCTION(AActor, DistanceBySpeed) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(targ, AActor); + PARAM_FLOAT(speed); + ACTION_RETURN_FLOAT(self->DistanceBySpeed(targ, speed)); +} + DEFINE_ACTION_FUNCTION(AActor, SetXYZ) { PARAM_SELF_PROLOGUE(AActor); @@ -6879,6 +6893,7 @@ DEFINE_ACTION_FUNCTION(AActor, Vec2OffsetZ) PARAM_BOOL_DEF(absolute); ACTION_RETURN_VEC3(self->Vec2OffsetZ(x, y, z, absolute)); } + //---------------------------------------------------------------------------- // // DropItem handling diff --git a/src/r_utility.cpp b/src/r_utility.cpp index b009912f03..1588349299 100644 --- a/src/r_utility.cpp +++ b/src/r_utility.cpp @@ -1104,3 +1104,27 @@ void FCanvasTextureInfo::Mark() } } + +//========================================================================== +// +// CVAR transsouls +// +// How translucent things drawn with STYLE_SoulTrans are. Normally, only +// Lost Souls have this render style. +// Values less than 0.25 will automatically be set to +// 0.25 to ensure some degree of visibility. Likewise, values above 1.0 will +// be set to 1.0, because anything higher doesn't make sense. +// +//========================================================================== + +CUSTOM_CVAR(Float, transsouls, 0.75f, CVAR_ARCHIVE) +{ + if (self < 0.25f) + { + self = 0.25f; + } + else if (self > 1.f) + { + self = 1.f; + } +} diff --git a/src/scripting/decorate/thingdef_states.cpp b/src/scripting/decorate/thingdef_states.cpp index 59cf309386..3b99309285 100644 --- a/src/scripting/decorate/thingdef_states.cpp +++ b/src/scripting/decorate/thingdef_states.cpp @@ -99,7 +99,9 @@ FxVMFunctionCall *DoActionSpecials(FScanner &sc, FState & state, Baggage &bag) { sc.ScriptError ("Too many arguments to %s", specname.GetChars()); } - return new FxVMFunctionCall(new FxSelf(sc), FindGlobalActionFunction("A_CallSpecial"), args, sc, false); + auto f = dyn_cast(RUNTIME_CLASS(AActor)->Symbols.FindSymbol("A_CallSpecial", false)); + assert(f != nullptr); + return new FxVMFunctionCall(new FxSelf(sc), f, args, sc, false); } return NULL; } diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 74c685ea83..8152e9977b 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -602,9 +602,10 @@ AFuncDesc *FindFunction(const char * string) // //========================================================================== -PFunction *FindGlobalActionFunction(const char *name) +VMFunction *FindVMFunction(PClass *cls, const char *name) { - return dyn_cast(RUNTIME_CLASS(AActor)->Symbols.FindSymbol(name, false)); + auto f = dyn_cast(cls->Symbols.FindSymbol(name, true)); + return f == nullptr ? nullptr : f->Variants[0].Implementation; } diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index 3120bbd61d..abce2f5571 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -1071,7 +1071,8 @@ void CallAction(VMFrameStack *stack, VMFunction *vmfunc, AActor *self); class PFunction; -PFunction *FindGlobalActionFunction(const char *name); +VMFunction *FindVMFunction(PClass *cls, const char *name); +#define DECLARE_VMFUNC(cls, name) static VMFunction *name; if (name == nullptr) name = FindVMFunction(RUNTIME_CLASS(cls), #name); diff --git a/src/scripting/vm/vmframe.cpp b/src/scripting/vm/vmframe.cpp index 1ccf3321e1..f622e114d2 100644 --- a/src/scripting/vm/vmframe.cpp +++ b/src/scripting/vm/vmframe.cpp @@ -495,6 +495,7 @@ int VMFrameStack::Call(VMFunction *func, VMValue *params, int numparams, VMRetur class AActor; void CallAction(VMFrameStack *stack, VMFunction *vmfunc, AActor *self) { - VMValue params[3] = { self, self, VMValue(nullptr, ATAG_GENERIC) }; + // Without the type cast this picks the 'void *' assignment... + VMValue params[3] = { (DObject*)self, (DObject*)self, VMValue(nullptr, ATAG_GENERIC) }; stack->Call(vmfunc, params, vmfunc->ImplicitArgs, nullptr, 0, nullptr); } diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 0365be6573..287808b673 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -81,6 +81,8 @@ class Actor : Thinker native native void CopyFriendliness (Actor other, bool changeTarget, bool resetHealth = true); native bool LookForPlayers(bool allaround); native bool TeleportMove(Vector3 pos, bool telefrag, bool modifyactor = true); + native double DistanceBySpeed(Actor other, double speed); + native name GetSpecies(); // DECORATE compatible functions native bool CheckClass(class checkclass, int ptr_select = AAPTR_DEFAULT, bool match_superclass = false); @@ -241,8 +243,6 @@ class Actor : Thinker native native void A_SkelFist(); native void A_SkelMissile(); native void A_BossDeath(); - native void A_SkullAttack(float speed = 20); - native void A_BetaSkullAttack(); native void A_Detonate(); native bool A_CallSpecial(int special, int arg1=0, int arg2=0, int arg3=0, int arg4=0, int arg5=0); diff --git a/wadsrc/static/zscript/doom/lostsoul.txt b/wadsrc/static/zscript/doom/lostsoul.txt index 69574e5c7c..00158e071c 100644 --- a/wadsrc/static/zscript/doom/lostsoul.txt +++ b/wadsrc/static/zscript/doom/lostsoul.txt @@ -81,3 +81,41 @@ class BetaSkull : LostSoul Wait; } } + +//=========================================================================== +// +// Code (must be attached to Actor) +// +//=========================================================================== + +extend class Actor +{ + const SKULLSPEED = 20; + + void A_SkullAttack(float skullspeed = SKULLSPEED) + { + if (target == null) return; + + if (skullspeed <= 0) skullspeed = SKULLSPEED; + + bSkullfly = true; + A_PlaySound(AttackSound, CHAN_VOICE); + A_FaceTarget(); + VelFromAngle(skullspeed); + Vel.Z = (target.pos.Z + target.Height/2 - Vel.Z) / DistanceBySpeed(target, speed); + } + + void A_BetaSkullAttack() + { + if (target == null || target.GetSpecies() == self.GetSpecies()) return; + + A_PlaySound(AttackSound, CHAN_WEAPON); + A_FaceTarget(); + + int damage = GetMissileDamage(7,1); + target.DamageMobj(self, self, damage, 'None'); + } +} + + +