- took several methods out of the native PlayerPawn implementation, either by scriptification or moving them to other places.

This commit is contained in:
Christoph Oelckers 2019-01-03 13:58:53 +01:00
parent 4cc78c3273
commit 2258a71c36
18 changed files with 203 additions and 235 deletions

View file

@ -822,6 +822,7 @@ public:
// Return starting health adjusted by skill level // Return starting health adjusted by skill level
int SpawnHealth() const; int SpawnHealth() const;
virtual int GetMaxHealth(bool withupgrades = false) const;
int GetGibHealth() const; int GetGibHealth() const;
double GetCameraHeight() const; double GetCameraHeight() const;

View file

@ -213,6 +213,7 @@ DEFINE_FIELD_X(DehInfo, DehInfo, ExplosionAlpha)
DEFINE_FIELD_X(DehInfo, DehInfo, NoAutofreeze) DEFINE_FIELD_X(DehInfo, DehInfo, NoAutofreeze)
DEFINE_FIELD_X(DehInfo, DehInfo, BFGCells) DEFINE_FIELD_X(DehInfo, DehInfo, BFGCells)
DEFINE_FIELD_X(DehInfo, DehInfo, BlueAC) DEFINE_FIELD_X(DehInfo, DehInfo, BlueAC)
DEFINE_FIELD_X(DehInfo, DehInfo, MaxHealth)
// Doom identified pickup items by their sprites. ZDoom prefers to use their // Doom identified pickup items by their sprites. ZDoom prefers to use their
// class type to identify them instead. To support the traditional Doom // class type to identify them instead. To support the traditional Doom

View file

@ -92,15 +92,6 @@ public:
virtual void BeginPlay () override; virtual void BeginPlay () override;
virtual bool UpdateWaterLevel (bool splash) override; virtual bool UpdateWaterLevel (bool splash) override;
int GetMaxHealth(bool withupgrades = false) const;
void GiveDeathmatchInventory ();
void GiveDefaultInventory ();
// These are virtual on the script side only.
void PlayIdle();
int hasBuddha(); // returns 0 for no buddha, 1 for regular buddha and 2 for strong buddha
enum EInvulState enum EInvulState
{ {
@ -112,7 +103,6 @@ public:
int crouchsprite; int crouchsprite;
int MaxHealth;
int BonusHealth; int BonusHealth;
int MugShotMaxHealth; int MugShotMaxHealth;
@ -132,6 +122,7 @@ public:
double UseRange; // [NS] Distance at which player can +use double UseRange; // [NS] Distance at which player can +use
// Everything below this point is only used by scripted code or through the scripted variable interface. // Everything below this point is only used by scripted code or through the scripted variable interface.
int MaxHealth;
int RunHealth; int RunHealth;
TObjPtr<AActor*> InvFirst; // first inventory item displayed on inventory bar TObjPtr<AActor*> InvFirst; // first inventory item displayed on inventory bar
@ -157,6 +148,9 @@ public:
}; };
void PlayIdle(AActor *player);
// //
// PlayerPawn flags // PlayerPawn flags
// //

View file

@ -1290,7 +1290,12 @@ void G_PlayerReborn (int player)
if (gamestate != GS_TITLELEVEL) if (gamestate != GS_TITLELEVEL)
{ {
// [GRB] Give inventory specified in DECORATE // [GRB] Give inventory specified in DECORATE
actor->GiveDefaultInventory ();
IFVIRTUALPTR(actor, APlayerPawn, GiveDefaultInventory)
{
VMValue params[1] = { actor };
VMCall(func, params, 1, nullptr, 0);
}
p->ReadyWeapon = p->PendingWeapon; p->ReadyWeapon = p->PendingWeapon;
} }

View file

@ -1041,6 +1041,7 @@ xx(Slot)
xx(SoundClass) xx(SoundClass)
xx(ViewBob) xx(ViewBob)
xx(DamageFade) xx(DamageFade)
xx(MaxHealth)
xx(BlueCard) xx(BlueCard)
xx(YellowCard) xx(YellowCard)

View file

@ -1816,10 +1816,7 @@ int CheckInventory (AActor *activator, const char *type, bool max)
{ {
if (max) if (max)
{ {
if (activator->IsKindOf (RUNTIME_CLASS (APlayerPawn))) return activator->GetMaxHealth();
return static_cast<APlayerPawn *>(activator)->GetMaxHealth();
else
return activator->SpawnHealth();
} }
return activator->health; return activator->health;
} }
@ -4268,7 +4265,7 @@ void DLevelScript::DoSetActorProperty (AActor *actor, int property, int value)
case APROP_SpawnHealth: case APROP_SpawnHealth:
if (actor->IsKindOf (RUNTIME_CLASS (APlayerPawn))) if (actor->IsKindOf (RUNTIME_CLASS (APlayerPawn)))
{ {
static_cast<APlayerPawn *>(actor)->MaxHealth = value; actor->IntVar(NAME_MaxHealth) = value;
} }
break; break;
@ -4428,14 +4425,7 @@ int DLevelScript::GetActorProperty (int tid, int property)
case APROP_Notarget: return !!(actor->flags3 & MF3_NOTARGET); case APROP_Notarget: return !!(actor->flags3 & MF3_NOTARGET);
case APROP_Notrigger: return !!(actor->flags6 & MF6_NOTRIGGER); case APROP_Notrigger: return !!(actor->flags6 & MF6_NOTRIGGER);
case APROP_Dormant: return !!(actor->flags2 & MF2_DORMANT); case APROP_Dormant: return !!(actor->flags2 & MF2_DORMANT);
case APROP_SpawnHealth: if (actor->IsKindOf (RUNTIME_CLASS (APlayerPawn))) case APROP_SpawnHealth: return actor->GetMaxHealth();
{
return static_cast<APlayerPawn *>(actor)->GetMaxHealth();
}
else
{
return actor->SpawnHealth();
}
case APROP_JumpZ: if (actor->IsKindOf (RUNTIME_CLASS (APlayerPawn))) case APROP_JumpZ: if (actor->IsKindOf (RUNTIME_CLASS (APlayerPawn)))
{ {

View file

@ -1935,34 +1935,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_Burst)
return 0; return 0;
} }
//===========================================================================
//
// A_Stop
// resets all velocity of the actor to 0
//
//===========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_Stop)
{
PARAM_SELF_PROLOGUE(AActor);
self->Vel.Zero();
if (self->player && self->player->mo == self && !(self->player->cheats & CF_PREDICTING))
{
self->player->mo->PlayIdle();
self->player->Vel.Zero();
}
return 0;
}
static void CheckStopped(AActor *self)
{
if (self->player != NULL &&
self->player->mo == self &&
!(self->player->cheats & CF_PREDICTING) && !self->Vel.isZero())
{
self->player->mo->PlayIdle();
self->player->Vel.Zero();
}
}
//=========================================================================== //===========================================================================
// //
@ -2881,89 +2853,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_SetRoll)
return 0; return 0;
} }
//===========================================================================
//
// A_ScaleVelocity
//
// Scale actor's velocity.
//
//===========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_ScaleVelocity)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_FLOAT(scale);
PARAM_INT(ptr);
AActor *ref = COPY_AAPTR(self, ptr);
if (ref == NULL)
{
return 0;
}
bool was_moving = !ref->Vel.isZero();
ref->Vel *= scale;
// If the actor was previously moving but now is not, and is a player,
// update its player variables. (See A_Stop.)
if (was_moving)
{
CheckStopped(ref);
}
return 0;
}
//===========================================================================
//
// A_ChangeVelocity
//
//===========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_ChangeVelocity)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_FLOAT (x)
PARAM_FLOAT (y)
PARAM_FLOAT (z)
PARAM_INT (flags)
PARAM_INT (ptr)
AActor *ref = COPY_AAPTR(self, ptr);
if (ref == NULL)
{
return 0;
}
INTBOOL was_moving = !ref->Vel.isZero();
DVector3 vel(x, y, z);
double sina = ref->Angles.Yaw.Sin();
double cosa = ref->Angles.Yaw.Cos();
if (flags & 1) // relative axes - make x, y relative to actor's current angle
{
vel.X = x*cosa - y*sina;
vel.Y = x*sina + y*cosa;
}
if (flags & 2) // discard old velocity - replace old velocity with new velocity
{
ref->Vel = vel;
}
else // add new velocity to old velocity
{
ref->Vel += vel;
}
if (was_moving)
{
CheckStopped(ref);
}
return 0;
}
//=========================================================================== //===========================================================================
// //
// A_SetUserVar // A_SetUserVar

View file

@ -771,7 +771,7 @@ void P_StartConversation (AActor *npc, AActor *pc, bool facetalker, bool saveang
pc->Vel.Zero(); pc->Vel.Zero();
pc->player->Vel.Zero(); pc->player->Vel.Zero();
static_cast<APlayerPawn*>(pc)->PlayIdle (); PlayIdle (pc);
pc->player->ConversationPC = pc; pc->player->ConversationPC = pc;
pc->player->ConversationNPC = npc; pc->player->ConversationNPC = npc;

View file

@ -984,6 +984,25 @@ DEFINE_ACTION_FUNCTION(AActor, TriggerPainChance)
================== ==================
*/ */
//===========================================================================
//
// APlayerPawn :: hasBuddha
//
//===========================================================================
static int hasBuddha(player_t *player)
{
if (player->playerstate == PST_DEAD) return 0;
if (player->cheats & CF_BUDDHA2) return 2;
if ((player->cheats & CF_BUDDHA) ||
(player->mo->flags7 & MF7_BUDDHA) ||
player->mo->FindInventory(PClass::FindActor(NAME_PowerBuddha), true) != nullptr) return 1;
return 0;
}
// Returns the amount of damage actually inflicted upon the target, or -1 if // Returns the amount of damage actually inflicted upon the target, or -1 if
// the damage was cancelled. // the damage was cancelled.
@ -1312,7 +1331,7 @@ static int DamageMobj (AActor *target, AActor *inflictor, AActor *source, int da
// but telefragging should still do enough damage to kill the player) // but telefragging should still do enough damage to kill the player)
// Ignore players that are already dead. // Ignore players that are already dead.
// [MC]Buddha2 absorbs telefrag damage, and anything else thrown their way. // [MC]Buddha2 absorbs telefrag damage, and anything else thrown their way.
int buddha = player->mo->hasBuddha(); int buddha = hasBuddha(player);
if (flags & DMG_FORCED) buddha = 0; if (flags & DMG_FORCED) buddha = 0;
if (telefragDamage && buddha == 1) buddha = 0; if (telefragDamage && buddha == 1) buddha = 0;
if (buddha) if (buddha)
@ -1759,7 +1778,7 @@ void P_PoisonDamage (player_t *player, AActor *source, int damage, bool playPain
target->health -= damage; target->health -= damage;
if (target->health <= 0) if (target->health <= 0)
{ // Death { // Death
int buddha = player->mo->hasBuddha(); int buddha = hasBuddha(player);
if (telefragDamage && buddha == 1) buddha = 0; if (telefragDamage && buddha == 1) buddha = 0;
if (buddha) if (buddha)
{ // [SP] Save the player... { // [SP] Save the player...

View file

@ -2279,7 +2279,7 @@ explode:
// Don't affect main player when voodoo dolls stop: // Don't affect main player when voodoo dolls stop:
if (player && player->mo == mo && !(player->cheats & CF_PREDICTING)) if (player && player->mo == mo && !(player->cheats & CF_PREDICTING))
{ {
player->mo->PlayIdle (); PlayIdle (player->mo);
} }
mo->Vel.X = mo->Vel.Y = 0; mo->Vel.X = mo->Vel.Y = 0;
@ -5077,7 +5077,11 @@ APlayerPawn *P_SpawnPlayer (FPlayerStart *mthing, int playernum, int flags)
if (deathmatch) if (deathmatch)
{ // Give all cards in death match mode. { // Give all cards in death match mode.
p->mo->GiveDeathmatchInventory (); IFVIRTUALPTR(p->mo, APlayerPawn, GiveDeathmatchInventory)
{
VMValue params[1] = { p->mo };
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) !!G_SkillProperty(SKILLP_PlayerRespawn)) && state == PST_REBORN && oldactor != NULL)
@ -7072,6 +7076,18 @@ int AActor::SpawnHealth() const
} }
} }
int AActor::GetMaxHealth(bool withupgrades) const
{
int ret = 100;
IFVIRTUAL(AActor, GetMaxHealth)
{
VMValue param[] = { const_cast<AActor*>(this), withupgrades };
VMReturn r(&ret);
VMCall(func, param, 2, &r, 1);
}
return ret;
}
FState *AActor::GetRaiseState() FState *AActor::GetRaiseState()
{ {
if (!(flags & MF_CORPSE)) if (!(flags & MF_CORPSE))

View file

@ -406,7 +406,7 @@ bool EV_Teleport (int tid, int tag, line_t *line, int side, AActor *thing, int f
} }
if (vx == 0 && vy == 0 && thing->player != NULL && thing->player->mo == thing && !predicting) if (vx == 0 && vy == 0 && thing->player != NULL && thing->player->mo == thing && !predicting)
{ {
thing->player->mo->PlayIdle (); PlayIdle (thing->player->mo);
} }
return true; return true;
} }

View file

@ -919,74 +919,6 @@ void APlayerPawn::PostBeginPlay()
} }
} }
//===========================================================================
//
// APlayerPawn :: GiveDeathmatchInventory
//
// Gives players items they should have in addition to their default
// inventory when playing deathmatch. (i.e. all keys)
//
//===========================================================================
void APlayerPawn::GiveDeathmatchInventory()
{
for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
{
if (PClassActor::AllActorClasses[i]->IsDescendantOf (PClass::FindActor(NAME_Key)))
{
auto key = GetDefaultByType (PClassActor::AllActorClasses[i]);
if (key->special1 != 0)
{
key = Spawn(PClassActor::AllActorClasses[i]);
if (!CallTryPickup (key, this))
{
key->Destroy ();
}
}
}
}
}
//===========================================================================
//
// APlayerPawn :: hasBuddha
//
//===========================================================================
int APlayerPawn::hasBuddha()
{
if (player->playerstate == PST_DEAD) return 0;
if (player->cheats & CF_BUDDHA2) return 2;
if ((player->cheats & CF_BUDDHA) ||
(player->mo->flags7 & MF7_BUDDHA) ||
player->mo->FindInventory (PClass::FindActor(NAME_PowerBuddha),true) != nullptr) return 1;
return 0;
}
//===========================================================================
//
// APlayerPawn :: GetMaxHealth
//
// only needed because Boom screwed up Dehacked.
//
//===========================================================================
int APlayerPawn::GetMaxHealth(bool withupgrades) const
{
int ret = MaxHealth > 0? MaxHealth : ((i_compatflags&COMPATF_DEHHEALTH)? 100 : deh.MaxHealth);
if (withupgrades) ret += stamina + BonusHealth;
return ret;
}
DEFINE_ACTION_FUNCTION(APlayerPawn, GetMaxHealth)
{
PARAM_SELF_PROLOGUE(APlayerPawn);
PARAM_BOOL(withupgrades);
ACTION_RETURN_INT(self->GetMaxHealth(withupgrades));
}
//=========================================================================== //===========================================================================
// //
// APlayerPawn :: UpdateWaterLevel // APlayerPawn :: UpdateWaterLevel
@ -1023,30 +955,15 @@ bool APlayerPawn::UpdateWaterLevel (bool splash)
// //
//=========================================================================== //===========================================================================
void APlayerPawn::PlayIdle () void PlayIdle (AActor *player)
{ {
IFVIRTUAL(APlayerPawn, PlayIdle) IFVIRTUALPTR(player, APlayerPawn, PlayIdle)
{ {
VMValue params[1] = { (DObject*)this }; VMValue params[1] = { (DObject*)player };
VMCall(func, params, 1, nullptr, 0); VMCall(func, params, 1, nullptr, 0);
} }
} }
//===========================================================================
//
// APlayerPawn :: GiveDefaultInventory
//
//===========================================================================
void APlayerPawn::GiveDefaultInventory ()
{
IFVIRTUAL(APlayerPawn, GiveDefaultInventory)
{
VMValue params[1] = { (DObject*)this };
VMCall(func, params, 1, nullptr, 0);
}
}
//=========================================================================== //===========================================================================
// //
// A_PlayerScream // A_PlayerScream

View file

@ -321,10 +321,6 @@ struct VMValue
{ {
sp = s; sp = s;
} }
VMValue(DObject *v)
{
a = v;
}
VMValue(void *v) VMValue(void *v)
{ {
a = v; a = v;

View file

@ -9,6 +9,7 @@ version "3.7"
#include "zscript/actor_checks.txt" #include "zscript/actor_checks.txt"
#include "zscript/actor_interaction.txt" #include "zscript/actor_interaction.txt"
#include "zscript/actor_inventory.txt" #include "zscript/actor_inventory.txt"
#include "zscript/actor_actions.txt"
#include "zscript/events.txt" #include "zscript/events.txt"
#include "zscript/destructible.txt" #include "zscript/destructible.txt"
#include "zscript/level_compatibility.txt" #include "zscript/level_compatibility.txt"

View file

@ -615,6 +615,10 @@ class Actor : Thinker native
native void ExplodeMissile(line lin = null, Actor target = null, bool onsky = false); native void ExplodeMissile(line lin = null, Actor target = null, bool onsky = false);
native void RestoreDamage(); native void RestoreDamage();
native clearscope int SpawnHealth() const; native clearscope int SpawnHealth() const;
virtual clearscope int GetMaxHealth(bool withupgrades = false) const // this only exists to make checks for player health easier so they can avoid the type check and just call this method.
{
return SpawnHealth();
}
native void SetDamage(int dmg); native void SetDamage(int dmg);
native clearscope double Distance2D(Actor other) const; native clearscope double Distance2D(Actor other) const;
native clearscope double Distance3D(Actor other) const; native clearscope double Distance3D(Actor other) const;
@ -1086,7 +1090,6 @@ class Actor : Thinker native
native int GetRadiusDamage(Actor thing, int damage, int distance, int fulldmgdistance = 0, bool oldradiusdmg = false); native int GetRadiusDamage(Actor thing, int damage, int distance, int fulldmgdistance = 0, bool oldradiusdmg = false);
native int RadiusAttack(Actor bombsource, int bombdamage, int bombdistance, Name bombmod = 'none', int flags = RADF_HURTSOURCE, int fulldamagedistance = 0); native int RadiusAttack(Actor bombsource, int bombdamage, int bombdistance, Name bombmod = 'none', int flags = RADF_HURTSOURCE, int fulldamagedistance = 0);
native void A_Stop();
native void A_Respawn(int flags = 1); native void A_Respawn(int flags = 1);
native void A_RestoreSpecialPosition(); native void A_RestoreSpecialPosition();
native void A_QueueCorpse(); native void A_QueueCorpse();
@ -1097,8 +1100,6 @@ class Actor : Thinker native
native void A_SetAngle(double angle = 0, int flags = 0, int ptr = AAPTR_DEFAULT); native void A_SetAngle(double angle = 0, int flags = 0, int ptr = AAPTR_DEFAULT);
native void A_SetPitch(double pitch, int flags = 0, int ptr = AAPTR_DEFAULT); native void A_SetPitch(double pitch, int flags = 0, int ptr = AAPTR_DEFAULT);
native void A_SetRoll(double roll, int flags = 0, int ptr = AAPTR_DEFAULT); native void A_SetRoll(double roll, int flags = 0, int ptr = AAPTR_DEFAULT);
native void A_ScaleVelocity(double scale, int ptr = AAPTR_DEFAULT);
native void A_ChangeVelocity(double x = 0, double y = 0, double z = 0, int flags = 0, int ptr = AAPTR_DEFAULT);
deprecated("2.3") native void A_SetUserVar(name varname, int value); deprecated("2.3") native void A_SetUserVar(name varname, int value);
deprecated("2.3") native void A_SetUserArray(name varname, int index, int value); deprecated("2.3") native void A_SetUserArray(name varname, int index, int value);
deprecated("2.3") native void A_SetUserVarFloat(name varname, double value); deprecated("2.3") native void A_SetUserVarFloat(name varname, double value);

View file

@ -0,0 +1,99 @@
extend class Actor
{
private void CheckStopped()
{
let player = self.player;
if (player && player.mo == self && !(player.cheats & CF_PREDICTING) && Vel == (0, 0, 0))
{
player.mo.PlayIdle();
player.Vel = (0, 0);
}
}
//===========================================================================
//
// A_Stop
// resets all velocity of the actor to 0
//
//===========================================================================
void A_Stop()
{
let player = self.player;
Vel = (0, 0, 0);
CheckStopped();
}
//===========================================================================
//
// A_ScaleVelocity
//
// Scale actor's velocity.
//
//===========================================================================
void A_ScaleVelocity(double scale, int ptr = AAPTR_DEFAULT)
{
let ref = GetPointer(ptr);
if (ref == NULL)
{
return;
}
bool was_moving = ref.Vel != (0, 0, 0);
ref.Vel *= scale;
// If the actor was previously moving but now is not, and is a player,
// update its player variables. (See A_Stop.)
if (was_moving)
{
ref.CheckStopped();
}
}
//===========================================================================
//
// A_ChangeVelocity
//
//===========================================================================
void A_ChangeVelocity(double x = 0, double y = 0, double z = 0, int flags = 0, int ptr = AAPTR_DEFAULT)
{
let ref = GetPointer(ptr);
if (ref == NULL)
{
return;
}
bool was_moving = ref.Vel != (0, 0, 0);
let newvel = (x, y, z);
double sina = sin(ref.Angle);
double cosa = cos(ref.Angle);
if (flags & 1) // relative axes - make x, y relative to actor's current angle
{
newvel.X = x * cosa - y * sina;
newvel.Y = x * sina + y * cosa;
}
if (flags & 2) // discard old velocity - replace old velocity with new velocity
{
ref.Vel = newvel;
}
else // add new velocity to old velocity
{
ref.Vel += newvel;
}
if (was_moving)
{
ref.CheckStopped();
}
}
}

View file

@ -724,6 +724,7 @@ struct DehInfo native
native readonly int NoAutofreeze; native readonly int NoAutofreeze;
native readonly int BFGCells; native readonly int BFGCells;
native readonly int BlueAC; native readonly int BlueAC;
native readonly int MaxHealth;
} }
struct State native struct State native

