- Added DavidPH's A_Teleport submission but removed the now redundant GetSpotWithMinDistance functions.

SVN r2451 (trunk)
This commit is contained in:
Christoph Oelckers 2010-07-23 21:55:01 +00:00
parent f430881a54
commit bc47f7133b
6 changed files with 100 additions and 6 deletions

View file

@ -139,7 +139,7 @@ void P_DSparilTeleport (AActor *actor)
DSpotState *state = DSpotState::GetSpotState();
if (state == NULL) return;
spot = state->GetSpotWithMinDistance(PClass::FindClass("BossSpot"), actor->x, actor->y, 128*FRACUNIT);
spot = state->GetSpotWithMinMaxDistance(PClass::FindClass("BossSpot"), actor->x, actor->y, 128*FRACUNIT, 0);
if (spot == NULL) return;
prevX = actor->x;

View file

@ -147,14 +147,20 @@ struct FSpotList
//
//----------------------------------------------------------------------------
ASpecialSpot *GetSpotWithMinDistance(fixed_t x, fixed_t y, fixed_t distance)
ASpecialSpot *GetSpotWithMinMaxDistance(fixed_t x, fixed_t y, fixed_t mindist, fixed_t maxdist)
{
if (Spots.Size() == 0) return NULL;
int i = pr_spot() % Spots.Size();
int initial = i;
while (P_AproxDistance(Spots[i]->x - x, Spots[i]->y - y) < distance)
fixed_t distance;
while (true)
{
distance = P_AproxDistance(Spots[i]->x - x, Spots[i]->y - y);
if ((distance >= mindist) && ((maxdist == 0) || (distance <= maxdist))) break;
i = (i+1) % Spots.Size();
if (i == initial) return NULL;
}
@ -329,10 +335,10 @@ ASpecialSpot *DSpotState::GetNextInList(const PClass *type, int skipcounter)
//
//----------------------------------------------------------------------------
ASpecialSpot *DSpotState::GetSpotWithMinDistance(const PClass *type, fixed_t x, fixed_t y, fixed_t distance)
ASpecialSpot *DSpotState::GetSpotWithMinMaxDistance(const PClass *type, fixed_t x, fixed_t y, fixed_t mindist, fixed_t maxdist)
{
FSpotList *list = FindSpotList(type);
if (list != NULL) return list->GetSpotWithMinDistance(x, y, distance);
if (list != NULL) return list->GetSpotWithMinMaxDistance(x, y, mindist, maxdist);
return NULL;
}

View file

@ -36,7 +36,7 @@ public:
bool RemoveSpot(ASpecialSpot *spot);
void Serialize(FArchive &arc);
ASpecialSpot *GetNextInList(const PClass *type, int skipcounter);
ASpecialSpot *GetSpotWithMinDistance(const PClass *type, fixed_t x, fixed_t y, fixed_t distance);
ASpecialSpot *GetSpotWithMinMaxDistance(const PClass *type, fixed_t x, fixed_t y, fixed_t mindist, fixed_t maxdist);
ASpecialSpot *GetRandomSpot(const PClass *type, bool onlyonce = false);
};

View file

@ -66,6 +66,7 @@
#include "v_font.h"
#include "doomstat.h"
#include "v_palette.h"
#include "g_shared/a_specialspot.h"
static FRandom pr_camissile ("CustomActorfire");
@ -81,6 +82,7 @@ static FRandom pr_spawndebris ("SpawnDebris");
static FRandom pr_spawnitemex ("SpawnItemEx");
static FRandom pr_burst ("Burst");
static FRandom pr_monsterrefire ("MonsterRefire");
static FRandom pr_teleport("Teleport");
//==========================================================================
@ -3194,6 +3196,87 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetUserArray)
((int *)(reinterpret_cast<BYTE *>(self) + var->offset))[pos] = value;
}
//===========================================================================
//
// A_Teleport(optional state teleportstate, optional class targettype,
// optional class fogtype, optional int flags, optional fixed mindist,
// optional fixed maxdist)
//
// Attempts to teleport to a targettype at least mindist away and at most
// maxdist away (0 means unlimited). If successful, spawn a fogtype at old
// location and place calling actor in teleportstate.
//
//===========================================================================
enum T_Flags
{
TF_TELEFRAG = 1, // Allow telefrag in order to teleport.
TF_RANDOMDECIDE = 2, // Randomly fail based on health. (A_Srcr2Decide)
};
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport)
{
ACTION_PARAM_START(6);
ACTION_PARAM_STATE(TeleportState, 0);
ACTION_PARAM_CLASS(TargetType, 1);
ACTION_PARAM_CLASS(FogType, 2);
ACTION_PARAM_INT(Flags, 3);
ACTION_PARAM_FIXED(MinDist, 4);
ACTION_PARAM_FIXED(MaxDist, 5);
// Randomly choose not to teleport like A_Srcr2Decide.
if (Flags & TF_RANDOMDECIDE)
{
static const int chance[] =
{
192, 120, 120, 120, 64, 64, 32, 16, 0
};
unsigned int chanceindex = self->health / ((self->SpawnHealth()/8 == 0) ? 1 : self->SpawnHealth()/8);
if (chanceindex >= countof(chance))
{
chanceindex = countof(chance) - 1;
}
if (pr_teleport() >= chance[chanceindex]) return;
}
if (TeleportState == NULL)
{
// Default to Teleport.
TeleportState = self->FindState("Teleport");
// If still nothing, then return.
if (!TeleportState) return;
}
DSpotState *state = DSpotState::GetSpotState();
if (state == NULL) return;
if (!TargetType) TargetType = PClass::FindClass("BossSpot");
AActor * spot = state->GetSpotWithMinMaxDistance(TargetType, self->x, self->y, MinDist, MaxDist);
if (spot == NULL) return;
fixed_t prevX = self->x;
fixed_t prevY = self->y;
fixed_t prevZ = self->z;
if (P_TeleportMove (self, spot->x, spot->y, spot->z, Flags & TF_TELEFRAG))
{
ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains!
if (FogType)
{
Spawn(FogType, prevX, prevY, prevZ, ALLOW_REPLACE);
}
ACTION_JUMP(TeleportState);
self->z = self->floorz;
self->angle = spot->angle;
self->velx = self->vely = self->velz = 0;
}
}
//===========================================================================
//
// A_Turn

View file

@ -224,6 +224,7 @@ ACTOR Actor native //: Thinker
action native A_CheckCeiling(state label);
action native A_PlayerSkinCheck(state label);
action native A_BasicAttack(int meleedamage, sound meleesound, class<actor> missiletype, float missileheight);
action native A_Teleport(state teleportstate = "", class<SpecialSpot> targettype = "BossSpot", class<Actor> fogtype = "TeleportFog", int flags = 0, float mindist = 128, float maxdist = 0);
action native A_ThrowGrenade(class<Actor> itemtype, float zheight = 0, float xyvel = 0, float zvel = 0, bool useammo = true);
action native A_Weave(int xspeed, int yspeed, float xdist, float ydist);

View file

@ -95,6 +95,10 @@ const int CPF_USEAMMO = 1;
const int CPF_DAGGER = 2;
const int CPF_PULLIN = 4;
// Flags for A_Teleport
const int TF_TELEFRAG = 1;
const int TF_RANDOMDECIDE = 2;
// Activation flags
enum
{