diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f96bf7d36..12df2e61c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -835,7 +835,6 @@ set( NOT_COMPILED_SOURCE_FILES ${OTHER_SYSTEM_SOURCES} sc_man_scanner.h sc_man_scanner.re - g_doom/a_archvile.cpp g_doom/a_bossbrain.cpp g_doom/a_doomweaps.cpp g_doom/a_keen.cpp diff --git a/src/g_doom/a_archvile.cpp b/src/g_doom/a_archvile.cpp deleted file mode 100644 index 959c5763d..000000000 --- a/src/g_doom/a_archvile.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/* -#include "actor.h" -#include "info.h" -#include "p_local.h" -#include "s_sound.h" -#include "p_enemy.h" -#include "gstrings.h" -#include "a_action.h" -#include "vm.h" -*/ - -// -// PIT_VileCheck -// Detect a corpse that could be raised. -// -void A_Fire(AActor *self, double height); - - -// -// A_VileStart -// -DEFINE_ACTION_FUNCTION(AActor, A_VileStart) -{ - PARAM_SELF_PROLOGUE(AActor); - S_Sound (self, CHAN_VOICE, "vile/start", 1, ATTN_NORM); - return 0; -} - - -// -// A_Fire -// Keep fire in front of player unless out of sight -// -DEFINE_ACTION_FUNCTION(AActor, A_StartFire) -{ - PARAM_SELF_PROLOGUE(AActor); - S_Sound (self, CHAN_BODY, "vile/firestrt", 1, ATTN_NORM); - A_Fire (self, 0); - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_FireCrackle) -{ - PARAM_SELF_PROLOGUE(AActor); - S_Sound (self, CHAN_BODY, "vile/firecrkl", 1, ATTN_NORM); - A_Fire (self, 0); - return 0; -} - -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Fire) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_FLOAT_DEF(height); - - A_Fire(self, height); - return 0; -} - -void A_Fire(AActor *self, double height) -{ - AActor *dest; - - dest = self->tracer; - if (dest == NULL || self->target == NULL) - return; - - // don't move it if the vile lost sight - if (!P_CheckSight (self->target, dest, 0) ) - return; - - DVector3 newpos = dest->Vec3Angle(24., dest->Angles.Yaw, height); - self->SetOrigin(newpos, true); -} - - - -// -// A_VileTarget -// Spawn the hellfire -// -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_VileTarget) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_CLASS_DEF(fire, AActor); - - AActor *fog; - - if (!self->target) - return 0; - - A_FaceTarget (self); - - fog = Spawn (fire, self->target->Pos(), ALLOW_REPLACE); - - self->tracer = fog; - fog->target = self; - fog->tracer = self->target; - A_Fire(fog, 0); - return 0; -} - - - - -// -// A_VileAttack -// - -// A_VileAttack flags -#define VAF_DMGTYPEAPPLYTODIRECT 1 - -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_VileAttack) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_SOUND_DEF (snd) - PARAM_INT_DEF (dmg) - PARAM_INT_DEF (blastdmg) - PARAM_INT_DEF (blastrad) - PARAM_FLOAT_DEF (thrust) - PARAM_NAME_DEF (dmgtype) - PARAM_INT_DEF (flags) - - AActor *fire, *target; - - if (NULL == (target = self->target)) - return 0; - - A_FaceTarget (self); - - if (!P_CheckSight (self, target, 0) ) - return 0; - - S_Sound (self, CHAN_WEAPON, snd, 1, ATTN_NORM); - - int newdam; - - if (flags & VAF_DMGTYPEAPPLYTODIRECT) - newdam = P_DamageMobj (target, self, self, dmg, dmgtype); - - else - newdam = P_DamageMobj (target, self, self, dmg, NAME_None); - - P_TraceBleed (newdam > 0 ? newdam : dmg, target); - - fire = self->tracer; - - if (fire != NULL) - { - // move the fire between the vile and the player - DVector3 pos = target->Vec3Angle(-24., self->Angles.Yaw, 0); - fire->SetOrigin (pos, true); - - P_RadiusAttack (fire, self, blastdmg, blastrad, dmgtype, 0); - } - if (!(target->flags7 & MF7_DONTTHRUST)) - { - target->Vel.Z = thrust * 1000 / MAX(1, target->Mass); - } - return 0; -} diff --git a/src/g_doom/a_doommisc.cpp b/src/g_doom/a_doommisc.cpp index 29e2fc8ee..31ee228f8 100644 --- a/src/g_doom/a_doommisc.cpp +++ b/src/g_doom/a_doommisc.cpp @@ -22,7 +22,6 @@ #include "vm.h" // Include all the other Doom stuff here to reduce compile time -#include "a_archvile.cpp" #include "a_bossbrain.cpp" #include "a_doomweaps.cpp" #include "a_keen.cpp" diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index 9f3a088d6..4748b1708 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -1362,6 +1362,7 @@ enum XF_HURTSOURCE = 1, XF_NOTMISSILE = 4, XF_NOACTORTYPE = 1 << 3, + XF_NOSPLASH = 16, }; DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Explode) @@ -1412,7 +1413,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Explode) if (flags & XF_NOTMISSILE) pflags |= RADF_SOURCEISSPOT; int count = P_RadiusAttack (self, self->target, damage, distance, damagetype, pflags, fulldmgdistance); - P_CheckSplash(self, distance); + if (!(flags & XF_NOSPLASH)) P_CheckSplash(self, distance); if (alert && self->target != NULL && self->target->player != NULL) { P_NoiseAlert(self->target, self); diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 3fd1be9a1..26987e622 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -6647,6 +6647,16 @@ DEFINE_ACTION_FUNCTION(AActor, SetXYZ) return 0; } +DEFINE_ACTION_FUNCTION(AActor, Vec3Angle) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_FLOAT(length) + PARAM_ANGLE(angle); + PARAM_FLOAT(z); + PARAM_BOOL_DEF(absolute); + ACTION_RETURN_VEC3(self->Vec3Angle(length, angle, z, absolute)); +} + //---------------------------------------------------------------------------- // // DropItem handling diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 4fa6da73e..66a7d8b41 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -345,6 +345,7 @@ static int EncodeRegType(ExpEmit reg) else if (reg.RegCount == 2) { regtype |= REGT_MULTIREG2; + } else if (reg.RegCount == 3) { @@ -3808,7 +3809,7 @@ FxExpression *FxConditional::Resolve(FCompileContext& ctx) ValueType = TypeVoid; //else if (truex->ValueType != falsex->ValueType) - if ((!IsNumeric() && !IsPointer() && !IsVector()) || ValueType == TypeVoid) + if (ValueType->GetRegType() == REGT_NIL) { ScriptPosition.Message(MSG_ERROR, "Incompatible types for ?: operator"); delete this; diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index 4109d4e79..ca7aa6d54 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -4,6 +4,7 @@ #include "zstring.h" #include "dobject.h" #include "autosegs.h" +#include "vectors.h" #define MAX_RETURNS 8 // Maximum number of results a function called by script code can return #define MAX_TRY_DEPTH 8 // Maximum number of nested TRYs in a single function @@ -296,12 +297,25 @@ struct VMReturn ((double *)Location)[1] = val[1]; ((double *)Location)[2] = val[2]; } + void SetVector(const DVector3 &val) + { + assert(RegType == (REGT_FLOAT | REGT_MULTIREG3)); + ((double *)Location)[0] = val[0]; + ((double *)Location)[1] = val[1]; + ((double *)Location)[2] = val[2]; + } void SetVector2(const double val[2]) { assert(RegType == (REGT_FLOAT|REGT_MULTIREG2)); ((double *)Location)[0] = val[0]; ((double *)Location)[1] = val[1]; } + void SetVector2(const DVector2 &val) + { + assert(RegType == (REGT_FLOAT | REGT_MULTIREG2)); + ((double *)Location)[0] = val[0]; + ((double *)Location)[1] = val[1]; + } void SetString(const FString &val) { assert(RegType == REGT_STRING); @@ -1029,6 +1043,7 @@ struct AFuncDesc #define ACTION_RETURN_STATE(v) do { FState *state = v; if (numret > 0) { assert(ret != NULL); ret->SetPointer(state, ATAG_STATE); return 1; } return 0; } while(0) #define ACTION_RETURN_OBJECT(v) do { auto state = v; if (numret > 0) { assert(ret != NULL); ret->SetPointer(state, ATAG_OBJECT); return 1; } return 0; } while(0) #define ACTION_RETURN_FLOAT(v) do { double u = v; if (numret > 0) { assert(ret != nullptr); ret->SetFloat(u); return 1; } return 0; } while(0) +#define ACTION_RETURN_VEC3(v) do { DVector3 u = v; if (numret > 0) { assert(ret != nullptr); ret[0].SetVector(u); return 1; } return 0; } while(0) #define ACTION_RETURN_INT(v) do { int u = v; if (numret > 0) { assert(ret != NULL); ret->SetInt(u); return 1; } return 0; } while(0) #define ACTION_RETURN_BOOL(v) ACTION_RETURN_INT(v) diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 4fc18d75d..83ea76cb7 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -70,6 +70,7 @@ class Actor : Thinker native native bool SetState(state st, bool nofunction = false); native void LinkToWorld(); native void UnlinkFromWorld(); + native vector3 Vec3Angle(float length, float angle, float z = 0, bool absolute = false); native void VelFromAngle(float speed = 0, float angle = 0); native bool isFriend(Actor other); @@ -209,12 +210,6 @@ class Actor : Thinker native native void A_Chase(state melee = null, state missile = null, int flags = 0); native void A_Scream(); native void A_VileChase(); - native void A_VileStart(); - native void A_VileTarget(class fire = "ArchvileFire"); - native void A_VileAttack(sound snd = "vile/stop", int initialdmg = 20, int blastdmg = 70, int blastradius = 70, float thrustfac = 1.0, name damagetype = "Fire", int flags = 0); - native void A_StartFire(); - native void A_Fire(float spawnheight = 0); - native void A_FireCrackle(); native void A_Tracer(); native void A_SkelWhoosh(); native void A_SkelFist(); diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index 5cbbbaf9e..9562e3f40 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -243,7 +243,8 @@ enum EExplodeFlags { XF_HURTSOURCE = 1, XF_NOTMISSILE = 4, - XF_EXPLICITDAMAGETYPE = 1 << 3, + XF_EXPLICITDAMAGETYPE = 8, + XF_NOSPLASH = 16, }; // Flags for A_RadiusThrust diff --git a/wadsrc/static/zscript/doom/archvile.txt b/wadsrc/static/zscript/doom/archvile.txt index bdca2b05f..0e9008570 100644 --- a/wadsrc/static/zscript/doom/archvile.txt +++ b/wadsrc/static/zscript/doom/archvile.txt @@ -87,3 +87,91 @@ class ArchvileFire : Actor } } + +//=========================================================================== +// +// Code (must be attached to Actor) +// +//=========================================================================== + +// A_VileAttack flags +//#define VAF_DMGTYPEAPPLYTODIRECT 1 + +extend class Actor +{ + + void A_VileStart() + { + A_PlaySound ("vile/start", CHAN_VOICE); + } + + // + // A_VileTarget + // Spawn the hellfire + // + void A_VileTarget(class fire = "ArchvileFire") + { + if (target) + { + A_FaceTarget (); + + Actor fog = Spawn (fire, target.Pos, ALLOW_REPLACE); + tracer = fog; + fog.target = self; + fog.tracer = self.target; + fog.A_Fire(0); + } + } + + void A_VileAttack(sound snd = "vile/stop", int initialdmg = 20, int blastdmg = 70, int blastradius = 70, float thrust = 1.0, name damagetype = "Fire", int flags = 0) + { + if (target) + { + A_FaceTarget(); + if (!CheckSight(target, 0)) return; + A_PlaySound(snd, CHAN_WEAPON); + int newdam = target.DamageMobj (self, self, initialdmg, (flags & VAF_DMGTYPEAPPLYTODIRECT)? damagetype : 'none'); + + TraceBleed (newdam > 0 ? newdam : initialdmg, target); + + Actor fire = tracer; + if (fire) + { + // move the fire between the vile and the player + fire.SetOrigin(target.Vec3Angle(-24., angle, 0), true); + fire.A_Explode(blastdmg, blastradius, XF_NOSPLASH, false, 0, 0, 0, "BulletPuff", damagetype); + } + if (!target.bDontThrust) + { + target.Vel.z = thrust * 1000 / max(1, target.Mass); + } + } + } + + void A_StartFire() + { + A_PlaySound ("vile/firestrt", CHAN_BODY); + A_Fire(); + } + + // + // A_Fire + // Keep fire in front of player unless out of sight + // + void A_Fire(float spawnheight = 0) + { + Actor dest = tracer; + if (!dest || !target) return; + + // don't move it if the vile lost sight + if (!target.CheckSight (dest, 0) ) return; + + SetOrigin(dest.Vec3Angle(24, dest.angle, height), true); + } + + void A_FireCrackle() + { + A_PlaySound ("vile/firecrkl", CHAN_BODY); + A_Fire(); + } +}