mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-27 14:22:13 +00:00
- scriptified FastProjectile.
This commit is contained in:
parent
cc58f13e4e
commit
85a84b5e94
12 changed files with 200 additions and 186 deletions
|
@ -1159,7 +1159,6 @@ set (PCH_SOURCES
|
||||||
g_strife/strife_sbar.cpp
|
g_strife/strife_sbar.cpp
|
||||||
g_shared/a_action.cpp
|
g_shared/a_action.cpp
|
||||||
g_shared/a_decals.cpp
|
g_shared/a_decals.cpp
|
||||||
g_shared/a_fastprojectile.cpp
|
|
||||||
g_shared/a_flashfader.cpp
|
g_shared/a_flashfader.cpp
|
||||||
g_shared/a_fountain.cpp
|
g_shared/a_fountain.cpp
|
||||||
g_shared/a_lightning.cpp
|
g_shared/a_lightning.cpp
|
||||||
|
|
|
@ -110,8 +110,8 @@ public:
|
||||||
bool IsDangerous (sector_t *sec);
|
bool IsDangerous (sector_t *sec);
|
||||||
|
|
||||||
TArray<FString> getspawned; //Array of bots (their names) which should be spawned when starting a game.
|
TArray<FString> getspawned; //Array of bots (their names) which should be spawned when starting a game.
|
||||||
BYTE freeze:1; //Game in freeze mode.
|
BYTE freeze; //Game in freeze mode.
|
||||||
BYTE changefreeze:1; //Game wants to change freeze mode.
|
BYTE changefreeze; //Game wants to change freeze mode.
|
||||||
int botnum;
|
int botnum;
|
||||||
botinfo_t *botinfo;
|
botinfo_t *botinfo;
|
||||||
int spawn_tries;
|
int spawn_tries;
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
class AAmmo : public AInventory
|
class AAmmo : public AInventory
|
||||||
{
|
{
|
||||||
DECLARE_CLASS(AAmmo, AInventory)
|
DECLARE_CLASS (AAmmo, AInventory)
|
||||||
public:
|
public:
|
||||||
|
|
||||||
virtual void Serialize(FSerializer &arc) override;
|
virtual void Serialize(FSerializer &arc) override;
|
||||||
|
|
|
@ -182,7 +182,7 @@ private:
|
||||||
|
|
||||||
class AStateProvider : public AInventory
|
class AStateProvider : public AInventory
|
||||||
{
|
{
|
||||||
DECLARE_CLASS(AStateProvider, AInventory)
|
DECLARE_CLASS (AStateProvider, AInventory)
|
||||||
};
|
};
|
||||||
|
|
||||||
// CustomInventory: Supports the Use, Pickup, and Drop states from 96x
|
// CustomInventory: Supports the Use, Pickup, and Drop states from 96x
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
class AWeaponPiece : public AInventory
|
class AWeaponPiece : public AInventory
|
||||||
{
|
{
|
||||||
DECLARE_CLASS(AWeaponPiece, AInventory)
|
DECLARE_CLASS (AWeaponPiece, AInventory)
|
||||||
HAS_OBJECT_POINTERS
|
HAS_OBJECT_POINTERS
|
||||||
protected:
|
protected:
|
||||||
bool PrivateShouldStay ();
|
bool PrivateShouldStay ();
|
||||||
|
@ -26,7 +26,7 @@ public:
|
||||||
// [BL] Needs to be available for SBarInfo to check weaponpieces
|
// [BL] Needs to be available for SBarInfo to check weaponpieces
|
||||||
class AWeaponHolder : public AInventory
|
class AWeaponHolder : public AInventory
|
||||||
{
|
{
|
||||||
DECLARE_CLASS(AWeaponHolder, AInventory)
|
DECLARE_CLASS (AWeaponHolder, AInventory)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int PieceMask;
|
int PieceMask;
|
||||||
|
|
|
@ -221,7 +221,7 @@ enum
|
||||||
|
|
||||||
class AWeaponGiver : public AWeapon
|
class AWeaponGiver : public AWeapon
|
||||||
{
|
{
|
||||||
DECLARE_CLASS(AWeaponGiver, AWeapon)
|
DECLARE_CLASS (AWeaponGiver, AWeapon)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual bool TryPickup(AActor *&toucher) override;
|
virtual bool TryPickup(AActor *&toucher) override;
|
||||||
|
|
|
@ -1,164 +0,0 @@
|
||||||
|
|
||||||
#include "a_sharedglobal.h"
|
|
||||||
#include "p_local.h"
|
|
||||||
#include "g_level.h"
|
|
||||||
#include "r_sky.h"
|
|
||||||
#include "p_lnspec.h"
|
|
||||||
#include "b_bot.h"
|
|
||||||
#include "p_checkposition.h"
|
|
||||||
#include "virtual.h"
|
|
||||||
#include "g_levellocals.h"
|
|
||||||
|
|
||||||
IMPLEMENT_CLASS(AFastProjectile, false, false)
|
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// AFastProjectile :: Tick
|
|
||||||
//
|
|
||||||
// Thinker for the ultra-fast projectiles used by Heretic and Hexen
|
|
||||||
//
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void AFastProjectile::Tick ()
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
DVector3 frac;
|
|
||||||
int changexy;
|
|
||||||
|
|
||||||
ClearInterpolation();
|
|
||||||
double oldz = Z();
|
|
||||||
|
|
||||||
if (!(flags5 & MF5_NOTIMEFREEZE))
|
|
||||||
{
|
|
||||||
//Added by MC: Freeze mode.
|
|
||||||
if (bglobal.freeze || level.flags2 & LEVEL2_FROZEN)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// [RH] Ripping is a little different than it was in Hexen
|
|
||||||
FCheckPosition tm(!!(flags2 & MF2_RIP));
|
|
||||||
|
|
||||||
int count = 8;
|
|
||||||
if (radius > 0)
|
|
||||||
{
|
|
||||||
while ( fabs(Vel.X) > radius * count || fabs(Vel.Y) > radius * count)
|
|
||||||
{
|
|
||||||
// we need to take smaller steps.
|
|
||||||
count += count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle movement
|
|
||||||
if (!Vel.isZero() || (Z() != floorz))
|
|
||||||
{
|
|
||||||
// force some lateral movement so that collision detection works as intended.
|
|
||||||
if ((flags & MF_MISSILE) && Vel.X == 0 && Vel.Y == 0 && !IsZeroDamage())
|
|
||||||
{
|
|
||||||
Vel.X = MinVel;
|
|
||||||
}
|
|
||||||
|
|
||||||
frac = Vel / count;
|
|
||||||
changexy = frac.X != 0 || frac.Y != 0;
|
|
||||||
int ripcount = count / 8;
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
if (changexy)
|
|
||||||
{
|
|
||||||
if (--ripcount <= 0)
|
|
||||||
{
|
|
||||||
tm.LastRipped.Clear(); // [RH] Do rip damage each step, like Hexen
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!P_TryMove (this, Pos() + frac, true, NULL, tm))
|
|
||||||
{ // Blocked move
|
|
||||||
if (!(flags3 & MF3_SKYEXPLODE))
|
|
||||||
{
|
|
||||||
if (tm.ceilingline &&
|
|
||||||
tm.ceilingline->backsector &&
|
|
||||||
tm.ceilingline->backsector->GetTexture(sector_t::ceiling) == skyflatnum &&
|
|
||||||
Z() >= tm.ceilingline->backsector->ceilingplane.ZatPoint(PosRelative(tm.ceilingline)))
|
|
||||||
{
|
|
||||||
// Hack to prevent missiles exploding against the sky.
|
|
||||||
// Does not handle sky floors.
|
|
||||||
Destroy ();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// [RH] Don't explode on horizon lines.
|
|
||||||
if (BlockingLine != NULL && BlockingLine->special == Line_Horizon)
|
|
||||||
{
|
|
||||||
Destroy ();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
P_ExplodeMissile (this, BlockingLine, BlockingMobj);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AddZ(frac.Z);
|
|
||||||
UpdateWaterLevel ();
|
|
||||||
oldz = Z();
|
|
||||||
if (oldz <= floorz)
|
|
||||||
{ // Hit the floor
|
|
||||||
|
|
||||||
if (floorpic == skyflatnum && !(flags3 & MF3_SKYEXPLODE))
|
|
||||||
{
|
|
||||||
// [RH] Just remove the missile without exploding it
|
|
||||||
// if this is a sky floor.
|
|
||||||
Destroy ();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SetZ(floorz);
|
|
||||||
P_HitFloor (this);
|
|
||||||
P_ExplodeMissile (this, NULL, NULL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (Top() > ceilingz)
|
|
||||||
{ // Hit the ceiling
|
|
||||||
|
|
||||||
if (ceilingpic == skyflatnum && !(flags3 & MF3_SKYEXPLODE))
|
|
||||||
{
|
|
||||||
Destroy ();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SetZ(ceilingz - Height);
|
|
||||||
P_ExplodeMissile (this, NULL, NULL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!frac.isZero() && ripcount <= 0)
|
|
||||||
{
|
|
||||||
ripcount = count >> 3;
|
|
||||||
|
|
||||||
// call the scripted 'Effect' method.
|
|
||||||
IFVIRTUAL(AFastProjectile, Effect)
|
|
||||||
{
|
|
||||||
// Without the type cast this picks the 'void *' assignment...
|
|
||||||
VMValue params[1] = { (DObject*)this };
|
|
||||||
GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!CheckNoDelay())
|
|
||||||
return; // freed itself
|
|
||||||
// Advance the state
|
|
||||||
if (tics != -1)
|
|
||||||
{
|
|
||||||
if (tics > 0) tics--;
|
|
||||||
while (!tics)
|
|
||||||
{
|
|
||||||
if (!SetState (state->GetNextState ()))
|
|
||||||
{ // mobj was removed
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -215,12 +215,4 @@ public:
|
||||||
ActorFlags FlagsSave;
|
ActorFlags FlagsSave;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AFastProjectile : public AActor
|
|
||||||
{
|
|
||||||
DECLARE_CLASS(AFastProjectile, AActor)
|
|
||||||
public:
|
|
||||||
void Tick ();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif //__A_SHAREDGLOBAL_H__
|
#endif //__A_SHAREDGLOBAL_H__
|
||||||
|
|
|
@ -4333,6 +4333,12 @@ bool AActor::CheckNoDelay()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(AActor, CheckNoDelay)
|
||||||
|
{
|
||||||
|
PARAM_SELF_PROLOGUE(AActor);
|
||||||
|
ACTION_RETURN_BOOL(self->CheckNoDelay());
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// AActor :: CheckSectorTransition
|
// AActor :: CheckSectorTransition
|
||||||
|
@ -4486,6 +4492,12 @@ bool AActor::UpdateWaterLevel (bool dosplash)
|
||||||
return false; // we did the splash ourselves
|
return false; // we did the splash ourselves
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(AActor, UpdateWaterLevel)
|
||||||
|
{
|
||||||
|
PARAM_SELF_PROLOGUE(AActor);
|
||||||
|
PARAM_BOOL_DEF(splash);
|
||||||
|
ACTION_RETURN_BOOL(self->UpdateWaterLevel(splash));
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
|
@ -7821,6 +7833,13 @@ DEFINE_ACTION_FUNCTION(AActor, Vec3Offset)
|
||||||
ACTION_RETURN_VEC3(self->Vec3Offset(x, y, z, absolute));
|
ACTION_RETURN_VEC3(self->Vec3Offset(x, y, z, absolute));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(AActor, PosRelative)
|
||||||
|
{
|
||||||
|
PARAM_SELF_PROLOGUE(AActor);
|
||||||
|
PARAM_POINTER(sec, sector_t);
|
||||||
|
ACTION_RETURN_VEC3(self->PosRelative(sec));
|
||||||
|
}
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(AActor, RestoreDamage)
|
DEFINE_ACTION_FUNCTION(AActor, RestoreDamage)
|
||||||
{
|
{
|
||||||
PARAM_SELF_PROLOGUE(AActor);
|
PARAM_SELF_PROLOGUE(AActor);
|
||||||
|
@ -7861,6 +7880,19 @@ DEFINE_ACTION_FUNCTION(AActor, CountsAsKill)
|
||||||
ACTION_RETURN_FLOAT(self->CountsAsKill());
|
ACTION_RETURN_FLOAT(self->CountsAsKill());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(AActor, IsZeroDamage)
|
||||||
|
{
|
||||||
|
PARAM_SELF_PROLOGUE(AActor);
|
||||||
|
ACTION_RETURN_BOOL(self->IsZeroDamage());
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(AActor, ClearInterpolation)
|
||||||
|
{
|
||||||
|
PARAM_SELF_PROLOGUE(AActor);
|
||||||
|
self->ClearInterpolation();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(AActor, ApplyDamageFactors)
|
DEFINE_ACTION_FUNCTION(AActor, ApplyDamageFactors)
|
||||||
{
|
{
|
||||||
PARAM_PROLOGUE;
|
PARAM_PROLOGUE;
|
||||||
|
@ -7880,6 +7912,7 @@ DEFINE_ACTION_FUNCTION(AActor, ApplyDamageFactors)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// DropItem handling
|
// DropItem handling
|
||||||
|
|
|
@ -52,6 +52,7 @@
|
||||||
#include "g_levellocals.h"
|
#include "g_levellocals.h"
|
||||||
#include "vm.h"
|
#include "vm.h"
|
||||||
#include "p_checkposition.h"
|
#include "p_checkposition.h"
|
||||||
|
#include "r_sky.h"
|
||||||
|
|
||||||
static TArray<FPropertyInfo*> properties;
|
static TArray<FPropertyInfo*> properties;
|
||||||
static TArray<AFuncDesc> AFTable;
|
static TArray<AFuncDesc> AFTable;
|
||||||
|
@ -742,9 +743,8 @@ void InitThingdef()
|
||||||
// As a result, the size has to be set to something large and arbritrary because it can change between maps. This will need some serious improvement when things get cleaned up.
|
// As a result, the size has to be set to something large and arbritrary because it can change between maps. This will need some serious improvement when things get cleaned up.
|
||||||
sectorstruct->AddNativeField("lines", NewPointer(NewResizableArray(NewPointer(linestruct, false)), false), myoffsetof(sector_t, Lines), VARF_Native);
|
sectorstruct->AddNativeField("lines", NewPointer(NewResizableArray(NewPointer(linestruct, false)), false), myoffsetof(sector_t, Lines), VARF_Native);
|
||||||
|
|
||||||
// add the sector planes. These are value items of native structs so they have to be done here. Write access should be through functions only to allow later optimization inside the renderer.
|
sectorstruct->AddNativeField("ceilingplane", secplanestruct, myoffsetof(sector_t, ceilingplane), VARF_Native);
|
||||||
sectorstruct->AddNativeField("ceilingplane", secplanestruct, myoffsetof(sector_t, ceilingplane), VARF_Native|VARF_ReadOnly);
|
sectorstruct->AddNativeField("floorplane", secplanestruct, myoffsetof(sector_t, floorplane), VARF_Native);
|
||||||
sectorstruct->AddNativeField("floorplane", secplanestruct, myoffsetof(sector_t, floorplane), VARF_Native|VARF_ReadOnly);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -788,6 +788,12 @@ void InitThingdef()
|
||||||
playerf = new PField("gameaction", TypeUInt8, VARF_Native | VARF_Static, (intptr_t)&gameaction);
|
playerf = new PField("gameaction", TypeUInt8, VARF_Native | VARF_Static, (intptr_t)&gameaction);
|
||||||
GlobalSymbols.AddSymbol(playerf);
|
GlobalSymbols.AddSymbol(playerf);
|
||||||
|
|
||||||
|
playerf = new PField("skyflatnum", TypeTextureID, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&skyflatnum);
|
||||||
|
GlobalSymbols.AddSymbol(playerf);
|
||||||
|
|
||||||
|
playerf = new PField("globalfreeze", TypeUInt8, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&bglobal.freeze);
|
||||||
|
GlobalSymbols.AddSymbol(playerf);
|
||||||
|
|
||||||
playerf = new PField("consoleplayer", TypeSInt32, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&consoleplayer);
|
playerf = new PField("consoleplayer", TypeSInt32, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&consoleplayer);
|
||||||
GlobalSymbols.AddSymbol(playerf);
|
GlobalSymbols.AddSymbol(playerf);
|
||||||
|
|
||||||
|
|
|
@ -145,6 +145,7 @@ class Actor : Thinker native
|
||||||
native int lastbump;
|
native int lastbump;
|
||||||
native int DesignatedTeam;
|
native int DesignatedTeam;
|
||||||
native Actor BlockingMobj;
|
native Actor BlockingMobj;
|
||||||
|
native Line BlockingLine;
|
||||||
native int PoisonDamage;
|
native int PoisonDamage;
|
||||||
native name PoisonDamageType;
|
native name PoisonDamageType;
|
||||||
native int PoisonDuration;
|
native int PoisonDuration;
|
||||||
|
@ -207,7 +208,6 @@ class Actor : Thinker native
|
||||||
|
|
||||||
// need some definition work first
|
// need some definition work first
|
||||||
//FRenderStyle RenderStyle;
|
//FRenderStyle RenderStyle;
|
||||||
//line_t *BlockingLine; // Line that blocked the last move
|
|
||||||
//int ConversationRoot; // THe root of the current dialogue
|
//int ConversationRoot; // THe root of the current dialogue
|
||||||
|
|
||||||
// deprecated things.
|
// deprecated things.
|
||||||
|
@ -345,6 +345,11 @@ class Actor : Thinker native
|
||||||
native void ClearBounce();
|
native void ClearBounce();
|
||||||
native TerrainDef GetFloorTerrain();
|
native TerrainDef GetFloorTerrain();
|
||||||
native bool CheckLocalView(int consoleplayer);
|
native bool CheckLocalView(int consoleplayer);
|
||||||
|
native bool CheckNoDelay();
|
||||||
|
native bool UpdateWaterLevel (bool splash = true);
|
||||||
|
native bool IsZeroDamage();
|
||||||
|
native void ClearInterpolation();
|
||||||
|
native Vector3 PosRelative(sector sec);
|
||||||
|
|
||||||
native void ExplodeMissile(line lin = null, Actor target = null);
|
native void ExplodeMissile(line lin = null, Actor target = null);
|
||||||
native void RestoreDamage();
|
native void RestoreDamage();
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Fast projectiles --------------------------------------------------------
|
// Fast projectiles --------------------------------------------------------
|
||||||
|
|
||||||
class FastProjectile : Actor native
|
class FastProjectile : Actor
|
||||||
{
|
{
|
||||||
Default
|
Default
|
||||||
{
|
{
|
||||||
|
@ -37,5 +37,148 @@ class FastProjectile : Actor native
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// AFastProjectile :: Tick
|
||||||
|
//
|
||||||
|
// Thinker for the ultra-fast projectiles used by Heretic and Hexen
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
override void Tick ()
|
||||||
|
{
|
||||||
|
ClearInterpolation();
|
||||||
|
double oldz = pos.Z;
|
||||||
|
|
||||||
|
if (!bNoTimeFreeze)
|
||||||
|
{
|
||||||
|
//Added by MC: Freeze mode.
|
||||||
|
if (globalfreeze || level.Frozen)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// [RH] Ripping is a little different than it was in Hexen
|
||||||
|
FCheckPosition tm;
|
||||||
|
tm.DoRipping = bRipper;
|
||||||
|
|
||||||
|
int count = 8;
|
||||||
|
if (radius > 0)
|
||||||
|
{
|
||||||
|
while ( abs(Vel.X) > radius * count || abs(Vel.Y) > radius * count)
|
||||||
|
{
|
||||||
|
// we need to take smaller steps.
|
||||||
|
count += count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle movement
|
||||||
|
if (Vel != (0, 0, 0) || (pos.Z != floorz))
|
||||||
|
{
|
||||||
|
// force some lateral movement so that collision detection works as intended.
|
||||||
|
if (bMissile && Vel.X == 0 && Vel.Y == 0 && !IsZeroDamage())
|
||||||
|
{
|
||||||
|
Vel.X = MinVel;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3 frac = Vel / count;
|
||||||
|
int changexy = frac.X != 0 || frac.Y != 0;
|
||||||
|
int ripcount = count / 8;
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
if (changexy)
|
||||||
|
{
|
||||||
|
if (--ripcount <= 0)
|
||||||
|
{
|
||||||
|
tm.ClearLastRipped(); // [RH] Do rip damage each step, like Hexen
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!TryMove (Pos.XY + frac.XY, true, NULL, tm))
|
||||||
|
{ // Blocked move
|
||||||
|
if (!bSkyExplode)
|
||||||
|
{
|
||||||
|
let l = tm.ceilingline;
|
||||||
|
if (l &&
|
||||||
|
l.backsector &&
|
||||||
|
l.backsector.GetTexture(sector.ceiling) == skyflatnum)
|
||||||
|
{
|
||||||
|
let posr = PosRelative(l.backsector);
|
||||||
|
if (pos.Z >= l.backsector.ceilingplane.ZatPoint(posr.XY))
|
||||||
|
{
|
||||||
|
// Hack to prevent missiles exploding against the sky.
|
||||||
|
// Does not handle sky floors.
|
||||||
|
Destroy ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// [RH] Don't explode on horizon lines.
|
||||||
|
if (BlockingLine != NULL && BlockingLine.special == Line_Horizon)
|
||||||
|
{
|
||||||
|
Destroy ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ExplodeMissile (BlockingLine, BlockingMobj);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AddZ(frac.Z);
|
||||||
|
UpdateWaterLevel ();
|
||||||
|
oldz = pos.Z;
|
||||||
|
if (oldz <= floorz)
|
||||||
|
{ // Hit the floor
|
||||||
|
|
||||||
|
if (floorpic == skyflatnum && !bSkyExplode)
|
||||||
|
{
|
||||||
|
// [RH] Just remove the missile without exploding it
|
||||||
|
// if this is a sky floor.
|
||||||
|
Destroy ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetZ(floorz);
|
||||||
|
HitFloor ();
|
||||||
|
ExplodeMissile (NULL, NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (pos.Z + height > ceilingz)
|
||||||
|
{ // Hit the ceiling
|
||||||
|
|
||||||
|
if (ceilingpic == skyflatnum && !bSkyExplode)
|
||||||
|
{
|
||||||
|
Destroy ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetZ(ceilingz - Height);
|
||||||
|
ExplodeMissile (NULL, NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (frac != (0, 0, 0) && ripcount <= 0)
|
||||||
|
{
|
||||||
|
ripcount = count >> 3;
|
||||||
|
|
||||||
|
// call the 'Effect' method.
|
||||||
|
Effect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!CheckNoDelay())
|
||||||
|
return; // freed itself
|
||||||
|
// Advance the state
|
||||||
|
if (tics != -1)
|
||||||
|
{
|
||||||
|
if (tics > 0) tics--;
|
||||||
|
while (!tics)
|
||||||
|
{
|
||||||
|
if (!SetState (CurState.NextState))
|
||||||
|
{ // mobj was removed
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue