mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-01-31 13:50:48 +00:00
- removed level references from p_mobj.cpp.
This time there was one important exported script function: Actor.Spawn. Since this will require a level pointer in the new scheme of things the old version had to be deprecated, because it is static with no argument that allows retrieving the level. However, since this is probably one of the most widely used functions I added a workaround to let it continue to work if used from inside an actor class, which should constitute >95% of all uses. This required a little bit of hackery in the compiler backend to swap out the function if appropriate. Aside from that there were 5 places in the internal ZScript that needed handling, which mostly consisted of making a formerly static internal function non-static.
This commit is contained in:
parent
7d060dc696
commit
480dd347c9
33 changed files with 221 additions and 175 deletions
26
src/actor.h
26
src/actor.h
|
@ -651,7 +651,7 @@ public:
|
|||
virtual void PostBeginPlay() override; // Called immediately before the actor's first tick
|
||||
virtual void Tick() override;
|
||||
|
||||
static AActor *StaticSpawn (PClassActor *type, const DVector3 &pos, replace_t allowreplacement, bool SpawningMapThing = false);
|
||||
static AActor *StaticSpawn (FLevelLocals *Level, PClassActor *type, const DVector3 &pos, replace_t allowreplacement, bool SpawningMapThing = false);
|
||||
|
||||
inline AActor *GetDefault () const
|
||||
{
|
||||
|
@ -1569,34 +1569,34 @@ int P_FindUniqueTID(int start_tid, int limit);
|
|||
|
||||
PClassActor *ClassForSpawn(FName classname);
|
||||
|
||||
inline AActor *Spawn(PClassActor *type)
|
||||
inline AActor *Spawn(FLevelLocals *l, PClassActor *type)
|
||||
{
|
||||
return AActor::StaticSpawn(type, DVector3(0, 0, 0), NO_REPLACE);
|
||||
return AActor::StaticSpawn(l, type, DVector3(0, 0, 0), NO_REPLACE);
|
||||
}
|
||||
|
||||
inline AActor *Spawn(PClassActor *type, const DVector3 &pos, replace_t allowreplacement)
|
||||
inline AActor *Spawn(FLevelLocals *l, PClassActor *type, const DVector3 &pos, replace_t allowreplacement)
|
||||
{
|
||||
return AActor::StaticSpawn(type, pos, allowreplacement);
|
||||
return AActor::StaticSpawn(l, type, pos, allowreplacement);
|
||||
}
|
||||
|
||||
inline AActor *Spawn(FName type)
|
||||
inline AActor *Spawn(FLevelLocals *l, FName type)
|
||||
{
|
||||
return AActor::StaticSpawn(ClassForSpawn(type), DVector3(0, 0, 0), NO_REPLACE);
|
||||
return AActor::StaticSpawn(l, ClassForSpawn(type), DVector3(0, 0, 0), NO_REPLACE);
|
||||
}
|
||||
|
||||
inline AActor *Spawn(FName type, const DVector3 &pos, replace_t allowreplacement)
|
||||
inline AActor *Spawn(FLevelLocals *l, FName type, const DVector3 &pos, replace_t allowreplacement)
|
||||
{
|
||||
return AActor::StaticSpawn(ClassForSpawn(type), pos, allowreplacement);
|
||||
return AActor::StaticSpawn(l, ClassForSpawn(type), pos, allowreplacement);
|
||||
}
|
||||
|
||||
template<class T> inline T *Spawn(const DVector3 &pos, replace_t allowreplacement)
|
||||
template<class T> inline T *Spawn(FLevelLocals *l, const DVector3 &pos, replace_t allowreplacement)
|
||||
{
|
||||
return static_cast<T *>(AActor::StaticSpawn(RUNTIME_CLASS(T), pos, allowreplacement));
|
||||
return static_cast<T *>(AActor::StaticSpawn(l, RUNTIME_CLASS(T), pos, allowreplacement));
|
||||
}
|
||||
|
||||
template<class T> inline T *Spawn() // for inventory items we do not need coordinates and replacement info.
|
||||
template<class T> inline T *Spawn(FLevelLocals *l) // for inventory items we do not need coordinates and replacement info.
|
||||
{
|
||||
return static_cast<T *>(AActor::StaticSpawn(RUNTIME_CLASS(T), DVector3(0, 0, 0), NO_REPLACE));
|
||||
return static_cast<T *>(AActor::StaticSpawn(l, RUNTIME_CLASS(T), DVector3(0, 0, 0), NO_REPLACE));
|
||||
}
|
||||
|
||||
inline PClassActor *PClass::FindActor(FName name)
|
||||
|
|
|
@ -129,7 +129,7 @@ public:
|
|||
void StartTravel ();
|
||||
void FinishTravel ();
|
||||
bool IsLeader (player_t *player);
|
||||
void SetBodyAt (const DVector3 &pos, int hostnum);
|
||||
void SetBodyAt (FLevelLocals *l, const DVector3 &pos, int hostnum);
|
||||
double FakeFire (AActor *source, AActor *dest, ticcmd_t *cmd);
|
||||
bool SafeCheckPosition (AActor *actor, double x, double y, FCheckPosition &tm);
|
||||
void BotTick(AActor *mo);
|
||||
|
|
|
@ -235,7 +235,7 @@ void DBot::Dofire (ticcmd_t *cmd)
|
|||
// prediction aiming
|
||||
Dist = player->mo->Distance2D(enemy);
|
||||
fm = Dist / GetDefaultByType (GetBotInfo(player->ReadyWeapon).projectileType)->Speed;
|
||||
bglobal.SetBodyAt(enemy->Pos() + enemy->Vel.XY() * fm * 2, 1);
|
||||
bglobal.SetBodyAt(enemy->__GetLevel(), enemy->Pos() + enemy->Vel.XY() * fm * 2, 1);
|
||||
Angle = player->mo->AngleTo(bglobal.body1);
|
||||
if (Check_LOS (enemy, SHOOTFOV))
|
||||
no_fire = false;
|
||||
|
@ -479,7 +479,7 @@ AActor *DBot::Find_enemy ()
|
|||
|
||||
|
||||
//Creates a temporary mobj (invisible) at the given location.
|
||||
void FCajunMaster::SetBodyAt (const DVector3 &pos, int hostnum)
|
||||
void FCajunMaster::SetBodyAt (FLevelLocals *l, const DVector3 &pos, int hostnum)
|
||||
{
|
||||
if (hostnum == 1)
|
||||
{
|
||||
|
@ -489,7 +489,7 @@ void FCajunMaster::SetBodyAt (const DVector3 &pos, int hostnum)
|
|||
}
|
||||
else
|
||||
{
|
||||
body1 = Spawn ("CajunBodyNode", pos, NO_REPLACE);
|
||||
body1 = Spawn (l, "CajunBodyNode", pos, NO_REPLACE);
|
||||
}
|
||||
}
|
||||
else if (hostnum == 2)
|
||||
|
@ -500,7 +500,7 @@ void FCajunMaster::SetBodyAt (const DVector3 &pos, int hostnum)
|
|||
}
|
||||
else
|
||||
{
|
||||
body2 = Spawn ("CajunBodyNode", pos, NO_REPLACE);
|
||||
body2 = Spawn (l, "CajunBodyNode", pos, NO_REPLACE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -517,7 +517,7 @@ void FCajunMaster::SetBodyAt (const DVector3 &pos, int hostnum)
|
|||
//Emulates missile travel. Returns distance travelled.
|
||||
double FCajunMaster::FakeFire (AActor *source, AActor *dest, ticcmd_t *cmd)
|
||||
{
|
||||
AActor *th = Spawn ("CajunTrace", source->PosPlusZ(4*8.), NO_REPLACE);
|
||||
AActor *th = Spawn (source->__GetLevel(), "CajunTrace", source->PosPlusZ(4*8.), NO_REPLACE);
|
||||
|
||||
th->target = source; // where it came from
|
||||
|
||||
|
@ -543,7 +543,7 @@ DAngle DBot::FireRox (AActor *enemy, ticcmd_t *cmd)
|
|||
AActor *actor;
|
||||
double m;
|
||||
|
||||
bglobal.SetBodyAt(player->mo->PosPlusZ(player->mo->Height / 2) + player->mo->Vel.XY() * 5, 2);
|
||||
bglobal.SetBodyAt(player->mo->__GetLevel(), player->mo->PosPlusZ(player->mo->Height / 2) + player->mo->Vel.XY() * 5, 2);
|
||||
|
||||
actor = bglobal.body2;
|
||||
|
||||
|
@ -553,7 +553,7 @@ DAngle DBot::FireRox (AActor *enemy, ticcmd_t *cmd)
|
|||
//Predict.
|
||||
m = ((dist+1) / GetDefaultByName("Rocket")->Speed);
|
||||
|
||||
bglobal.SetBodyAt(DVector3((enemy->Pos() + enemy->Vel * (m + 2)), ONFLOORZ), 1);
|
||||
bglobal.SetBodyAt(player->mo->__GetLevel(), DVector3((enemy->Pos() + enemy->Vel * (m + 2)), ONFLOORZ), 1);
|
||||
|
||||
//try the predicted location
|
||||
if (P_CheckSight (actor, bglobal.body1, SF_IGNOREVISIBILITY)) //See the predicted location, so give a test missile
|
||||
|
|
|
@ -2334,7 +2334,7 @@ void Net_DoCommand (int type, uint8_t **stream, int player)
|
|||
const AActor *def = GetDefaultByType (typeinfo);
|
||||
DVector3 spawnpos = source->Vec3Angle(def->radius * 2 + source->radius, source->Angles.Yaw, 8.);
|
||||
|
||||
AActor *spawned = Spawn (typeinfo, spawnpos, ALLOW_REPLACE);
|
||||
AActor *spawned = Spawn (source->__GetLevel(), typeinfo, spawnpos, ALLOW_REPLACE);
|
||||
if (spawned != NULL)
|
||||
{
|
||||
if (type == DEM_SUMMONFRIEND || type == DEM_SUMMONFRIEND2 || type == DEM_SUMMONMBF)
|
||||
|
|
|
@ -881,7 +881,7 @@ void FParser::SF_Spawn(void)
|
|||
}
|
||||
|
||||
t_return.type = svt_mobj;
|
||||
t_return.value.mobj = Spawn(pclass, pos, ALLOW_REPLACE);
|
||||
t_return.value.mobj = Spawn(Level, pclass, pos, ALLOW_REPLACE);
|
||||
|
||||
if (t_return.value.mobj)
|
||||
{
|
||||
|
@ -2930,7 +2930,7 @@ void FParser::SF_SpawnExplosion()
|
|||
else
|
||||
pos.Z = P_PointInSector(pos)->floorplane.ZatPoint(pos);
|
||||
|
||||
spawn = Spawn (pclass, pos, ALLOW_REPLACE);
|
||||
spawn = Spawn (Level, pclass, pos, ALLOW_REPLACE);
|
||||
t_return.type = svt_int;
|
||||
t_return.value.i=0;
|
||||
if (spawn)
|
||||
|
@ -3761,7 +3761,7 @@ void FParser::SF_SpawnShot2(void)
|
|||
|
||||
t_return.type = svt_mobj;
|
||||
|
||||
AActor *mo = Spawn(pclass, source->PosPlusZ(z), ALLOW_REPLACE);
|
||||
AActor *mo = Spawn(Level, pclass, source->PosPlusZ(z), ALLOW_REPLACE);
|
||||
if (mo)
|
||||
{
|
||||
S_Sound(mo, CHAN_VOICE, mo->SeeSound, 1, ATTN_NORM);
|
||||
|
|
|
@ -1493,7 +1493,7 @@ void G_DeathMatchSpawnPlayer (int playernum)
|
|||
}
|
||||
}
|
||||
}
|
||||
AActor *mo = P_SpawnPlayer(spot, playernum);
|
||||
AActor *mo = P_SpawnPlayer(&level, spot, playernum);
|
||||
if (mo != NULL) P_PlayerStartStomp(mo);
|
||||
}
|
||||
|
||||
|
@ -1638,13 +1638,13 @@ void G_DoReborn (int playernum, bool freshbot)
|
|||
level.playerstarts[playernum].type != 0 &&
|
||||
G_CheckSpot (playernum, &level.playerstarts[playernum]))
|
||||
{
|
||||
AActor *mo = P_SpawnPlayer(&level.playerstarts[playernum], playernum);
|
||||
AActor *mo = P_SpawnPlayer(&level, &level.playerstarts[playernum], playernum);
|
||||
if (mo != NULL) P_PlayerStartStomp(mo, true);
|
||||
}
|
||||
else
|
||||
{ // try to spawn at any random player's spot
|
||||
FPlayerStart *start = G_PickPlayerStart(playernum, PPS_FORCERANDOM);
|
||||
AActor *mo = P_SpawnPlayer(start, playernum);
|
||||
AActor *mo = P_SpawnPlayer(&level, start, playernum);
|
||||
if (mo != NULL) P_PlayerStartStomp(mo, true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1366,7 +1366,7 @@ int G_FinishTravel ()
|
|||
|
||||
// The player being spawned here is a short lived dummy and
|
||||
// must not start any ENTER script or big problems will happen.
|
||||
pawndup = P_SpawnPlayer(start, pnum, SPF_TEMPPLAYER);
|
||||
pawndup = P_SpawnPlayer(pawn->__GetLevel(), start, pnum, SPF_TEMPPLAYER);
|
||||
if (pawndup != NULL)
|
||||
{
|
||||
if (!(changeflags & CHANGELEVEL_KEEPFACING))
|
||||
|
|
|
@ -462,7 +462,7 @@ void cht_DoCheat (player_t *player, int cheat)
|
|||
if (player->mo != NULL && player->health >= 0)
|
||||
{
|
||||
static VMFunction *gsp = nullptr;
|
||||
if (gsp == nullptr) PClass::FindFunction(&gsp, NAME_Sigil, NAME_GiveSigilPiece);
|
||||
if (gsp == nullptr) PClass::FindFunction(&gsp, NAME_Actor, NAME_GiveSigilPiece);
|
||||
if (gsp)
|
||||
{
|
||||
VMValue params[1] = { player->mo };
|
||||
|
|
|
@ -111,7 +111,7 @@ void BloodCrypt (void *data, int key, int len);
|
|||
void P_ClearUDMFKeys();
|
||||
void InitRenderInfo();
|
||||
|
||||
extern AActor *SpawnMapThing (int index, FMapThing *mthing, int position);
|
||||
extern AActor *SpawnMapThing (FLevelLocals *Level, int index, FMapThing *mthing, int position);
|
||||
|
||||
EXTERN_CVAR(Bool, am_textured)
|
||||
|
||||
|
@ -1380,7 +1380,7 @@ void MapLoader::SpawnThings (int position)
|
|||
|
||||
for (int i=0; i < numthings; i++)
|
||||
{
|
||||
AActor *actor = SpawnMapThing (i, &MapThingsConverted[i], position);
|
||||
AActor *actor = SpawnMapThing (Level, i, &MapThingsConverted[i], position);
|
||||
unsigned *udi = MapThingsUserDataIndex.CheckKey((unsigned)i);
|
||||
if (udi != nullptr)
|
||||
{
|
||||
|
|
|
@ -1070,4 +1070,5 @@ xx(SpotOuterAngle)
|
|||
xx(lightflags)
|
||||
xx(lighttype)
|
||||
xx(InternalDynamicLight)
|
||||
xx(_a_chase_default)
|
||||
xx(_a_chase_default)
|
||||
xx(Spawn2)
|
||||
|
|
|
@ -3737,7 +3737,7 @@ int DLevelScript::DoSpawn (int type, const DVector3 &pos, int tid, DAngle angle,
|
|||
return 0;
|
||||
}
|
||||
|
||||
actor = Spawn (info, pos, ALLOW_REPLACE);
|
||||
actor = Spawn (&level, info, pos, ALLOW_REPLACE);
|
||||
if (actor != NULL)
|
||||
{
|
||||
ActorFlags2 oldFlags2 = actor->flags2;
|
||||
|
|
|
@ -871,7 +871,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_RadiusDamageSelf)
|
|||
// the player to indicate bad things happened.
|
||||
AActor *flash = NULL;
|
||||
if(flashtype != NULL)
|
||||
flash = Spawn(flashtype, self->target->PosPlusZ(self->target->Height / 4), ALLOW_REPLACE);
|
||||
flash = Spawn(self->__GetLevel(), flashtype, self->target->PosPlusZ(self->target->Height / 4), ALLOW_REPLACE);
|
||||
|
||||
int dmgFlags = 0;
|
||||
FName dmgType = NAME_BFGSplash;
|
||||
|
@ -1575,7 +1575,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnDebris)
|
|||
double xo = (pr_spawndebris() - 128) / 16.;
|
||||
double yo = (pr_spawndebris() - 128) / 16.;
|
||||
double zo = pr_spawndebris()*self->Height / 256 + self->GetBobOffset();
|
||||
mo = Spawn(debris, self->Vec3Offset(xo, yo, zo), ALLOW_REPLACE);
|
||||
mo = Spawn(self->__GetLevel(), debris, self->Vec3Offset(xo, yo, zo), ALLOW_REPLACE);
|
||||
if (mo)
|
||||
{
|
||||
if (transfer_translation)
|
||||
|
@ -1911,7 +1911,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Burst)
|
|||
double xo = (pr_burst() - 128) * self->radius / 128;
|
||||
double yo = (pr_burst() - 128) * self->radius / 128;
|
||||
double zo = (pr_burst() * self->Height / 255);
|
||||
mo = Spawn(chunk, self->Vec3Offset(xo, yo, zo), ALLOW_REPLACE);
|
||||
mo = Spawn(self->__GetLevel(), chunk, self->Vec3Offset(xo, yo, zo), ALLOW_REPLACE);
|
||||
|
||||
if (mo)
|
||||
{
|
||||
|
@ -3102,7 +3102,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Teleport)
|
|||
P_SpawnTeleportFog(ref, prev, true, true);
|
||||
else
|
||||
{
|
||||
fog1 = Spawn(fog_type, prev, ALLOW_REPLACE);
|
||||
fog1 = Spawn(self->__GetLevel(), fog_type, prev, ALLOW_REPLACE);
|
||||
if (fog1 != NULL)
|
||||
fog1->target = ref;
|
||||
}
|
||||
|
@ -3113,7 +3113,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Teleport)
|
|||
P_SpawnTeleportFog(ref, ref->Pos(), false, true);
|
||||
else
|
||||
{
|
||||
fog2 = Spawn(fog_type, ref->Pos(), ALLOW_REPLACE);
|
||||
fog2 = Spawn(self->__GetLevel(), fog_type, ref->Pos(), ALLOW_REPLACE);
|
||||
if (fog2 != NULL)
|
||||
fog2->target = ref;
|
||||
}
|
||||
|
@ -3641,7 +3641,7 @@ static bool DoRadiusGive(AActor *self, AActor *thing, PClassActor *item, int amo
|
|||
|
||||
if ((flags & RGF_NOSIGHT) || P_CheckSight(thing, self, SF_IGNOREVISIBILITY | SF_IGNOREWATERBOUNDARY))
|
||||
{ // OK to give; target is in direct path, or the monster doesn't care about it being in line of sight.
|
||||
auto gift = Spawn(item);
|
||||
auto gift = Spawn(thing->__GetLevel(), item);
|
||||
if (gift->IsKindOf(NAME_Health))
|
||||
{
|
||||
gift->IntVar(NAME_Amount) *= amount;
|
||||
|
|
|
@ -961,7 +961,7 @@ static void HandleReply(player_t *player, bool isconsole, int nodenum, int reply
|
|||
|
||||
if (takestuff)
|
||||
{
|
||||
auto item = Spawn(reply->GiveType);
|
||||
auto item = Spawn(player->mo->__GetLevel(), reply->GiveType);
|
||||
// Items given here should not count as items!
|
||||
item->ClearCounters();
|
||||
if (item->GetClass()->TypeName == NAME_FlameThrower)
|
||||
|
|
|
@ -879,7 +879,7 @@ void P_DrawRailTrail(AActor *source, TArray<SPortalHit> &portalhits, int color1,
|
|||
if (rnd & 4)
|
||||
diff.Z = clamp<double>(diff.Z + ((rnd & 32) ? 1 : -1), -maxdiff, maxdiff);
|
||||
}
|
||||
AActor *thing = Spawn (spawnclass, pos + diff, ALLOW_REPLACE);
|
||||
AActor *thing = Spawn (source->__GetLevel(), spawnclass, pos + diff, ALLOW_REPLACE);
|
||||
if (thing)
|
||||
{
|
||||
if (source) thing->target = source;
|
||||
|
|
|
@ -3285,13 +3285,13 @@ FUNC(LS_GlassBreak)
|
|||
{
|
||||
if (type != nullptr)
|
||||
{
|
||||
glass = Spawn(*type, DVector3(linemid, ONFLOORZ), ALLOW_REPLACE);
|
||||
glass = Spawn(Level, *type, DVector3(linemid, ONFLOORZ), ALLOW_REPLACE);
|
||||
glass->AddZ(24.);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
glass = Spawn("GlassJunk", DVector3(linemid, ONFLOORZ), ALLOW_REPLACE);
|
||||
glass = Spawn(Level, "GlassJunk", DVector3(linemid, ONFLOORZ), ALLOW_REPLACE);
|
||||
glass->AddZ(24.);
|
||||
glass->SetState(glass->SpawnState + (pr_glass() % glass->health));
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ struct secplane_t;
|
|||
struct FCheckPosition;
|
||||
struct FTranslatedLineTarget;
|
||||
struct FLinePortal;
|
||||
struct FLevelLocals;
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
|
@ -97,7 +98,7 @@ void P_PredictionLerpReset();
|
|||
#define SPF_TEMPPLAYER 1 // spawning a short-lived dummy player
|
||||
#define SPF_WEAPONFULLYUP 2 // spawn with weapon already raised
|
||||
|
||||
AActor *P_SpawnPlayer (FPlayerStart *mthing, int playernum, int flags=0);
|
||||
AActor *P_SpawnPlayer (FLevelLocals *Level, FPlayerStart *mthing, int playernum, int flags=0);
|
||||
|
||||
int P_FaceMobj (AActor *source, AActor *target, DAngle *delta);
|
||||
bool P_SeekerMissile (AActor *actor, double thresh, double turnMax, bool precise = false, bool usecurspeed=false);
|
||||
|
|
|
@ -4442,7 +4442,7 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance,
|
|||
|
||||
AActor *tempuff = NULL;
|
||||
if (pufftype != NULL)
|
||||
tempuff = Spawn(pufftype, t1->Pos(), ALLOW_REPLACE);
|
||||
tempuff = Spawn(t1->__GetLevel(), pufftype, t1->Pos(), ALLOW_REPLACE);
|
||||
if (tempuff != NULL)
|
||||
{
|
||||
TData.PuffSpecies = tempuff->GetSpecies();
|
||||
|
@ -5187,7 +5187,7 @@ void P_RailAttack(FRailParams *p)
|
|||
// used as damage inflictor
|
||||
AActor *thepuff = NULL;
|
||||
|
||||
if (puffclass != NULL) thepuff = Spawn(puffclass, source->Pos(), ALLOW_REPLACE);
|
||||
if (puffclass != NULL) thepuff = Spawn(source->__GetLevel(), puffclass, source->Pos(), ALLOW_REPLACE);
|
||||
rail_data.PuffSpecies = (thepuff != NULL) ? thepuff->GetSpecies() : NAME_None;
|
||||
|
||||
Trace(start, source->Sector, vec, p->distance, MF_SHOOTABLE, ML_BLOCKEVERYTHING, source, trace, flags, ProcessRailHit, &rail_data);
|
||||
|
@ -6183,7 +6183,7 @@ void P_DoCrunch(AActor *thing, FChangePosition *cpos)
|
|||
{
|
||||
AActor *mo;
|
||||
|
||||
mo = Spawn(bloodcls, thing->PosPlusZ(thing->Height / 2), ALLOW_REPLACE);
|
||||
mo = Spawn(thing->__GetLevel(), bloodcls, thing->PosPlusZ(thing->Height / 2), ALLOW_REPLACE);
|
||||
|
||||
mo->Vel.X = pr_crunch.Random2() / 16.;
|
||||
mo->Vel.Y = pr_crunch.Random2() / 16.;
|
||||
|
|
177
src/p_mobj.cpp
177
src/p_mobj.cpp
|
@ -739,7 +739,7 @@ AActor *AActor::GiveInventoryType (PClassActor *type)
|
|||
{
|
||||
if (type != nullptr)
|
||||
{
|
||||
auto item = Spawn (type);
|
||||
auto item = Spawn (__GetLevel(), type);
|
||||
if (!CallTryPickup (item, this))
|
||||
{
|
||||
item->Destroy ();
|
||||
|
@ -784,7 +784,8 @@ void AActor::ClearInventory()
|
|||
|
||||
void AActor::CopyFriendliness (AActor *other, bool changeTarget, bool resetHealth)
|
||||
{
|
||||
level.total_monsters -= CountsAsKill();
|
||||
auto Level = __GetLevel();
|
||||
Level->total_monsters -= CountsAsKill();
|
||||
TIDtoHate = other->TIDtoHate;
|
||||
LastLookActor = other->LastLookActor;
|
||||
LastLookPlayerNumber = other->LastLookPlayerNumber;
|
||||
|
@ -799,7 +800,7 @@ void AActor::CopyFriendliness (AActor *other, bool changeTarget, bool resetHealt
|
|||
LastHeard = target = other->target;
|
||||
}
|
||||
if (resetHealth) health = SpawnHealth();
|
||||
level.total_monsters += CountsAsKill();
|
||||
Level->total_monsters += CountsAsKill();
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, CopyFriendliness)
|
||||
|
@ -1226,7 +1227,7 @@ bool AActor::Grind(bool items)
|
|||
return false;
|
||||
}
|
||||
|
||||
AActor *gib = Spawn (i, Pos(), ALLOW_REPLACE);
|
||||
AActor *gib = Spawn (__GetLevel(), i, Pos(), ALLOW_REPLACE);
|
||||
if (gib != NULL)
|
||||
{
|
||||
gib->RenderStyle = RenderStyle;
|
||||
|
@ -1793,6 +1794,7 @@ double P_XYMovement (AActor *mo, DVector2 scroll)
|
|||
DVector2 start;
|
||||
double Oldfloorz = mo->floorz;
|
||||
double oldz = mo->Z();
|
||||
auto Level = mo->__GetLevel();
|
||||
|
||||
double maxmove = (mo->waterlevel < 1) || (mo->flags & MF_MISSILE) ||
|
||||
(mo->player && mo->player->crouchoffset<-10) ? MAXMOVE : MAXMOVE/4;
|
||||
|
@ -2225,15 +2227,15 @@ explode:
|
|||
(!(mo->flags2 & MF2_FLY) || !(mo->flags & MF_NOGRAVITY)) &&
|
||||
!mo->waterlevel)
|
||||
{ // [RH] Friction when falling is available for larger aircontrols
|
||||
if (player != NULL && level.airfriction != 1.)
|
||||
if (player != NULL && Level->airfriction != 1.)
|
||||
{
|
||||
mo->Vel.X *= level.airfriction;
|
||||
mo->Vel.Y *= level.airfriction;
|
||||
mo->Vel.X *= Level->airfriction;
|
||||
mo->Vel.Y *= Level->airfriction;
|
||||
|
||||
if (player->mo == mo) // Not voodoo dolls
|
||||
{
|
||||
player->Vel.X *= level.airfriction;
|
||||
player->Vel.Y *= level.airfriction;
|
||||
player->Vel.X *= Level->airfriction;
|
||||
player->Vel.Y *= Level->airfriction;
|
||||
}
|
||||
}
|
||||
return Oldfloorz;
|
||||
|
@ -2333,10 +2335,11 @@ explode:
|
|||
// Move this to p_inter ***
|
||||
void P_MonsterFallingDamage (AActor *mo)
|
||||
{
|
||||
auto Level = mo->__GetLevel();
|
||||
int damage;
|
||||
double vel;
|
||||
|
||||
if (!(level.flags2 & LEVEL2_MONSTERFALLINGDAMAGE))
|
||||
if (!(Level->flags2 & LEVEL2_MONSTERFALLINGDAMAGE))
|
||||
return;
|
||||
if (mo->floorsector->Flags & SECF_NOFALLINGDAMAGE)
|
||||
return;
|
||||
|
@ -2464,6 +2467,7 @@ void P_ZMovement (AActor *mo, double oldfloorz)
|
|||
mo->SetZ(mo->floorz + mo->specialf1);
|
||||
}
|
||||
|
||||
auto Level = mo->__GetLevel();
|
||||
|
||||
//
|
||||
// adjust height
|
||||
|
@ -2484,7 +2488,7 @@ void P_ZMovement (AActor *mo, double oldfloorz)
|
|||
{
|
||||
if (!mo->IsNoClip2())
|
||||
{
|
||||
mo->AddZ(DAngle(360 / 80.f * level.maptime).Sin() / 8);
|
||||
mo->AddZ(DAngle(360 / 80.f * Level->maptime).Sin() / 8);
|
||||
}
|
||||
|
||||
if (!(mo->flags8 & MF8_NOFRICTION))
|
||||
|
@ -2818,7 +2822,7 @@ void P_NightmareRespawn (AActor *mobj)
|
|||
z = ONFLOORZ;
|
||||
|
||||
// spawn it
|
||||
mo = AActor::StaticSpawn(mobj->GetClass(), DVector3(mobj->SpawnPoint.X, mobj->SpawnPoint.Y, z), NO_REPLACE, true);
|
||||
mo = AActor::StaticSpawn(mobj->__GetLevel(), mobj->GetClass(), DVector3(mobj->SpawnPoint.X, mobj->SpawnPoint.Y, z), NO_REPLACE, true);
|
||||
mo->health = mobj->SpawnHealth();
|
||||
|
||||
if (z == ONFLOORZ)
|
||||
|
@ -3516,6 +3520,8 @@ void AActor::Tick ()
|
|||
return;
|
||||
}
|
||||
|
||||
auto Level = __GetLevel();
|
||||
|
||||
if (flags5 & MF5_NOINTERACTION)
|
||||
{
|
||||
// only do the minimally necessary things here to save time:
|
||||
|
@ -3526,7 +3532,7 @@ void AActor::Tick ()
|
|||
if (!(flags5 & MF5_NOTIMEFREEZE))
|
||||
{
|
||||
//Added by MC: Freeze mode.
|
||||
if (bglobal.freeze || level.flags2 & LEVEL2_FROZEN)
|
||||
if (bglobal.freeze || Level->flags2 & LEVEL2_FROZEN)
|
||||
{
|
||||
// Boss cubes shouldn't be accelerated by timefreeze
|
||||
if (flags6 & MF6_BOSSCUBE)
|
||||
|
@ -3587,7 +3593,7 @@ void AActor::Tick ()
|
|||
}
|
||||
|
||||
// Apply freeze mode.
|
||||
if ((level.flags2 & LEVEL2_FROZEN) && (player == NULL || player->timefreezer == 0))
|
||||
if ((Level->flags2 & LEVEL2_FROZEN) && (player == NULL || player->timefreezer == 0))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -3600,7 +3606,7 @@ void AActor::Tick ()
|
|||
{
|
||||
// add some smoke behind the rocket
|
||||
smokecounter = 0;
|
||||
AActor *th = Spawn("RocketSmokeTrail", Vec3Offset(-Vel), ALLOW_REPLACE);
|
||||
AActor *th = Spawn(__GetLevel(), "RocketSmokeTrail", Vec3Offset(-Vel), ALLOW_REPLACE);
|
||||
if (th)
|
||||
{
|
||||
th->tics -= pr_rockettrail()&3;
|
||||
|
@ -3618,7 +3624,7 @@ void AActor::Tick ()
|
|||
double xo = -moveangle.Cos() * radius * 2 + pr_rockettrail() / 64.;
|
||||
double yo = -moveangle.Sin() * radius * 2 + pr_rockettrail() / 64.;
|
||||
double zo = -Height * Vel.Z / 8. + Height * (2 / 3.);
|
||||
AActor * th = Spawn("GrenadeSmokeTrail", Vec3Offset(xo, yo, zo), ALLOW_REPLACE);
|
||||
AActor * th = Spawn(__GetLevel(), "GrenadeSmokeTrail", Vec3Offset(xo, yo, zo), ALLOW_REPLACE);
|
||||
if (th)
|
||||
{
|
||||
th->tics -= pr_rockettrail()&3;
|
||||
|
@ -3704,7 +3710,7 @@ void AActor::Tick ()
|
|||
// [RH] Consider carrying sectors here
|
||||
DVector2 cumm(0, 0);
|
||||
|
||||
if ((((flags8 & MF8_INSCROLLSEC) && level.Scrolls.Size() > 0) || player != NULL) && !(flags & MF_NOCLIP) && !(flags & MF_NOSECTOR))
|
||||
if ((((flags8 & MF8_INSCROLLSEC) && Level->Scrolls.Size() > 0) || player != NULL) && !(flags & MF_NOCLIP) && !(flags & MF_NOSECTOR))
|
||||
{
|
||||
double height, waterheight; // killough 4/4/98: add waterheight
|
||||
const msecnode_t *node;
|
||||
|
@ -3728,9 +3734,9 @@ void AActor::Tick ()
|
|||
sector_t *sec = node->m_sector;
|
||||
DVector2 scrollv;
|
||||
|
||||
if (level.Scrolls.Size() > unsigned(sec->Index()))
|
||||
if (Level->Scrolls.Size() > unsigned(sec->Index()))
|
||||
{
|
||||
scrollv = level.Scrolls[sec->Index()];
|
||||
scrollv = Level->Scrolls[sec->Index()];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -3931,7 +3937,7 @@ void AActor::Tick ()
|
|||
{
|
||||
if (player)
|
||||
{
|
||||
if (Vel.Z < level.gravity * Sector->gravity * (-1./100)// -655.36f)
|
||||
if (Vel.Z < Level->gravity * Sector->gravity * (-1./100)// -655.36f)
|
||||
&& !(flags&MF_NOGRAVITY))
|
||||
{
|
||||
PlayerLandedOnThing (this, onmo);
|
||||
|
@ -3959,12 +3965,12 @@ void AActor::Tick ()
|
|||
if ((onmo->flags6 & MF6_BUMPSPECIAL) && ((player != NULL)
|
||||
|| ((onmo->activationtype & THINGSPEC_MonsterTrigger) && (flags3 & MF3_ISMONSTER))
|
||||
|| ((onmo->activationtype & THINGSPEC_MissileTrigger) && (flags & MF_MISSILE))
|
||||
) && (level.maptime > onmo->lastbump)) // Leave the bumper enough time to go away
|
||||
) && (Level->maptime > onmo->lastbump)) // Leave the bumper enough time to go away
|
||||
{
|
||||
if (player == NULL || !(player->cheats & CF_PREDICTING))
|
||||
{
|
||||
if (P_ActivateThingSpecial(onmo, this))
|
||||
onmo->lastbump = level.maptime + TICRATE;
|
||||
onmo->lastbump = Level->maptime + TICRATE;
|
||||
}
|
||||
}
|
||||
if (Vel.Z != 0 && (BounceFlags & BOUNCE_Actors))
|
||||
|
@ -4005,7 +4011,7 @@ void AActor::Tick ()
|
|||
}
|
||||
|
||||
// Check for poison damage, but only once per PoisonPeriod tics (or once per second if none).
|
||||
if (PoisonDurationReceived && (level.time % (PoisonPeriodReceived ? PoisonPeriodReceived : TICRATE) == 0))
|
||||
if (PoisonDurationReceived && (Level->time % (PoisonPeriodReceived ? PoisonPeriodReceived : TICRATE) == 0))
|
||||
{
|
||||
P_DamageMobj(this, NULL, Poisoner, PoisonDamageReceived, PoisonDamageTypeReceived ? PoisonDamageTypeReceived : (FName)NAME_Poison, 0);
|
||||
|
||||
|
@ -4059,7 +4065,7 @@ void AActor::Tick ()
|
|||
if (movecount < respawn_monsters)
|
||||
return;
|
||||
|
||||
if (level.time & 31)
|
||||
if (Level->time & 31)
|
||||
return;
|
||||
|
||||
if (pr_nightmarerespawn() > 4)
|
||||
|
@ -4352,7 +4358,8 @@ bool AActor::UpdateWaterLevel(bool dosplash)
|
|||
else if (oldlevel == 3 && waterlevel < 3)
|
||||
{
|
||||
// Our head just came up.
|
||||
if (player->air_finished > level.time)
|
||||
auto Level = __GetLevel();
|
||||
if (player->air_finished > Level->time)
|
||||
{
|
||||
// We hadn't run out of air yet.
|
||||
S_Sound(this, CHAN_VOICE, "*surface", 1, ATTN_NORM);
|
||||
|
@ -4377,7 +4384,7 @@ DEFINE_ACTION_FUNCTION(AActor, UpdateWaterLevel)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
AActor *AActor::StaticSpawn (PClassActor *type, const DVector3 &pos, replace_t allowreplacement, bool SpawningMapThing)
|
||||
AActor *AActor::StaticSpawn (FLevelLocals *Level, PClassActor *type, const DVector3 &pos, replace_t allowreplacement, bool SpawningMapThing)
|
||||
{
|
||||
if (type == NULL)
|
||||
{
|
||||
|
@ -4392,8 +4399,8 @@ AActor *AActor::StaticSpawn (PClassActor *type, const DVector3 &pos, replace_t a
|
|||
AActor *actor;
|
||||
|
||||
actor = static_cast<AActor *>(const_cast<PClassActor *>(type)->CreateNew ());
|
||||
actor->SpawnTime = level.totaltime;
|
||||
actor->SpawnOrder = level.spawnindex++;
|
||||
actor->SpawnTime = Level->totaltime;
|
||||
actor->SpawnOrder = Level->spawnindex++;
|
||||
|
||||
// Set default dialogue
|
||||
actor->ConversationRoot = GetConversation(actor->GetClass()->TypeName);
|
||||
|
@ -4540,39 +4547,39 @@ AActor *AActor::StaticSpawn (PClassActor *type, const DVector3 &pos, replace_t a
|
|||
return NULL;
|
||||
}
|
||||
}
|
||||
if (level.flags & LEVEL_NOALLIES && !actor->player)
|
||||
if (Level->flags & LEVEL_NOALLIES && !actor->player)
|
||||
{
|
||||
actor->flags &= ~MF_FRIENDLY;
|
||||
}
|
||||
// [RH] Count monsters whenever they are spawned.
|
||||
if (actor->CountsAsKill())
|
||||
{
|
||||
level.total_monsters++;
|
||||
Level->total_monsters++;
|
||||
}
|
||||
// [RH] Same, for items
|
||||
if (actor->flags & MF_COUNTITEM)
|
||||
{
|
||||
level.total_items++;
|
||||
Level->total_items++;
|
||||
}
|
||||
// And for secrets
|
||||
if (actor->flags5 & MF5_COUNTSECRET)
|
||||
{
|
||||
level.total_secrets++;
|
||||
Level->total_secrets++;
|
||||
}
|
||||
// force scroller check in the first tic.
|
||||
actor->flags8 |= MF8_INSCROLLSEC;
|
||||
return actor;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, Spawn)
|
||||
DEFINE_ACTION_FUNCTION(FLevelLocals, Spawn)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals);
|
||||
PARAM_CLASS_NOT_NULL(type, AActor);
|
||||
PARAM_FLOAT(x);
|
||||
PARAM_FLOAT(y);
|
||||
PARAM_FLOAT(z);
|
||||
PARAM_INT(flags);
|
||||
ACTION_RETURN_OBJECT(AActor::StaticSpawn(type, DVector3(x, y, z), replace_t(flags)));
|
||||
ACTION_RETURN_OBJECT(AActor::StaticSpawn(self, type, DVector3(x, y, z), replace_t(flags)));
|
||||
}
|
||||
|
||||
PClassActor *ClassForSpawn(FName classname)
|
||||
|
@ -4606,6 +4613,7 @@ void AActor::LevelSpawned ()
|
|||
|
||||
void AActor::HandleSpawnFlags ()
|
||||
{
|
||||
auto Level = __GetLevel();
|
||||
if (SpawnFlags & MTF_AMBUSH)
|
||||
{
|
||||
flags |= MF_AMBUSH;
|
||||
|
@ -4625,7 +4633,7 @@ void AActor::HandleSpawnFlags ()
|
|||
if (flags & MF_COUNTKILL)
|
||||
{
|
||||
flags &= ~MF_COUNTKILL;
|
||||
level.total_monsters--;
|
||||
Level->total_monsters--;
|
||||
}
|
||||
}
|
||||
if (SpawnFlags & MTF_SHADOW)
|
||||
|
@ -4644,7 +4652,7 @@ void AActor::HandleSpawnFlags ()
|
|||
{
|
||||
//Printf("Secret %s in sector %i!\n", GetTag(), Sector->sectornum);
|
||||
flags5 |= MF5_COUNTSECRET;
|
||||
level.total_secrets++;
|
||||
Level->total_secrets++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4896,7 +4904,7 @@ DEFINE_ACTION_FUNCTION(AActor, AdjustFloorClip)
|
|||
|
||||
//
|
||||
// P_SpawnPlayer
|
||||
// Called when a player is spawned on the level.
|
||||
// Called when a player is spawned on the Level->
|
||||
// Most of the player structure stays unchanged between levels.
|
||||
//
|
||||
EXTERN_CVAR (Bool, chasedemo)
|
||||
|
@ -4905,7 +4913,7 @@ EXTERN_CVAR(Float, fov)
|
|||
|
||||
extern bool demonew;
|
||||
|
||||
AActor *P_SpawnPlayer (FPlayerStart *mthing, int playernum, int flags)
|
||||
AActor *P_SpawnPlayer (FLevelLocals *Level, FPlayerStart *mthing, int playernum, int flags)
|
||||
{
|
||||
player_t *p;
|
||||
AActor *mobj, *oldactor;
|
||||
|
@ -4989,9 +4997,9 @@ AActor *P_SpawnPlayer (FPlayerStart *mthing, int playernum, int flags)
|
|||
spawn.Z = ONFLOORZ;
|
||||
}
|
||||
|
||||
mobj = Spawn (p->cls, spawn, NO_REPLACE);
|
||||
mobj = Spawn (Level, p->cls, spawn, NO_REPLACE);
|
||||
|
||||
if (level.flags & LEVEL_USEPLAYERSTARTZ)
|
||||
if (Level->flags & LEVEL_USEPLAYERSTARTZ)
|
||||
{
|
||||
if (spawn.Z == ONFLOORZ)
|
||||
mobj->AddZ(mthing->pos.Z);
|
||||
|
@ -5017,7 +5025,7 @@ AActor *P_SpawnPlayer (FPlayerStart *mthing, int playernum, int flags)
|
|||
VMValue params[] = { mobj, oldactor };
|
||||
VMCall(func, params, 2, nullptr, 0);
|
||||
}
|
||||
level.Behaviors.StopMyScripts (oldactor); // cancel all ENTER/RESPAWN scripts for the voodoo doll
|
||||
Level->Behaviors.StopMyScripts (oldactor); // cancel all ENTER/RESPAWN scripts for the voodoo doll
|
||||
}
|
||||
|
||||
// [GRB] Reset skin
|
||||
|
@ -5100,7 +5108,7 @@ AActor *P_SpawnPlayer (FPlayerStart *mthing, int playernum, int flags)
|
|||
VMCall(func, params, 1, nullptr, 0);
|
||||
}
|
||||
}
|
||||
else if ((multiplayer || (level.flags2 & LEVEL2_ALLOWRESPAWN) || sv_singleplayerrespawn ||
|
||||
else if ((multiplayer || (Level->flags2 & LEVEL2_ALLOWRESPAWN) || sv_singleplayerrespawn ||
|
||||
!!G_SkillProperty(SKILLP_PlayerRespawn)) && state == PST_REBORN && oldactor != NULL)
|
||||
{ // Special inventory handling for respawning in coop
|
||||
IFVM(PlayerPawn, FilterCoopRespawnInventory)
|
||||
|
@ -5146,7 +5154,7 @@ AActor *P_SpawnPlayer (FPlayerStart *mthing, int playernum, int flags)
|
|||
{
|
||||
if (state == PST_ENTER || (state == PST_LIVE && !savegamerestore))
|
||||
{
|
||||
level.Behaviors.StartTypedScripts (SCRIPT_Enter, p->mo, true);
|
||||
Level->Behaviors.StartTypedScripts (SCRIPT_Enter, p->mo, true);
|
||||
}
|
||||
else if (state == PST_REBORN)
|
||||
{
|
||||
|
@ -5162,7 +5170,7 @@ AActor *P_SpawnPlayer (FPlayerStart *mthing, int playernum, int flags)
|
|||
{
|
||||
if (th->LastHeard == oldactor) th->LastHeard = NULL;
|
||||
}
|
||||
for(auto &sec : level.sectors)
|
||||
for(auto &sec : Level->sectors)
|
||||
{
|
||||
if (sec.SoundTarget == oldactor) sec.SoundTarget = nullptr;
|
||||
}
|
||||
|
@ -5170,7 +5178,7 @@ AActor *P_SpawnPlayer (FPlayerStart *mthing, int playernum, int flags)
|
|||
DObject::StaticPointerSubstitution (oldactor, p->mo);
|
||||
|
||||
E_PlayerRespawned(int(p - players));
|
||||
level.Behaviors.StartTypedScripts (SCRIPT_Respawn, p->mo, true);
|
||||
Level->Behaviors.StartTypedScripts (SCRIPT_Respawn, p->mo, true);
|
||||
}
|
||||
}
|
||||
return mobj;
|
||||
|
@ -5183,7 +5191,7 @@ AActor *P_SpawnPlayer (FPlayerStart *mthing, int playernum, int flags)
|
|||
// already be in host byte order.
|
||||
//
|
||||
// [RH] position is used to weed out unwanted start spots
|
||||
AActor *P_SpawnMapThing (FMapThing *mthing, int position)
|
||||
AActor *P_SpawnMapThing (FLevelLocals *Level, FMapThing *mthing, int position)
|
||||
{
|
||||
PClassActor *i;
|
||||
int mask;
|
||||
|
@ -5229,7 +5237,7 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position)
|
|||
{
|
||||
// count deathmatch start positions
|
||||
FPlayerStart start(mthing, 0);
|
||||
level.deathmatchstarts.Push(start);
|
||||
Level->deathmatchstarts.Push(start);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -5257,7 +5265,7 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position)
|
|||
}
|
||||
}
|
||||
|
||||
if (pnum == -1 || (level.flags & LEVEL_FILTERSTARTS))
|
||||
if (pnum == -1 || (Level->flags & LEVEL_FILTERSTARTS))
|
||||
{
|
||||
// check for appropriate game type
|
||||
if (deathmatch)
|
||||
|
@ -5322,10 +5330,10 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position)
|
|||
|
||||
// save spots for respawning in network games
|
||||
FPlayerStart start(mthing, pnum+1);
|
||||
level.playerstarts[pnum] = start;
|
||||
if (level.flags2 & LEVEL2_RANDOMPLAYERSTARTS)
|
||||
Level->playerstarts[pnum] = start;
|
||||
if (Level->flags2 & LEVEL2_RANDOMPLAYERSTARTS)
|
||||
{ // When using random player starts, all starts count
|
||||
level.AllPlayerStarts.Push(start);
|
||||
Level->AllPlayerStarts.Push(start);
|
||||
}
|
||||
else
|
||||
{ // When not using random player starts, later single player
|
||||
|
@ -5333,22 +5341,22 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position)
|
|||
// ones are for voodoo dolls and not likely to be ideal for
|
||||
// spawning regular players.
|
||||
unsigned i;
|
||||
for (i = 0; i < level.AllPlayerStarts.Size(); ++i)
|
||||
for (i = 0; i < Level->AllPlayerStarts.Size(); ++i)
|
||||
{
|
||||
if (level.AllPlayerStarts[i].type == pnum+1)
|
||||
if (Level->AllPlayerStarts[i].type == pnum+1)
|
||||
{
|
||||
level.AllPlayerStarts[i] = start;
|
||||
Level->AllPlayerStarts[i] = start;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == level.AllPlayerStarts.Size())
|
||||
if (i == Level->AllPlayerStarts.Size())
|
||||
{
|
||||
level.AllPlayerStarts.Push(start);
|
||||
Level->AllPlayerStarts.Push(start);
|
||||
}
|
||||
}
|
||||
if (!deathmatch && !(level.flags2 & LEVEL2_RANDOMPLAYERSTARTS))
|
||||
if (!deathmatch && !(Level->flags2 & LEVEL2_RANDOMPLAYERSTARTS))
|
||||
{
|
||||
return P_SpawnPlayer(&start, pnum, (level.flags2 & LEVEL2_PRERAISEWEAPON) ? SPF_WEAPONFULLYUP : 0);
|
||||
return P_SpawnPlayer(Level, &start, pnum, (Level->flags2 & LEVEL2_PRERAISEWEAPON) ? SPF_WEAPONFULLYUP : 0);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
@ -5408,7 +5416,7 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position)
|
|||
}
|
||||
|
||||
// don't spawn any monsters if -nomonsters
|
||||
if (((level.flags2 & LEVEL2_NOMONSTERS) || (dmflags & DF_NO_MONSTERS)) && info->flags3 & MF3_ISMONSTER )
|
||||
if (((Level->flags2 & LEVEL2_NOMONSTERS) || (dmflags & DF_NO_MONSTERS)) && info->flags3 & MF3_ISMONSTER )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
@ -5433,7 +5441,7 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position)
|
|||
else
|
||||
sz = ONFLOORZ;
|
||||
|
||||
mobj = AActor::StaticSpawn (i, DVector3(mthing->pos, sz), NO_REPLACE, true);
|
||||
mobj = AActor::StaticSpawn (Level, i, DVector3(mthing->pos, sz), NO_REPLACE, true);
|
||||
|
||||
if (sz == ONFLOORZ)
|
||||
{
|
||||
|
@ -5560,16 +5568,16 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position)
|
|||
//===========================================================================
|
||||
CVAR(Bool, dumpspawnedthings, false, 0)
|
||||
|
||||
AActor *SpawnMapThing(int index, FMapThing *mt, int position)
|
||||
AActor *SpawnMapThing(FLevelLocals *Level, int index, FMapThing *mt, int position)
|
||||
{
|
||||
AActor *spawned = P_SpawnMapThing(mt, position);
|
||||
AActor *spawned = P_SpawnMapThing(Level, mt, position);
|
||||
if (dumpspawnedthings)
|
||||
{
|
||||
Printf("%5d: (%5f, %5f, %5f), doomednum = %5d, flags = %04x, type = %s\n",
|
||||
index, mt->pos.X, mt->pos.Y, mt->pos.Z, mt->EdNum, mt->flags,
|
||||
spawned ? spawned->GetClass()->TypeName.GetChars() : "(none)");
|
||||
}
|
||||
T_AddSpawnedThing(&level, spawned);
|
||||
T_AddSpawnedThing(Level, spawned);
|
||||
return spawned;
|
||||
}
|
||||
|
||||
|
@ -5592,7 +5600,7 @@ AActor *P_SpawnPuff (AActor *source, PClassActor *pufftype, const DVector3 &pos1
|
|||
if (pufftype == nullptr) return nullptr;
|
||||
|
||||
if (!(flags & PF_NORANDOMZ)) pos.Z += pr_spawnpuff.Random2() / 64.;
|
||||
puff = Spawn(pufftype, pos, ALLOW_REPLACE);
|
||||
puff = Spawn(source->__GetLevel(), pufftype, pos, ALLOW_REPLACE);
|
||||
if (puff == NULL) return NULL;
|
||||
|
||||
if ((puff->flags4 & MF4_RANDOMIZE) && puff->tics > 0)
|
||||
|
@ -5695,7 +5703,7 @@ void P_SpawnBlood (const DVector3 &pos1, DAngle dir, int damage, AActor *origina
|
|||
|
||||
if (bloodcls != NULL)
|
||||
{
|
||||
th = Spawn(bloodcls, pos, NO_REPLACE); // GetBloodType already performed the replacement
|
||||
th = Spawn(originator->__GetLevel(), bloodcls, pos, NO_REPLACE); // GetBloodType already performed the replacement
|
||||
th->Vel.Z = 2;
|
||||
th->Angles.Yaw = dir;
|
||||
// [NG] Applying PUFFGETSOWNER to the blood will make it target the owner
|
||||
|
@ -5802,7 +5810,7 @@ void P_BloodSplatter (const DVector3 &pos, AActor *originator, DAngle hitangle)
|
|||
{
|
||||
AActor *mo;
|
||||
|
||||
mo = Spawn(bloodcls, pos, NO_REPLACE); // GetBloodType already performed the replacement
|
||||
mo = Spawn(originator->__GetLevel(), bloodcls, pos, NO_REPLACE); // GetBloodType already performed the replacement
|
||||
mo->target = originator;
|
||||
mo->Vel.X = pr_splatter.Random2 () / 64.;
|
||||
mo->Vel.Y = pr_splatter.Random2() / 64.;
|
||||
|
@ -5846,7 +5854,7 @@ void P_BloodSplatter2 (const DVector3 &pos, AActor *originator, DAngle hitangle)
|
|||
AActor *mo;
|
||||
|
||||
|
||||
mo = Spawn (bloodcls, pos + add, NO_REPLACE); // GetBloodType already performed the replacement
|
||||
mo = Spawn (originator->__GetLevel(), bloodcls, pos + add, NO_REPLACE); // GetBloodType already performed the replacement
|
||||
mo->target = originator;
|
||||
|
||||
// colorize the blood!
|
||||
|
@ -5900,7 +5908,7 @@ void P_RipperBlood (AActor *mo, AActor *bleeder)
|
|||
if (bloodcls != NULL)
|
||||
{
|
||||
AActor *th;
|
||||
th = Spawn (bloodcls, pos, NO_REPLACE); // GetBloodType already performed the replacement
|
||||
th = Spawn (bleeder->__GetLevel(), bloodcls, pos, NO_REPLACE); // GetBloodType already performed the replacement
|
||||
// [NG] Applying PUFFGETSOWNER to the blood will make it target the owner
|
||||
if (th->flags5 & MF5_PUFFGETSOWNER) th->target = bleeder;
|
||||
if (gameinfo.gametype == GAME_Heretic)
|
||||
|
@ -6039,18 +6047,19 @@ foundone:
|
|||
if (thing->Mass < 10)
|
||||
smallsplash = true;
|
||||
|
||||
auto Level = thing->__GetLevel();
|
||||
if (!(thing->flags3 & MF3_DONTSPLASH))
|
||||
{
|
||||
if (smallsplash && splash->SmallSplash)
|
||||
{
|
||||
mo = Spawn(splash->SmallSplash, pos, ALLOW_REPLACE);
|
||||
mo = Spawn(Level, splash->SmallSplash, pos, ALLOW_REPLACE);
|
||||
if (mo) mo->Floorclip += splash->SmallSplashClip;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (splash->SplashChunk)
|
||||
{
|
||||
mo = Spawn(splash->SplashChunk, pos, ALLOW_REPLACE);
|
||||
mo = Spawn(Level, splash->SplashChunk, pos, ALLOW_REPLACE);
|
||||
mo->target = thing;
|
||||
if (splash->ChunkXVelShift != 255)
|
||||
{
|
||||
|
@ -6064,7 +6073,7 @@ foundone:
|
|||
}
|
||||
if (splash->SplashBase)
|
||||
{
|
||||
mo = Spawn(splash->SplashBase, pos, ALLOW_REPLACE);
|
||||
mo = Spawn(Level, splash->SplashBase, pos, ALLOW_REPLACE);
|
||||
}
|
||||
if (thing->player && !splash->NoAlert && alert)
|
||||
{
|
||||
|
@ -6344,7 +6353,7 @@ AActor *P_SpawnMissileXYZ (DVector3 pos, AActor *source, AActor *dest, PClassAct
|
|||
pos.Z -= source->Floorclip;
|
||||
}
|
||||
|
||||
AActor *th = Spawn (type, pos, ALLOW_REPLACE);
|
||||
AActor *th = Spawn (source->__GetLevel(), type, pos, ALLOW_REPLACE);
|
||||
|
||||
P_PlaySpawnSound(th, source);
|
||||
|
||||
|
@ -6455,7 +6464,7 @@ AActor *P_OldSpawnMissile(AActor *source, AActor *owner, AActor *dest, PClassAct
|
|||
{
|
||||
return nullptr;
|
||||
}
|
||||
AActor *th = Spawn (type, source->PosPlusZ(32.), ALLOW_REPLACE);
|
||||
AActor *th = Spawn (source->__GetLevel(), type, source->PosPlusZ(32.), ALLOW_REPLACE);
|
||||
|
||||
P_PlaySpawnSound(th, source);
|
||||
th->target = owner; // record missile's originator
|
||||
|
@ -6569,7 +6578,7 @@ AActor *P_SpawnMissileAngleZSpeed (AActor *source, double z,
|
|||
z -= source->Floorclip;
|
||||
}
|
||||
|
||||
mo = Spawn (type, source->PosAtZ(z), ALLOW_REPLACE);
|
||||
mo = Spawn (source->__GetLevel(), type, source->PosAtZ(z), ALLOW_REPLACE);
|
||||
|
||||
P_PlaySpawnSound(mo, source);
|
||||
if (owner == NULL) owner = source;
|
||||
|
@ -6602,7 +6611,7 @@ DEFINE_ACTION_FUNCTION(AActor, SpawnMissileAngleZSpeed)
|
|||
|
||||
AActor *P_SpawnSubMissile(AActor *source, PClassActor *type, AActor *target)
|
||||
{
|
||||
AActor *other = Spawn(type, source->Pos(), ALLOW_REPLACE);
|
||||
AActor *other = Spawn(source->__GetLevel(), type, source->Pos(), ALLOW_REPLACE);
|
||||
|
||||
if (source == nullptr || type == nullptr)
|
||||
{
|
||||
|
@ -6665,6 +6674,7 @@ AActor *P_SpawnPlayerMissile (AActor *source, double x, double y, double z,
|
|||
FTranslatedLineTarget scratch;
|
||||
AActor *defaultobject = GetDefaultByType(type);
|
||||
DAngle vrange = nofreeaim ? 35. : 0.;
|
||||
auto Level = source->__GetLevel();
|
||||
|
||||
if (!pLineTarget) pLineTarget = &scratch;
|
||||
if (!(aimflags & ALF_NOWEAPONCHECK) && source->player && source->player->ReadyWeapon && ((source->player->ReadyWeapon->IntVar(NAME_WeaponFlags) & WIF_NOAUTOAIM) || noautoaim))
|
||||
|
@ -6689,7 +6699,7 @@ AActor *P_SpawnPlayerMissile (AActor *source, double x, double y, double z,
|
|||
|
||||
if (source->player != NULL &&
|
||||
!nofreeaim &&
|
||||
level.IsFreelookAllowed() &&
|
||||
Level->IsFreelookAllowed() &&
|
||||
source->player->userinfo.GetAimDist() <= 0.5)
|
||||
{
|
||||
break;
|
||||
|
@ -6699,7 +6709,7 @@ AActor *P_SpawnPlayerMissile (AActor *source, double x, double y, double z,
|
|||
if (pLineTarget->linetarget == NULL)
|
||||
{
|
||||
an = angle;
|
||||
if (nofreeaim || !level.IsFreelookAllowed())
|
||||
if (nofreeaim || !Level->IsFreelookAllowed())
|
||||
{
|
||||
pitch = 0.;
|
||||
}
|
||||
|
@ -6717,7 +6727,7 @@ AActor *P_SpawnPlayerMissile (AActor *source, double x, double y, double z,
|
|||
}
|
||||
}
|
||||
DVector3 pos = source->Vec2OffsetZ(x, y, z);
|
||||
AActor *MissileActor = Spawn (type, pos, ALLOW_REPLACE);
|
||||
AActor *MissileActor = Spawn (source->__GetLevel(), type, pos, ALLOW_REPLACE);
|
||||
if (pMissileActor) *pMissileActor = MissileActor;
|
||||
P_PlaySpawnSound(MissileActor, source);
|
||||
MissileActor->target = source;
|
||||
|
@ -7143,7 +7153,7 @@ void AActor::Revive()
|
|||
// [RH] If it's a monster, it gets to count as another kill
|
||||
if (CountsAsKill())
|
||||
{
|
||||
level.total_monsters++;
|
||||
__GetLevel()->total_monsters++;
|
||||
}
|
||||
|
||||
// [ZZ] resurrect hook
|
||||
|
@ -7208,21 +7218,22 @@ void AActor::SetTag(const char *def)
|
|||
|
||||
void AActor::ClearCounters()
|
||||
{
|
||||
auto Level = __GetLevel();
|
||||
if (CountsAsKill() && health > 0)
|
||||
{
|
||||
level.total_monsters--;
|
||||
Level->total_monsters--;
|
||||
flags &= ~MF_COUNTKILL;
|
||||
}
|
||||
// Same, for items
|
||||
if (flags & MF_COUNTITEM)
|
||||
{
|
||||
level.total_items--;
|
||||
Level->total_items--;
|
||||
flags &= ~MF_COUNTITEM;
|
||||
}
|
||||
// And finally for secrets
|
||||
if (flags5 & MF5_COUNTSECRET)
|
||||
{
|
||||
level.total_secrets--;
|
||||
Level->total_secrets--;
|
||||
flags5 &= ~MF5_COUNTSECRET;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -908,7 +908,7 @@ static void SpawnExtraPlayers(FLevelLocals *Level)
|
|||
if (playeringame[i] && players[i].mo == NULL)
|
||||
{
|
||||
players[i].playerstate = PST_ENTER;
|
||||
P_SpawnPlayer(&Level->playerstarts[i], i, (level.flags2 & LEVEL2_PRERAISEWEAPON) ? SPF_WEAPONFULLYUP : 0);
|
||||
P_SpawnPlayer(Level, &Level->playerstarts[i], i, (Level->flags2 & LEVEL2_PRERAISEWEAPON) ? SPF_WEAPONFULLYUP : 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,8 +75,6 @@
|
|||
|
||||
void P_ClearUDMFKeys();
|
||||
|
||||
extern AActor *SpawnMapThing (int index, FMapThing *mthing, int position);
|
||||
|
||||
extern unsigned int R_OldBlend;
|
||||
|
||||
static void P_Shutdown ();
|
||||
|
@ -450,7 +448,7 @@ void P_SetupLevel(const char *lumpname, int position, bool newGame)
|
|||
{
|
||||
players[i].mo = nullptr;
|
||||
FPlayerStart *mthing = G_PickPlayerStart(i);
|
||||
P_SpawnPlayer(mthing, i, (level.flags2 & LEVEL2_PRERAISEWEAPON) ? SPF_WEAPONFULLYUP : 0);
|
||||
P_SpawnPlayer(&level, mthing, i, (level.flags2 & LEVEL2_PRERAISEWEAPON) ? SPF_WEAPONFULLYUP : 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ void P_SpawnTeleportFog(AActor *mobj, const DVector3 &pos, bool beforeTele, bool
|
|||
else
|
||||
{
|
||||
double fogDelta = mobj->flags & MF_MISSILE ? 0 : TELEFOGHEIGHT;
|
||||
mo = Spawn((beforeTele ? mobj->TeleFogSourceType : mobj->TeleFogDestType), DVector3(pos, pos.Z + fogDelta), ALLOW_REPLACE);
|
||||
mo = Spawn(mobj->__GetLevel(), (beforeTele ? mobj->TeleFogSourceType : mobj->TeleFogDestType), DVector3(pos, pos.Z + fogDelta), ALLOW_REPLACE);
|
||||
}
|
||||
|
||||
if (mo != NULL && setTarget)
|
||||
|
|
|
@ -81,7 +81,7 @@ bool P_Thing_Spawn (int tid, AActor *source, int type, DAngle angle, bool fog, i
|
|||
}
|
||||
while (spot != NULL)
|
||||
{
|
||||
mobj = Spawn (kind, spot->Pos(), ALLOW_REPLACE);
|
||||
mobj = Spawn (spot->__GetLevel(), kind, spot->Pos(), ALLOW_REPLACE);
|
||||
|
||||
if (mobj != NULL)
|
||||
{
|
||||
|
@ -302,7 +302,7 @@ bool P_Thing_Projectile (int tid, AActor *source, int type, const char *type_nam
|
|||
{
|
||||
z -= spot->Floorclip;
|
||||
}
|
||||
mobj = Spawn (kind, spot->PosAtZ(z), ALLOW_REPLACE);
|
||||
mobj = Spawn (spot->__GetLevel(), kind, spot->PosAtZ(z), ALLOW_REPLACE);
|
||||
|
||||
if (mobj)
|
||||
{
|
||||
|
|
|
@ -2858,7 +2858,7 @@ CCMD (loopsound)
|
|||
}
|
||||
else
|
||||
{
|
||||
AActor *icon = Spawn("SpeakerIcon", players[consoleplayer].mo->PosPlusZ(32.), ALLOW_REPLACE);
|
||||
AActor *icon = Spawn(&level, "SpeakerIcon", players[consoleplayer].mo->PosPlusZ(32.), ALLOW_REPLACE);
|
||||
if (icon != NULL)
|
||||
{
|
||||
S_Sound(icon, CHAN_BODY | CHAN_LOOP, id, 1.f, ATTN_IDLE);
|
||||
|
|
|
@ -7600,7 +7600,7 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx)
|
|||
|
||||
if (ctx.Class != nullptr)
|
||||
{
|
||||
PFunction *afd = FindClassMemberFunction(ctx.Class, ctx.Class, MethodName, ScriptPosition, &error, ctx.Version);
|
||||
PFunction *afd = FindClassMemberFunction(ctx.Class, ctx.Class, MethodName, ScriptPosition, &error, ctx.Version, true);
|
||||
|
||||
if (afd != nullptr)
|
||||
{
|
||||
|
@ -7642,6 +7642,20 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
// Redirect Spawn to another function when called from a non-static method of an actor.
|
||||
// In this special case the missing Level parameter of the static variant can be worked around
|
||||
// and deprecation is not needed. The only problem is that it is impossible to declare
|
||||
// the replacement method in a way that lets it get picked automatically, so it needs to be done here.
|
||||
if (afd->SymbolName == NAME_Spawn)
|
||||
{
|
||||
if ((outerflags & VARF_Method) && ctx.Function->OwningClass->isClass() &&
|
||||
static_cast<PClassType*>(ctx.Function->OwningClass)->Descriptor->IsDescendantOf(RUNTIME_CLASS(AActor)))
|
||||
{
|
||||
PFunction *afd2 = FindClassMemberFunction(ctx.Class, ctx.Class, NAME_Spawn2, ScriptPosition, &error, ctx.Version, true);
|
||||
if (afd2 != nullptr) afd = afd2;
|
||||
}
|
||||
}
|
||||
|
||||
auto self = (afd->Variants[0].Flags & VARF_Method) ? new FxSelf(ScriptPosition) : nullptr;
|
||||
auto x = new FxVMFunctionCall(self, afd, ArgList, ScriptPosition, false);
|
||||
delete this;
|
||||
|
|
|
@ -236,7 +236,7 @@ PFunction *CreateAnonymousFunction(PContainerType *containingclass, PType *retur
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
PFunction *FindClassMemberFunction(PContainerType *selfcls, PContainerType *funccls, FName name, FScriptPosition &sc, bool *error, const VersionInfo &version)
|
||||
PFunction *FindClassMemberFunction(PContainerType *selfcls, PContainerType *funccls, FName name, FScriptPosition &sc, bool *error, const VersionInfo &version, bool nodeprecated)
|
||||
{
|
||||
// Skip ACS_NamedExecuteWithResult. Anything calling this should use the builtin instead.
|
||||
if (name == NAME_ACS_NamedExecuteWithResult) return nullptr;
|
||||
|
@ -263,7 +263,8 @@ PFunction *FindClassMemberFunction(PContainerType *selfcls, PContainerType *func
|
|||
{
|
||||
sc.Message(MSG_ERROR, "%s is declared protected and not accessible", symbol->SymbolName.GetChars());
|
||||
}
|
||||
else if ((funcsym->Variants[0].Flags & VARF_Deprecated) && funcsym->mVersion <= version)
|
||||
// ZScript will skip this because it prints its own message.
|
||||
else if ((funcsym->Variants[0].Flags & VARF_Deprecated) && funcsym->mVersion <= version && !nodeprecated)
|
||||
{
|
||||
sc.Message(MSG_WARNING, "Call to deprecated function %s", symbol->SymbolName.GetChars());
|
||||
}
|
||||
|
|
|
@ -204,7 +204,7 @@ class FxVMFunctionCall *ParseAction(FScanner &sc, FState state, FString statestr
|
|||
FName CheckCastKludges(FName in);
|
||||
void SetImplicitArgs(TArray<PType *> *args, TArray<uint32_t> *argflags, TArray<FName> *argnames, PContainerType *cls, uint32_t funcflags, int useflags);
|
||||
PFunction *CreateAnonymousFunction(PContainerType *containingclass, PType *returntype, int flags);
|
||||
PFunction *FindClassMemberFunction(PContainerType *cls, PContainerType *funccls, FName name, FScriptPosition &sc, bool *error, const VersionInfo &version);
|
||||
PFunction *FindClassMemberFunction(PContainerType *cls, PContainerType *funccls, FName name, FScriptPosition &sc, bool *error, const VersionInfo &version, bool nodeprecated = false);
|
||||
void CreateDamageFunction(PNamespace *ns, const VersionInfo &ver, PClassActor *info, AActor *defaults, FxExpression *id, bool fromDecorate, int lumpnum);
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -636,7 +636,18 @@ class Actor : Thinker native
|
|||
native bool CheckMissileSpawn(double maxdist);
|
||||
native bool CheckPosition(Vector2 pos, bool actorsonly = false, FCheckPosition tm = null);
|
||||
native bool TestMobjLocation();
|
||||
native static Actor Spawn(class<Actor> type, vector3 pos = (0,0,0), int replace = NO_REPLACE);
|
||||
|
||||
// Since this depends on the global level variable it should not be used any longer because this may block compatibility with future features.
|
||||
deprecated("3.8") static Actor Spawn(class<Actor> type, vector3 pos = (0,0,0), int replace = NO_REPLACE)
|
||||
{
|
||||
return level.Spawn(type, pos, replace);
|
||||
}
|
||||
|
||||
// Helper so that not all old code needs to be changed for the above deprecation.
|
||||
protected Actor Spawn2(class<Actor> type, vector3 pos = (0,0,0), int replace = NO_REPLACE)
|
||||
{
|
||||
return Level.Spawn(type, pos, replace);
|
||||
}
|
||||
native Actor SpawnMissile(Actor dest, class<Actor> type, Actor owner = null);
|
||||
native Actor SpawnMissileXYZ(Vector3 pos, Actor dest, Class<Actor> type, bool checkspawn = true, Actor owner = null);
|
||||
native Actor SpawnMissileZ (double z, Actor dest, class<Actor> type);
|
||||
|
|
|
@ -389,7 +389,7 @@ extend class Actor
|
|||
//
|
||||
//===========================================================================
|
||||
|
||||
static bool DoGiveInventory(Actor receiver, bool orresult, class<Inventory> mi, int amount, int setreceiver)
|
||||
private bool DoGiveInventory(Actor receiver, bool orresult, class<Inventory> mi, int amount, int setreceiver)
|
||||
{
|
||||
int paramnum = 0;
|
||||
|
||||
|
|
|
@ -706,6 +706,7 @@ struct LevelLocals native
|
|||
native void StartIntermission(Name type, int state) const;
|
||||
native SpotState GetSpotState(bool create = true);
|
||||
native void ReplaceTextures(String from, String to, int flags);
|
||||
native Actor Spawn(class<Actor> type, vector3 pos = (0,0,0), int replace = NO_REPLACE);
|
||||
|
||||
native clearscope bool IsPointInMap(vector3 p);
|
||||
|
||||
|
|
|
@ -151,9 +151,9 @@ extend class Actor
|
|||
A_PlaySound("brain/pain", CHAN_VOICE, 1, false, ATTN_NONE);
|
||||
}
|
||||
|
||||
private static void BrainishExplosion(vector3 pos)
|
||||
private void BrainishExplosion(vector3 pos)
|
||||
{
|
||||
Actor boom = Actor.Spawn("Rocket", pos, NO_REPLACE);
|
||||
Actor boom = Spawn("Rocket", pos, NO_REPLACE);
|
||||
if (boom)
|
||||
{
|
||||
boom.DeathSound = "misc/brainexplode";
|
||||
|
|
|
@ -258,7 +258,7 @@ class HolyMissile : Actor
|
|||
mo.bSkullFly = true;
|
||||
mo.bMissile = false;
|
||||
}
|
||||
HolyTail.SpawnSpiritTail (mo);
|
||||
SpawnSpiritTail (mo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -558,28 +558,6 @@ class HolyTail : Actor
|
|||
Stop;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// SpawnSpiritTail
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
static void SpawnSpiritTail (Actor spirit)
|
||||
{
|
||||
Actor tail = Spawn ("HolyTail", spirit.Pos, ALLOW_REPLACE);
|
||||
if (tail != null)
|
||||
{
|
||||
tail.target = spirit; // parent
|
||||
for (int i = 1; i < 3; i++)
|
||||
{
|
||||
Actor next = Spawn ("HolyTailTrail", spirit.Pos, ALLOW_REPLACE);
|
||||
tail.tracer = next;
|
||||
tail = next;
|
||||
}
|
||||
tail.tracer = null; // last tail bit
|
||||
}
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// CHolyTailFollow
|
||||
|
@ -674,3 +652,29 @@ class HolyTailTrail : HolyTail
|
|||
Goto TailTrail;
|
||||
}
|
||||
}
|
||||
|
||||
extend class Actor
|
||||
{
|
||||
//============================================================================
|
||||
//
|
||||
// SpawnSpiritTail
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
void SpawnSpiritTail (Actor spirit)
|
||||
{
|
||||
Actor tail = Spawn ("HolyTail", spirit.Pos, ALLOW_REPLACE);
|
||||
if (tail != null)
|
||||
{
|
||||
tail.target = spirit; // parent
|
||||
for (int i = 1; i < 3; i++)
|
||||
{
|
||||
Actor next = Spawn ("HolyTailTrail", spirit.Pos, ALLOW_REPLACE);
|
||||
tail.tracer = next;
|
||||
tail = next;
|
||||
}
|
||||
tail.tracer = null; // last tail bit
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -234,7 +234,7 @@ class Korax : Actor
|
|||
spirit.args[1] = 0; // initial look angle
|
||||
|
||||
// Spawn a tail for spirit
|
||||
HolyTail.SpawnSpiritTail (spirit);
|
||||
SpawnSpiritTail (spirit);
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
|
|
@ -414,12 +414,16 @@ class Sigil : Weapon
|
|||
{
|
||||
if (playeringame[i] && players[i].mo != null)
|
||||
{
|
||||
GiveSigilPiece (players[i].mo);
|
||||
players[i].mo.GiveSigilPiece ();
|
||||
Destroy ();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
extend class Actor
|
||||
{
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
|
@ -430,13 +434,13 @@ class Sigil : Weapon
|
|||
//
|
||||
//============================================================================
|
||||
|
||||
static int GiveSigilPiece (Actor receiver)
|
||||
int GiveSigilPiece ()
|
||||
{
|
||||
Sigil sigl = Sigil(receiver.FindInventory("Sigil"));
|
||||
Sigil sigl = Sigil(FindInventory("Sigil"));
|
||||
if (sigl == null)
|
||||
{
|
||||
sigl = Sigil(Spawn("Sigil1"));
|
||||
if (!sigl.CallTryPickup (receiver))
|
||||
if (!sigl.CallTryPickup (self))
|
||||
{
|
||||
sigl.Destroy ();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue