mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-10 14:51:51 +00:00
- partial scriptification of AInventory.
- scriptification of CustomInventory.
This commit is contained in:
parent
19b1c10ba8
commit
7c6542e595
10 changed files with 294 additions and 391 deletions
|
@ -2620,9 +2620,9 @@ void FParser::SF_MaxPlayerAmmo()
|
|||
if(amount < 0) amount = 0;
|
||||
if (!iammo)
|
||||
{
|
||||
iammo = static_cast<AInventory *>(Spawn (ammotype));
|
||||
players[playernum].mo->GiveAmmo(ammotype, 1);
|
||||
iammo = players[playernum].mo->FindInventory(ammotype);
|
||||
iammo->Amount = 0;
|
||||
iammo->AttachToOwner (players[playernum].mo);
|
||||
}
|
||||
iammo->MaxAmount = amount;
|
||||
|
||||
|
|
|
@ -332,28 +332,6 @@ DEFINE_ACTION_FUNCTION(AInventory, HandlePickup)
|
|||
ACTION_RETURN_BOOL(self->HandlePickup(item));
|
||||
}
|
||||
|
||||
bool AInventory::CallHandlePickup(AInventory *item)
|
||||
{
|
||||
auto self = this;
|
||||
while (self != nullptr)
|
||||
{
|
||||
IFVIRTUALPTR(self, AInventory, HandlePickup)
|
||||
{
|
||||
// Without the type cast this picks the 'void *' assignment...
|
||||
VMValue params[2] = { (DObject*)self, (DObject*)item };
|
||||
VMReturn ret;
|
||||
int retval;
|
||||
ret.IntAt(&retval);
|
||||
GlobalVMStack.Call(func, params, 2, &ret, 1, nullptr);
|
||||
if (retval) return true;
|
||||
}
|
||||
else if (self->HandlePickup(item)) return true;
|
||||
self = self->Inventory;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// AInventory :: GoAway
|
||||
|
@ -450,20 +428,6 @@ DEFINE_ACTION_FUNCTION(AInventory, CreateCopy)
|
|||
ACTION_RETURN_OBJECT(self->CreateCopy(other));
|
||||
}
|
||||
|
||||
AInventory *AInventory::CallCreateCopy(AActor *other)
|
||||
{
|
||||
IFVIRTUAL(AInventory, CreateCopy)
|
||||
{
|
||||
VMValue params[2] = { (DObject*)this, (DObject*)other };
|
||||
VMReturn ret;
|
||||
AInventory *retval;
|
||||
ret.PointerAt((void**)&retval);
|
||||
GlobalVMStack.Call(func, params, 2, &ret, 1, nullptr);
|
||||
return retval;
|
||||
}
|
||||
else return CreateCopy(other);
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
|
@ -475,47 +439,7 @@ AInventory *AInventory::CallCreateCopy(AActor *other)
|
|||
//
|
||||
//===========================================================================
|
||||
|
||||
AInventory *AInventory::CreateTossable ()
|
||||
{
|
||||
AInventory *copy;
|
||||
|
||||
// If this actor lacks a SpawnState, don't drop it. (e.g. A base weapon
|
||||
// like the fist can't be dropped because you'll never see it.)
|
||||
if (SpawnState == ::GetDefault<AActor>()->SpawnState ||
|
||||
SpawnState == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if ((ItemFlags & (IF_UNDROPPABLE|IF_UNTOSSABLE)) || Owner == NULL || Amount <= 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if (Amount == 1 && !(ItemFlags & IF_KEEPDEPLETED))
|
||||
{
|
||||
BecomePickup ();
|
||||
DropTime = 30;
|
||||
flags &= ~(MF_SPECIAL|MF_SOLID);
|
||||
return this;
|
||||
}
|
||||
copy = static_cast<AInventory *>(Spawn (GetClass(), Owner->Pos(), NO_REPLACE));
|
||||
if (copy != NULL)
|
||||
{
|
||||
copy->MaxAmount = MaxAmount;
|
||||
copy->Amount = 1;
|
||||
copy->DropTime = 30;
|
||||
copy->flags &= ~(MF_SPECIAL|MF_SOLID);
|
||||
Amount--;
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AInventory, CreateTossable)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AInventory);
|
||||
ACTION_RETURN_OBJECT(self->CreateTossable());
|
||||
}
|
||||
|
||||
AInventory *AInventory::CallCreateTossable()
|
||||
AInventory *AInventory::CreateTossable()
|
||||
{
|
||||
IFVIRTUAL(AInventory, CreateTossable)
|
||||
{
|
||||
|
@ -594,30 +518,6 @@ DEFINE_ACTION_FUNCTION(AInventory, BecomePickup)
|
|||
return 0;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// AInventory :: AbsorbDamage
|
||||
//
|
||||
// Allows inventory items (primarily armor) to reduce the amount of damage
|
||||
// taken. Damage is the amount of damage that would be done without armor,
|
||||
// and newdamage is the amount that should be done after the armor absorbs
|
||||
// it.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void AInventory::AbsorbDamage (int damage, FName damageType, int &newdamage)
|
||||
{
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AInventory, AbsorbDamage)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AInventory);
|
||||
PARAM_INT(damage);
|
||||
PARAM_NAME(type);
|
||||
PARAM_POINTER(newdmg, int);
|
||||
self->AbsorbDamage(damage, type, *newdmg);
|
||||
return 0;
|
||||
}
|
||||
//===========================================================================
|
||||
//
|
||||
// AInventory :: ModifyDamage
|
||||
|
@ -699,18 +599,6 @@ bool AInventory::GetNoTeleportFreeze ()
|
|||
//
|
||||
//===========================================================================
|
||||
|
||||
bool AInventory::Use (bool pickup)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AInventory, Use)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AInventory);
|
||||
PARAM_BOOL(pickup);
|
||||
ACTION_RETURN_BOOL(self->Use(pickup));
|
||||
}
|
||||
|
||||
bool AInventory::CallUse(bool pickup)
|
||||
{
|
||||
IFVIRTUAL(AInventory, Use)
|
||||
|
@ -721,9 +609,7 @@ bool AInventory::CallUse(bool pickup)
|
|||
ret.IntAt(&retval);
|
||||
GlobalVMStack.Call(func, params, 2, &ret, 1, nullptr);
|
||||
return !!retval;
|
||||
|
||||
}
|
||||
else return Use(pickup);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1153,28 +1039,6 @@ AInventory *AInventory::NextInv ()
|
|||
return item;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// AInventory :: DrawPowerup
|
||||
//
|
||||
// Gives this item a chance to draw a special status indicator on the screen.
|
||||
// Returns false if it didn't draw anything.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
bool AInventory::DrawPowerup (int x, int y)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AInventory, DrawPowerup)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AInventory);
|
||||
PARAM_INT(x);
|
||||
PARAM_INT(y);
|
||||
ACTION_RETURN_BOOL(self->DrawPowerup(x, y));
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// AInventory :: DoRespawn
|
||||
|
@ -1219,117 +1083,6 @@ void AInventory::GiveQuest (AActor *toucher)
|
|||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// AInventory :: TryPickup
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
bool AInventory::TryPickup (AActor *&toucher)
|
||||
{
|
||||
AActor *newtoucher = toucher; // in case changed by the powerup
|
||||
|
||||
// If HandlePickup() returns true, it will set the IF_PICKUPGOOD flag
|
||||
// to indicate that this item has been picked up. If the item cannot be
|
||||
// picked up, then it leaves the flag cleared.
|
||||
|
||||
ItemFlags &= ~IF_PICKUPGOOD;
|
||||
if (toucher->Inventory != NULL && toucher->Inventory->CallHandlePickup (this))
|
||||
{
|
||||
// Let something else the player is holding intercept the pickup.
|
||||
if (!(ItemFlags & IF_PICKUPGOOD))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
ItemFlags &= ~IF_PICKUPGOOD;
|
||||
GoAwayAndDie ();
|
||||
}
|
||||
else if (MaxAmount > 0)
|
||||
{
|
||||
// Add the item to the inventory. It is not already there, or HandlePickup
|
||||
// would have already taken care of it.
|
||||
AInventory *copy = CallCreateCopy (toucher);
|
||||
if (copy == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Some powerups cannot activate absolutely, for
|
||||
// example, PowerMorph; fail the pickup if so.
|
||||
if (copy->ItemFlags & IF_INITEFFECTFAILED)
|
||||
{
|
||||
if (copy != this) copy->Destroy();
|
||||
else ItemFlags &= ~IF_INITEFFECTFAILED;
|
||||
return false;
|
||||
}
|
||||
// Handle owner-changing powerups
|
||||
if (copy->ItemFlags & IF_CREATECOPYMOVED)
|
||||
{
|
||||
newtoucher = copy->Owner;
|
||||
copy->Owner = NULL;
|
||||
copy->ItemFlags &= ~IF_CREATECOPYMOVED;
|
||||
}
|
||||
// Continue onwards with the rest
|
||||
copy->CallAttachToOwner (newtoucher);
|
||||
if (ItemFlags & IF_AUTOACTIVATE)
|
||||
{
|
||||
if (copy->CallUse (true))
|
||||
{
|
||||
if (--copy->Amount <= 0)
|
||||
{
|
||||
copy->flags &= ~MF_SPECIAL;
|
||||
copy->SetState (copy->FindState("HoldAndDestroy"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ItemFlags & IF_AUTOACTIVATE)
|
||||
{
|
||||
// Special case: If an item's MaxAmount is 0, you can still pick it
|
||||
// up if it is autoactivate-able.
|
||||
|
||||
// The item is placed in the inventory just long enough to be used.
|
||||
toucher->AddInventory(this);
|
||||
bool usegood = CallUse(true);
|
||||
toucher->RemoveInventory(this);
|
||||
|
||||
if (usegood)
|
||||
{
|
||||
GoAwayAndDie();
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AInventory, TryPickup)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AInventory);
|
||||
PARAM_POINTER_NOT_NULL(toucher, AActor*);
|
||||
ACTION_RETURN_BOOL(self->TryPickup(*toucher));
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// AInventory :: TryPickupRestricted
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
bool AInventory::TryPickupRestricted (AActor *&toucher)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AInventory, TryPickupRestricted)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AInventory);
|
||||
PARAM_POINTER_NOT_NULL(toucher, AActor*);
|
||||
ACTION_RETURN_BOOL(self->TryPickupRestricted(*toucher));
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// AInventory :: CallTryPickup
|
||||
|
@ -1355,7 +1108,6 @@ bool AInventory::CallTryPickup (AActor *toucher, AActor **toucher_return)
|
|||
GlobalVMStack.Call(func, params, 2, &ret, 1, nullptr);
|
||||
res = !!retval;
|
||||
}
|
||||
else res = TryPickup(toucher);
|
||||
}
|
||||
else if (!(ItemFlags & IF_RESTRICTABSOLUTELY))
|
||||
{
|
||||
|
@ -1369,7 +1121,6 @@ bool AInventory::CallTryPickup (AActor *toucher, AActor **toucher_return)
|
|||
GlobalVMStack.Call(func, params, 2, &ret, 1, nullptr);
|
||||
res = !!retval;
|
||||
}
|
||||
else res = TryPickupRestricted(toucher);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
@ -1502,20 +1253,6 @@ CCMD (targetinv)
|
|||
//
|
||||
//===========================================================================
|
||||
|
||||
void AInventory::AttachToOwner (AActor *other)
|
||||
{
|
||||
BecomeItem ();
|
||||
other->AddInventory (this);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AInventory, AttachToOwner)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AInventory);
|
||||
PARAM_OBJECT_NOT_NULL(other, AActor);
|
||||
self->AttachToOwner(other);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AInventory::CallAttachToOwner(AActor *other)
|
||||
{
|
||||
IFVIRTUAL(AInventory, AttachToOwner)
|
||||
|
@ -1523,87 +1260,13 @@ void AInventory::CallAttachToOwner(AActor *other)
|
|||
VMValue params[2] = { (DObject*)this, (DObject*)other };
|
||||
GlobalVMStack.Call(func, params, 2, nullptr, 0, nullptr);
|
||||
}
|
||||
else AttachToOwner(other);
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// AInventory :: DetachFromOwner
|
||||
//
|
||||
// Performs any special work needed when the item leaves an inventory,
|
||||
// either through destruction or becoming a pickup.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void AInventory::DetachFromOwner ()
|
||||
{
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AInventory, DetachFromOwner)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AInventory);
|
||||
self->DetachFromOwner();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AInventory::CallDetachFromOwner()
|
||||
{
|
||||
IFVIRTUAL(AInventory, DetachFromOwner)
|
||||
{
|
||||
VMValue params[1] = { (DObject*)this };
|
||||
GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr);
|
||||
}
|
||||
else DetachFromOwner();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//===========================================================================
|
||||
|
||||
|
||||
|
||||
IMPLEMENT_CLASS(AStateProvider, false, false)
|
||||
IMPLEMENT_CLASS(ACustomInventory, false, false)
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// ACustomInventory :: SpecialDropAction
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
bool ACustomInventory::SpecialDropAction (AActor *dropper)
|
||||
{
|
||||
return CallStateChain (dropper, FindState(NAME_Drop));
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// ACustomInventory :: Use
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
bool ACustomInventory::Use (bool pickup)
|
||||
{
|
||||
return CallStateChain (Owner, FindState(NAME_Use));
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// ACustomInventory :: TryPickup
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
bool ACustomInventory::TryPickup (AActor *&toucher)
|
||||
{
|
||||
FState *pickupstate = FindState(NAME_Pickup);
|
||||
bool useok = CallStateChain (toucher, pickupstate);
|
||||
if ((useok || pickupstate == NULL) && FindState(NAME_Use) != NULL)
|
||||
{
|
||||
useok = Super::TryPickup (toucher);
|
||||
}
|
||||
else if (useok)
|
||||
{
|
||||
GoAwayAndDie();
|
||||
}
|
||||
return useok;
|
||||
}
|
||||
|
|
|
@ -90,23 +90,17 @@ public:
|
|||
virtual bool SpecialDropAction (AActor *dropper);
|
||||
bool CallSpecialDropAction(AActor *dropper);
|
||||
|
||||
virtual bool TryPickup(AActor *&toucher);
|
||||
virtual bool TryPickupRestricted(AActor *&toucher);
|
||||
bool CallTryPickup(AActor *toucher, AActor **toucher_return = NULL); // This wraps both virtual methods plus a few more checks.
|
||||
|
||||
virtual AInventory *CreateCopy(AActor *other);
|
||||
AInventory *CallCreateCopy(AActor *other);
|
||||
|
||||
virtual AInventory *CreateTossable();
|
||||
AInventory *CallCreateTossable();
|
||||
AInventory *CreateTossable();
|
||||
|
||||
virtual FString PickupMessage();
|
||||
FString GetPickupMessage();
|
||||
|
||||
virtual bool HandlePickup(AInventory *item);
|
||||
bool CallHandlePickup(AInventory *item);
|
||||
|
||||
virtual bool Use(bool pickup);
|
||||
bool CallUse(bool pickup);
|
||||
|
||||
virtual PalEntry GetBlend();
|
||||
|
@ -120,20 +114,11 @@ public:
|
|||
virtual void PlayPickupSound(AActor *toucher);
|
||||
void CallPlayPickupSound(AActor *toucher);
|
||||
|
||||
virtual void AttachToOwner(AActor *other);
|
||||
void CallAttachToOwner(AActor *other);
|
||||
|
||||
virtual void DetachFromOwner();
|
||||
void CallDetachFromOwner();
|
||||
|
||||
// still need to be done.
|
||||
virtual void AbsorbDamage(int damage, FName damageType, int &newdamage);
|
||||
void ModifyDamage(int damage, FName damageType, int &newdamage, bool passive);
|
||||
|
||||
// visual stuff is for later. Right now the VM has not yet access to the needed functionality.
|
||||
virtual bool DrawPowerup(int x, int y);
|
||||
|
||||
|
||||
// virtual on the script side only.
|
||||
double GetSpeedFactor();
|
||||
bool GetNoTeleportFreeze();
|
||||
|
@ -151,6 +136,8 @@ public:
|
|||
AInventory *PrevInv(); // Returns the previous item with IF_INVBAR set.
|
||||
AInventory *NextInv(); // Returns the next item with IF_INVBAR set.
|
||||
|
||||
bool CallStateChain(AActor *actor, FState *state);
|
||||
|
||||
TObjPtr<AActor> Owner; // Who owns this item? NULL if it's still a pickup.
|
||||
int Amount; // Amount of item this instance has
|
||||
int MaxAmount; // Max amount of item this instance can have
|
||||
|
@ -180,20 +167,6 @@ class AStateProvider : public AInventory
|
|||
DECLARE_CLASS (AStateProvider, AInventory)
|
||||
};
|
||||
|
||||
// CustomInventory: Supports the Use, Pickup, and Drop states from 96x
|
||||
class ACustomInventory : public AStateProvider
|
||||
{
|
||||
DECLARE_CLASS (ACustomInventory, AStateProvider)
|
||||
public:
|
||||
|
||||
// This is used when an inventory item's use state sequence is executed.
|
||||
bool CallStateChain (AActor *actor, FState *state);
|
||||
|
||||
virtual bool TryPickup (AActor *&toucher) override;
|
||||
virtual bool Use (bool pickup) override;
|
||||
virtual bool SpecialDropAction (AActor *dropper) override;
|
||||
};
|
||||
|
||||
extern PClassActor *QuestItemClasses[31];
|
||||
|
||||
|
||||
|
|
|
@ -196,6 +196,7 @@ xx(PowerWeaponLevel2)
|
|||
xx(PowerFlight)
|
||||
xx(PowerSpeed)
|
||||
xx(PowerTorch)
|
||||
xx(CustomInventory)
|
||||
|
||||
xx(AcolyteBlue)
|
||||
xx(SpectralLightningV1)
|
||||
|
|
|
@ -108,7 +108,7 @@ static FRandom pr_bfgselfdamage("BFGSelfDamage");
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
bool ACustomInventory::CallStateChain (AActor *actor, FState *state)
|
||||
bool AInventory::CallStateChain (AActor *actor, FState *state)
|
||||
{
|
||||
INTBOOL result = false;
|
||||
int counter = 0;
|
||||
|
@ -223,6 +223,13 @@ bool ACustomInventory::CallStateChain (AActor *actor, FState *state)
|
|||
return !!result;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AInventory, CallStateChain)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AInventory);
|
||||
PARAM_OBJECT(affectee, AActor);
|
||||
PARAM_STATE(state);
|
||||
ACTION_RETURN_BOOL(self->CallStateChain(affectee, state));
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
|
|
@ -844,7 +844,13 @@ void AActor::RemoveInventory(AInventory *item)
|
|||
if (inv == item)
|
||||
{
|
||||
*invp = item->Inventory;
|
||||
item->DetachFromOwner();
|
||||
|
||||
IFVIRTUALPTR(item, AInventory, DetachFromOwner)
|
||||
{
|
||||
VMValue params[1] = { item };
|
||||
GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr);
|
||||
}
|
||||
|
||||
item->Owner = NULL;
|
||||
item->Inventory = NULL;
|
||||
break;
|
||||
|
@ -1032,7 +1038,7 @@ DEFINE_ACTION_FUNCTION(AActor, UseInventory)
|
|||
|
||||
AInventory *AActor::DropInventory (AInventory *item)
|
||||
{
|
||||
AInventory *drop = item->CallCreateTossable ();
|
||||
AInventory *drop = item->CreateTossable ();
|
||||
|
||||
if (drop == NULL)
|
||||
{
|
||||
|
@ -3622,7 +3628,6 @@ int AActor::AbsorbDamage(int damage, FName dmgtype)
|
|||
VMValue params[4] = { item, damage, dmgtype.GetIndex(), &damage };
|
||||
GlobalVMStack.Call(func, params, 4, nullptr, 0, nullptr);
|
||||
}
|
||||
else item->AbsorbDamage(damage, dmgtype, damage);
|
||||
}
|
||||
return damage;
|
||||
}
|
||||
|
|
|
@ -253,12 +253,16 @@ static void CheckForUnsafeStates(PClassActor *obj)
|
|||
if (obj->Size == RUNTIME_CLASS(AWeapon)->Size) return; // This class cannot have user variables.
|
||||
test = weaponstates;
|
||||
}
|
||||
else if (obj->IsDescendantOf(RUNTIME_CLASS(ACustomInventory)))
|
||||
else
|
||||
{
|
||||
if (obj->Size == RUNTIME_CLASS(ACustomInventory)->Size) return; // This class cannot have user variables.
|
||||
test = pickupstates;
|
||||
auto citype = PClass::FindActor(NAME_CustomInventory);
|
||||
if (obj->IsDescendantOf(citype))
|
||||
{
|
||||
if (obj->Size == citype->Size) return; // This class cannot have user variables.
|
||||
test = pickupstates;
|
||||
}
|
||||
else return; // something else derived from AStateProvider. We do not know what this may be.
|
||||
}
|
||||
else return; // something else derived from AStateProvider. We do not know what this may be.
|
||||
|
||||
for (; *test != NAME_None; test++)
|
||||
{
|
||||
|
@ -338,7 +342,7 @@ static void CheckStates(PClassActor *obj)
|
|||
{
|
||||
CheckStateLabels(obj, weaponstates, SUF_WEAPON, "weapon sprites");
|
||||
}
|
||||
else if (obj->IsDescendantOf(RUNTIME_CLASS(ACustomInventory)))
|
||||
else if (obj->IsDescendantOf(PClass::FindActor(NAME_CustomInventory)))
|
||||
{
|
||||
CheckStateLabels(obj, pickupstates, SUF_ITEM, "CustomInventory state chain");
|
||||
}
|
||||
|
|
|
@ -2464,7 +2464,12 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
|
|||
PFunction *virtsym = nullptr;
|
||||
if (cls != nullptr && cls->ParentClass != nullptr) virtsym = dyn_cast<PFunction>(cls->ParentClass->Symbols.FindSymbol(FName(f->Name), true));
|
||||
unsigned vindex = ~0u;
|
||||
if (virtsym != nullptr) vindex = virtsym->Variants[0].Implementation->VirtualIndex;
|
||||
if (virtsym != nullptr)
|
||||
{
|
||||
auto imp = virtsym->Variants[0].Implementation;
|
||||
if (imp != nullptr) vindex = imp->VirtualIndex;
|
||||
else Error(f, "Virtual base function %s not found in %s", FName(f->Name).GetChars(), cls->ParentClass->TypeName.GetChars());
|
||||
}
|
||||
|
||||
if (!(f->Flags & ZCC_Native))
|
||||
{
|
||||
|
|
|
@ -9,9 +9,9 @@ class Inventory : Actor native
|
|||
{
|
||||
const BLINKTHRESHOLD = (4*32);
|
||||
|
||||
native Actor Owner; // Who owns this item? NULL if it's still a pickup.
|
||||
native int Amount; // Amount of item this instance has
|
||||
native int MaxAmount; // Max amount of item this instance can have
|
||||
native Actor Owner; // Who owns self item? NULL if it's still a pickup.
|
||||
native int Amount; // Amount of item self instance has
|
||||
native int MaxAmount; // Max amount of item self instance can have
|
||||
native int InterHubAmount; // Amount of item that can be kept between hubs or levels
|
||||
native int RespawnTics; // Tics from pickup time to respawn time
|
||||
native TextureID Icon; // Icon to show on status bar or HUD
|
||||
|
@ -33,19 +33,13 @@ class Inventory : Actor native
|
|||
Inventory.PickupMessage "$TXT_DEFAULTPICKUPMSG";
|
||||
}
|
||||
|
||||
virtual native bool Use (bool pickup);
|
||||
virtual native color GetBlend ();
|
||||
virtual native bool HandlePickup(Inventory item);
|
||||
virtual native Inventory CreateCopy(Actor other);
|
||||
virtual native Inventory CreateTossable();
|
||||
virtual native bool SpecialDropAction (Actor dropper);
|
||||
virtual native String PickupMessage();
|
||||
virtual native bool ShouldStay();
|
||||
virtual native void PlayPickupSound(Actor user);
|
||||
virtual native void AttachToOwner(Actor user);
|
||||
virtual native void DetachFromOwner();
|
||||
virtual native bool DrawPowerup(int x, int y);
|
||||
virtual native void AbsorbDamage (int damage, Name damageType, out int newdamage);
|
||||
|
||||
native bool DoRespawn();
|
||||
native bool GoAway();
|
||||
|
@ -55,9 +49,8 @@ class Inventory : Actor native
|
|||
|
||||
// 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.
|
||||
virtual protected native bool TryPickup(in out Actor toucher);
|
||||
virtual protected native bool TryPickupRestricted(in out Actor toucher);
|
||||
native bool, Actor CallTryPickup(Actor toucher);
|
||||
native bool CallStateChain (Actor actor, State state);
|
||||
|
||||
States(Actor, Overlay, Weapon, Item)
|
||||
{
|
||||
|
@ -138,6 +131,188 @@ class Inventory : Actor native
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// AInventory :: CallHandlePickup
|
||||
//
|
||||
// Runs all HandlePickup methods in the chain
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
private bool CallHandlePickup(Inventory item)
|
||||
{
|
||||
let me = self;
|
||||
while (me != null)
|
||||
{
|
||||
if (me.HandlePickup(item)) return true;
|
||||
me = me.Inv;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// AInventory :: TryPickup
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
virtual protected bool TryPickup (in out Actor toucher)
|
||||
{
|
||||
Actor newtoucher = toucher; // in case changed by the powerup
|
||||
|
||||
// If HandlePickup() returns true, it will set the IF_PICKUPGOOD flag
|
||||
// to indicate that self item has been picked up. If the item cannot be
|
||||
// picked up, then it leaves the flag cleared.
|
||||
|
||||
bPickupGood = false;
|
||||
if (toucher.Inv != NULL && toucher.Inv.CallHandlePickup (self))
|
||||
{
|
||||
// Let something else the player is holding intercept the pickup.
|
||||
if (!bPickupGood)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bPickupGood = false;
|
||||
GoAwayAndDie ();
|
||||
}
|
||||
else if (MaxAmount > 0)
|
||||
{
|
||||
// Add the item to the inventory. It is not already there, or HandlePickup
|
||||
// would have already taken care of it.
|
||||
let copy = CreateCopy (toucher);
|
||||
if (copy == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Some powerups cannot activate absolutely, for
|
||||
// example, PowerMorph; fail the pickup if so.
|
||||
if (copy.bInitEffectFailed)
|
||||
{
|
||||
if (copy != self) copy.Destroy();
|
||||
else bInitEffectFailed;
|
||||
return false;
|
||||
}
|
||||
// Handle owner-changing powerups
|
||||
if (copy.bCreateCopyMoved)
|
||||
{
|
||||
newtoucher = copy.Owner;
|
||||
copy.Owner = NULL;
|
||||
bCreateCopyMoved = false;
|
||||
}
|
||||
// Continue onwards with the rest
|
||||
copy.AttachToOwner (newtoucher);
|
||||
if (bAutoActivate)
|
||||
{
|
||||
if (copy.Use (true))
|
||||
{
|
||||
if (--copy.Amount <= 0)
|
||||
{
|
||||
copy.bSpecial = false;
|
||||
copy.SetStateLabel ("HoldAndDestroy");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (bAutoActivate)
|
||||
{
|
||||
// Special case: If an item's MaxAmount is 0, you can still pick it
|
||||
// up if it is autoactivate-able.
|
||||
|
||||
// The item is placed in the inventory just long enough to be used.
|
||||
toucher.AddInventory(self);
|
||||
bool usegood = Use(true);
|
||||
toucher.RemoveInventory(self);
|
||||
|
||||
if (usegood)
|
||||
{
|
||||
GoAwayAndDie();
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// AInventory :: TryPickupRestricted
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
virtual bool TryPickupRestricted (in out Actor toucher)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// AInventory :: AttachToOwner
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
virtual void AttachToOwner (Actor other)
|
||||
{
|
||||
BecomeItem ();
|
||||
other.AddInventory (self);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// AInventory :: DetachFromOwner
|
||||
//
|
||||
// Performs any special work needed when the item leaves an inventory,
|
||||
// either through destruction or becoming a pickup.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
virtual void DetachFromOwner ()
|
||||
{
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// AInventory::CreateTossable
|
||||
//
|
||||
// Creates a copy of the item suitable for dropping. If this actor embodies
|
||||
// only one item, then it is tossed out itself. Otherwise, the count drops
|
||||
// by one and a new item with an amount of 1 is spawned.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
virtual Inventory CreateTossable ()
|
||||
{
|
||||
// If self actor lacks a SpawnState, don't drop it. (e.g. A base weapon
|
||||
// like the fist can't be dropped because you'll never see it.)
|
||||
if (SpawnState == GetDefaultByType("Actor").SpawnState || SpawnState == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if (bUndroppable || bUntossable || Owner == NULL || Amount <= 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if (Amount == 1 && !bKeepDepleted)
|
||||
{
|
||||
BecomePickup ();
|
||||
DropTime = 30;
|
||||
bSpecial = bSolid = false;
|
||||
return self;
|
||||
}
|
||||
let copy = Inventory(Spawn (GetClass(), Owner.Pos, NO_REPLACE));
|
||||
if (copy != NULL)
|
||||
{
|
||||
copy.MaxAmount = MaxAmount;
|
||||
copy.Amount = 1;
|
||||
copy.DropTime = 30;
|
||||
copy.bSpecial = copy.bSolid = false;
|
||||
Amount--;
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// AInventory :: DepleteOrDestroy
|
||||
|
@ -186,11 +361,37 @@ class Inventory : Actor native
|
|||
|
||||
virtual void DoEffect() {}
|
||||
|
||||
|
||||
virtual bool Use (bool pickup) { return false; }
|
||||
virtual double GetSpeedFactor() { return 1; }
|
||||
virtual bool GetNoTeleportFreeze() { return false; }
|
||||
virtual void ModifyDamage(int damage, Name damageType, out int newdamage, bool passive) {}
|
||||
virtual void AlterWeaponSprite(VisStyle vis, in out int changed) {}
|
||||
virtual void OwnerDied() {}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// AInventory :: DrawPowerup
|
||||
//
|
||||
// Gives self item a chance to draw a special status indicator on the screen.
|
||||
// Returns false if it didn't draw anything.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
virtual bool DrawPowerup(int x, int y) { return false; }
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// AInventory :: AbsorbDamage
|
||||
//
|
||||
// Allows inventory items (primarily armor) to reduce the amount of damage
|
||||
// taken. Damage is the amount of damage that would be done without armor,
|
||||
// and newdamage is the amount that should be done after the armor absorbs
|
||||
// it.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
virtual void AbsorbDamage (int damage, Name damageType, out int newdamage) {}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -36,4 +36,48 @@ class CustomInventory : StateProvider native
|
|||
deprecated action void A_Lower() {}
|
||||
deprecated action void A_Raise() {}
|
||||
deprecated action void A_CheckReload() {}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// ACustomInventory :: SpecialDropAction
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
override bool SpecialDropAction (Actor dropper)
|
||||
{
|
||||
return CallStateChain (dropper, FindState('Drop'));
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// ACustomInventory :: Use
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
override bool Use (bool pickup)
|
||||
{
|
||||
return CallStateChain (Owner, FindState('Use'));
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// ACustomInventory :: TryPickup
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
override bool TryPickup (in out Actor toucher)
|
||||
{
|
||||
let pickupstate = FindState('Pickup');
|
||||
bool useok = CallStateChain (toucher, pickupstate);
|
||||
if ((useok || pickupstate == NULL) && FindState('Use') != NULL)
|
||||
{
|
||||
useok = Super.TryPickup (toucher);
|
||||
}
|
||||
else if (useok)
|
||||
{
|
||||
GoAwayAndDie();
|
||||
}
|
||||
return useok;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue