mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-13 07:57:58 +00:00
- scriptified A_PainShootSkull which was the last remaining bit in g_doom, so this directory is gone now.
This commit is contained in:
parent
f8c6adb7eb
commit
1a20a5b999
8 changed files with 160 additions and 218 deletions
|
@ -824,7 +824,6 @@ endif()
|
||||||
file( GLOB HEADER_FILES
|
file( GLOB HEADER_FILES
|
||||||
${EXTRA_HEADER_DIRS}
|
${EXTRA_HEADER_DIRS}
|
||||||
fragglescript/*.h
|
fragglescript/*.h
|
||||||
g_doom/*.h
|
|
||||||
g_heretic/*.h
|
g_heretic/*.h
|
||||||
g_hexen/*.h
|
g_hexen/*.h
|
||||||
g_raven/*.h
|
g_raven/*.h
|
||||||
|
@ -858,7 +857,6 @@ set( NOT_COMPILED_SOURCE_FILES
|
||||||
${OTHER_SYSTEM_SOURCES}
|
${OTHER_SYSTEM_SOURCES}
|
||||||
sc_man_scanner.h
|
sc_man_scanner.h
|
||||||
sc_man_scanner.re
|
sc_man_scanner.re
|
||||||
g_doom/a_painelemental.cpp
|
|
||||||
g_heretic/a_dsparil.cpp
|
g_heretic/a_dsparil.cpp
|
||||||
g_heretic/a_hereticartifacts.cpp
|
g_heretic/a_hereticartifacts.cpp
|
||||||
g_heretic/a_hereticweaps.cpp
|
g_heretic/a_hereticweaps.cpp
|
||||||
|
@ -1153,7 +1151,6 @@ set (PCH_SOURCES
|
||||||
w_wad.cpp
|
w_wad.cpp
|
||||||
wi_stuff.cpp
|
wi_stuff.cpp
|
||||||
zstrformat.cpp
|
zstrformat.cpp
|
||||||
g_doom/a_doommisc.cpp
|
|
||||||
g_heretic/a_hereticmisc.cpp
|
g_heretic/a_hereticmisc.cpp
|
||||||
g_hexen/a_hexenmisc.cpp
|
g_hexen/a_hexenmisc.cpp
|
||||||
g_raven/a_artitele.cpp
|
g_raven/a_artitele.cpp
|
||||||
|
@ -1309,7 +1306,6 @@ endif()
|
||||||
|
|
||||||
target_link_libraries( zdoom ${ZDOOM_LIBS} gdtoa dumb lzma )
|
target_link_libraries( zdoom ${ZDOOM_LIBS} gdtoa dumb lzma )
|
||||||
include_directories( .
|
include_directories( .
|
||||||
g_doom
|
|
||||||
g_heretic
|
g_heretic
|
||||||
g_hexen
|
g_hexen
|
||||||
g_raven
|
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("External\\RapidJSON" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/rapidjson/.+")
|
||||||
source_group("Externak\\SFMT" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/sfmt/.+")
|
source_group("Externak\\SFMT" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/sfmt/.+")
|
||||||
source_group("FraggleScript" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/fragglescript/.+")
|
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\\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\\Hexen Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_hexen/.+")
|
||||||
source_group("Games\\Raven Shared" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_raven/.+")
|
source_group("Games\\Raven Shared" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_raven/.+")
|
||||||
|
|
|
@ -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__
|
|
|
@ -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"
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
|
@ -7115,6 +7115,23 @@ DEFINE_ACTION_FUNCTION(AActor, AngleTo)
|
||||||
ACTION_RETURN_FLOAT(self->AngleTo(targ, absolute).Degrees);
|
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)
|
DEFINE_ACTION_FUNCTION(AActor, DistanceBySpeed)
|
||||||
{
|
{
|
||||||
PARAM_SELF_PROLOGUE(AActor);
|
PARAM_SELF_PROLOGUE(AActor);
|
||||||
|
|
|
@ -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_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_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_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_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_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)
|
#define ACTION_RETURN_BOOL(v) ACTION_RETURN_INT(v)
|
||||||
|
|
|
@ -4,6 +4,8 @@ class Actor : Thinker native
|
||||||
const ONFLOORZ = -2147483648.0;
|
const ONFLOORZ = -2147483648.0;
|
||||||
const ONCEILINGZ = 2147483647.0;
|
const ONCEILINGZ = 2147483647.0;
|
||||||
const FLOATRANDZ = ONCEILINGZ-1;
|
const FLOATRANDZ = ONCEILINGZ-1;
|
||||||
|
const TELEFRAG_DAMAGE = 1000000;
|
||||||
|
|
||||||
|
|
||||||
// flags are not defined here, the native fields for those get synthesized from the internal tables.
|
// 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
|
// 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)
|
bool IsPointerEqual(int ptr_select1, int ptr_select2)
|
||||||
{
|
{
|
||||||
return GetPointer(ptr_select1) == GetPointer(ptr_select2);
|
return GetPointer(ptr_select1) == GetPointer(ptr_select2);
|
||||||
|
@ -231,8 +240,6 @@ class Actor : Thinker native
|
||||||
|
|
||||||
native void AdjustPlayerAngle(FTranslatedLineTarget t);
|
native void AdjustPlayerAngle(FTranslatedLineTarget t);
|
||||||
native static readonly<Actor> GetDefaultByType(class<Actor> cls);
|
native static readonly<Actor> GetDefaultByType(class<Actor> cls);
|
||||||
native static double deltaangle(double ang1, double ang2);
|
|
||||||
native static double absangle(double ang1, double ang2);
|
|
||||||
native static double GetDefaultSpeed(class<Actor> type);
|
native static double GetDefaultSpeed(class<Actor> type);
|
||||||
native void RemoveFromHash();
|
native void RemoveFromHash();
|
||||||
native string GetTag(string defstr = "");
|
native string GetTag(string defstr = "");
|
||||||
|
|
|
@ -61,7 +61,138 @@ class PainElemental : Actor
|
||||||
|
|
||||||
extend class Actor
|
extend class Actor
|
||||||
{
|
{
|
||||||
native void A_PainShootSkull(Class<Actor> 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<Actor> 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<Actor> spawntype = "LostSoul", double addangle = 0, int flags = 0, int limit = -1)
|
void A_PainAttack(class<Actor> spawntype = "LostSoul", double addangle = 0, int flags = 0, int limit = -1)
|
||||||
{
|
{
|
||||||
|
@ -71,6 +202,7 @@ extend class Actor
|
||||||
A_PainShootSkull(spawntype, angle + addangle, flags, limit);
|
A_PainShootSkull(spawntype, angle + addangle, flags, limit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void A_DualPainAttack(class<Actor> spawntype = "LostSoul")
|
void A_DualPainAttack(class<Actor> spawntype = "LostSoul")
|
||||||
{
|
{
|
||||||
if (target)
|
if (target)
|
||||||
|
|
Loading…
Reference in a new issue