From 062574b7266a8ffcde3bf04c9d32d6e11318dcce Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 6 Nov 2016 11:36:12 +0100 Subject: [PATCH] - fixed damage handling in A_BetaSkullAttack. For unknown reasons this completely bypassed the normal damage function semantics and even multiplied that with a random value. - made some tests about calling script code from native functions. * scriptified A_SkullAttack to have something to test * changed the A_SkullAttack call in A_PainShootSkull. * use a macro to declare the function pointer. Using local static variable init directly results in hideous code for the need of being thread-safe (which, even if the engine was made multithreaded is not needed here.) * Importsnt node here: Apparently passing an actor pointer to the VMValue constructor results in the void * version being called, not the DObject * version. --- src/g_doom/a_doommisc.cpp | 1 - src/g_doom/a_lostsoul.cpp | 86 ---------------------- src/g_doom/a_painelemental.cpp | 10 ++- src/info.cpp | 2 +- src/p_mobj.cpp | 15 ++++ src/r_utility.cpp | 24 ++++++ src/scripting/decorate/thingdef_states.cpp | 4 +- src/scripting/thingdef_data.cpp | 5 +- src/scripting/vm/vm.h | 3 +- src/scripting/vm/vmframe.cpp | 3 +- wadsrc/static/zscript/actor.txt | 4 +- wadsrc/static/zscript/doom/lostsoul.txt | 38 ++++++++++ 12 files changed, 97 insertions(+), 98 deletions(-) delete mode 100644 src/g_doom/a_lostsoul.cpp diff --git a/src/g_doom/a_doommisc.cpp b/src/g_doom/a_doommisc.cpp index 9f3178295..1df9a4e7c 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 1c33f47a7..000000000 --- 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 09160ddeb..f2db5a240 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 26bd306fa..4705e0e53 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 3ea4a25e1..d0c0af1f5 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 b009912f0..158834929 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 59cf30938..3b9930928 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 74c685ea8..8152e9977 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 3120bbd61..abce2f557 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 1ccf3321e..f622e114d 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 0365be657..287808b67 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 69574e5c7..00158e071 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'); + } +} + + +