View file

@ -1847,6 +1847,44 @@ class PlayerPawn : Actor native
} }
} }
//===========================================================================
//
// APlayerPawn :: GiveDeathmatchInventory
//
// Gives players items they should have in addition to their default
// inventory when playing deathmatch. (i.e. all keys)
//
//===========================================================================
virtual void GiveDeathmatchInventory()
{
for ( int i = 0; i < AllActorClasses.Size(); ++i)
{
let cls = (class<Key>)(AllActorClasses[i]);
if (cls)
{
let keyobj = GetDefaultByType(cls);
if (keyobj.special1 != 0)
{
GiveInventoryType(cls);
}
}
}
}
//===========================================================================
//
//
//
//===========================================================================
override int GetMaxHealth(bool withupgrades) const
{
int ret = MaxHealth > 0? MaxHealth : (compat_dehhealth? 100 : deh.MaxHealth);
if (withupgrades) ret += stamina + BonusHealth;
return ret;
}
//=========================================================================== //===========================================================================
// //
// //
@ -2347,7 +2385,6 @@ class PlayerPawn : Actor native
// //
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
native clearscope int GetMaxHealth(bool withupgrades = false) const;
native clearscope static String GetPrintableDisplayName(Class<Actor> cls); native clearscope static String GetPrintableDisplayName(Class<Actor> cls);
native void CheckMusicChange(); native void CheckMusicChange();
native void CheckEnvironment(); native void CheckEnvironment();