- scriptified PowerTargeter.

This commit is contained in:
Christoph Oelckers 2017-01-15 19:44:43 +01:00
parent bf52ce19e4
commit 7503937a84
11 changed files with 147 additions and 147 deletions

View file

@ -1150,7 +1150,6 @@ set (PCH_SOURCES
g_inventory/a_ammo.cpp
g_inventory/a_armor.cpp
g_inventory/a_artifacts.cpp
g_inventory/a_health.cpp
g_inventory/a_keys.cpp
g_inventory/a_pickups.cpp
g_inventory/a_weaponpiece.cpp

View file

@ -1307,121 +1307,6 @@ void APowerSpeed::DoEffect ()
}
}
// Targeter powerup ---------------------------------------------------------
IMPLEMENT_CLASS(APowerTargeter, false, false)
void APowerTargeter::Travelled ()
{
CallInitEffect ();
}
void APowerTargeter::InitEffect ()
{
// Why is this called when the inventory isn't even attached yet
// in APowerup::CreateCopy?
if (!Owner->FindInventory(GetClass(), true))
return;
player_t *player;
Super::InitEffect();
if ((player = Owner->player) == nullptr)
return;
FState *state = FindState("Targeter");
if (state != nullptr)
{
P_SetPsprite(player, PSP_TARGETCENTER, state + 0);
P_SetPsprite(player, PSP_TARGETLEFT, state + 1);
P_SetPsprite(player, PSP_TARGETRIGHT, state + 2);
}
player->GetPSprite(PSP_TARGETCENTER)->x = (160-3);
player->GetPSprite(PSP_TARGETCENTER)->y =
player->GetPSprite(PSP_TARGETLEFT)->y =
player->GetPSprite(PSP_TARGETRIGHT)->y = (100-3);
PositionAccuracy ();
}
void APowerTargeter::AttachToOwner(AActor *other)
{
Super::AttachToOwner(other);
// Let's actually properly call this for the targeters.
CallInitEffect();
}
bool APowerTargeter::HandlePickup(AInventory *item)
{
if (Super::HandlePickup(item))
{
CallInitEffect(); // reset the HUD sprites
return true;
}
return false;
}
void APowerTargeter::DoEffect ()
{
Super::DoEffect ();
if (Owner != nullptr && Owner->player != nullptr)
{
player_t *player = Owner->player;
PositionAccuracy ();
if (EffectTics < 5*TICRATE)
{
FState *state = FindState("Targeter");
if (state != nullptr)
{
if (EffectTics & 32)
{
P_SetPsprite(player, PSP_TARGETRIGHT, nullptr);
P_SetPsprite(player, PSP_TARGETLEFT, state + 1);
}
else if (EffectTics & 16)
{
P_SetPsprite(player, PSP_TARGETRIGHT, state + 2);
P_SetPsprite(player, PSP_TARGETLEFT, nullptr);
}
}
}
}
}
void APowerTargeter::EndEffect ()
{
Super::EndEffect();
if (Owner != nullptr && Owner->player != nullptr)
{
// Calling GetPSprite here could crash if we're creating a new game.
// This is because P_SetupLevel nulls the player's mo before destroying
// every DThinker which in turn ends up calling this.
// However P_SetupLevel is only called after G_NewInit which calls
// every player's dtor which destroys all their psprites.
DPSprite *pspr;
if ((pspr = Owner->player->FindPSprite(PSP_TARGETCENTER)) != nullptr) pspr->SetState(nullptr);
if ((pspr = Owner->player->FindPSprite(PSP_TARGETLEFT)) != nullptr) pspr->SetState(nullptr);
if ((pspr = Owner->player->FindPSprite(PSP_TARGETRIGHT)) != nullptr) pspr->SetState(nullptr);
}
}
void APowerTargeter::PositionAccuracy ()
{
player_t *player = Owner->player;
if (player != nullptr)
{
player->GetPSprite(PSP_TARGETLEFT)->x = (160-3) - ((100 - player->mo->accuracy));
player->GetPSprite(PSP_TARGETRIGHT)->x = (160-3)+ ((100 - player->mo->accuracy));
}
}
// Morph powerup ------------------------------------------------------
IMPLEMENT_CLASS(APowerMorph, false, true)

View file

@ -161,19 +161,6 @@ public:
#define PSF_NOTRAIL 1
class APowerTargeter : public APowerup
{
DECLARE_CLASS (APowerTargeter, APowerup)
protected:
virtual void InitEffect () override;
virtual void DoEffect () override;
virtual void EndEffect () override;
void PositionAccuracy ();
virtual void Travelled () override;
virtual void AttachToOwner(AActor *other) override;
virtual bool HandlePickup(AInventory *item) override;
};
class APowerMorph : public APowerup
{
DECLARE_CLASS( APowerMorph, APowerup )

View file

@ -368,19 +368,6 @@ void AInventory::CallDoEffect()
}
//===========================================================================
//
// AInventory :: Travelled
//
// Called when an item in somebody's inventory is carried over to another
// map, in case it needs to do special reinitialization.
//
//===========================================================================
void AInventory::Travelled ()
{
}
//===========================================================================
//
// AInventory :: OwnerDied
@ -1403,7 +1390,7 @@ bool AInventory::TryPickup (AActor *&toucher)
copy->ItemFlags &= ~IF_CREATECOPYMOVED;
}
// Continue onwards with the rest
copy->AttachToOwner (newtoucher);
copy->CallAttachToOwner (newtoucher);
if (ItemFlags & IF_AUTOACTIVATE)
{
if (copy->CallUse (true))

View file

@ -140,7 +140,6 @@ public:
double GetSpeedFactor();
bool GetNoTeleportFreeze();
// Stuff for later when more features are exported.
virtual void Travelled();
virtual void OwnerDied();

View file

@ -84,6 +84,7 @@
#include "r_utility.h"
#include "p_spec.h"
#include "serializer.h"
#include "virtual.h"
#include "gi.h"
@ -1313,7 +1314,13 @@ void G_FinishTravel ()
{
inv->ChangeStatNum (STAT_INVENTORY);
inv->LinkToWorld (nullptr);
inv->Travelled ();
IFVIRTUALPTR(inv, AInventory, Travelled)
{
VMValue params[1] = { inv };
VMFrameStack stack;
GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr);
}
}
if (ib_compatflags & BCOMPATF_RESETPLAYERSPEED)
{

View file

@ -171,6 +171,7 @@ xx(PuzzleItemNumber)
xx(HealthPickup)
xx(autousemode)
xx(Ammo)
xx(PowerTargeter)
xx(AcolyteBlue)
xx(SpectralLightningV1)

View file

@ -233,7 +233,7 @@ DPSprite *player_t::GetPSprite(PSPLayers layer)
{
if (mo != nullptr)
{
newcaller = mo->FindInventory(RUNTIME_CLASS(APowerTargeter), true);
newcaller = mo->FindInventory(PClass::FindActor(NAME_PowerTargeter), true);
}
}
else if (layer == PSP_STRIFEHANDS)

View file

@ -38,6 +38,18 @@ class Inventory : Actor native
virtual native void AttachToOwner(Actor user);
virtual native void DetachFromOwner();
//===========================================================================
//
// AInventory :: Travelled
//
// Called when an item in somebody's inventory is carried over to another
// map, in case it needs to do special reinitialization.
//
//===========================================================================
virtual void Travelled()
{}
virtual double GetSpeedFactor() { return 1; }
virtual bool GetNoTeleportFreeze() { return false; }
virtual void ModifyDamage(int damage, Name damageType, out int newdamage, bool passive) {}

View file

@ -179,7 +179,7 @@ class PowerMinotaur : Powerup
}
}
class PowerTargeter : Powerup native
class PowerTargeter : Powerup
{
Default
{
@ -196,6 +196,119 @@ class PowerTargeter : Powerup native
TRGT C -1;
Stop;
}
override void Travelled ()
{
InitEffect ();
}
override void InitEffect ()
{
// Why is this called when the inventory isn't even attached yet
// in APowerup.CreateCopy?
if (!Owner.FindInventory(GetClass(), true))
return;
let player = Owner.player;
Super.InitEffect();
if (player == null)
return;
let stat = FindState("Targeter");
if (stat != null)
{
player.SetPsprite(PSprite.TARGETCENTER, stat);
player.SetPsprite(PSprite.TARGETLEFT, stat + 1);
player.SetPsprite(PSprite.TARGETRIGHT, stat + 2);
}
player.GetPSprite(PSprite.TARGETCENTER).x = (160-3);
player.GetPSprite(PSprite.TARGETCENTER).y =
player.GetPSprite(PSprite.TARGETLEFT).y =
player.GetPSprite(PSprite.TARGETRIGHT).y = (100-3);
PositionAccuracy ();
}
override void AttachToOwner(Actor other)
{
Super.AttachToOwner(other);
// Let's actually properly call this for the targeters.
InitEffect();
}
override bool HandlePickup(Inventory item)
{
if (Super.HandlePickup(item))
{
InitEffect(); // reset the HUD sprites
return true;
}
return false;
}
override void DoEffect ()
{
Super.DoEffect ();
if (Owner != null && Owner.player != null)
{
let player = Owner.player;
PositionAccuracy ();
if (EffectTics < 5*TICRATE)
{
let stat = FindState("Targeter");
if (stat != null)
{
if (EffectTics & 32)
{
player.SetPsprite(PSprite.TARGETRIGHT, null);
player.SetPsprite(PSprite.TARGETLEFT, stat + 1);
}
else if (EffectTics & 16)
{
player.SetPsprite(PSprite.TARGETRIGHT, stat + 2);
player.SetPsprite(PSprite.TARGETLEFT, null);
}
}
}
}
}
override void EndEffect ()
{
Super.EndEffect();
if (Owner != null && Owner.player != null)
{
// Calling GetPSprite here could crash if we're creating a new game.
// This is because P_SetupLevel nulls the player's mo before destroying
// every DThinker which in turn ends up calling this.
// However P_SetupLevel is only called after G_NewInit which calls
// every player's dtor which destroys all their psprites.
let player = Owner.player;
PSprite pspr;
if ((pspr = player.FindPSprite(PSprite.TARGETCENTER)) != null) pspr.SetState(null);
if ((pspr = player.FindPSprite(PSprite.TARGETLEFT)) != null) pspr.SetState(null);
if ((pspr = player.FindPSprite(PSprite.TARGETRIGHT)) != null) pspr.SetState(null);
}
}
private void PositionAccuracy ()
{
let player = Owner.player;
if (player != null)
{
player.GetPSprite(PSprite.TARGETLEFT).x = (160-3) - ((100 - player.mo.accuracy));
player.GetPSprite(PSprite.TARGETRIGHT).x = (160-3)+ ((100 - player.mo.accuracy));
}
}
}
//===========================================================================

View file

@ -128,6 +128,16 @@ class PlayerChunk : PlayerPawn native
class PSprite : Object native
{
enum PSPLayers
{
STRIFEHANDS = -1,
WEAPON = 1,
FLASH = 1000,
TARGETCENTER = 0x7fffffff - 2,
TARGETLEFT,
TARGETRIGHT,
};
native readonly State CurState;
native readonly Actor Caller;
native readonly PSprite Next;