- more exporting of AInventory.

This commit is contained in:
Christoph Oelckers 2017-01-19 20:56:31 +01:00
parent 7c6542e595
commit 1750ded7c4
14 changed files with 291 additions and 397 deletions

View file

@ -26,6 +26,8 @@ IMPLEMENT_POINTERS_START(DBot)
IMPLEMENT_POINTER(last_mate) IMPLEMENT_POINTER(last_mate)
IMPLEMENT_POINTERS_END IMPLEMENT_POINTERS_END
DEFINE_FIELD(DBot, dest)
DBot::DBot () DBot::DBot ()
: DThinker(STAT_BOT) : DThinker(STAT_BOT)
{ {

View file

@ -3158,9 +3158,10 @@ bool ADehackedPickup::TryPickup (AActor *&toucher)
FString ADehackedPickup::PickupMessage () FString ADehackedPickup::PickupMessage ()
{ {
/*
if (RealPickup != nullptr) if (RealPickup != nullptr)
return RealPickup->PickupMessage (); return RealPickup->PickupMessage ();
else return ""; else*/ return "";
} }
bool ADehackedPickup::ShouldStay () bool ADehackedPickup::ShouldStay ()

View file

@ -39,7 +39,7 @@ void PClassInventory::DeriveData(PClass *newclass)
Super::DeriveData(newclass); Super::DeriveData(newclass);
PClassInventory *newc = static_cast<PClassInventory *>(newclass); PClassInventory *newc = static_cast<PClassInventory *>(newclass);
newc->PickupMessage = PickupMessage; newc->PickupMsg = PickupMsg;
newc->GiveQuest = GiveQuest; newc->GiveQuest = GiveQuest;
newc->AltHUDIcon = AltHUDIcon; newc->AltHUDIcon = AltHUDIcon;
newc->ForbiddenToPlayerClass = ForbiddenToPlayerClass; newc->ForbiddenToPlayerClass = ForbiddenToPlayerClass;
@ -79,19 +79,16 @@ void PClassInventory::Finalize(FStateDefinitions &statedef)
((AActor*)Defaults)->flags |= MF_SPECIAL; ((AActor*)Defaults)->flags |= MF_SPECIAL;
} }
int AInventory::StaticLastMessageTic;
FString AInventory::StaticLastMessage;
IMPLEMENT_CLASS(AInventory, false, true) IMPLEMENT_CLASS(AInventory, false, true)
IMPLEMENT_POINTERS_START(AInventory) IMPLEMENT_POINTERS_START(AInventory)
IMPLEMENT_POINTER(Owner) IMPLEMENT_POINTER(Owner)
IMPLEMENT_POINTERS_END IMPLEMENT_POINTERS_END
DEFINE_FIELD_BIT(AInventory, ItemFlags, bPickupGood, IF_PICKUPGOOD) DEFINE_FIELD_BIT(AInventory, ItemFlags, bPickupGood, IF_PICKUPGOOD)
DEFINE_FIELD_BIT(AInventory, ItemFlags, bCreateCopyMoved, IF_CREATECOPYMOVED) DEFINE_FIELD_BIT(AInventory, ItemFlags, bCreateCopyMoved, IF_CREATECOPYMOVED)
DEFINE_FIELD_BIT(AInventory, ItemFlags, bInitEffectFailed, IF_INITEFFECTFAILED) DEFINE_FIELD_BIT(AInventory, ItemFlags, bInitEffectFailed, IF_INITEFFECTFAILED)
DEFINE_FIELD(AInventory, Owner) DEFINE_FIELD(AInventory, Owner)
DEFINE_FIELD(AInventory, Amount) DEFINE_FIELD(AInventory, Amount)
DEFINE_FIELD(AInventory, MaxAmount) DEFINE_FIELD(AInventory, MaxAmount)
DEFINE_FIELD(AInventory, InterHubAmount) DEFINE_FIELD(AInventory, InterHubAmount)
@ -101,6 +98,7 @@ DEFINE_FIELD(AInventory, DropTime)
DEFINE_FIELD(AInventory, SpawnPointClass) DEFINE_FIELD(AInventory, SpawnPointClass)
DEFINE_FIELD(AInventory, PickupFlash) DEFINE_FIELD(AInventory, PickupFlash)
DEFINE_FIELD(AInventory, PickupSound) DEFINE_FIELD(AInventory, PickupSound)
DEFINE_FIELD(PClassInventory, PickupMsg)
//=========================================================================== //===========================================================================
// //
@ -179,42 +177,6 @@ void AInventory::MarkPrecacheSounds() const
PickupSound.MarkUsed(); PickupSound.MarkUsed();
} }
//===========================================================================
//
// AInventory :: SpecialDropAction
//
// Called by P_DropItem. Return true to prevent the standard drop tossing.
// A few Strife items that are meant to trigger actions rather than be
// picked up use this. Normal items shouldn't need it.
//
//===========================================================================
bool AInventory::SpecialDropAction (AActor *dropper)
{
return false;
}
DEFINE_ACTION_FUNCTION(AInventory, SpecialDropAction)
{
PARAM_SELF_PROLOGUE(AInventory);
PARAM_OBJECT_NOT_NULL(dropper, AActor);
ACTION_RETURN_BOOL(self->SpecialDropAction(dropper));
}
bool AInventory::CallSpecialDropAction(AActor *dropper)
{
IFVIRTUAL(AInventory, SpecialDropAction)
{
VMValue params[2] = { (DObject*)this, (DObject*)dropper };
VMReturn ret;
int retval;
ret.IntAt(&retval);
GlobalVMStack.Call(func, params, 2, &ret, 1, nullptr);
return !!retval;
}
return SpecialDropAction(dropper);
}
//=========================================================================== //===========================================================================
// //
// AInventory :: ShouldRespawn // AInventory :: ShouldRespawn
@ -231,18 +193,6 @@ bool AInventory::ShouldRespawn ()
return !!((dmflags & DF_ITEMS_RESPAWN) || (ItemFlags & IF_ALWAYSRESPAWN)); return !!((dmflags & DF_ITEMS_RESPAWN) || (ItemFlags & IF_ALWAYSRESPAWN));
} }
//===========================================================================
//
// AInventory :: BeginPlay
//
//===========================================================================
void AInventory::BeginPlay ()
{
Super::BeginPlay ();
flags |= MF_DROPPED; // [RH] Items are dropped by default
}
//=========================================================================== //===========================================================================
// //
// AInventory :: Grind // AInventory :: Grind
@ -270,68 +220,6 @@ bool AInventory::Grind(bool items)
return Super::Grind(items); return Super::Grind(items);
} }
//===========================================================================
//
// AInventory :: DoEffect
//
// Handles any effect an item might apply to its owner
// Normally only used by subclasses of Powerup
//
//===========================================================================
void AInventory::DoEffect()
{
IFVIRTUAL(AInventory, DoEffect)
{
VMValue params[1] = { (DObject*)this };
VMFrameStack stack;
GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr);
}
}
//===========================================================================
//
// AInventory :: HandlePickup
//
// Returns true if the pickup was handled (or should not happen at all),
// false if not.
//
//===========================================================================
bool AInventory::HandlePickup (AInventory *item)
{
if (item->GetClass() == GetClass())
{
if (Amount < MaxAmount || (sv_unlimited_pickup && !item->CallShouldStay()))
{
if (Amount > 0 && Amount + item->Amount < 0)
{
Amount = 0x7fffffff;
}
else
{
Amount += item->Amount;
}
if (Amount > MaxAmount && !sv_unlimited_pickup)
{
Amount = MaxAmount;
}
item->ItemFlags |= IF_PICKUPGOOD;
}
return true;
}
return false;
}
DEFINE_ACTION_FUNCTION(AInventory, HandlePickup)
{
PARAM_SELF_PROLOGUE(AInventory);
PARAM_OBJECT_NOT_NULL(item, AInventory);
ACTION_RETURN_BOOL(self->HandlePickup(item));
}
//=========================================================================== //===========================================================================
// //
// AInventory :: GoAway // AInventory :: GoAway
@ -392,67 +280,6 @@ DEFINE_ACTION_FUNCTION(AInventory, GoAwayAndDie)
return 0; return 0;
} }
//===========================================================================
//
// AInventory :: CreateCopy
//
// Returns an actor suitable for placing in an inventory, either itself or
// a copy based on whether it needs to respawn or not. Returning NULL
// indicates the item should not be picked up.
//
//===========================================================================
AInventory *AInventory::CreateCopy (AActor *other)
{
AInventory *copy;
Amount = MIN(Amount, MaxAmount);
if (GoAway ())
{
copy = static_cast<AInventory *>(Spawn (GetClass()));
copy->Amount = Amount;
copy->MaxAmount = MaxAmount;
}
else
{
copy = this;
}
return copy;
}
DEFINE_ACTION_FUNCTION(AInventory, CreateCopy)
{
PARAM_SELF_PROLOGUE(AInventory);
PARAM_OBJECT(other, AActor);
ACTION_RETURN_OBJECT(self->CreateCopy(other));
}
//===========================================================================
//
// 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.
//
//===========================================================================
AInventory *AInventory::CreateTossable()
{
IFVIRTUAL(AInventory, CreateTossable)
{
VMValue params[1] = { (DObject*)this };
VMReturn ret;
AInventory *retval;
ret.PointerAt((void**)&retval);
GlobalVMStack.Call(func, params, 1, &ret, 1, nullptr);
return retval;
}
else return CreateTossable();
}
//=========================================================================== //===========================================================================
// //
// AInventory :: BecomeItem // AInventory :: BecomeItem
@ -518,30 +345,6 @@ DEFINE_ACTION_FUNCTION(AInventory, BecomePickup)
return 0; return 0;
} }
//===========================================================================
//
// AInventory :: ModifyDamage
//
// Allows inventory items to manipulate the amount of damage
// inflicted. Damage is the amount of damage that would be done without manipulation,
// and newdamage is the amount that should be done after the item has changed
// it.
// 'active' means it is called by the inflictor, 'passive' by the target.
// It may seem that this is redundant and AbsorbDamage is the same. However,
// AbsorbDamage is called only for players and also depends on other settings
// which are undesirable for a protection artifact.
//
//===========================================================================
void AInventory::ModifyDamage (int damage, FName damageType, int &newdamage, bool passive)
{
IFVIRTUAL(AInventory, ModifyDamage)
{
VMValue params[5] = { (DObject*)this, damage, int(damageType), &newdamage, passive };
GlobalVMStack.Call(func, params, 5, nullptr, 0, nullptr);
}
}
//=========================================================================== //===========================================================================
// //
// AInventory :: GetSpeedFactor // AInventory :: GetSpeedFactor
@ -556,10 +359,9 @@ double AInventory::GetSpeedFactor()
{ {
IFVIRTUALPTR(self, AInventory, GetSpeedFactor) IFVIRTUALPTR(self, AInventory, GetSpeedFactor)
{ {
VMValue params[2] = { (DObject*)self }; VMValue params[1] = { (DObject*)self };
VMReturn ret;
double retval; double retval;
ret.FloatAt(&retval); VMReturn ret(&retval);
GlobalVMStack.Call(func, params, 1, &ret, 1, nullptr); GlobalVMStack.Call(func, params, 1, &ret, 1, nullptr);
factor *= retval; factor *= retval;
} }
@ -581,10 +383,9 @@ bool AInventory::GetNoTeleportFreeze ()
{ {
IFVIRTUALPTR(self, AInventory, GetNoTeleportFreeze) IFVIRTUALPTR(self, AInventory, GetNoTeleportFreeze)
{ {
VMValue params[2] = { (DObject*)self }; VMValue params[1] = { (DObject*)self };
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);
if (retval) return true; if (retval) return true;
} }
@ -610,6 +411,7 @@ bool AInventory::CallUse(bool pickup)
GlobalVMStack.Call(func, params, 2, &ret, 1, nullptr); GlobalVMStack.Call(func, params, 2, &ret, 1, nullptr);
return !!retval; return !!retval;
} }
return false;
} }
@ -669,100 +471,25 @@ void AInventory::Hide ()
// //
// //
//=========================================================================== //===========================================================================
static int StaticLastMessageTic;
static FString StaticLastMessage;
static void PrintPickupMessage (const char *str) DEFINE_ACTION_FUNCTION(AInventory, PrintPickupMessage)
{ {
if (str != NULL) PARAM_PROLOGUE;
PARAM_BOOL(localview);
PARAM_STRING(str);
if (str.IsNotEmpty() && localview && (StaticLastMessageTic != gametic || StaticLastMessage.Compare(str)))
{ {
if (str[0]=='$') StaticLastMessageTic = gametic;
{ StaticLastMessage = str;
str=GStrings(str+1); const char *pstr = str.GetChars();
}
if (str[0] != 0) Printf (PRINT_LOW, "%s\n", str); if (pstr[0] == '$') pstr = GStrings(pstr + 1);
} if (pstr[0] != 0) Printf(PRINT_LOW, "%s\n", pstr);
} StatusBar->FlashCrosshair();
//===========================================================================
//
// AInventory :: Touch
//
// Handles collisions from another actor, possible adding itself to the
// collider's inventory.
//
//===========================================================================
void AInventory::Touch (AActor *toucher)
{
player_t *player = toucher->player;
// If a voodoo doll touches something, pretend the real player touched it instead.
if (player != NULL)
{
toucher = player->mo;
}
bool localview = toucher->CheckLocalView(consoleplayer);
if (!CallTryPickup (toucher, &toucher)) return;
// This is the only situation when a pickup flash should ever play.
if (PickupFlash != NULL && !CallShouldStay())
{
Spawn(PickupFlash, Pos(), ALLOW_REPLACE);
}
if (!(ItemFlags & IF_QUIET))
{
FString message = GetPickupMessage ();
if (message.IsNotEmpty() && localview
&& (StaticLastMessageTic != gametic || StaticLastMessage.Compare(message)))
{
StaticLastMessageTic = gametic;
StaticLastMessage = message;
PrintPickupMessage (message);
StatusBar->FlashCrosshair ();
}
// Special check so voodoo dolls picking up items cause the
// real player to make noise.
if (player != NULL)
{
CallPlayPickupSound (player->mo);
if (!(ItemFlags & IF_NOSCREENFLASH))
{
player->bonuscount = BONUSADD;
}
}
else
{
CallPlayPickupSound (toucher);
}
}
// [RH] Execute an attached special (if any)
DoPickupSpecial (toucher);
if (flags & MF_COUNTITEM)
{
if (player != NULL)
{
player->itemcount++;
}
level.found_items++;
}
if (flags5 & MF5_COUNTSECRET)
{
P_GiveSecret(player != NULL? (AActor*)player->mo : toucher, true, true, -1);
}
//Added by MC: Check if item taken was the roam destination of any bot
for (int i = 0; i < MAXPLAYERS; i++)
{
if (players[i].Bot != NULL && this == players[i].Bot->dest)
players[i].Bot->dest = NULL;
} }
return 0;
} }
//=========================================================================== //===========================================================================
@ -783,37 +510,12 @@ void AInventory::DoPickupSpecial (AActor *toucher)
} }
} }
//=========================================================================== DEFINE_ACTION_FUNCTION(AInventory, DoPickupSpecial)
//
// AInventory :: PickupMessage
//
// Returns the message to print when this actor is picked up.
//
//===========================================================================
FString AInventory::PickupMessage ()
{
return GetClass()->PickupMessage;
}
DEFINE_ACTION_FUNCTION(AInventory, PickupMessage)
{ {
PARAM_SELF_PROLOGUE(AInventory); PARAM_SELF_PROLOGUE(AInventory);
ACTION_RETURN_STRING(self->PickupMessage()); PARAM_OBJECT(toucher, AActor);
} self->DoPickupSpecial(toucher);
return 0;
FString AInventory::GetPickupMessage()
{
IFVIRTUAL(AInventory, PickupMessage)
{
VMValue params[1] = { (DObject*)this };
VMReturn ret;
FString retval;
ret.StringAt(&retval);
GlobalVMStack.Call(func, params, 1, &ret, 1, nullptr);
return retval;
}
else return PickupMessage();
} }
//=========================================================================== //===========================================================================
@ -881,17 +583,6 @@ void AInventory::CallPlayPickupSound(AActor *other)
// //
//=========================================================================== //===========================================================================
bool AInventory::ShouldStay ()
{
return false;
}
DEFINE_ACTION_FUNCTION(AInventory, ShouldStay)
{
PARAM_SELF_PROLOGUE(AInventory);
ACTION_RETURN_BOOL(self->ShouldStay());
}
bool AInventory::CallShouldStay() bool AInventory::CallShouldStay()
{ {
IFVIRTUAL(AInventory, ShouldStay) IFVIRTUAL(AInventory, ShouldStay)
@ -903,7 +594,7 @@ bool AInventory::CallShouldStay()
GlobalVMStack.Call(func, params, 1, &ret, 1, nullptr); GlobalVMStack.Call(func, params, 1, &ret, 1, nullptr);
return !!retval; return !!retval;
} }
else return ShouldStay(); return false;
} }

View file

@ -59,7 +59,7 @@ public:
virtual size_t PointerSubstitution(DObject *oldclass, DObject *newclass); virtual size_t PointerSubstitution(DObject *oldclass, DObject *newclass);
void Finalize(FStateDefinitions &statedef); void Finalize(FStateDefinitions &statedef);
FString PickupMessage; FString PickupMsg;
int GiveQuest; // Optionally give one of the quest items. int GiveQuest; // Optionally give one of the quest items.
FTextureID AltHUDIcon; FTextureID AltHUDIcon;
TArray<PClassPlayerPawn *> RestrictedToPlayerClass; TArray<PClassPlayerPawn *> RestrictedToPlayerClass;
@ -72,10 +72,8 @@ class AInventory : public AActor
HAS_OBJECT_POINTERS HAS_OBJECT_POINTERS
public: public:
virtual void Touch (AActor *toucher) override;
virtual void Serialize(FSerializer &arc) override; virtual void Serialize(FSerializer &arc) override;
virtual void MarkPrecacheSounds() const override; virtual void MarkPrecacheSounds() const override;
virtual void BeginPlay () override;
virtual void OnDestroy() override; virtual void OnDestroy() override;
virtual void Tick() override; virtual void Tick() override;
virtual bool Grind(bool items) override; virtual bool Grind(bool items) override;
@ -86,39 +84,20 @@ public:
virtual bool ShouldRespawn (); virtual bool ShouldRespawn ();
virtual void DoPickupSpecial (AActor *toucher); virtual void DoPickupSpecial (AActor *toucher);
// methods that can be overridden by scripts, plus their callers.
virtual bool SpecialDropAction (AActor *dropper);
bool CallSpecialDropAction(AActor *dropper);
bool CallTryPickup(AActor *toucher, AActor **toucher_return = NULL); // This wraps both virtual methods plus a few more checks. bool CallTryPickup(AActor *toucher, AActor **toucher_return = NULL); // This wraps both virtual methods plus a few more checks.
virtual AInventory *CreateCopy(AActor *other);
AInventory *CreateTossable();
virtual FString PickupMessage();
FString GetPickupMessage();
virtual bool HandlePickup(AInventory *item);
bool CallUse(bool pickup); bool CallUse(bool pickup);
virtual PalEntry GetBlend(); virtual PalEntry GetBlend();
PalEntry CallGetBlend(); PalEntry CallGetBlend();
virtual bool ShouldStay();
bool CallShouldStay(); bool CallShouldStay();
void DoEffect();
virtual void PlayPickupSound(AActor *toucher); virtual void PlayPickupSound(AActor *toucher);
void CallPlayPickupSound(AActor *toucher); void CallPlayPickupSound(AActor *toucher);
void CallAttachToOwner(AActor *other); void CallAttachToOwner(AActor *other);
// still need to be done.
void ModifyDamage(int damage, FName damageType, int &newdamage, bool passive);
// virtual on the script side only. // virtual on the script side only.
double GetSpeedFactor(); double GetSpeedFactor();
bool GetNoTeleportFreeze(); bool GetNoTeleportFreeze();
@ -136,8 +115,6 @@ public:
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.
bool CallStateChain(AActor *actor, FState *state);
TObjPtr<AActor> Owner; // Who owns this item? NULL if it's still a pickup. TObjPtr<AActor> Owner; // Who owns this item? NULL if it's still a pickup.
int Amount; // Amount of item this instance has int Amount; // Amount of item this instance has
int MaxAmount; // Max amount of item this instance can have int MaxAmount; // Max amount of item this instance can have
@ -158,13 +135,13 @@ protected:
void GiveQuest(AActor * toucher); void GiveQuest(AActor * toucher);
private: private:
static int StaticLastMessageTic;
static FString StaticLastMessage;
}; };
class AStateProvider : public AInventory class AStateProvider : public AInventory
{ {
DECLARE_CLASS (AStateProvider, AInventory) DECLARE_CLASS (AStateProvider, AInventory)
public:
bool CallStateChain(AActor *actor, FState *state);
}; };
extern PClassActor *QuestItemClasses[31]; extern PClassActor *QuestItemClasses[31];

View file

@ -56,8 +56,6 @@
#include "virtual.h" #include "virtual.h"
#define BONUSADD 6
extern FFlagDef WeaponFlagDefs[]; extern FFlagDef WeaponFlagDefs[];
IMPLEMENT_CLASS(AWeapon, false, true) IMPLEMENT_CLASS(AWeapon, false, true)

View file

@ -108,7 +108,7 @@ static FRandom pr_bfgselfdamage("BFGSelfDamage");
// //
//========================================================================== //==========================================================================
bool AInventory::CallStateChain (AActor *actor, FState *state) bool AStateProvider::CallStateChain (AActor *actor, FState *state)
{ {
INTBOOL result = false; INTBOOL result = false;
int counter = 0; int counter = 0;
@ -223,9 +223,9 @@ bool AInventory::CallStateChain (AActor *actor, FState *state)
return !!result; return !!result;
} }
DEFINE_ACTION_FUNCTION(AInventory, CallStateChain) DEFINE_ACTION_FUNCTION(ACustomInventory, CallStateChain)
{ {
PARAM_SELF_PROLOGUE(AInventory); PARAM_SELF_PROLOGUE(AStateProvider);
PARAM_OBJECT(affectee, AActor); PARAM_OBJECT(affectee, AActor);
PARAM_STATE(state); PARAM_STATE(state);
ACTION_RETURN_BOOL(self->CallStateChain(affectee, state)); ACTION_RETURN_BOOL(self->CallStateChain(affectee, state));

View file

@ -52,6 +52,7 @@
#include "p_checkposition.h" #include "p_checkposition.h"
#include "math/cmath.h" #include "math/cmath.h"
#include "g_levellocals.h" #include "g_levellocals.h"
#include "virtual.h"
#include "gi.h" #include "gi.h"
@ -3312,11 +3313,19 @@ AInventory *P_DropItem (AActor *source, PClassActor *type, int dropamount, int c
AInventory *inv = static_cast<AInventory *>(mo); AInventory *inv = static_cast<AInventory *>(mo);
ModifyDropAmount(inv, dropamount); ModifyDropAmount(inv, dropamount);
inv->ItemFlags |= IF_TOSSED; inv->ItemFlags |= IF_TOSSED;
if (inv->CallSpecialDropAction (source))
IFVIRTUALPTR(inv, AInventory, SpecialDropAction)
{ {
// The special action indicates that the item should not spawn VMValue params[2] = { inv, source };
inv->Destroy(); int retval;
return NULL; VMReturn ret(&retval);
GlobalVMStack.Call(func, params, 2, &ret, 1, nullptr);
if (retval)
{
// The special action indicates that the item should not spawn
inv->Destroy();
return NULL;
}
} }
return inv; return inv;
} }

View file

@ -48,8 +48,6 @@ struct FLinePortal;
#define STEEPSLOPE (46342/65536.) // [RH] Minimum floorplane.c value for walking #define STEEPSLOPE (46342/65536.) // [RH] Minimum floorplane.c value for walking
#define BONUSADD 6
// Inspired by Maes // Inspired by Maes
extern int bmapnegx; extern int bmapnegx;
extern int bmapnegy; extern int bmapnegy;

View file

@ -1038,12 +1038,14 @@ DEFINE_ACTION_FUNCTION(AActor, UseInventory)
AInventory *AActor::DropInventory (AInventory *item) AInventory *AActor::DropInventory (AInventory *item)
{ {
AInventory *drop = item->CreateTossable (); AInventory *drop = nullptr;
IFVIRTUALPTR(item, AInventory, CreateTossable)
if (drop == NULL)
{ {
return NULL; VMValue params[1] = { (DObject*)this };
VMReturn ret((void**)&drop);
GlobalVMStack.Call(func, params, 1, &ret, 1, nullptr);
} }
if (drop == nullptr) return NULL;
drop->SetOrigin(PosPlusZ(10.), false); drop->SetOrigin(PosPlusZ(10.), false);
drop->Angles.Yaw = Angles.Yaw; drop->Angles.Yaw = Angles.Yaw;
drop->VelFromAngle(5.); drop->VelFromAngle(5.);
@ -3945,7 +3947,11 @@ void AActor::Tick ()
// by the order in the inventory, not the order in the thinker table // by the order in the inventory, not the order in the thinker table
while (item != NULL && item->Owner == this) while (item != NULL && item->Owner == this)
{ {
item->DoEffect(); IFVIRTUALPTR(item, AInventory, DoEffect)
{
VMValue params[1] = { item };
GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr);
}
item = item->Inventory; item = item->Inventory;
} }
@ -7592,10 +7598,13 @@ int AActor::GetModifiedDamage(FName damagetype, int damage, bool passive)
auto inv = Inventory; auto inv = Inventory;
while (inv != nullptr) while (inv != nullptr)
{ {
inv->ModifyDamage(damage, damagetype, damage, passive); IFVIRTUALPTR(inv, AInventory, ModifyDamage)
{
VMValue params[5] = { (DObject*)inv, damage, int(damagetype), &damage, passive };
GlobalVMStack.Call(func, params, 5, nullptr, 0, nullptr);
}
inv = inv->Inventory; inv = inv->Inventory;
} }
return damage; return damage;
} }

