mirror of
https://github.com/ZDoom/qzdoom-gpl.git
synced 2024-11-26 22:01:13 +00:00
more inventory scriptification
* completely scriptified DehackedPickup and FakeInventory. * scriptified all remaining virtual functions of Inventory, so that its inheritance is now 100% script-side. * scriptified CallTryPickup and most of the code called by that. - fixed: Passing local variables by reference did not work in the VM.
This commit is contained in:
parent
1750ded7c4
commit
3c30b59bab
19 changed files with 485 additions and 614 deletions
|
@ -222,23 +222,17 @@ DEFINE_FIELD_X(DehInfo, DehInfo, BlueAC)
|
||||||
// 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
|
||||||
// behavior, for every thing touched by dehacked that has the MF_PICKUP flag,
|
// behavior, for every thing touched by dehacked that has the MF_PICKUP flag,
|
||||||
// a new subclass of ADehackedPickup will be created with properties copied
|
// a new subclass of DehackedPickup will be created with properties copied
|
||||||
// from the original actor's defaults. The original actor is then changed to
|
// from the original actor's defaults. The original actor is then changed to
|
||||||
// spawn the new class.
|
// spawn the new class.
|
||||||
|
|
||||||
IMPLEMENT_CLASS(ADehackedPickup, false, true)
|
|
||||||
|
|
||||||
IMPLEMENT_POINTERS_START(ADehackedPickup)
|
|
||||||
IMPLEMENT_POINTER(RealPickup)
|
|
||||||
IMPLEMENT_POINTERS_END
|
|
||||||
|
|
||||||
TArray<PClassActor *> TouchedActors;
|
TArray<PClassActor *> TouchedActors;
|
||||||
|
|
||||||
char *UnchangedSpriteNames;
|
char *UnchangedSpriteNames;
|
||||||
int NumUnchangedSprites;
|
int NumUnchangedSprites;
|
||||||
bool changedStates;
|
bool changedStates;
|
||||||
|
|
||||||
// Sprite<->Class map for ADehackedPickup::DetermineType
|
// Sprite<->Class map for DehackedPickup::DetermineType
|
||||||
static struct DehSpriteMap
|
static struct DehSpriteMap
|
||||||
{
|
{
|
||||||
char Sprite[5];
|
char Sprite[5];
|
||||||
|
@ -3009,12 +3003,12 @@ void FinishDehPatch ()
|
||||||
// Create a new class that will serve as the actual pickup
|
// Create a new class that will serve as the actual pickup
|
||||||
char typeNameBuilder[32];
|
char typeNameBuilder[32];
|
||||||
//
|
//
|
||||||
|
auto dehtype = PClass::FindActor(NAME_DehackedPickup);
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
// Retry until we find a free name. This is unlikely to happen but not impossible.
|
// Retry until we find a free name. This is unlikely to happen but not impossible.
|
||||||
mysnprintf(typeNameBuilder, countof(typeNameBuilder), "DehackedPickup%d", nameindex++);
|
mysnprintf(typeNameBuilder, countof(typeNameBuilder), "DehackedPickup%d", nameindex++);
|
||||||
subclass = static_cast<PClassActor *>(RUNTIME_CLASS(ADehackedPickup)->
|
subclass = static_cast<PClassActor *>(dehtype->CreateDerivedClass(typeNameBuilder, dehtype->Size));
|
||||||
CreateDerivedClass(typeNameBuilder, sizeof(ADehackedPickup)));
|
|
||||||
}
|
}
|
||||||
while (subclass == nullptr);
|
while (subclass == nullptr);
|
||||||
|
|
||||||
|
@ -3120,94 +3114,10 @@ void FinishDehPatch ()
|
||||||
WeaponNames.ShrinkToFit();
|
WeaponNames.ShrinkToFit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModifyDropAmount(AInventory *inv, int dropamount);
|
DEFINE_ACTION_FUNCTION(ADehackedPickup, DetermineType)
|
||||||
|
|
||||||
bool ADehackedPickup::TryPickup (AActor *&toucher)
|
|
||||||
{
|
{
|
||||||
PClassActor *type = DetermineType ();
|
PARAM_SELF_PROLOGUE(AInventory);
|
||||||
if (type == NULL)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
RealPickup = static_cast<AInventory *>(Spawn (type, Pos(), NO_REPLACE));
|
|
||||||
if (RealPickup != NULL)
|
|
||||||
{
|
|
||||||
// The internally spawned item should never count towards statistics.
|
|
||||||
RealPickup->ClearCounters();
|
|
||||||
if (!(flags & MF_DROPPED))
|
|
||||||
{
|
|
||||||
RealPickup->flags &= ~MF_DROPPED;
|
|
||||||
}
|
|
||||||
// If this item has been dropped by a monster the
|
|
||||||
// amount of ammo this gives must be adjusted.
|
|
||||||
if (droppedbymonster)
|
|
||||||
{
|
|
||||||
ModifyDropAmount(RealPickup, 0);
|
|
||||||
}
|
|
||||||
if (!RealPickup->CallTryPickup (toucher))
|
|
||||||
{
|
|
||||||
RealPickup->Destroy ();
|
|
||||||
RealPickup = NULL;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
GoAwayAndDie ();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
FString ADehackedPickup::PickupMessage ()
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
if (RealPickup != nullptr)
|
|
||||||
return RealPickup->PickupMessage ();
|
|
||||||
else*/ return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ADehackedPickup::ShouldStay ()
|
|
||||||
{
|
|
||||||
if (RealPickup != nullptr)
|
|
||||||
return RealPickup->CallShouldStay ();
|
|
||||||
else return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ADehackedPickup::ShouldRespawn ()
|
|
||||||
{
|
|
||||||
if (RealPickup != nullptr)
|
|
||||||
return RealPickup->ShouldRespawn ();
|
|
||||||
else return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ADehackedPickup::PlayPickupSound (AActor *toucher)
|
|
||||||
{
|
|
||||||
if (RealPickup != nullptr)
|
|
||||||
RealPickup->CallPlayPickupSound (toucher);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ADehackedPickup::DoPickupSpecial (AActor *toucher)
|
|
||||||
{
|
|
||||||
Super::DoPickupSpecial (toucher);
|
|
||||||
// If the real pickup hasn't joined the toucher's inventory, make sure it
|
|
||||||
// doesn't stick around.
|
|
||||||
if (RealPickup != nullptr && RealPickup->Owner != toucher)
|
|
||||||
{
|
|
||||||
RealPickup->Destroy ();
|
|
||||||
}
|
|
||||||
RealPickup = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ADehackedPickup::OnDestroy ()
|
|
||||||
{
|
|
||||||
if (RealPickup != nullptr)
|
|
||||||
{
|
|
||||||
RealPickup->Destroy ();
|
|
||||||
RealPickup = nullptr;
|
|
||||||
}
|
|
||||||
Super::OnDestroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
PClassActor *ADehackedPickup::DetermineType ()
|
|
||||||
{
|
|
||||||
// Look at the actor's current sprite to determine what kind of
|
// Look at the actor's current sprite to determine what kind of
|
||||||
// item to pretend to me.
|
// item to pretend to me.
|
||||||
int min = 0;
|
int min = 0;
|
||||||
|
@ -3216,10 +3126,10 @@ PClassActor *ADehackedPickup::DetermineType ()
|
||||||
while (min <= max)
|
while (min <= max)
|
||||||
{
|
{
|
||||||
int mid = (min + max) / 2;
|
int mid = (min + max) / 2;
|
||||||
int lex = memcmp (DehSpriteMappings[mid].Sprite, sprites[sprite].name, 4);
|
int lex = memcmp (DehSpriteMappings[mid].Sprite, sprites[self->sprite].name, 4);
|
||||||
if (lex == 0)
|
if (lex == 0)
|
||||||
{
|
{
|
||||||
return PClass::FindActor(DehSpriteMappings[mid].ClassName);
|
ACTION_RETURN_OBJECT(PClass::FindActor(DehSpriteMappings[mid].ClassName));
|
||||||
}
|
}
|
||||||
else if (lex < 0)
|
else if (lex < 0)
|
||||||
{
|
{
|
||||||
|
@ -3230,11 +3140,6 @@ PClassActor *ADehackedPickup::DetermineType ()
|
||||||
max = mid - 1;
|
max = mid - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
ACTION_RETURN_OBJECT(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ADehackedPickup::Serialize(FSerializer &arc)
|
|
||||||
{
|
|
||||||
Super::Serialize(arc);
|
|
||||||
arc("droppedbymonster", droppedbymonster);
|
|
||||||
}
|
|
||||||
|
|
|
@ -34,29 +34,6 @@
|
||||||
#ifndef __D_DEHACK_H__
|
#ifndef __D_DEHACK_H__
|
||||||
#define __D_DEHACK_H__
|
#define __D_DEHACK_H__
|
||||||
|
|
||||||
#include "a_pickups.h"
|
|
||||||
|
|
||||||
class ADehackedPickup : public AInventory
|
|
||||||
{
|
|
||||||
DECLARE_CLASS (ADehackedPickup, AInventory)
|
|
||||||
HAS_OBJECT_POINTERS
|
|
||||||
public:
|
|
||||||
void OnDestroy() override;
|
|
||||||
FString PickupMessage ();
|
|
||||||
bool ShouldRespawn ();
|
|
||||||
bool ShouldStay ();
|
|
||||||
bool TryPickup (AActor *&toucher);
|
|
||||||
void PlayPickupSound (AActor *toucher);
|
|
||||||
void DoPickupSpecial (AActor *toucher);
|
|
||||||
|
|
||||||
void Serialize(FSerializer &arc);
|
|
||||||
private:
|
|
||||||
PClassActor *DetermineType ();
|
|
||||||
AInventory *RealPickup;
|
|
||||||
public:
|
|
||||||
bool droppedbymonster;
|
|
||||||
};
|
|
||||||
|
|
||||||
int D_LoadDehLumps();
|
int D_LoadDehLumps();
|
||||||
bool D_LoadDehLump(int lumpnum);
|
bool D_LoadDehLump(int lumpnum);
|
||||||
bool D_LoadDehFile(const char *filename);
|
bool D_LoadDehFile(const char *filename);
|
||||||
|
|
|
@ -478,6 +478,7 @@ public:
|
||||||
void Destroy();
|
void Destroy();
|
||||||
|
|
||||||
// Add other types as needed.
|
// Add other types as needed.
|
||||||
|
bool &BoolVar(FName field);
|
||||||
int &IntVar(FName field);
|
int &IntVar(FName field);
|
||||||
PalEntry &ColorVar(FName field);
|
PalEntry &ColorVar(FName field);
|
||||||
FName &NameVar(FName field);
|
FName &NameVar(FName field);
|
||||||
|
|
|
@ -1073,6 +1073,11 @@ enum ETypeVal : BYTE
|
||||||
VAL_Class,
|
VAL_Class,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline bool &DObject::BoolVar(FName field)
|
||||||
|
{
|
||||||
|
return *(bool*)ScriptVar(field, TypeBool);
|
||||||
|
}
|
||||||
|
|
||||||
inline int &DObject::IntVar(FName field)
|
inline int &DObject::IntVar(FName field)
|
||||||
{
|
{
|
||||||
return *(int*)ScriptVar(field, TypeSInt32);
|
return *(int*)ScriptVar(field, TypeSInt32);
|
||||||
|
|
|
@ -99,6 +99,7 @@ DEFINE_FIELD(AInventory, SpawnPointClass)
|
||||||
DEFINE_FIELD(AInventory, PickupFlash)
|
DEFINE_FIELD(AInventory, PickupFlash)
|
||||||
DEFINE_FIELD(AInventory, PickupSound)
|
DEFINE_FIELD(AInventory, PickupSound)
|
||||||
DEFINE_FIELD(PClassInventory, PickupMsg)
|
DEFINE_FIELD(PClassInventory, PickupMsg)
|
||||||
|
DEFINE_FIELD(PClassInventory, GiveQuest)
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
|
@ -177,22 +178,6 @@ void AInventory::MarkPrecacheSounds() const
|
||||||
PickupSound.MarkUsed();
|
PickupSound.MarkUsed();
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// AInventory :: ShouldRespawn
|
|
||||||
//
|
|
||||||
// Returns true if the item should hide itself and reappear later when picked
|
|
||||||
// up.
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
bool AInventory::ShouldRespawn ()
|
|
||||||
{
|
|
||||||
if ((ItemFlags & IF_BIGPOWERUP) && !(dmflags2 & DF2_RESPAWN_SUPER)) return false;
|
|
||||||
if (ItemFlags & IF_NEVERRESPAWN) return false;
|
|
||||||
return !!((dmflags & DF_ITEMS_RESPAWN) || (ItemFlags & IF_ALWAYSRESPAWN));
|
|
||||||
}
|
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
// AInventory :: Grind
|
// AInventory :: Grind
|
||||||
|
@ -220,66 +205,6 @@ bool AInventory::Grind(bool items)
|
||||||
return Super::Grind(items);
|
return Super::Grind(items);
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// AInventory :: GoAway
|
|
||||||
//
|
|
||||||
// Returns true if you must create a copy of this item to give to the player
|
|
||||||
// or false if you can use this one instead.
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
bool AInventory::GoAway ()
|
|
||||||
{
|
|
||||||
// Dropped items never stick around
|
|
||||||
if (flags & MF_DROPPED)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!CallShouldStay ())
|
|
||||||
{
|
|
||||||
Hide ();
|
|
||||||
if (ShouldRespawn ())
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(AInventory, GoAway)
|
|
||||||
{
|
|
||||||
PARAM_SELF_PROLOGUE(AInventory);
|
|
||||||
ACTION_RETURN_BOOL(self->GoAway());
|
|
||||||
}
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// AInventory :: GoAwayAndDie
|
|
||||||
//
|
|
||||||
// Like GoAway but used by items that don't insert themselves into the
|
|
||||||
// inventory. If they won't be respawning, then they can destroy themselves.
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
void AInventory::GoAwayAndDie ()
|
|
||||||
{
|
|
||||||
if (!GoAway ())
|
|
||||||
{
|
|
||||||
flags &= ~MF_SPECIAL;
|
|
||||||
SetState (FindState("HoldAndDestroy"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(AInventory, GoAwayAndDie)
|
|
||||||
{
|
|
||||||
PARAM_SELF_PROLOGUE(AInventory);
|
|
||||||
self->GoAwayAndDie();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
// AInventory :: BecomeItem
|
// AInventory :: BecomeItem
|
||||||
|
@ -405,9 +330,8 @@ bool AInventory::CallUse(bool pickup)
|
||||||
IFVIRTUAL(AInventory, Use)
|
IFVIRTUAL(AInventory, Use)
|
||||||
{
|
{
|
||||||
VMValue params[2] = { (DObject*)this, pickup };
|
VMValue params[2] = { (DObject*)this, pickup };
|
||||||
VMReturn ret;
|
|
||||||
int retval;
|
int retval;
|
||||||
ret.IntAt(&retval);
|
VMReturn ret(&retval);
|
||||||
GlobalVMStack.Call(func, params, 2, &ret, 1, nullptr);
|
GlobalVMStack.Call(func, params, 2, &ret, 1, nullptr);
|
||||||
return !!retval;
|
return !!retval;
|
||||||
}
|
}
|
||||||
|
@ -415,58 +339,6 @@ bool AInventory::CallUse(bool pickup)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// AInventory :: Hide
|
|
||||||
//
|
|
||||||
// Hides this actor until it's time to respawn again.
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
void AInventory::Hide ()
|
|
||||||
{
|
|
||||||
FState *HideSpecialState = NULL, *HideDoomishState = NULL;
|
|
||||||
|
|
||||||
flags = (flags & ~MF_SPECIAL) | MF_NOGRAVITY;
|
|
||||||
renderflags |= RF_INVISIBLE;
|
|
||||||
|
|
||||||
if (gameinfo.gametype & GAME_Raven)
|
|
||||||
{
|
|
||||||
HideSpecialState = FindState("HideSpecial");
|
|
||||||
if (HideSpecialState == NULL)
|
|
||||||
{
|
|
||||||
HideDoomishState = FindState("HideDoomish");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
HideDoomishState = FindState("HideDoomish");
|
|
||||||
if (HideDoomishState == NULL)
|
|
||||||
{
|
|
||||||
HideSpecialState = FindState("HideSpecial");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(HideDoomishState != NULL || HideSpecialState != NULL);
|
|
||||||
|
|
||||||
if (HideSpecialState != NULL)
|
|
||||||
{
|
|
||||||
SetState (HideSpecialState);
|
|
||||||
tics = 1400;
|
|
||||||
if (PickupFlash != NULL) tics += 30;
|
|
||||||
}
|
|
||||||
else if (HideDoomishState != NULL)
|
|
||||||
{
|
|
||||||
SetState (HideDoomishState);
|
|
||||||
tics = 1050;
|
|
||||||
}
|
|
||||||
if (RespawnTics != 0)
|
|
||||||
{
|
|
||||||
tics = RespawnTics;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
@ -492,112 +364,6 @@ DEFINE_ACTION_FUNCTION(AInventory, PrintPickupMessage)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// AInventory :: DoPickupSpecial
|
|
||||||
//
|
|
||||||
// Executes this actor's special when it is picked up.
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
void AInventory::DoPickupSpecial (AActor *toucher)
|
|
||||||
{
|
|
||||||
if (special)
|
|
||||||
{
|
|
||||||
P_ExecuteSpecial(special, NULL, toucher, false,
|
|
||||||
args[0], args[1], args[2], args[3], args[4]);
|
|
||||||
special = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(AInventory, DoPickupSpecial)
|
|
||||||
{
|
|
||||||
PARAM_SELF_PROLOGUE(AInventory);
|
|
||||||
PARAM_OBJECT(toucher, AActor);
|
|
||||||
self->DoPickupSpecial(toucher);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// AInventory :: PlayPickupSound
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
void AInventory::PlayPickupSound (AActor *toucher)
|
|
||||||
{
|
|
||||||
float atten;
|
|
||||||
int chan;
|
|
||||||
|
|
||||||
if (ItemFlags & IF_NOATTENPICKUPSOUND)
|
|
||||||
{
|
|
||||||
atten = ATTN_NONE;
|
|
||||||
}
|
|
||||||
#if 0
|
|
||||||
else if ((ItemFlags & IF_FANCYPICKUPSOUND) &&
|
|
||||||
(toucher == NULL || toucher->CheckLocalView(consoeplayer)))
|
|
||||||
{
|
|
||||||
atten = ATTN_NONE;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
else
|
|
||||||
{
|
|
||||||
atten = ATTN_NORM;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (toucher != NULL && toucher->CheckLocalView(consoleplayer))
|
|
||||||
{
|
|
||||||
chan = CHAN_PICKUP|CHAN_NOPAUSE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
chan = CHAN_PICKUP;
|
|
||||||
}
|
|
||||||
S_Sound (toucher, chan, PickupSound, 1, atten);
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(AInventory, PlayPickupSound)
|
|
||||||
{
|
|
||||||
PARAM_SELF_PROLOGUE(AInventory);
|
|
||||||
PARAM_OBJECT(other, AActor);
|
|
||||||
self->PlayPickupSound(other);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AInventory::CallPlayPickupSound(AActor *other)
|
|
||||||
{
|
|
||||||
IFVIRTUAL(AInventory, PlayPickupSound)
|
|
||||||
{
|
|
||||||
VMValue params[2] = { (DObject*)this, (DObject*)other };
|
|
||||||
GlobalVMStack.Call(func, params, 2, nullptr, 0, nullptr);
|
|
||||||
}
|
|
||||||
else PlayPickupSound(other);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// AInventory :: ShouldStay
|
|
||||||
//
|
|
||||||
// Returns true if the item should not disappear, even temporarily.
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
bool AInventory::CallShouldStay()
|
|
||||||
{
|
|
||||||
IFVIRTUAL(AInventory, ShouldStay)
|
|
||||||
{
|
|
||||||
VMValue params[1] = { (DObject*)this };
|
|
||||||
VMReturn ret;
|
|
||||||
int retval;
|
|
||||||
ret.IntAt(&retval);
|
|
||||||
GlobalVMStack.Call(func, params, 1, &ret, 1, nullptr);
|
|
||||||
return !!retval;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
// AInventory :: Destroy
|
// AInventory :: Destroy
|
||||||
|
@ -644,29 +410,17 @@ void AInventory::DepleteOrDestroy ()
|
||||||
//
|
//
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
PalEntry AInventory::GetBlend ()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(AInventory, GetBlend)
|
|
||||||
{
|
|
||||||
PARAM_SELF_PROLOGUE(AInventory);
|
|
||||||
ACTION_RETURN_INT(self->GetBlend());
|
|
||||||
}
|
|
||||||
|
|
||||||
PalEntry AInventory::CallGetBlend()
|
PalEntry AInventory::CallGetBlend()
|
||||||
{
|
{
|
||||||
IFVIRTUAL(AInventory, GetBlend)
|
IFVIRTUAL(AInventory, GetBlend)
|
||||||
{
|
{
|
||||||
VMValue params[1] = { (DObject*)this };
|
VMValue params[1] = { (DObject*)this };
|
||||||
VMReturn ret;
|
|
||||||
int retval;
|
int retval;
|
||||||
ret.IntAt(&retval);
|
VMReturn ret(&retval);
|
||||||
GlobalVMStack.Call(func, params, 1, &ret, 1, nullptr);
|
GlobalVMStack.Call(func, params, 1, &ret, 1, nullptr);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
else return GetBlend();
|
else return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
@ -759,129 +513,51 @@ DEFINE_ACTION_FUNCTION(AInventory, DoRespawn)
|
||||||
ACTION_RETURN_BOOL(self->DoRespawn());
|
ACTION_RETURN_BOOL(self->DoRespawn());
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// AInventory :: GiveQuest
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
void AInventory::GiveQuest (AActor *toucher)
|
|
||||||
{
|
|
||||||
int quest = GetClass()->GiveQuest;
|
|
||||||
if (quest > 0 && quest <= (int)countof(QuestItemClasses))
|
|
||||||
{
|
|
||||||
toucher->GiveInventoryType (QuestItemClasses[quest-1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
// AInventory :: CallTryPickup
|
// AInventory :: CallTryPickup
|
||||||
//
|
//
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
bool AInventory::CallTryPickup (AActor *toucher, AActor **toucher_return)
|
bool AInventory::CallTryPickup(AActor *toucher, AActor **toucher_return)
|
||||||
{
|
{
|
||||||
TObjPtr<AInventory> Invstack = Inventory; // A pointer of the inventories item stack.
|
static VMFunction *func = nullptr;
|
||||||
|
if (func == nullptr) func = PClass::FindFunction(NAME_Inventory, NAME_CallTryPickup);
|
||||||
// unmorphed versions of a currently morphed actor cannot pick up anything.
|
VMValue params[2] = { (DObject*)this, toucher };
|
||||||
if (toucher->flags & MF_UNMORPHED) return false;
|
VMReturn ret[2];
|
||||||
|
int res;
|
||||||
bool res;
|
AActor *tret;
|
||||||
if (CanPickup(toucher))
|
ret[0].IntAt(&res);
|
||||||
{
|
ret[1].PointerAt((void**)&tret);
|
||||||
IFVIRTUAL(AInventory, TryPickup)
|
GlobalVMStack.Call(func, params, 2, ret, 2);
|
||||||
{
|
if (toucher_return) *toucher_return = tret;
|
||||||
VMValue params[2] = { (DObject*)this, (void*)&toucher };
|
return !!res;
|
||||||
VMReturn ret;
|
|
||||||
int retval;
|
|
||||||
ret.IntAt(&retval);
|
|
||||||
GlobalVMStack.Call(func, params, 2, &ret, 1, nullptr);
|
|
||||||
res = !!retval;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (!(ItemFlags & IF_RESTRICTABSOLUTELY))
|
|
||||||
{
|
|
||||||
// let an item decide for itself how it will handle this
|
|
||||||
IFVIRTUAL(AInventory, TryPickupRestricted)
|
|
||||||
{
|
|
||||||
VMValue params[2] = { (DObject*)this, (void*)&toucher };
|
|
||||||
VMReturn ret;
|
|
||||||
int retval;
|
|
||||||
ret.IntAt(&retval);
|
|
||||||
GlobalVMStack.Call(func, params, 2, &ret, 1, nullptr);
|
|
||||||
res = !!retval;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Morph items can change the toucher so we need an option to return this info.
|
|
||||||
if (toucher_return != NULL) *toucher_return = toucher;
|
|
||||||
|
|
||||||
if (!res && (ItemFlags & IF_ALWAYSPICKUP) && !CallShouldStay())
|
|
||||||
{
|
|
||||||
res = true;
|
|
||||||
GoAwayAndDie();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res)
|
|
||||||
{
|
|
||||||
GiveQuest(toucher);
|
|
||||||
|
|
||||||
// Transfer all inventory accross that the old object had, if requested.
|
|
||||||
if ((ItemFlags & IF_TRANSFER))
|
|
||||||
{
|
|
||||||
while (Invstack)
|
|
||||||
{
|
|
||||||
AInventory* titem = Invstack;
|
|
||||||
Invstack = titem->Inventory;
|
|
||||||
if (titem->Owner == this)
|
|
||||||
{
|
|
||||||
if (!titem->CallTryPickup(toucher)) // The object no longer can exist
|
|
||||||
{
|
|
||||||
titem->Destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(AInventory, CallTryPickup)
|
|
||||||
{
|
|
||||||
PARAM_SELF_PROLOGUE(AInventory);
|
|
||||||
PARAM_OBJECT(toucher, AActor);
|
|
||||||
AActor *t_ret;
|
|
||||||
bool res = self->CallTryPickup(toucher, &t_ret);
|
|
||||||
if (numret > 0) ret[0].SetInt(res);
|
|
||||||
if (numret > 1) ret[1].SetPointer(t_ret, ATAG_OBJECT), numret = 2;
|
|
||||||
return numret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
// AInventory :: CanPickup
|
// AInventory :: CanPickup
|
||||||
//
|
//
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
bool AInventory::CanPickup (AActor *toucher)
|
DEFINE_ACTION_FUNCTION(AInventory, CanPickup)
|
||||||
{
|
{
|
||||||
if (!toucher)
|
PARAM_SELF_PROLOGUE(AInventory);
|
||||||
return false;
|
PARAM_OBJECT(toucher, AActor);
|
||||||
|
|
||||||
PClassInventory *ai = GetClass();
|
if (!toucher)
|
||||||
|
ACTION_RETURN_BOOL(false);
|
||||||
|
|
||||||
|
PClassInventory *ai = self->GetClass();
|
||||||
// Is the item restricted to certain player classes?
|
// Is the item restricted to certain player classes?
|
||||||
if (ai->RestrictedToPlayerClass.Size() != 0)
|
if (ai->RestrictedToPlayerClass.Size() != 0)
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < ai->RestrictedToPlayerClass.Size(); ++i)
|
for (unsigned i = 0; i < ai->RestrictedToPlayerClass.Size(); ++i)
|
||||||
{
|
{
|
||||||
if (toucher->IsKindOf(ai->RestrictedToPlayerClass[i]))
|
if (toucher->IsKindOf(ai->RestrictedToPlayerClass[i]))
|
||||||
return true;
|
ACTION_RETURN_BOOL(true);
|
||||||
}
|
}
|
||||||
return false;
|
ACTION_RETURN_BOOL(false);
|
||||||
}
|
}
|
||||||
// Or is it forbidden to certain other classes?
|
// Or is it forbidden to certain other classes?
|
||||||
else
|
else
|
||||||
|
@ -889,10 +565,10 @@ bool AInventory::CanPickup (AActor *toucher)
|
||||||
for (unsigned i = 0; i < ai->ForbiddenToPlayerClass.Size(); ++i)
|
for (unsigned i = 0; i < ai->ForbiddenToPlayerClass.Size(); ++i)
|
||||||
{
|
{
|
||||||
if (toucher->IsKindOf(ai->ForbiddenToPlayerClass[i]))
|
if (toucher->IsKindOf(ai->ForbiddenToPlayerClass[i]))
|
||||||
return false;
|
ACTION_RETURN_BOOL(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
ACTION_RETURN_BOOL(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
@ -938,22 +614,6 @@ CCMD (targetinv)
|
||||||
"the NOBLOCKMAP flag or have height/radius of 0.\n");
|
"the NOBLOCKMAP flag or have height/radius of 0.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// AInventory :: AttachToOwner
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
void AInventory::CallAttachToOwner(AActor *other)
|
|
||||||
{
|
|
||||||
IFVIRTUAL(AInventory, AttachToOwner)
|
|
||||||
{
|
|
||||||
VMValue params[2] = { (DObject*)this, (DObject*)other };
|
|
||||||
GlobalVMStack.Call(func, params, 2, nullptr, 0, nullptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
|
|
|
@ -78,39 +78,19 @@ public:
|
||||||
virtual void Tick() override;
|
virtual void Tick() override;
|
||||||
virtual bool Grind(bool items) override;
|
virtual bool Grind(bool items) override;
|
||||||
|
|
||||||
// virtual methods that only get overridden by special internal classes, like DehackedPickup.
|
bool CallTryPickup(AActor *toucher, AActor **toucher_return = NULL); // Wrapper for script function.
|
||||||
// There is no need to expose these to scripts.
|
|
||||||
void DepleteOrDestroy ();
|
|
||||||
virtual bool ShouldRespawn ();
|
|
||||||
virtual void DoPickupSpecial (AActor *toucher);
|
|
||||||
|
|
||||||
bool CallTryPickup(AActor *toucher, AActor **toucher_return = NULL); // This wraps both virtual methods plus a few more checks.
|
void DepleteOrDestroy (); // virtual on the script side.
|
||||||
|
bool CallUse(bool pickup); // virtual on the script side.
|
||||||
|
PalEntry CallGetBlend(); // virtual on the script side.
|
||||||
|
double GetSpeedFactor(); // virtual on the script side.
|
||||||
|
bool GetNoTeleportFreeze(); // virtual on the script side.
|
||||||
|
|
||||||
bool CallUse(bool pickup);
|
|
||||||
|
|
||||||
virtual PalEntry GetBlend();
|
|
||||||
PalEntry CallGetBlend();
|
|
||||||
|
|
||||||
bool CallShouldStay();
|
|
||||||
|
|
||||||
virtual void PlayPickupSound(AActor *toucher);
|
|
||||||
void CallPlayPickupSound(AActor *toucher);
|
|
||||||
|
|
||||||
void CallAttachToOwner(AActor *other);
|
|
||||||
|
|
||||||
// virtual on the script side only.
|
|
||||||
double GetSpeedFactor();
|
|
||||||
bool GetNoTeleportFreeze();
|
|
||||||
|
|
||||||
|
|
||||||
bool GoAway();
|
|
||||||
void GoAwayAndDie();
|
|
||||||
|
|
||||||
void Hide();
|
|
||||||
void BecomeItem ();
|
void BecomeItem ();
|
||||||
void BecomePickup ();
|
void BecomePickup ();
|
||||||
|
|
||||||
bool DoRespawn();
|
bool DoRespawn();
|
||||||
|
|
||||||
AInventory *PrevItem(); // Returns the item preceding this one in the list.
|
AInventory *PrevItem(); // Returns the item preceding this one in the list.
|
||||||
AInventory *PrevInv(); // Returns the previous item with IF_INVBAR set.
|
AInventory *PrevInv(); // Returns the previous item with IF_INVBAR set.
|
||||||
AInventory *NextInv(); // Returns the next item with IF_INVBAR set.
|
AInventory *NextInv(); // Returns the next item with IF_INVBAR set.
|
||||||
|
@ -128,13 +108,6 @@ public:
|
||||||
PClassActor *PickupFlash; // actor to spawn as pickup flash
|
PClassActor *PickupFlash; // actor to spawn as pickup flash
|
||||||
|
|
||||||
FSoundIDNoInit PickupSound;
|
FSoundIDNoInit PickupSound;
|
||||||
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bool CanPickup(AActor * toucher);
|
|
||||||
void GiveQuest(AActor * toucher);
|
|
||||||
|
|
||||||
private:
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class AStateProvider : public AInventory
|
class AStateProvider : public AInventory
|
||||||
|
@ -144,7 +117,4 @@ public:
|
||||||
bool CallStateChain(AActor *actor, FState *state);
|
bool CallStateChain(AActor *actor, FState *state);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern PClassActor *QuestItemClasses[31];
|
|
||||||
|
|
||||||
|
|
||||||
#endif //__A_PICKUPS_H__
|
#endif //__A_PICKUPS_H__
|
||||||
|
|
|
@ -1097,8 +1097,8 @@ void G_WorldDone (void)
|
||||||
// Strife needs a special case here to choose between good and sad ending. Bad is handled elsewhere.
|
// Strife needs a special case here to choose between good and sad ending. Bad is handled elsewhere.
|
||||||
if (endsequence == NAME_Inter_Strife)
|
if (endsequence == NAME_Inter_Strife)
|
||||||
{
|
{
|
||||||
if (players[0].mo->FindInventory (QuestItemClasses[24]) ||
|
if (players[0].mo->FindInventory (NAME_QuestItem25) ||
|
||||||
players[0].mo->FindInventory (QuestItemClasses[27]))
|
players[0].mo->FindInventory (NAME_QuestItem28))
|
||||||
{
|
{
|
||||||
endsequence = NAME_Inter_Strife_Good;
|
endsequence = NAME_Inter_Strife_Good;
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,7 +77,7 @@ void gl_ParseVavoomSkybox();
|
||||||
inline PClassActor * GetRealType(PClassActor * ti)
|
inline PClassActor * GetRealType(PClassActor * ti)
|
||||||
{
|
{
|
||||||
PClassActor *rep = ti->GetReplacement(false);
|
PClassActor *rep = ti->GetReplacement(false);
|
||||||
if (rep != ti && rep != NULL && rep->IsDescendantOf(RUNTIME_CLASS(ADehackedPickup)))
|
if (rep != ti && rep != NULL && rep->IsDescendantOf(PClass::FindActor(NAME_DehackedPickup)))
|
||||||
{
|
{
|
||||||
return rep;
|
return rep;
|
||||||
}
|
}
|
||||||
|
|
|
@ -771,7 +771,7 @@ void FGLRenderer::SetFixedColormap (player_t *player)
|
||||||
auto litetype = PClass::FindActor(NAME_PowerLightAmp);
|
auto litetype = PClass::FindActor(NAME_PowerLightAmp);
|
||||||
for(AInventory * in = cplayer->mo->Inventory; in; in = in->Inventory)
|
for(AInventory * in = cplayer->mo->Inventory; in; in = in->Inventory)
|
||||||
{
|
{
|
||||||
PalEntry color = in->GetBlend ();
|
PalEntry color = in->CallGetBlend ();
|
||||||
|
|
||||||
// Need special handling for light amplifiers
|
// Need special handling for light amplifiers
|
||||||
if (in->IsKindOf(torchtype))
|
if (in->IsKindOf(torchtype))
|
||||||
|
|
|
@ -186,6 +186,7 @@ xx(HealthPickup)
|
||||||
xx(autousemode)
|
xx(autousemode)
|
||||||
xx(Ammo)
|
xx(Ammo)
|
||||||
xx(WeaponGiver)
|
xx(WeaponGiver)
|
||||||
|
xx(DehackedPickup)
|
||||||
xx(PowerTargeter)
|
xx(PowerTargeter)
|
||||||
xx(PowerInvulnerable)
|
xx(PowerInvulnerable)
|
||||||
xx(PowerStrength)
|
xx(PowerStrength)
|
||||||
|
@ -197,6 +198,11 @@ xx(PowerFlight)
|
||||||
xx(PowerSpeed)
|
xx(PowerSpeed)
|
||||||
xx(PowerTorch)
|
xx(PowerTorch)
|
||||||
xx(CustomInventory)
|
xx(CustomInventory)
|
||||||
|
xx(Inventory)
|
||||||
|
xx(CallTryPickup)
|
||||||
|
xx(QuestItem25)
|
||||||
|
xx(QuestItem28)
|
||||||
|
xx(QuestItem29)
|
||||||
|
|
||||||
xx(AcolyteBlue)
|
xx(AcolyteBlue)
|
||||||
xx(SpectralLightningV1)
|
xx(SpectralLightningV1)
|
||||||
|
|
|
@ -3261,13 +3261,22 @@ void ModifyDropAmount(AInventory *inv, int dropamount)
|
||||||
static_cast<AWeapon *>(inv)->AmmoGive2 = int(static_cast<AWeapon *>(inv)->AmmoGive2 * dropammofactor);
|
static_cast<AWeapon *>(inv)->AmmoGive2 = int(static_cast<AWeapon *>(inv)->AmmoGive2 * dropammofactor);
|
||||||
inv->ItemFlags |= flagmask;
|
inv->ItemFlags |= flagmask;
|
||||||
}
|
}
|
||||||
else if (inv->IsKindOf (RUNTIME_CLASS(ADehackedPickup)))
|
else if (inv->IsKindOf (PClass::FindClass(NAME_DehackedPickup)))
|
||||||
{
|
{
|
||||||
// For weapons and ammo modified by Dehacked we need to flag the item.
|
// For weapons and ammo modified by Dehacked we need to flag the item.
|
||||||
static_cast<ADehackedPickup *>(inv)->droppedbymonster = true;
|
inv->BoolVar("droppedbymonster") = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// todo: make this a scripted virtual function so it can better deal with some of the classes involved.
|
||||||
|
DEFINE_ACTION_FUNCTION(AInventory, ModifyDropAmount)
|
||||||
|
{
|
||||||
|
PARAM_SELF_PROLOGUE(AInventory);
|
||||||
|
PARAM_INT(dropamount);
|
||||||
|
ModifyDropAmount(self, dropamount);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// PROC P_DropItem
|
// PROC P_DropItem
|
||||||
|
|
|
@ -3230,7 +3230,7 @@ FUNC(LS_GlassBreak)
|
||||||
}
|
}
|
||||||
if (it != NULL)
|
if (it != NULL)
|
||||||
{
|
{
|
||||||
it->GiveInventoryType (QuestItemClasses[28]);
|
it->GiveInventoryType (PClass::FindActor("QuestItem29"));
|
||||||
it->GiveInventoryType (PClass::FindActor("UpgradeAccuracy"));
|
it->GiveInventoryType (PClass::FindActor("UpgradeAccuracy"));
|
||||||
it->GiveInventoryType (PClass::FindActor("UpgradeStamina"));
|
it->GiveInventoryType (PClass::FindActor("UpgradeStamina"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -420,6 +420,10 @@ PPrototype *FxExpression::ReturnProto()
|
||||||
static int EncodeRegType(ExpEmit reg)
|
static int EncodeRegType(ExpEmit reg)
|
||||||
{
|
{
|
||||||
int regtype = reg.RegType;
|
int regtype = reg.RegType;
|
||||||
|
if (reg.Fixed && reg.Target)
|
||||||
|
{
|
||||||
|
regtype |= REGT_ADDROF;
|
||||||
|
}
|
||||||
if (reg.Konst)
|
if (reg.Konst)
|
||||||
{
|
{
|
||||||
regtype |= REGT_KONST;
|
regtype |= REGT_KONST;
|
||||||
|
@ -10008,10 +10012,9 @@ FxExpression *FxReturnStatement::Resolve(FCompileContext &ctx)
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < Args.Size(); i++)
|
for (unsigned i = 0; i < Args.Size(); i++)
|
||||||
{
|
{
|
||||||
auto &Value = Args[0];
|
Args[i] = new FxTypeCast(Args[i], ctx.ReturnProto->ReturnTypes[i], false, false);
|
||||||
Value = new FxTypeCast(Value, ctx.ReturnProto->ReturnTypes[i], false, false);
|
Args[i] = Args[i]->Resolve(ctx);
|
||||||
Value = Value->Resolve(ctx);
|
if (Args[i] == nullptr) fail = true;
|
||||||
if (Value == nullptr) fail = true;
|
|
||||||
}
|
}
|
||||||
if (fail)
|
if (fail)
|
||||||
{
|
{
|
||||||
|
|
|
@ -65,40 +65,6 @@ struct FExtraInfo
|
||||||
double DeathHeight, BurnHeight;
|
double DeathHeight, BurnHeight;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AFakeInventory : public AInventory
|
|
||||||
{
|
|
||||||
DECLARE_CLASS (AFakeInventory, AInventory);
|
|
||||||
public:
|
|
||||||
bool Respawnable;
|
|
||||||
|
|
||||||
bool ShouldRespawn ()
|
|
||||||
{
|
|
||||||
return Respawnable && Super::ShouldRespawn();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TryPickup (AActor *&toucher)
|
|
||||||
{
|
|
||||||
INTBOOL success = P_ExecuteSpecial(special, NULL, toucher, false,
|
|
||||||
args[0], args[1], args[2], args[3], args[4]);
|
|
||||||
|
|
||||||
if (success)
|
|
||||||
{
|
|
||||||
GoAwayAndDie ();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DoPickupSpecial (AActor *toucher)
|
|
||||||
{
|
|
||||||
// The special was already executed by TryPickup, so do nothing here
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
IMPLEMENT_CLASS(AFakeInventory, false, false)
|
|
||||||
|
|
||||||
DEFINE_FIELD(AFakeInventory, Respawnable)
|
|
||||||
|
|
||||||
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
||||||
|
|
||||||
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
||||||
|
@ -125,16 +91,6 @@ static const char *RenderStyles[] =
|
||||||
|
|
||||||
// CODE --------------------------------------------------------------------
|
// CODE --------------------------------------------------------------------
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
DEFINE_CLASS_PROPERTY(respawns, 0, FakeInventory)
|
|
||||||
{
|
|
||||||
defaults->Respawnable = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// ParseOldDecoration
|
// ParseOldDecoration
|
||||||
|
@ -154,7 +110,7 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def)
|
||||||
PClassActor *parent;
|
PClassActor *parent;
|
||||||
FName typeName;
|
FName typeName;
|
||||||
|
|
||||||
parent = (def == DEF_Pickup) ? RUNTIME_CLASS(AFakeInventory) : RUNTIME_CLASS(AActor);
|
parent = (def == DEF_Pickup) ? PClass::FindActor("FakeInventory") : RUNTIME_CLASS(AActor);
|
||||||
|
|
||||||
sc.MustGetString();
|
sc.MustGetString();
|
||||||
typeName = FName(sc.String);
|
typeName = FName(sc.String);
|
||||||
|
@ -360,7 +316,7 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def)
|
||||||
static void ParseInsideDecoration (Baggage &bag, AActor *defaults,
|
static void ParseInsideDecoration (Baggage &bag, AActor *defaults,
|
||||||
FExtraInfo &extra, EDefinitionType def, FScanner &sc, TArray<FState> &StateArray, TArray<FScriptPosition> &SourceLines)
|
FExtraInfo &extra, EDefinitionType def, FScanner &sc, TArray<FState> &StateArray, TArray<FScriptPosition> &SourceLines)
|
||||||
{
|
{
|
||||||
AFakeInventory *const inv = static_cast<AFakeInventory *>(defaults);
|
AInventory *const inv = static_cast<AInventory *>(defaults);
|
||||||
char sprite[5] = "TNT1";
|
char sprite[5] = "TNT1";
|
||||||
|
|
||||||
sc.MustGetString ();
|
sc.MustGetString ();
|
||||||
|
@ -588,7 +544,7 @@ static void ParseInsideDecoration (Baggage &bag, AActor *defaults,
|
||||||
}
|
}
|
||||||
else if (def == DEF_Pickup && sc.Compare ("Respawns"))
|
else if (def == DEF_Pickup && sc.Compare ("Respawns"))
|
||||||
{
|
{
|
||||||
inv->Respawnable = true;
|
inv->BoolVar("Respawnable") = true;
|
||||||
}
|
}
|
||||||
else if (def == DEF_BreakableDecoration && sc.Compare ("SolidOnDeath"))
|
else if (def == DEF_BreakableDecoration && sc.Compare ("SolidOnDeath"))
|
||||||
{
|
{
|
||||||
|
|
|
@ -842,7 +842,12 @@ static void DispatchScriptProperty(FScanner &sc, PProperty *prop, AActor *defaul
|
||||||
addr = ((char*)defaults) + f->Offset;
|
addr = ((char*)defaults) + f->Offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (f->Type->IsKindOf(RUNTIME_CLASS(PInt)))
|
if (f->Type == TypeBool)
|
||||||
|
{
|
||||||
|
bool val = sc.CheckNumber() ? !!sc.Number : true;
|
||||||
|
static_cast<PBool*>(f->Type)->SetValue(addr, !!val);
|
||||||
|
}
|
||||||
|
else if (f->Type->IsKindOf(RUNTIME_CLASS(PInt)))
|
||||||
{
|
{
|
||||||
sc.MustGetNumber();
|
sc.MustGetNumber();
|
||||||
static_cast<PInt*>(f->Type)->SetValue(addr, sc.Number);
|
static_cast<PInt*>(f->Type)->SetValue(addr, sc.Number);
|
||||||
|
|
|
@ -69,8 +69,6 @@
|
||||||
void InitThingdef();
|
void InitThingdef();
|
||||||
|
|
||||||
// STATIC FUNCTION PROTOTYPES --------------------------------------------
|
// STATIC FUNCTION PROTOTYPES --------------------------------------------
|
||||||
PClassActor *QuestItemClasses[31];
|
|
||||||
|
|
||||||
|
|
||||||
static TMap<FState *, FScriptPosition> StateSourceLines;
|
static TMap<FState *, FScriptPosition> StateSourceLines;
|
||||||
static FScriptPosition unknownstatesource("unknown file", 0);
|
static FScriptPosition unknownstatesource("unknown file", 0);
|
||||||
|
@ -448,12 +446,5 @@ void LoadActors()
|
||||||
|
|
||||||
// Now we may call the scripted OnDestroy method.
|
// Now we may call the scripted OnDestroy method.
|
||||||
PClass::bVMOperational = true;
|
PClass::bVMOperational = true;
|
||||||
// Since these are defined in DECORATE now the table has to be initialized here.
|
|
||||||
for (int i = 0; i < 31; i++)
|
|
||||||
{
|
|
||||||
char fmt[20];
|
|
||||||
mysnprintf(fmt, countof(fmt), "QuestItem%d", i + 1);
|
|
||||||
QuestItemClasses[i] = PClass::FindActor(fmt);
|
|
||||||
}
|
|
||||||
StateSourceLines.Clear();
|
StateSourceLines.Clear();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1926,6 +1926,7 @@ void ZCCCompiler::DispatchProperty(FPropertyInfo *prop, ZCC_PropertyStmt *proper
|
||||||
|
|
||||||
void ZCCCompiler::DispatchScriptProperty(PProperty *prop, ZCC_PropertyStmt *property, AActor *defaults, Baggage &bag)
|
void ZCCCompiler::DispatchScriptProperty(PProperty *prop, ZCC_PropertyStmt *property, AActor *defaults, Baggage &bag)
|
||||||
{
|
{
|
||||||
|
ZCC_ExprConstant one;
|
||||||
unsigned parmcount = 1;
|
unsigned parmcount = 1;
|
||||||
ZCC_TreeNode *x = property->Values;
|
ZCC_TreeNode *x = property->Values;
|
||||||
while (x->SiblingNext != property->Values)
|
while (x->SiblingNext != property->Values)
|
||||||
|
@ -1933,7 +1934,16 @@ void ZCCCompiler::DispatchScriptProperty(PProperty *prop, ZCC_PropertyStmt *prop
|
||||||
x = x->SiblingNext;
|
x = x->SiblingNext;
|
||||||
parmcount++;
|
parmcount++;
|
||||||
}
|
}
|
||||||
if (parmcount != prop->Variables.Size())
|
if (parmcount == 0 && prop->Variables.Size() == 1 && prop->Variables[0]->Type == TypeBool)
|
||||||
|
{
|
||||||
|
// allow boolean properties to have the parameter omitted
|
||||||
|
one.Operation = PEX_ConstValue;
|
||||||
|
one.NodeType = AST_ExprConstant;
|
||||||
|
one.Type = TypeBool;
|
||||||
|
one.IntVal = 1;
|
||||||
|
property->Values = &one;
|
||||||
|
}
|
||||||
|
else if (parmcount != prop->Variables.Size())
|
||||||
{
|
{
|
||||||
Error(x, "Argument count mismatch: Got %u, expected %u", parmcount, prop->Variables.Size());
|
Error(x, "Argument count mismatch: Got %u, expected %u", parmcount, prop->Variables.Size());
|
||||||
return;
|
return;
|
||||||
|
@ -1954,6 +1964,10 @@ void ZCCCompiler::DispatchScriptProperty(PProperty *prop, ZCC_PropertyStmt *prop
|
||||||
addr = ((char*)defaults) + f->Offset;
|
addr = ((char*)defaults) + f->Offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (f->Type == TypeBool)
|
||||||
|
{
|
||||||
|
static_cast<PBool*>(f->Type)->SetValue(addr, !!GetInt(exp));
|
||||||
|
}
|
||||||
if (f->Type->IsKindOf(RUNTIME_CLASS(PInt)))
|
if (f->Type->IsKindOf(RUNTIME_CLASS(PInt)))
|
||||||
{
|
{
|
||||||
static_cast<PInt*>(f->Type)->SetValue(addr, GetInt(exp));
|
static_cast<PInt*>(f->Type)->SetValue(addr, GetInt(exp));
|
||||||
|
|
|
@ -411,7 +411,9 @@ enum ESoundFlags
|
||||||
CHAN_LISTENERZ = 8,
|
CHAN_LISTENERZ = 8,
|
||||||
CHAN_MAYBE_LOCAL = 16,
|
CHAN_MAYBE_LOCAL = 16,
|
||||||
CHAN_UI = 32,
|
CHAN_UI = 32,
|
||||||
CHAN_NOPAUSE = 64
|
CHAN_NOPAUSE = 64,
|
||||||
|
CHAN_PICKUP = (CHAN_ITEM|CHAN_MAYBE_LOCAL)
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// sound attenuation values
|
// sound attenuation values
|
||||||
|
|
|
@ -24,6 +24,7 @@ class Inventory : Actor native
|
||||||
native bool bCreateCopyMoved;
|
native bool bCreateCopyMoved;
|
||||||
native bool bInitEffectFailed;
|
native bool bInitEffectFailed;
|
||||||
native meta String PickupMsg;
|
native meta String PickupMsg;
|
||||||
|
native meta int GiveQuest;
|
||||||
|
|
||||||
Default
|
Default
|
||||||
{
|
{
|
||||||
|
@ -35,19 +36,11 @@ class Inventory : Actor native
|
||||||
Inventory.PickupMessage "$TXT_DEFAULTPICKUPMSG";
|
Inventory.PickupMessage "$TXT_DEFAULTPICKUPMSG";
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual native color GetBlend ();
|
native bool CanPickup(Actor toucher);
|
||||||
virtual native void PlayPickupSound(Actor user);
|
|
||||||
virtual native void DoPickupSpecial (Actor toucher);
|
|
||||||
|
|
||||||
native bool DoRespawn();
|
native bool DoRespawn();
|
||||||
native bool GoAway();
|
|
||||||
native void GoAwayAndDie();
|
|
||||||
native void BecomeItem();
|
native void BecomeItem();
|
||||||
native void BecomePickup();
|
native void BecomePickup();
|
||||||
|
native void ModifyDropAmount(int dropamount);
|
||||||
// In this case the caller function is more than a simple wrapper around the virtual method and
|
|
||||||
// is what must be actually called to pick up an item.
|
|
||||||
native bool, Actor CallTryPickup(Actor toucher);
|
|
||||||
native static void PrintPickupMessage (bool localview, String str);
|
native static void PrintPickupMessage (bool localview, String str);
|
||||||
|
|
||||||
States(Actor, Overlay, Weapon, Item)
|
States(Actor, Overlay, Weapon, Item)
|
||||||
|
@ -307,6 +300,86 @@ class Inventory : Actor native
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// AInventory :: GiveQuest
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
void GiveQuestItem (Actor toucher)
|
||||||
|
{
|
||||||
|
if (GiveQuest > 0)
|
||||||
|
{
|
||||||
|
String qname = "QuestItem" .. GiveQuest;
|
||||||
|
class<Inventory> type = qname;
|
||||||
|
if (type != null)
|
||||||
|
{
|
||||||
|
toucher.GiveInventoryType (type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// AInventory :: CallTryPickup
|
||||||
|
//
|
||||||
|
// In this case the caller function is more than a simple wrapper around the virtual method and
|
||||||
|
// is what must be actually called to pick up an item.
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
bool, Actor CallTryPickup(Actor toucher)
|
||||||
|
{
|
||||||
|
let saved_toucher = toucher;
|
||||||
|
let Invstack = Inv; // A pointer of the inventories item stack.
|
||||||
|
|
||||||
|
// unmorphed versions of a currently morphed actor cannot pick up anything.
|
||||||
|
if (bUnmorphed) return false, null;
|
||||||
|
|
||||||
|
bool res;
|
||||||
|
if (CanPickup(toucher))
|
||||||
|
{
|
||||||
|
res = TryPickup(toucher);
|
||||||
|
}
|
||||||
|
else if (!bRestrictAbsolutely)
|
||||||
|
{
|
||||||
|
// let an item decide for itself how it will handle this
|
||||||
|
res = TryPickupRestricted(toucher);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false, null;
|
||||||
|
|
||||||
|
|
||||||
|
if (!res && (bAlwaysPickup) && !ShouldStay())
|
||||||
|
{
|
||||||
|
res = true;
|
||||||
|
GoAwayAndDie();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res)
|
||||||
|
{
|
||||||
|
GiveQuestItem(toucher);
|
||||||
|
|
||||||
|
// Transfer all inventory across that the old object had, if requested.
|
||||||
|
if (bTransfer)
|
||||||
|
{
|
||||||
|
while (Invstack)
|
||||||
|
{
|
||||||
|
let titem = Invstack;
|
||||||
|
Invstack = titem.Inv;
|
||||||
|
if (titem.Owner == self)
|
||||||
|
{
|
||||||
|
if (!titem.CallTryPickup(toucher)) // The object no longer can exist
|
||||||
|
{
|
||||||
|
titem.Destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res, toucher;
|
||||||
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
// AInventory :: ShouldStay
|
// AInventory :: ShouldStay
|
||||||
|
@ -536,6 +609,121 @@ class Inventory : Actor native
|
||||||
|
|
||||||
virtual void DoEffect() {}
|
virtual void DoEffect() {}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// AInventory :: Hide
|
||||||
|
//
|
||||||
|
// Hides this actor until it's time to respawn again.
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
virtual void Hide ()
|
||||||
|
{
|
||||||
|
State HideSpecialState = NULL, HideDoomishState = NULL;
|
||||||
|
|
||||||
|
bSpecial = false;
|
||||||
|
bNoGravity = true;
|
||||||
|
bInvisible = true;
|
||||||
|
|
||||||
|
if (gameinfo.gametype & GAME_Raven)
|
||||||
|
{
|
||||||
|
HideSpecialState = FindState("HideSpecial");
|
||||||
|
if (HideSpecialState == NULL)
|
||||||
|
{
|
||||||
|
HideDoomishState = FindState("HideDoomish");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HideDoomishState = FindState("HideDoomish");
|
||||||
|
if (HideDoomishState == NULL)
|
||||||
|
{
|
||||||
|
HideSpecialState = FindState("HideSpecial");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HideSpecialState != NULL)
|
||||||
|
{
|
||||||
|
SetState (HideSpecialState);
|
||||||
|
tics = 1400;
|
||||||
|
if (PickupFlash != NULL) tics += 30;
|
||||||
|
}
|
||||||
|
else if (HideDoomishState != NULL)
|
||||||
|
{
|
||||||
|
SetState (HideDoomishState);
|
||||||
|
tics = 1050;
|
||||||
|
}
|
||||||
|
if (RespawnTics != 0)
|
||||||
|
{
|
||||||
|
tics = RespawnTics;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// AInventory :: ShouldRespawn
|
||||||
|
//
|
||||||
|
// Returns true if the item should hide itself and reappear later when picked
|
||||||
|
// up.
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
virtual bool ShouldRespawn ()
|
||||||
|
{
|
||||||
|
if (bBigPowerup && !sv_respawnsuper) return false;
|
||||||
|
if (bNeverRespawn) return false;
|
||||||
|
return sv_itemrespawn || bAlwaysRespawn;
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// AInventory :: GoAway
|
||||||
|
//
|
||||||
|
// Returns true if you must create a copy of this item to give to the player
|
||||||
|
// or false if you can use this one instead.
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
protected bool GoAway ()
|
||||||
|
{
|
||||||
|
// Dropped items never stick around
|
||||||
|
if (bDropped)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ShouldStay ())
|
||||||
|
{
|
||||||
|
Hide ();
|
||||||
|
if (ShouldRespawn ())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// AInventory :: GoAwayAndDie
|
||||||
|
//
|
||||||
|
// Like GoAway but used by items that don't insert themselves into the
|
||||||
|
// inventory. If they won't be respawning, then they can destroy themselves.
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
protected void GoAwayAndDie ()
|
||||||
|
{
|
||||||
|
if (!GoAway ())
|
||||||
|
{
|
||||||
|
bSpecial = false;
|
||||||
|
SetStateLabel("HoldAndDestroy");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
// AInventory :: ModifyDamage
|
// AInventory :: ModifyDamage
|
||||||
|
@ -559,6 +747,61 @@ class Inventory : Actor native
|
||||||
virtual bool GetNoTeleportFreeze() { return false; }
|
virtual bool GetNoTeleportFreeze() { return false; }
|
||||||
virtual void AlterWeaponSprite(VisStyle vis, in out int changed) {}
|
virtual void AlterWeaponSprite(VisStyle vis, in out int changed) {}
|
||||||
virtual void OwnerDied() {}
|
virtual void OwnerDied() {}
|
||||||
|
virtual Color GetBlend () { return 0; }
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// AInventory :: DoPickupSpecial
|
||||||
|
//
|
||||||
|
// Executes this actor's special when it is picked up.
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
virtual void DoPickupSpecial (Actor toucher)
|
||||||
|
{
|
||||||
|
if (special)
|
||||||
|
{
|
||||||
|
toucher.A_CallSpecial(special, args[0], args[1], args[2], args[3], args[4]);
|
||||||
|
special = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// AInventory :: PlayPickupSound
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
virtual void PlayPickupSound (Actor toucher)
|
||||||
|
{
|
||||||
|
double atten;
|
||||||
|
int chan;
|
||||||
|
|
||||||
|
if (bNoAttenPickupSound)
|
||||||
|
{
|
||||||
|
atten = ATTN_NONE;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
else if ((ItemFlags & IF_FANCYPICKUPSOUND) &&
|
||||||
|
(toucher == NULL || toucher->CheckLocalView(consoeplayer)))
|
||||||
|
{
|
||||||
|
atten = ATTN_NONE;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
else
|
||||||
|
{
|
||||||
|
atten = ATTN_NORM;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toucher != NULL && toucher.CheckLocalView(consoleplayer))
|
||||||
|
{
|
||||||
|
chan = CHAN_PICKUP|CHAN_NOPAUSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
chan = CHAN_PICKUP;
|
||||||
|
}
|
||||||
|
toucher.A_PlaySound(PickupSound, chan, 1, false, atten);
|
||||||
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
|
@ -602,11 +845,135 @@ class Inventory : Actor native
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class DehackedPickup : Inventory native
|
//===========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
class DehackedPickup : Inventory
|
||||||
{
|
{
|
||||||
|
Inventory RealPickup;
|
||||||
|
bool droppedbymonster;
|
||||||
|
|
||||||
|
private native class<Inventory> DetermineType();
|
||||||
|
|
||||||
|
override bool TryPickup (in out Actor toucher)
|
||||||
|
{
|
||||||
|
let type = DetermineType ();
|
||||||
|
if (type == NULL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
RealPickup = Inventory(Spawn (type, Pos, NO_REPLACE));
|
||||||
|
if (RealPickup != NULL)
|
||||||
|
{
|
||||||
|
// The internally spawned item should never count towards statistics.
|
||||||
|
RealPickup.ClearCounters();
|
||||||
|
if (!bDropped)
|
||||||
|
{
|
||||||
|
RealPickup.bDropped = false;
|
||||||
|
}
|
||||||
|
// If this item has been dropped by a monster the
|
||||||
|
// amount of ammo this gives must be adjusted.
|
||||||
|
if (droppedbymonster)
|
||||||
|
{
|
||||||
|
RealPickup.ModifyDropAmount(0);
|
||||||
|
}
|
||||||
|
if (!RealPickup.CallTryPickup (toucher))
|
||||||
|
{
|
||||||
|
RealPickup.Destroy ();
|
||||||
|
RealPickup = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
GoAwayAndDie ();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
override String PickupMessage ()
|
||||||
|
{
|
||||||
|
if (RealPickup != null)
|
||||||
|
return RealPickup.PickupMessage ();
|
||||||
|
else return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
override bool ShouldStay ()
|
||||||
|
{
|
||||||
|
if (RealPickup != null)
|
||||||
|
return RealPickup.ShouldStay ();
|
||||||
|
else return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
override bool ShouldRespawn ()
|
||||||
|
{
|
||||||
|
if (RealPickup != null)
|
||||||
|
return RealPickup.ShouldRespawn ();
|
||||||
|
else return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
override void PlayPickupSound (Actor toucher)
|
||||||
|
{
|
||||||
|
if (RealPickup != null)
|
||||||
|
RealPickup.PlayPickupSound (toucher);
|
||||||
|
}
|
||||||
|
|
||||||
|
override void DoPickupSpecial (Actor toucher)
|
||||||
|
{
|
||||||
|
Super.DoPickupSpecial (toucher);
|
||||||
|
// If the real pickup hasn't joined the toucher's inventory, make sure it
|
||||||
|
// doesn't stick around.
|
||||||
|
if (RealPickup != null && RealPickup.Owner != toucher)
|
||||||
|
{
|
||||||
|
RealPickup.Destroy ();
|
||||||
|
}
|
||||||
|
RealPickup = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
override void OnDestroy ()
|
||||||
|
{
|
||||||
|
if (RealPickup != null)
|
||||||
|
{
|
||||||
|
RealPickup.Destroy ();
|
||||||
|
RealPickup = null;
|
||||||
|
}
|
||||||
|
Super.OnDestroy();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FakeInventory : Inventory native
|
//===========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
class FakeInventory : Inventory
|
||||||
{
|
{
|
||||||
native bool Respawnable;
|
bool Respawnable;
|
||||||
|
|
||||||
|
property respawns: Respawnable;
|
||||||
|
|
||||||
|
override bool ShouldRespawn ()
|
||||||
|
{
|
||||||
|
return Respawnable && Super.ShouldRespawn();
|
||||||
|
}
|
||||||
|
|
||||||
|
override bool TryPickup (in out Actor toucher)
|
||||||
|
{
|
||||||
|
let success = toucher.A_CallSpecial(special, args[0], args[1], args[2], args[3], args[4]);
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
GoAwayAndDie ();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
override void DoPickupSpecial (Actor toucher)
|
||||||
|
{
|
||||||
|
// The special was already executed by TryPickup, so do nothing here
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue