diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 77e756b38..9499cb64f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -824,7 +824,6 @@ endif() file( GLOB HEADER_FILES ${EXTRA_HEADER_DIRS} fragglescript/*.h - g_doom/*.h g_heretic/*.h g_hexen/*.h g_raven/*.h @@ -858,7 +857,6 @@ set( NOT_COMPILED_SOURCE_FILES ${OTHER_SYSTEM_SOURCES} sc_man_scanner.h sc_man_scanner.re - g_doom/a_painelemental.cpp g_heretic/a_dsparil.cpp g_heretic/a_hereticartifacts.cpp g_heretic/a_hereticweaps.cpp @@ -1153,7 +1151,6 @@ set (PCH_SOURCES w_wad.cpp wi_stuff.cpp zstrformat.cpp - g_doom/a_doommisc.cpp g_heretic/a_hereticmisc.cpp g_hexen/a_hexenmisc.cpp g_raven/a_artitele.cpp @@ -1309,7 +1306,6 @@ endif() target_link_libraries( zdoom ${ZDOOM_LIBS} gdtoa dumb lzma ) include_directories( . - g_doom g_heretic g_hexen g_raven @@ -1443,7 +1439,6 @@ source_group("External\\Math" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/m source_group("External\\RapidJSON" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/rapidjson/.+") source_group("Externak\\SFMT" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/sfmt/.+") source_group("FraggleScript" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/fragglescript/.+") -source_group("Games\\Doom Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_doom/.+") source_group("Games\\Heretic Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_heretic/.+") source_group("Games\\Hexen Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_hexen/.+") source_group("Games\\Raven Shared" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_raven/.+") diff --git a/src/g_doom/a_doomglobal.h b/src/g_doom/a_doomglobal.h deleted file mode 100644 index 73e3d3239..000000000 --- a/src/g_doom/a_doomglobal.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef __A_DOOMGLOBAL_H__ -#define __A_DOOMGLOBAL_H__ - -#include "info.h" - -class AScriptedMarine : public AActor -{ - DECLARE_CLASS (AScriptedMarine, AActor) -public: - - void Activate (AActor *activator); - void Deactivate (AActor *activator); - void BeginPlay (); - void Tick (); - void SetWeapon (EMarineWeapon); - void SetSprite (PClassActor *source); - - void Serialize(FSerializer &arc); - - int CurrentWeapon; - -protected: - bool GetWeaponStates(int weap, FState *&melee, FState *&missile); - - int SpriteOverride; -}; - -#endif //__A_DOOMGLOBAL_H__ diff --git a/src/g_doom/a_doommisc.cpp b/src/g_doom/a_doommisc.cpp deleted file mode 100644 index 40c8e2f8d..000000000 --- a/src/g_doom/a_doommisc.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "actor.h" -#include "info.h" -#include "p_local.h" -#include "p_spec.h" -#include "a_sharedglobal.h" -#include "m_random.h" -#include "gi.h" -#include "doomstat.h" -#include "gstrings.h" -#include "g_level.h" -#include "p_enemy.h" -#include "a_specialspot.h" -#include "templates.h" -#include "m_bbox.h" -#include "portal.h" -#include "d_player.h" -#include "p_maputl.h" -#include "serializer.h" -#include "g_shared/a_pickups.h" - -// Include all the other Doom stuff here to reduce compile time -#include "a_painelemental.cpp" diff --git a/src/g_doom/a_painelemental.cpp b/src/g_doom/a_painelemental.cpp deleted file mode 100644 index 3fca0896c..000000000 --- a/src/g_doom/a_painelemental.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/* -#include "actor.h" -#include "info.h" -#include "p_enemy.h" -#include "p_local.h" -#include "a_action.h" -#include "templates.h" -#include "m_bbox.h" -#include "vm.h" -#include "doomstat.h" -*/ - -enum PA_Flags -{ - PAF_NOSKULLATTACK = 1, - PAF_AIMFACING = 2, - PAF_NOTARGET = 4, -}; - -// -// A_PainShootSkull -// Spawn a lost soul and launch it at the target -// -void A_PainShootSkull (VMFrameStack *stack, AActor *self, DAngle Angle, PClassActor *spawntype, int flags = 0, int limit = -1) -{ - AActor *other; - double prestep; - - if (spawntype == NULL) spawntype = PClass::FindActor("LostSoul"); - assert(spawntype != NULL); - if (self->DamageType == NAME_Massacre) return; - - // [RH] check to make sure it's not too close to the ceiling - if (self->Top() + 8 > self->ceilingz) - { - if (self->flags & MF_FLOAT) - { - self->Vel.Z -= 2; - self->flags |= MF_INFLOAT; - self->flags4 |= MF4_VFRICTION; - } - return; - } - - // [RH] make this optional - if (limit == -1 && (i_compatflags & COMPATF_LIMITPAIN)) - limit = 21; - - if (limit) - { - // count total number of skulls currently on the level - // if there are already 21 skulls on the level, don't spit another one - int count = limit; - FThinkerIterator iterator (spawntype); - DThinker *othink; - - while ( (othink = iterator.Next ()) ) - { - if (--count == 0) - return; - } - } - - // okay, there's room for another one - double otherradius = GetDefaultByType(spawntype)->radius; - prestep = 4 + (self->radius + otherradius) * 1.5; - - DVector2 move = Angle.ToVector(prestep); - DVector3 spawnpos = self->PosPlusZ(8.0); - DVector3 destpos = spawnpos + move; - - other = Spawn(spawntype, spawnpos, ALLOW_REPLACE); - - // Now check if the spawn is legal. Unlike Boom's hopeless attempt at fixing it, let's do it the same way - // P_XYMovement solves the line skipping: Spawn the Lost Soul near the PE's center and then use multiple - // smaller steps to get it to its intended position. This will also result in proper clipping, but - // it will avoid all the problems of the Boom method, which checked too many lines and despite some - // adjustments never worked with portals. - - if (other != nullptr) - { - double maxmove = other->radius - 1; - - if (maxmove <= 0) maxmove = MAXMOVE; - - const double xspeed = fabs(move.X); - const double yspeed = fabs(move.Y); - - int steps = 1; - - if (xspeed > yspeed) - { - if (xspeed > maxmove) - { - steps = int(1 + xspeed / maxmove); - } - } - else - { - if (yspeed > maxmove) - { - steps = int(1 + yspeed / maxmove); - } - } - - DVector2 stepmove = move / steps; - self->flags &= ~MF_SOLID; // make it solid again - other->flags2 |= MF2_NOTELEPORT; // we do not want the LS to teleport - for (int i = 0; i < steps; i++) - { - DVector2 ptry = other->Pos().XY() + stepmove; - DAngle oldangle = other->Angles.Yaw; - if (!P_TryMove(other, ptry, 0, nullptr)) - { - // kill it immediately - other->ClearCounters(); - P_DamageMobj(other, self, self, TELEFRAG_DAMAGE, NAME_None); - return; - } - - if (other->Pos().XY() != ptry) - { - // If the new position does not match the desired position, the player - // must have gone through a portal. - // For that we need to adjust the movement vector for the following steps. - DAngle anglediff = deltaangle(oldangle, other->Angles.Yaw); - - if (anglediff != 0) - { - stepmove = stepmove.Rotated(anglediff); - } - } - - } - self->flags |= MF_SOLID; // don't let the LS be stuck in the PE while checking the move - - // [RH] Lost souls hate the same things as their pain elementals - other->CopyFriendliness (self, !(flags & PAF_NOTARGET)); - - if (!(flags & PAF_NOSKULLATTACK)) - { - DECLARE_VMFUNC(AActor, A_SkullAttack); - CallAction(stack, A_SkullAttack, other); - } - } -} - - -DEFINE_ACTION_FUNCTION(AActor, A_PainShootSkull) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_CLASS(spawntype, AActor); - PARAM_FLOAT(angle); - PARAM_INT_DEF(flags); - PARAM_INT_DEF(limit); - A_PainShootSkull(stack, self, angle, spawntype, flags, limit); - - return 0; -} - diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index a4dc45df2..075d34c4e 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -7115,6 +7115,23 @@ DEFINE_ACTION_FUNCTION(AActor, AngleTo) ACTION_RETURN_FLOAT(self->AngleTo(targ, absolute).Degrees); } +DEFINE_ACTION_FUNCTION(AActor, AngleToVector) +{ + PARAM_PROLOGUE; + PARAM_ANGLE(angle); + PARAM_FLOAT_DEF(length); + ACTION_RETURN_VEC2(angle.ToVector(length)); +} + +DEFINE_ACTION_FUNCTION(AActor, RotateVector) +{ + PARAM_PROLOGUE; + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_ANGLE(angle); + ACTION_RETURN_VEC2(DVector2(x, y).Rotated(angle)); +} + DEFINE_ACTION_FUNCTION(AActor, DistanceBySpeed) { PARAM_SELF_PROLOGUE(AActor); diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index 7b05fae36..05c43aa1f 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -1097,6 +1097,7 @@ void CallAction(VMFrameStack *stack, VMFunction *vmfunc, AActor *self); #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_VEC2(v) do { DVector2 u = v; if (numret > 0) { assert(ret != nullptr); ret[0].SetVector2(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 da9db687c..1aa02e5af 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -4,6 +4,8 @@ class Actor : Thinker native const ONFLOORZ = -2147483648.0; const ONCEILINGZ = 2147483647.0; const FLOATRANDZ = ONCEILINGZ-1; + const TELEFRAG_DAMAGE = 1000000; + // flags are not defined here, the native fields for those get synthesized from the internal tables. @@ -215,6 +217,13 @@ class Actor : Thinker native // Functions + // 'parked' global functions. + native static double deltaangle(double ang1, double ang2); + native static double absangle(double ang1, double ang2); + native static Vector2 AngleToVector(double angle, double length = 1); + native static Vector2 RotateVector(Vector2 vec, double angle); + + bool IsPointerEqual(int ptr_select1, int ptr_select2) { return GetPointer(ptr_select1) == GetPointer(ptr_select2); @@ -231,8 +240,6 @@ class Actor : Thinker native native void AdjustPlayerAngle(FTranslatedLineTarget t); native static readonly GetDefaultByType(class cls); - native static double deltaangle(double ang1, double ang2); - native static double absangle(double ang1, double ang2); native static double GetDefaultSpeed(class type); native void RemoveFromHash(); native string GetTag(string defstr = ""); diff --git a/wadsrc/static/zscript/doom/painelemental.txt b/wadsrc/static/zscript/doom/painelemental.txt index 03a4d82c4..fe9e0590a 100644 --- a/wadsrc/static/zscript/doom/painelemental.txt +++ b/wadsrc/static/zscript/doom/painelemental.txt @@ -61,8 +61,139 @@ class PainElemental : Actor extend class Actor { - native void A_PainShootSkull(Class spawntype, double angle, int flags = 0, int limit = -1); + // + // A_PainShootSkull + // Spawn a lost soul and launch it at the target + // + void A_PainShootSkull(Class spawntype, double angle, int flags = 0, int limit = -1) + { + // Don't spawn if we get massacred. + if (DamageType == 'Massacre') return; + if (spawntype == null) spawntype = "LostSoul"; + + // [RH] check to make sure it's not too close to the ceiling + if (pos.z + height + 8 > ceilingz) + { + if (bFloat) + { + Vel.Z -= 2; + bInFloat = true; + bVFriction = true; + } + return; + } + + // [RH] make this optional + if (limit < 0 && compat_limitpain) + limit = 21; + + if (limit > 0) + { + // count total number of skulls currently on the level + // if there are already 21 skulls on the level, don't spit another one + int count = limit; + ThinkerIterator it = ThinkerIterator.Create(spawntype); + Thinker othink; + + while ( (othink = it.Next ()) ) + { + if (--count == 0) + return; + } + } + + // okay, there's room for another one + double otherradius = GetDefaultByType(spawntype).radius; + double prestep = 4 + (radius + otherradius) * 1.5; + + Vector2 move = AngleToVector(angle, prestep); + Vector3 spawnpos = pos + (0,0,8); + Vector3 destpos = spawnpos + move; + + Actor other = Spawn(spawntype, spawnpos, ALLOW_REPLACE); + + // Now check if the spawn is legal. Unlike Boom's hopeless attempt at fixing it, let's do it the same way + // P_XYMovement solves the line skipping: Spawn the Lost Soul near the PE's center and then use multiple + // smaller steps to get it to its intended position. This will also result in proper clipping, but + // it will avoid all the problems of the Boom method, which checked too many lines that weren't even touched + // and despite some adjustments never worked with portals. + + if (other != null) + { + double maxmove = other.radius - 1; + + if (maxmove <= 0) maxmove = 16; + + double xspeed = abs(move.X); + double yspeed = abs(move.Y); + + int steps = 1; + + if (xspeed > yspeed) + { + if (xspeed > maxmove) + { + steps = int(1 + xspeed / maxmove); + } + } + else + { + if (yspeed > maxmove) + { + steps = int(1 + yspeed / maxmove); + } + } + + Vector2 stepmove = move / steps; + bool savedsolid = bSolid; + bool savednoteleport = other.bNoTeleport; + + // make the PE nonsolid for the check and the LS non-teleporting so that P_TryMove doesn't do unwanted things. + bSolid = false; + other.bNoTeleport = true; + for (int i = 0; i < steps; i++) + { + Vector2 ptry = other.pos.xy + stepmove; + double oldangle = other.angle; + if (!other.TryMove(ptry, 0)) + { + // kill it immediately + other.ClearCounters(); + other.DamageMobj(self, self, TELEFRAG_DAMAGE, 'None'); + bSolid = savedsolid; + other.bNoTeleport = savednoteleport; + return; + } + + if (other.pos.xy != ptry) + { + // If the new position does not match the desired position, the player + // must have gone through a portal. + // For that we need to adjust the movement vector for the following steps. + double anglediff = deltaangle(oldangle, other.angle); + + if (anglediff != 0) + { + stepmove = RotateVector(stepmove, anglediff); + } + } + + } + bSolid = savedsolid; + other.bNoTeleport = savednoteleport; + + // [RH] Lost souls hate the same things as their pain elementals + other.CopyFriendliness (self, !(flags & PAF_NOTARGET)); + + if (!(flags & PAF_NOSKULLATTACK)) + { + other.A_SkullAttack(); + } + } + } + + void A_PainAttack(class spawntype = "LostSoul", double addangle = 0, int flags = 0, int limit = -1) { if (target) @@ -71,6 +202,7 @@ extend class Actor A_PainShootSkull(spawntype, angle + addangle, flags, limit); } } + void A_DualPainAttack(class spawntype = "LostSoul") { if (target)