View file

@ -584,7 +584,7 @@ static void ParseInsideDecoration (Baggage &bag, AActor *defaults,
else if (def == DEF_Pickup && sc.Compare ("PickupMessage")) else if (def == DEF_Pickup && sc.Compare ("PickupMessage"))
{ {
sc.MustGetString (); sc.MustGetString ();
static_cast<PClassInventory *>(bag.Info)->PickupMessage = sc.String; static_cast<PClassInventory *>(bag.Info)->PickupMsg = sc.String;
} }
else if (def == DEF_Pickup && sc.Compare ("Respawns")) else if (def == DEF_Pickup && sc.Compare ("Respawns"))
{ {

View file

@ -1802,7 +1802,7 @@ DEFINE_CLASS_PROPERTY(pickupmessage, T, Inventory)
{ {
PROP_STRING_PARM(str, 0); PROP_STRING_PARM(str, 0);
assert(info->IsKindOf(RUNTIME_CLASS(PClassInventory))); assert(info->IsKindOf(RUNTIME_CLASS(PClassInventory)));
static_cast<PClassInventory *>(info)->PickupMessage = str; static_cast<PClassInventory *>(info)->PickupMsg = str;
} }
//========================================================================== //==========================================================================

View file

@ -8,6 +8,7 @@ struct VisStyle
class Inventory : Actor native class Inventory : Actor native
{ {
const BLINKTHRESHOLD = (4*32); const BLINKTHRESHOLD = (4*32);
const BONUSADD = 6;
native Actor Owner; // Who owns self item? NULL if it's still a pickup. 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 Amount; // Amount of item self instance has
@ -22,6 +23,7 @@ class Inventory : Actor native
native bool bPickupGood; native bool bPickupGood;
native bool bCreateCopyMoved; native bool bCreateCopyMoved;
native bool bInitEffectFailed; native bool bInitEffectFailed;
native meta String PickupMsg;
Default Default
{ {
@ -34,12 +36,8 @@ class Inventory : Actor native
} }
virtual native color GetBlend (); virtual native color GetBlend ();
virtual native bool HandlePickup(Inventory item);
virtual native Inventory CreateCopy(Actor other);
virtual native bool SpecialDropAction (Actor dropper);
virtual native String PickupMessage();
virtual native bool ShouldStay();
virtual native void PlayPickupSound(Actor user); virtual native void PlayPickupSound(Actor user);
virtual native void DoPickupSpecial (Actor toucher);
native bool DoRespawn(); native bool DoRespawn();
native bool GoAway(); native bool GoAway();
@ -50,7 +48,7 @@ class Inventory : Actor native
// In this case the caller function is more than a simple wrapper around the virtual method and // 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. // is what must be actually called to pick up an item.
native bool, Actor CallTryPickup(Actor toucher); native bool, Actor CallTryPickup(Actor toucher);
native bool CallStateChain (Actor actor, State state); native static void PrintPickupMessage (bool localview, String str);
States(Actor, Overlay, Weapon, Item) States(Actor, Overlay, Weapon, Item)
{ {
@ -74,8 +72,18 @@ class Inventory : Actor native
Stop; Stop;
} }
// These are regular functions for the item itself. //===========================================================================
//
// AInventory :: BeginPlay
//
//===========================================================================
override void BeginPlay ()
{
Super.BeginPlay ();
bDropped = true; // [RH] Items are dropped by default
}
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// //
// PROC A_RestoreSpecialThing1 // PROC A_RestoreSpecialThing1
@ -132,6 +140,69 @@ class Inventory : Actor native
} }
//===========================================================================
//
// AInventory :: CreateCopy
//
// Returns an actor suitable for placing in an inventory, either itself or
// a copy based on whether it needs to respawn or not. Returning NULL
// indicates the item should not be picked up.
//
//===========================================================================
virtual Inventory CreateCopy (Actor other)
{
Inventory copy;
Amount = MIN(Amount, MaxAmount);
if (GoAway ())
{
copy = Inventory(Spawn (GetClass()));
copy.Amount = Amount;
copy.MaxAmount = MaxAmount;
}
else
{
copy = self;
}
return copy;
}
//===========================================================================
//
// AInventory :: HandlePickup
//
// Returns true if the pickup was handled (or should not happen at all),
// false if not.
//
//===========================================================================
virtual bool HandlePickup (Inventory item)
{
if (item.GetClass() == GetClass())
{
if (Amount < MaxAmount || (sv_unlimited_pickup && !item.ShouldStay()))
{
if (Amount > 0 && Amount + item.Amount < 0)
{
Amount = 0x7fffffff;
}
else
{
Amount += item.Amount;
}
if (Amount > MaxAmount && !sv_unlimited_pickup)
{
Amount = MaxAmount;
}
item.bPickupGood = true;
}
return true;
}
return false;
}
//=========================================================================== //===========================================================================
// //
// AInventory :: CallHandlePickup // AInventory :: CallHandlePickup
@ -236,6 +307,19 @@ class Inventory : Actor native
return true; return true;
} }
//===========================================================================
//
// AInventory :: ShouldStay
//
// Returns true if the item should not disappear, even temporarily.
//
//===========================================================================
virtual bool ShouldStay ()
{
return false;
}
//=========================================================================== //===========================================================================
// //
// AInventory :: TryPickupRestricted // AInventory :: TryPickupRestricted
@ -313,6 +397,97 @@ class Inventory : Actor native
return copy; return copy;
} }
//===========================================================================
//
// AInventory :: PickupMessage
//
// Returns the message to print when this actor is picked up.
//
//===========================================================================
virtual String PickupMessage ()
{
return PickupMsg;
}
//===========================================================================
//
// AInventory :: Touch
//
// Handles collisions from another actor, possible adding itself to the
// collider's inventory.
//
//===========================================================================
override void Touch (Actor toucher)
{
let player = toucher.player;
// If a voodoo doll touches something, pretend the real player touched it instead.
if (player != NULL)
{
toucher = player.mo;
}
bool localview = toucher.CheckLocalView(consoleplayer);
bool res;
[res, toucher] = CallTryPickup(toucher);
if (!res) return;
// This is the only situation when a pickup flash should ever play.
if (PickupFlash != NULL && !ShouldStay())
{
Spawn(PickupFlash, Pos, ALLOW_REPLACE);
}
if (!bQuiet)
{
PrintPickupMessage(localview, PickupMessage ());
// Special check so voodoo dolls picking up items cause the
// real player to make noise.
if (player != NULL)
{
PlayPickupSound (player.mo);
if (!bNoScreenFlash)
{
player.bonuscount = BONUSADD;
}
}
else
{
PlayPickupSound (toucher);
}
}
// [RH] Execute an attached special (if any)
DoPickupSpecial (toucher);
if (bCountItem)
{
if (player != NULL)
{
player.itemcount++;
}
level.found_items++;
}
if (bCountSecret)
{
Actor ac = player != NULL? Actor(player.mo) : toucher;
ac.GiveSecret(true, true);
}
//Added by MC: Check if item taken was the roam destination of any bot
for (int i = 0; i < MAXPLAYERS; i++)
{
if (players[i].Bot != NULL && self == players[i].Bot.dest)
players[i].Bot.dest = NULL;
}
}
//=========================================================================== //===========================================================================
// //
// AInventory :: DepleteOrDestroy // AInventory :: DepleteOrDestroy
@ -361,11 +536,27 @@ class Inventory : Actor native
virtual void DoEffect() {} virtual void DoEffect() {}
//===========================================================================
//
// AInventory :: ModifyDamage
//
// Allows inventory items to manipulate the amount of damage
// inflicted. Damage is the amount of damage that would be done without manipulation,
// and newdamage is the amount that should be done after the item has changed
// it.
// 'active' means it is called by the inflictor, 'passive' by the target.
// It may seem that this is redundant and AbsorbDamage is the same. However,
// AbsorbDamage is called only for players and also depends on other settings
// which are undesirable for a protection artifact.
//
//===========================================================================
virtual void ModifyDamage(int damage, Name damageType, out int newdamage, bool passive) {}
virtual bool Use (bool pickup) { return false; } virtual bool Use (bool pickup) { return false; }
virtual double GetSpeedFactor() { return 1; } virtual double GetSpeedFactor() { return 1; }
virtual bool GetNoTeleportFreeze() { return false; } 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 AlterWeaponSprite(VisStyle vis, in out int changed) {}
virtual void OwnerDied() {} virtual void OwnerDied() {}
@ -393,6 +584,22 @@ class Inventory : Actor native
virtual void AbsorbDamage (int damage, Name damageType, out int newdamage) {} virtual void AbsorbDamage (int damage, Name damageType, out int newdamage) {}
//===========================================================================
//
// AInventory :: SpecialDropAction
//
// Called by P_DropItem. Return true to prevent the standard drop tossing.
// A few Strife items that are meant to trigger actions rather than be
// picked up use this. Normal items shouldn't need it.
//
//===========================================================================
virtual bool SpecialDropAction (Actor dropper)
{
return false;
}
} }
class DehackedPickup : Inventory native class DehackedPickup : Inventory native

View file

@ -13,7 +13,7 @@ class StateProvider : Inventory native
action native void A_ResetReloadCounter(); action native void A_ResetReloadCounter();
} }
class CustomInventory : StateProvider native class CustomInventory : StateProvider
{ {
Default Default
{ {
@ -36,7 +36,8 @@ class CustomInventory : StateProvider native
deprecated action void A_Lower() {} deprecated action void A_Lower() {}
deprecated action void A_Raise() {} deprecated action void A_Raise() {}
deprecated action void A_CheckReload() {} deprecated action void A_CheckReload() {}
native bool CallStateChain (Actor actor, State state);
//=========================================================================== //===========================================================================
// //
// ACustomInventory :: SpecialDropAction // ACustomInventory :: SpecialDropAction

View file

@ -24,6 +24,7 @@ class CajunTrace : Actor
} }
} }
struct Bot native class Bot native
{ {
native Actor dest;
} }