- scriptified Hexen's Bloodscourge and Serpent.
- merged the FrontBlock searcher for the Bloodscourge into RoughMonsterSearch. This also fixes the bug that the searcher was not initialized properly for the MageBoss.
This commit is contained in:
parent
f9a1388066
commit
ebd2c27e0a
17 changed files with 507 additions and 620 deletions
|
|
@ -860,8 +860,6 @@ set( NOT_COMPILED_SOURCE_FILES
|
|||
sc_man_scanner.h
|
||||
sc_man_scanner.re
|
||||
g_hexen/a_heresiarch.cpp
|
||||
g_hexen/a_magestaff.cpp
|
||||
g_hexen/a_serpent.cpp
|
||||
g_hexen/a_spike.cpp
|
||||
g_hexen/a_teleportother.cpp
|
||||
g_strife/a_acolyte.cpp
|
||||
|
|
|
|||
|
|
@ -25,7 +25,5 @@
|
|||
|
||||
// Include all the Hexen stuff here to reduce compile time
|
||||
#include "a_heresiarch.cpp"
|
||||
#include "a_magestaff.cpp"
|
||||
#include "a_serpent.cpp"
|
||||
#include "a_spike.cpp"
|
||||
#include "a_teleportother.cpp"
|
||||
|
|
|
|||
|
|
@ -1,260 +0,0 @@
|
|||
/*
|
||||
#include "actor.h"
|
||||
#include "info.h"
|
||||
#include "p_local.h"
|
||||
#include "m_random.h"
|
||||
#include "s_sound.h"
|
||||
#include "a_hexenglobal.h"
|
||||
#include "gstrings.h"
|
||||
#include "a_weaponpiece.h"
|
||||
#include "vm.h"
|
||||
#include "doomstat.h"
|
||||
*/
|
||||
|
||||
class AMageWeapon : public AWeapon
|
||||
{
|
||||
DECLARE_CLASS (AMageWeapon, AWeapon);
|
||||
public:
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS(AMageWeapon, false, false)
|
||||
|
||||
static FRandom pr_mstafftrack ("MStaffTrack");
|
||||
static FRandom pr_bloodscourgedrop ("BloodScourgeDrop");
|
||||
|
||||
void A_MStaffTrack (AActor *);
|
||||
void A_DropBloodscourgePieces (AActor *);
|
||||
void A_MStaffAttack (AActor *actor);
|
||||
void A_MStaffPalette (AActor *actor);
|
||||
|
||||
static AActor *FrontBlockCheck (AActor *mo, int index, void *);
|
||||
static divline_t BlockCheckLine;
|
||||
|
||||
//==========================================================================
|
||||
// The Mages's Staff (Bloodscourge) -----------------------------------------
|
||||
|
||||
class AMWeapBloodscourge : public AMageWeapon
|
||||
{
|
||||
DECLARE_CLASS (AMWeapBloodscourge, AMageWeapon)
|
||||
public:
|
||||
|
||||
void Serialize(FSerializer &arc)
|
||||
{
|
||||
Super::Serialize (arc);
|
||||
arc("mstaffcount", MStaffCount);
|
||||
}
|
||||
PalEntry GetBlend ()
|
||||
{
|
||||
if (paletteflash & PF_HEXENWEAPONS)
|
||||
{
|
||||
if (MStaffCount == 3)
|
||||
return PalEntry(128, 100, 73, 0);
|
||||
else if (MStaffCount == 2)
|
||||
return PalEntry(128, 125, 92, 0);
|
||||
else if (MStaffCount == 1)
|
||||
return PalEntry(128, 150, 110, 0);
|
||||
else
|
||||
return PalEntry(0, 0, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return PalEntry (MStaffCount * 128 / 3, 151, 110, 0);
|
||||
}
|
||||
}
|
||||
BYTE MStaffCount;
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS(AMWeapBloodscourge, false, false)
|
||||
|
||||
// Mage Staff FX2 (Bloodscourge) --------------------------------------------
|
||||
|
||||
class AMageStaffFX2 : public AActor
|
||||
{
|
||||
DECLARE_CLASS(AMageStaffFX2, AActor)
|
||||
public:
|
||||
bool SpecialBlastHandling (AActor *source, double strength);
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS(AMageStaffFX2, false, false)
|
||||
|
||||
bool AMageStaffFX2::SpecialBlastHandling (AActor *source, double strength)
|
||||
{
|
||||
// Reflect to originator
|
||||
tracer = target;
|
||||
target = source;
|
||||
return true;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// MStaffSpawn
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
void MStaffSpawn (AActor *pmo, DAngle angle, AActor *alttarget)
|
||||
{
|
||||
AActor *mo;
|
||||
FTranslatedLineTarget t;
|
||||
|
||||
mo = P_SpawnPlayerMissile (pmo, 0, 0, 8, RUNTIME_CLASS(AMageStaffFX2), angle, &t);
|
||||
if (mo)
|
||||
{
|
||||
mo->target = pmo;
|
||||
if (t.linetarget && !t.unlinked)
|
||||
mo->tracer = t.linetarget;
|
||||
else
|
||||
mo->tracer = alttarget;
|
||||
}
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_MStaffAttack
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_MStaffAttack)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE(AActor);
|
||||
|
||||
DAngle angle;
|
||||
player_t *player;
|
||||
FTranslatedLineTarget t;
|
||||
|
||||
if (NULL == (player = self->player))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
AMWeapBloodscourge *weapon = static_cast<AMWeapBloodscourge *> (self->player->ReadyWeapon);
|
||||
if (weapon != NULL)
|
||||
{
|
||||
if (!weapon->DepleteAmmo (weapon->bAltFire))
|
||||
return 0;
|
||||
}
|
||||
angle = self->Angles.Yaw;
|
||||
|
||||
// [RH] Let's try and actually track what the player aimed at
|
||||
P_AimLineAttack (self, angle, PLAYERMISSILERANGE, &t, 32.);
|
||||
if (t.linetarget == NULL)
|
||||
{
|
||||
BlockCheckLine.x = self->X();
|
||||
BlockCheckLine.y = self->Y();
|
||||
BlockCheckLine.dx = -angle.Sin();
|
||||
BlockCheckLine.dy = -angle.Cos();
|
||||
t.linetarget = P_BlockmapSearch (self, 10, FrontBlockCheck);
|
||||
}
|
||||
MStaffSpawn (self, angle, t.linetarget);
|
||||
MStaffSpawn (self, angle-5, t.linetarget);
|
||||
MStaffSpawn (self, angle+5, t.linetarget);
|
||||
S_Sound (self, CHAN_WEAPON, "MageStaffFire", 1, ATTN_NORM);
|
||||
weapon->MStaffCount = 3;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_MStaffPalette
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_MStaffPalette)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE(AActor);
|
||||
|
||||
if (self->player != NULL)
|
||||
{
|
||||
AMWeapBloodscourge *weapon = static_cast<AMWeapBloodscourge *> (self->player->ReadyWeapon);
|
||||
if (weapon != NULL && weapon->MStaffCount != 0)
|
||||
{
|
||||
weapon->MStaffCount--;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_MStaffTrack
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_MStaffTrack)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
|
||||
if ((self->tracer == 0) && (pr_mstafftrack()<50))
|
||||
{
|
||||
self->tracer = P_RoughMonsterSearch (self, 10, true);
|
||||
}
|
||||
P_SeekerMissile(self, 2, 10);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// FrontBlockCheck
|
||||
//
|
||||
// [RH] Like RoughBlockCheck, but it won't return anything behind a line.
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
static AActor *FrontBlockCheck (AActor *mo, int index, void *)
|
||||
{
|
||||
FBlockNode *link;
|
||||
|
||||
for (link = blocklinks[index]; link != NULL; link = link->NextActor)
|
||||
{
|
||||
if (link->Me != mo)
|
||||
{
|
||||
if (P_PointOnDivlineSide(link->Me->X(), link->Me->Y(), &BlockCheckLine) == 0 &&
|
||||
mo->IsOkayToAttack (link->Me))
|
||||
{
|
||||
return link->Me;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// MStaffSpawn2 - for use by mage class boss
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
void MStaffSpawn2 (AActor *actor, DAngle angle)
|
||||
{
|
||||
AActor *mo;
|
||||
|
||||
mo = P_SpawnMissileAngleZ (actor, actor->Z()+40, RUNTIME_CLASS(AMageStaffFX2), angle, 0.);
|
||||
if (mo)
|
||||
{
|
||||
mo->target = actor;
|
||||
mo->tracer = P_BlockmapSearch (mo, 10, FrontBlockCheck);
|
||||
}
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_MStaffAttack2 - for use by mage class boss
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_MageAttack)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
|
||||
if (self->target == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
DAngle angle = self->Angles.Yaw;
|
||||
MStaffSpawn2(self, angle);
|
||||
MStaffSpawn2(self, angle - 5);
|
||||
MStaffSpawn2(self, angle + 5);
|
||||
S_Sound(self, CHAN_WEAPON, "MageStaffFire", 1, ATTN_NORM);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,311 +0,0 @@
|
|||
/*
|
||||
#include "actor.h"
|
||||
#include "info.h"
|
||||
#include "p_local.h"
|
||||
#include "s_sound.h"
|
||||
#include "p_enemy.h"
|
||||
#include "a_action.h"
|
||||
#include "m_random.h"
|
||||
#include "p_terrain.h"
|
||||
#include "vm.h"
|
||||
*/
|
||||
|
||||
static FRandom pr_serpentchase ("SerpentChase");
|
||||
static FRandom pr_serpenthump ("SerpentHump");
|
||||
static FRandom pr_serpentattack ("SerpentAttack");
|
||||
static FRandom pr_serpentmeattack ("SerpentMeAttack");
|
||||
static FRandom pr_serpentgibs ("SerpentGibs");
|
||||
static FRandom pr_delaygib ("DelayGib");
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_SerpentUnHide
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_SerpentUnHide)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
|
||||
self->renderflags &= ~RF_INVISIBLE;
|
||||
self->Floorclip = 24;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_SerpentHide
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_SerpentHide)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
|
||||
self->renderflags |= RF_INVISIBLE;
|
||||
self->Floorclip = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_SerpentRaiseHump
|
||||
//
|
||||
// Raises the hump above the surface by raising the floorclip level
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_SerpentRaiseHump)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
|
||||
self->Floorclip -= 4;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_SerpentLowerHump
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_SerpentLowerHump)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
|
||||
self->Floorclip += 4;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_SerpentHumpDecide
|
||||
//
|
||||
// Decided whether to hump up, or if the mobj is a serpent leader,
|
||||
// to missile attack
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_SerpentHumpDecide)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
|
||||
if (self->MissileState != NULL)
|
||||
{
|
||||
if (pr_serpenthump() > 30)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (pr_serpenthump() < 40)
|
||||
{ // Missile attack
|
||||
self->SetState (self->MeleeState);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (pr_serpenthump() > 3)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (!self->CheckMeleeRange ())
|
||||
{ // The hump shouldn't occur when within melee range
|
||||
if (self->MissileState != NULL && pr_serpenthump() < 128)
|
||||
{
|
||||
self->SetState (self->MeleeState);
|
||||
}
|
||||
else
|
||||
{
|
||||
self->SetState (self->FindState ("Hump"));
|
||||
S_Sound (self, CHAN_BODY, "SerpentActive", 1, ATTN_NORM);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_SerpentCheckForAttack
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_SerpentCheckForAttack)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
|
||||
if (!self->target)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (self->MissileState != NULL)
|
||||
{
|
||||
if (!self->CheckMeleeRange ())
|
||||
{
|
||||
self->SetState (self->FindState ("Attack"));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (P_CheckMeleeRange2 (self))
|
||||
{
|
||||
self->SetState (self->FindState ("Walk"));
|
||||
}
|
||||
else if (self->CheckMeleeRange ())
|
||||
{
|
||||
if (pr_serpentattack() < 32)
|
||||
{
|
||||
self->SetState (self->FindState ("Walk"));
|
||||
}
|
||||
else
|
||||
{
|
||||
self->SetState (self->FindState ("Attack"));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_SerpentChooseAttack
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_SerpentChooseAttack)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
|
||||
if (!self->target || self->CheckMeleeRange())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (self->MissileState != NULL)
|
||||
{
|
||||
self->SetState (self->MissileState);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_SerpentMeleeAttack
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_SerpentMeleeAttack)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
|
||||
if (!self->target)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (self->CheckMeleeRange ())
|
||||
{
|
||||
int damage = pr_serpentmeattack.HitDice (5);
|
||||
int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee);
|
||||
P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self);
|
||||
S_Sound (self, CHAN_BODY, "SerpentMeleeHit", 1, ATTN_NORM);
|
||||
}
|
||||
if (pr_serpentmeattack() < 96)
|
||||
{
|
||||
CALL_ACTION(A_SerpentCheckForAttack, self);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_SerpentSpawnGibs
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_SerpentSpawnGibs)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
|
||||
AActor *mo;
|
||||
static const char *GibTypes[] =
|
||||
{
|
||||
"SerpentGib3",
|
||||
"SerpentGib2",
|
||||
"SerpentGib1"
|
||||
};
|
||||
|
||||
for (int i = countof(GibTypes)-1; i >= 0; --i)
|
||||
{
|
||||
double x = (pr_serpentgibs() - 128) / 16.;
|
||||
double y = (pr_serpentgibs() - 128) / 16.;
|
||||
|
||||
mo = Spawn (GibTypes[i], self->Vec2OffsetZ(x, y, self->floorz + 1), ALLOW_REPLACE);
|
||||
if (mo)
|
||||
{
|
||||
mo->Vel.X = (pr_serpentgibs() - 128) / 1024.f;
|
||||
mo->Vel.Y = (pr_serpentgibs() - 128) / 1024.f;
|
||||
mo->Floorclip = 6;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_FloatGib
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_FloatGib)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
|
||||
self->Floorclip -= 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_SinkGib
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_SinkGib)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
|
||||
self->Floorclip += 1;;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_DelayGib
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_DelayGib)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
|
||||
self->tics -= pr_delaygib()>>2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_SerpentHeadCheck
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_SerpentHeadCheck)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
|
||||
if (self->Z() <= self->floorz)
|
||||
{
|
||||
if (Terrains[P_GetThingFloorType(self)].IsLiquid)
|
||||
{
|
||||
P_HitFloor (self);
|
||||
self->SetState (NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
self->SetState (self->FindState(NAME_Death));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -365,6 +365,12 @@ bool P_CheckMeleeRange2 (AActor *actor)
|
|||
return true;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, CheckMeleeRange2)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
ACTION_RETURN_INT(P_CheckMeleeRange2(self));
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
|
|
|
|||
|
|
@ -238,7 +238,7 @@ enum PCM
|
|||
|
||||
|
||||
AActor *P_BlockmapSearch (AActor *mo, int distance, AActor *(*check)(AActor*, int, void *), void *params = NULL);
|
||||
AActor *P_RoughMonsterSearch (AActor *mo, int distance, bool onlyseekable=false);
|
||||
AActor *P_RoughMonsterSearch (AActor *mo, int distance, bool onlyseekable=false, bool frontonly = false);
|
||||
|
||||
//
|
||||
// P_MAP
|
||||
|
|
|
|||
|
|
@ -45,7 +45,6 @@
|
|||
#include "templates.h"
|
||||
#include "po_man.h"
|
||||
|
||||
static AActor *RoughBlockCheck (AActor *mo, int index, void *);
|
||||
sector_t *P_PointInSectorBuggy(double x, double y);
|
||||
int P_VanillaPointOnDivlineSide(double x, double y, const divline_t* line);
|
||||
|
||||
|
|
@ -1685,19 +1684,6 @@ FPathTraverse::~FPathTraverse()
|
|||
// distance is in MAPBLOCKUNITS
|
||||
//===========================================================================
|
||||
|
||||
AActor *P_RoughMonsterSearch (AActor *mo, int distance, bool onlyseekable)
|
||||
{
|
||||
return P_BlockmapSearch (mo, distance, RoughBlockCheck, (void *)onlyseekable);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, RoughMonsterSearch)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_INT(distance);
|
||||
PARAM_BOOL_DEF(onlyseekable);
|
||||
ACTION_RETURN_OBJECT(P_RoughMonsterSearch(self, distance, onlyseekable));
|
||||
}
|
||||
|
||||
AActor *P_BlockmapSearch (AActor *mo, int distance, AActor *(*check)(AActor*, int, void *), void *params)
|
||||
{
|
||||
int blockX;
|
||||
|
|
@ -1787,6 +1773,13 @@ AActor *P_BlockmapSearch (AActor *mo, int distance, AActor *(*check)(AActor*, in
|
|||
return NULL;
|
||||
}
|
||||
|
||||
struct BlockCheckInfo
|
||||
{
|
||||
bool onlyseekable;
|
||||
bool frontonly;
|
||||
divline_t frontline;
|
||||
};
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// RoughBlockCheck
|
||||
|
|
@ -1795,14 +1788,19 @@ AActor *P_BlockmapSearch (AActor *mo, int distance, AActor *(*check)(AActor*, in
|
|||
|
||||
static AActor *RoughBlockCheck (AActor *mo, int index, void *param)
|
||||
{
|
||||
bool onlyseekable = param != NULL;
|
||||
BlockCheckInfo *info = (BlockCheckInfo *)param;
|
||||
|
||||
FBlockNode *link;
|
||||
|
||||
for (link = blocklinks[index]; link != NULL; link = link->NextActor)
|
||||
{
|
||||
if (link->Me != mo)
|
||||
{
|
||||
if (onlyseekable && !mo->CanSeek(link->Me))
|
||||
if (info->onlyseekable && !mo->CanSeek(link->Me))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (info->frontonly && P_PointOnDivlineSide(link->Me->X(), link->Me->Y(), &info->frontline) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
|
@ -1815,6 +1813,30 @@ static AActor *RoughBlockCheck (AActor *mo, int index, void *param)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
AActor *P_RoughMonsterSearch(AActor *mo, int distance, bool onlyseekable, bool frontonly)
|
||||
{
|
||||
BlockCheckInfo info;
|
||||
info.onlyseekable = onlyseekable;
|
||||
if ((info.frontonly = frontonly))
|
||||
{
|
||||
info.frontline.x = mo->X();
|
||||
info.frontline.y = mo->Y();
|
||||
info.frontline.dx = -mo->Angles.Yaw.Sin();
|
||||
info.frontline.dy = -mo->Angles.Yaw.Cos();
|
||||
}
|
||||
|
||||
return P_BlockmapSearch(mo, distance, RoughBlockCheck, (void *)&info);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, RoughMonsterSearch)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_INT(distance);
|
||||
PARAM_BOOL_DEF(onlyseekable);
|
||||
PARAM_BOOL_DEF(frontonly);
|
||||
ACTION_RETURN_OBJECT(P_RoughMonsterSearch(self, distance, onlyseekable, frontonly));
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// [RH] LinkToWorldForMapThing
|
||||
|
|
|
|||
|
|
@ -5908,6 +5908,13 @@ int P_GetThingFloorType (AActor *thing)
|
|||
}
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, GetFloorTerrain)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
ACTION_RETURN_POINTER(&Terrains[P_GetThingFloorType(self)]);
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// FUNC P_HitWater
|
||||
|
|
|
|||
|
|
@ -724,3 +724,18 @@ FName P_GetTerrainName(int terrainnum)
|
|||
}
|
||||
}
|
||||
|
||||
DEFINE_FIELD_NAMED(FTerrainDef, Name, TerrainName)
|
||||
DEFINE_FIELD(FTerrainDef, Splash)
|
||||
DEFINE_FIELD(FTerrainDef, DamageAmount)
|
||||
DEFINE_FIELD(FTerrainDef, DamageMOD)
|
||||
DEFINE_FIELD(FTerrainDef, DamageTimeMask)
|
||||
DEFINE_FIELD(FTerrainDef, FootClip)
|
||||
DEFINE_FIELD(FTerrainDef, StepVolume)
|
||||
DEFINE_FIELD(FTerrainDef, WalkStepTics)
|
||||
DEFINE_FIELD(FTerrainDef, RunStepTics)
|
||||
DEFINE_FIELD(FTerrainDef, LeftStepSound)
|
||||
DEFINE_FIELD(FTerrainDef, RightStepSound)
|
||||
DEFINE_FIELD(FTerrainDef, IsLiquid)
|
||||
DEFINE_FIELD(FTerrainDef, AllowProtection)
|
||||
DEFINE_FIELD(FTerrainDef, Friction)
|
||||
DEFINE_FIELD(FTerrainDef, MoveFactor)
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@
|
|||
#include "autosegs.h"
|
||||
#include "p_maputl.h"
|
||||
#include "gi.h"
|
||||
#include "p_terrain.h"
|
||||
|
||||
static TArray<FPropertyInfo*> properties;
|
||||
static TArray<AFuncDesc> AFTable;
|
||||
|
|
|
|||
|
|
@ -1095,6 +1095,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_POINTER(v) do { void *state = v; if (numret > 0) { assert(ret != NULL); ret->SetPointer(state, ATAG_GENERIC); 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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue