- 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
int SpawnHealth() const;
virtual int GetMaxHealth(bool withupgrades = false) const;
int GetGibHealth() 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, BFGCells)
DEFINE_FIELD_X(DehInfo, DehInfo, BlueAC)
DEFINE_FIELD_X(DehInfo, DehInfo, MaxHealth)
// Doom identified pickup items by their sprites. ZDoom prefers to use their
// class type to identify them instead. To support the traditional Doom

View File

@ -92,15 +92,6 @@ public:
virtual void BeginPlay () 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
{
@ -112,7 +103,6 @@ public:
int crouchsprite;
int MaxHealth;
int BonusHealth;
int MugShotMaxHealth;
@ -132,6 +122,7 @@ public:
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.
int MaxHealth;
int RunHealth;
TObjPtr<AActor*> InvFirst; // first inventory item displayed on inventory bar
@ -157,6 +148,9 @@ public:
};
void PlayIdle(AActor *player);
//
// PlayerPawn flags
//

View File

@ -1290,7 +1290,12 @@ void G_PlayerReborn (int player)
if (gamestate != GS_TITLELEVEL)
{
// [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;
}

View File

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

View File

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

View File

@ -1935,34 +1935,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_Burst)
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;
}
//===========================================================================
//
// 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

View File

@ -771,7 +771,7 @@ void P_StartConversation (AActor *npc, AActor *pc, bool facetalker, bool saveang
pc->Vel.Zero();
pc->player->Vel.Zero();
static_cast<APlayerPawn*>(pc)->PlayIdle ();
PlayIdle (pc);
pc->player->ConversationPC = pc;
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
// 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)
// Ignore players that are already dead.
// [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 (telefragDamage && buddha == 1) buddha = 0;
if (buddha)
@ -1759,7 +1778,7 @@ void P_PoisonDamage (player_t *player, AActor *source, int damage, bool playPain
target->health -= damage;
if (target->health <= 0)
{ // Death
int buddha = player->mo->hasBuddha();
int buddha = hasBuddha(player);
if (telefragDamage && buddha == 1) buddha = 0;
if (buddha)
{ // [SP] Save the player...

View File

@ -2279,7 +2279,7 @@ explode:
// Don't affect main player when voodoo dolls stop:
if (player && player->mo == mo && !(player->cheats & CF_PREDICTING))
{
player->mo->PlayIdle ();
PlayIdle (player->mo);
}
mo->Vel.X = mo->Vel.Y = 0;
@ -5077,7 +5077,11 @@ APlayerPawn *P_SpawnPlayer (FPlayerStart *mthing, int playernum, int flags)
if (deathmatch)
{ // 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 ||
!!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()
{
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)
{
thing->player->mo->PlayIdle ();
PlayIdle (thing->player->mo);
}
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
@ -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);
}
}
//===========================================================================
//
// APlayerPawn :: GiveDefaultInventory
//
//===========================================================================
void APlayerPawn::GiveDefaultInventory ()
{
IFVIRTUAL(APlayerPawn, GiveDefaultInventory)
{
VMValue params[1] = { (DObject*)this };
VMCall(func, params, 1, nullptr, 0);
}
}
//===========================================================================
//
// A_PlayerScream

View File

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

View File

@ -9,6 +9,7 @@ version "3.7"
#include "zscript/actor_checks.txt"
#include "zscript/actor_interaction.txt"
#include "zscript/actor_inventory.txt"
#include "zscript/actor_actions.txt"
#include "zscript/events.txt"
#include "zscript/destructible.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 RestoreDamage();
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 clearscope double Distance2D(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 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_RestoreSpecialPosition();
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_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_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_SetUserArray(name varname, int index, int 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 BFGCells;
native readonly int BlueAC;
native readonly int MaxHealth;
}
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 void CheckMusicChange();
native void CheckEnvironment();