mirror of
https://github.com/ZDoom/qzdoom-gpl.git
synced 2025-02-22 11:11:25 +00:00
- scriptified the backpack.
- added GetParentClass builtin to compiler.
This commit is contained in:
parent
1f4342b48e
commit
4759f9a399
9 changed files with 246 additions and 192 deletions
|
@ -2637,7 +2637,7 @@ void FParser::SF_MaxPlayerAmmo()
|
||||||
|
|
||||||
for (AInventory *item = players[playernum].mo->Inventory; item != NULL; item = item->Inventory)
|
for (AInventory *item = players[playernum].mo->Inventory; item != NULL; item = item->Inventory)
|
||||||
{
|
{
|
||||||
if (item->IsKindOf(RUNTIME_CLASS(ABackpackItem)))
|
if (item->IsKindOf(PClass::FindClass(NAME_BackpackItem)))
|
||||||
{
|
{
|
||||||
if (t_argc>=4) amount = intvalue(t_argv[3]);
|
if (t_argc>=4) amount = intvalue(t_argv[3]);
|
||||||
else amount*=2;
|
else amount*=2;
|
||||||
|
|
|
@ -89,173 +89,3 @@ DEFINE_ACTION_FUNCTION(AAmmo, GetParentAmmo)
|
||||||
PARAM_SELF_PROLOGUE(AAmmo);
|
PARAM_SELF_PROLOGUE(AAmmo);
|
||||||
ACTION_RETURN_OBJECT(self->GetParentAmmo());
|
ACTION_RETURN_OBJECT(self->GetParentAmmo());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Backpack -----------------------------------------------------------------
|
|
||||||
|
|
||||||
IMPLEMENT_CLASS(ABackpackItem, false, false)
|
|
||||||
|
|
||||||
DEFINE_FIELD(ABackpackItem, bDepleted)
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// ABackpackItem :: Serialize
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
void ABackpackItem::Serialize(FSerializer &arc)
|
|
||||||
{
|
|
||||||
Super::Serialize (arc);
|
|
||||||
auto def = (ABackpackItem*)GetDefault();
|
|
||||||
arc("bdepleted", bDepleted, def->bDepleted);
|
|
||||||
}
|
|
||||||
|
|
||||||
EXTERN_CVAR(Bool, sv_unlimited_pickup)
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// ABackpackItem :: CreateCopy
|
|
||||||
//
|
|
||||||
// A backpack is being added to a player who doesn't yet have one. Give them
|
|
||||||
// every kind of ammo, and increase their max amounts.
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
AInventory *ABackpackItem::CreateCopy (AActor *other)
|
|
||||||
{
|
|
||||||
// Find every unique type of ammo. Give it to the player if
|
|
||||||
// he doesn't have it already, and double its maximum capacity.
|
|
||||||
for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
|
|
||||||
{
|
|
||||||
PClass *type = PClassActor::AllActorClasses[i];
|
|
||||||
|
|
||||||
if (type->ParentClass == RUNTIME_CLASS(AAmmo))
|
|
||||||
{
|
|
||||||
PClassActor *atype = static_cast<PClassActor *>(type);
|
|
||||||
AAmmo *ammo = static_cast<AAmmo *>(other->FindInventory(atype));
|
|
||||||
int amount = static_cast<AAmmo *>(GetDefaultByType(type))->BackpackAmount;
|
|
||||||
// extra ammo in baby mode and nightmare mode
|
|
||||||
if (!(ItemFlags&IF_IGNORESKILL))
|
|
||||||
{
|
|
||||||
amount = int(amount * G_SkillProperty(SKILLP_AmmoFactor));
|
|
||||||
}
|
|
||||||
if (amount < 0) amount = 0;
|
|
||||||
if (ammo == NULL)
|
|
||||||
{ // The player did not have the ammo. Add it.
|
|
||||||
ammo = static_cast<AAmmo *>(Spawn(atype));
|
|
||||||
ammo->Amount = bDepleted ? 0 : amount;
|
|
||||||
if (ammo->BackpackMaxAmount > ammo->MaxAmount)
|
|
||||||
{
|
|
||||||
ammo->MaxAmount = ammo->BackpackMaxAmount;
|
|
||||||
}
|
|
||||||
if (ammo->Amount > ammo->MaxAmount)
|
|
||||||
{
|
|
||||||
ammo->Amount = ammo->MaxAmount;
|
|
||||||
}
|
|
||||||
ammo->AttachToOwner (other);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ // The player had the ammo. Give some more.
|
|
||||||
if (ammo->MaxAmount < ammo->BackpackMaxAmount)
|
|
||||||
{
|
|
||||||
ammo->MaxAmount = ammo->BackpackMaxAmount;
|
|
||||||
}
|
|
||||||
if (!bDepleted && ammo->Amount < ammo->MaxAmount)
|
|
||||||
{
|
|
||||||
ammo->Amount += amount;
|
|
||||||
if (ammo->Amount > ammo->MaxAmount)
|
|
||||||
{
|
|
||||||
ammo->Amount = ammo->MaxAmount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Super::CreateCopy (other);
|
|
||||||
}
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// ABackpackItem :: HandlePickup
|
|
||||||
//
|
|
||||||
// When the player picks up another backpack, just give them more ammo.
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
bool ABackpackItem::HandlePickup (AInventory *item)
|
|
||||||
{
|
|
||||||
// Since you already have a backpack, that means you already have every
|
|
||||||
// kind of ammo in your inventory, so we don't need to look at the
|
|
||||||
// entire PClass list to discover what kinds of ammo exist, and we don't
|
|
||||||
// have to alter the MaxAmount either.
|
|
||||||
if (item->IsKindOf (RUNTIME_CLASS(ABackpackItem)))
|
|
||||||
{
|
|
||||||
for (AInventory *probe = Owner->Inventory; probe != NULL; probe = probe->Inventory)
|
|
||||||
{
|
|
||||||
if (probe->GetClass()->ParentClass == RUNTIME_CLASS(AAmmo))
|
|
||||||
{
|
|
||||||
if (probe->Amount < probe->MaxAmount || sv_unlimited_pickup)
|
|
||||||
{
|
|
||||||
int amount = static_cast<AAmmo*>(probe->GetDefault())->BackpackAmount;
|
|
||||||
// extra ammo in baby mode and nightmare mode
|
|
||||||
if (!(item->ItemFlags&IF_IGNORESKILL))
|
|
||||||
{
|
|
||||||
amount = int(amount * G_SkillProperty(SKILLP_AmmoFactor));
|
|
||||||
}
|
|
||||||
probe->Amount += amount;
|
|
||||||
if (probe->Amount > probe->MaxAmount && !sv_unlimited_pickup)
|
|
||||||
{
|
|
||||||
probe->Amount = probe->MaxAmount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// The pickup always succeeds, even if you didn't get anything
|
|
||||||
item->ItemFlags |= IF_PICKUPGOOD;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// ABackpackItem :: CreateTossable
|
|
||||||
//
|
|
||||||
// The tossed backpack must not give out any more ammo, otherwise a player
|
|
||||||
// could cheat by dropping their backpack and picking it up for more ammo.
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
AInventory *ABackpackItem::CreateTossable ()
|
|
||||||
{
|
|
||||||
ABackpackItem *pack = static_cast<ABackpackItem *>(Super::CreateTossable());
|
|
||||||
if (pack != NULL)
|
|
||||||
{
|
|
||||||
pack->bDepleted = true;
|
|
||||||
}
|
|
||||||
return pack;
|
|
||||||
}
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// ABackpackItem :: DetachFromOwner
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
void ABackpackItem::DetachFromOwner ()
|
|
||||||
{
|
|
||||||
// When removing a backpack, drop the player's ammo maximums to normal
|
|
||||||
AInventory *item;
|
|
||||||
|
|
||||||
for (item = Owner->Inventory; item != NULL; item = item->Inventory)
|
|
||||||
{
|
|
||||||
if (item->GetClass()->ParentClass == RUNTIME_CLASS(AAmmo) &&
|
|
||||||
item->MaxAmount == static_cast<AAmmo*>(item)->BackpackMaxAmount)
|
|
||||||
{
|
|
||||||
item->MaxAmount = static_cast<AInventory*>(item->GetDefault())->MaxAmount;
|
|
||||||
if (item->Amount > item->MaxAmount)
|
|
||||||
{
|
|
||||||
item->Amount = item->MaxAmount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -12,21 +12,3 @@ public:
|
||||||
int BackpackAmount, BackpackMaxAmount, DropAmount;
|
int BackpackAmount, BackpackMaxAmount, DropAmount;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// A backpack gives you one clip of each ammo and doubles your
|
|
||||||
// normal maximum ammo amounts.
|
|
||||||
class ABackpackItem : public AInventory
|
|
||||||
{
|
|
||||||
DECLARE_CLASS (ABackpackItem, AInventory)
|
|
||||||
public:
|
|
||||||
|
|
||||||
virtual void Serialize(FSerializer &arc) override;
|
|
||||||
virtual bool HandlePickup (AInventory *item) override;
|
|
||||||
virtual AInventory *CreateCopy (AActor *other) override;
|
|
||||||
virtual AInventory *CreateTossable () override;
|
|
||||||
virtual void DetachFromOwner () override;
|
|
||||||
|
|
||||||
bool bDepleted;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -859,7 +859,7 @@ void cht_Take (player_t *player, const char *name, int amount)
|
||||||
{
|
{
|
||||||
PClass *type = PClassActor::AllActorClasses[i];
|
PClass *type = PClassActor::AllActorClasses[i];
|
||||||
|
|
||||||
if (type->IsDescendantOf(RUNTIME_CLASS (ABackpackItem)))
|
if (type->IsDescendantOf(PClass::FindClass(NAME_BackpackItem)))
|
||||||
{
|
{
|
||||||
AInventory *pack = player->mo->FindInventory(static_cast<PClassActor *>(type));
|
AInventory *pack = player->mo->FindInventory(static_cast<PClassActor *>(type));
|
||||||
|
|
||||||
|
|
|
@ -165,6 +165,7 @@ xx(FlameThrower)
|
||||||
xx(MiniMissileLauncher)
|
xx(MiniMissileLauncher)
|
||||||
xx(StrifeGrenadeLauncher)
|
xx(StrifeGrenadeLauncher)
|
||||||
xx(Mauler)
|
xx(Mauler)
|
||||||
|
xx(BackpackItem)
|
||||||
|
|
||||||
xx(AcolyteBlue)
|
xx(AcolyteBlue)
|
||||||
xx(SpectralLightningV1)
|
xx(SpectralLightningV1)
|
||||||
|
@ -292,6 +293,7 @@ xx(Random2)
|
||||||
xx(RandomPick)
|
xx(RandomPick)
|
||||||
xx(FRandomPick)
|
xx(FRandomPick)
|
||||||
xx(GetClass)
|
xx(GetClass)
|
||||||
|
xx(GetParentClass)
|
||||||
xx(GetDefaultByType)
|
xx(GetDefaultByType)
|
||||||
xx(Exp)
|
xx(Exp)
|
||||||
xx(Log10)
|
xx(Log10)
|
||||||
|
|
|
@ -7265,6 +7265,13 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case NAME_GetParentClass:
|
||||||
|
if (CheckArgSize(NAME_GetParentClass, ArgList, 0, 0, ScriptPosition))
|
||||||
|
{
|
||||||
|
func = new FxGetParentClass(new FxSelf(ScriptPosition));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case NAME_GetDefaultByType:
|
case NAME_GetDefaultByType:
|
||||||
if (CheckArgSize(NAME_GetDefaultByType, ArgList, 1, 1, ScriptPosition))
|
if (CheckArgSize(NAME_GetDefaultByType, ArgList, 1, 1, ScriptPosition))
|
||||||
{
|
{
|
||||||
|
@ -7575,6 +7582,20 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (MethodName == NAME_GetParentClass &&
|
||||||
|
(Self->IsObject() || Self->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer))))
|
||||||
|
{
|
||||||
|
if (ArgList.Size() > 0)
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "too many parameters in call to %s", MethodName.GetChars());
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
auto x = new FxGetParentClass(Self);
|
||||||
|
return x->Resolve(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
if (Self->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)))
|
if (Self->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)))
|
||||||
{
|
{
|
||||||
auto ptype = static_cast<PPointer *>(Self->ValueType)->PointedType;
|
auto ptype = static_cast<PPointer *>(Self->ValueType)->PointedType;
|
||||||
|
@ -7591,6 +7612,8 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
||||||
auto x = new FxGetClass(Self);
|
auto x = new FxGetClass(Self);
|
||||||
return x->Resolve(ctx);
|
return x->Resolve(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
cls = static_cast<PStruct *>(ptype);
|
cls = static_cast<PStruct *>(ptype);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -8750,6 +8773,52 @@ ExpEmit FxGetClass::Emit(VMFunctionBuilder *build)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
|
FxGetParentClass::FxGetParentClass(FxExpression *self)
|
||||||
|
:FxExpression(EFX_GetClass, self->ScriptPosition)
|
||||||
|
{
|
||||||
|
Self = self;
|
||||||
|
}
|
||||||
|
|
||||||
|
FxGetParentClass::~FxGetParentClass()
|
||||||
|
{
|
||||||
|
SAFE_DELETE(Self);
|
||||||
|
}
|
||||||
|
|
||||||
|
FxExpression *FxGetParentClass::Resolve(FCompileContext &ctx)
|
||||||
|
{
|
||||||
|
SAFE_RESOLVE(Self, ctx);
|
||||||
|
|
||||||
|
if (!Self->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer)) && !Self->IsObject())
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "GetClass() requires an object");
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
ValueType = NewClassPointer(RUNTIME_CLASS(DObject)); //
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpEmit FxGetParentClass::Emit(VMFunctionBuilder *build)
|
||||||
|
{
|
||||||
|
ExpEmit op = Self->Emit(build);
|
||||||
|
op.Free(build);
|
||||||
|
if (Self->IsObject())
|
||||||
|
{
|
||||||
|
ExpEmit to(build, REGT_POINTER);
|
||||||
|
build->Emit(OP_META, to.RegNum, op.RegNum);
|
||||||
|
op = to;
|
||||||
|
op.Free(build);
|
||||||
|
}
|
||||||
|
ExpEmit to(build, REGT_POINTER);
|
||||||
|
build->Emit(OP_LO, to.RegNum, op.RegNum, build->GetConstantInt(myoffsetof(PClass, ParentClass)));
|
||||||
|
return to;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
FxGetDefaultByType::FxGetDefaultByType(FxExpression *self)
|
FxGetDefaultByType::FxGetDefaultByType(FxExpression *self)
|
||||||
:FxExpression(EFX_GetDefaultByType, self->ScriptPosition)
|
:FxExpression(EFX_GetDefaultByType, self->ScriptPosition)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1589,6 +1589,24 @@ public:
|
||||||
ExpEmit Emit(VMFunctionBuilder *build);
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FxGetClass
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
class FxGetParentClass : public FxExpression
|
||||||
|
{
|
||||||
|
FxExpression *Self;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
FxGetParentClass(FxExpression *self);
|
||||||
|
~FxGetParentClass();
|
||||||
|
FxExpression *Resolve(FCompileContext&);
|
||||||
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
|
};
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// FxGetDefaultByType
|
// FxGetDefaultByType
|
||||||
|
|
|
@ -772,6 +772,11 @@ void InitThingdef()
|
||||||
lstruct->AddNativeField("vertexes", NewPointer(NewResizableArray(vertstruct), false), myoffsetof(FLevelLocals, vertexes), VARF_Native|VARF_ReadOnly);
|
lstruct->AddNativeField("vertexes", NewPointer(NewResizableArray(vertstruct), false), myoffsetof(FLevelLocals, vertexes), VARF_Native|VARF_ReadOnly);
|
||||||
lstruct->AddNativeField("sectorportals", NewPointer(NewResizableArray(sectorportalstruct), false), myoffsetof(FLevelLocals, sectorPortals), VARF_Native);
|
lstruct->AddNativeField("sectorportals", NewPointer(NewResizableArray(sectorportalstruct), false), myoffsetof(FLevelLocals, sectorPortals), VARF_Native);
|
||||||
|
|
||||||
|
|
||||||
|
auto aact = NewPointer(NewResizableArray(NewClassPointer(RUNTIME_CLASS(AActor))), true);
|
||||||
|
PField *aacf = new PField("AllActorClasses", aact, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&PClassActor::AllActorClasses);
|
||||||
|
GlobalSymbols.AddSymbol(aacf);
|
||||||
|
|
||||||
// set up a variable for the DEH data
|
// set up a variable for the DEH data
|
||||||
PStruct *dstruct = NewNativeStruct("DehInfo", nullptr);
|
PStruct *dstruct = NewNativeStruct("DehInfo", nullptr);
|
||||||
PField *dehf = new PField("deh", dstruct, VARF_Native | VARF_Static, (intptr_t)&deh);
|
PField *dehf = new PField("deh", dstruct, VARF_Native | VARF_Static, (intptr_t)&deh);
|
||||||
|
|
|
@ -122,8 +122,156 @@ class Ammo : Inventory native
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class BackpackItem : Inventory native
|
class BackpackItem : Inventory
|
||||||
{
|
{
|
||||||
native bool bDepleted;
|
bool bDepleted;
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// ABackpackItem :: CreateCopy
|
||||||
|
//
|
||||||
|
// A backpack is being added to a player who doesn't yet have one. Give them
|
||||||
|
// every kind of ammo, and increase their max amounts.
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
override Inventory CreateCopy (Actor other)
|
||||||
|
{
|
||||||
|
// Find every unique type of ammoitem. Give it to the player if
|
||||||
|
// he doesn't have it already, and double its maximum capacity.
|
||||||
|
uint end = AllActorClasses.Size();
|
||||||
|
for (uint i = 0; i < end; ++i)
|
||||||
|
{
|
||||||
|
let type = AllActorClasses[i];
|
||||||
|
|
||||||
|
if (type.GetParentClass() == 'Ammo')
|
||||||
|
{
|
||||||
|
let ammotype = (class<Ammo>)(type);
|
||||||
|
let ammoitem = Ammo(other.FindInventory(ammotype));
|
||||||
|
int amount = GetDefaultByType(ammotype).BackpackAmount;
|
||||||
|
// extra ammo in baby mode and nightmare mode
|
||||||
|
if (!bIgnoreSkill)
|
||||||
|
{
|
||||||
|
amount = int(amount * G_SkillPropertyFloat(SKILLP_AmmoFactor));
|
||||||
|
}
|
||||||
|
if (amount < 0) amount = 0;
|
||||||
|
if (ammoitem == NULL)
|
||||||
|
{ // The player did not have the ammoitem. Add it.
|
||||||
|
ammoitem = Ammo(Spawn(ammotype));
|
||||||
|
ammoitem.Amount = bDepleted ? 0 : amount;
|
||||||
|
if (ammoitem.BackpackMaxAmount > ammoitem.MaxAmount)
|
||||||
|
{
|
||||||
|
ammoitem.MaxAmount = ammoitem.BackpackMaxAmount;
|
||||||
|
}
|
||||||
|
if (ammoitem.Amount > ammoitem.MaxAmount)
|
||||||
|
{
|
||||||
|
ammoitem.Amount = ammoitem.MaxAmount;
|
||||||
|
}
|
||||||
|
ammoitem.AttachToOwner (other);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // The player had the ammoitem. Give some more.
|
||||||
|
if (ammoitem.MaxAmount < ammoitem.BackpackMaxAmount)
|
||||||
|
{
|
||||||
|
ammoitem.MaxAmount = ammoitem.BackpackMaxAmount;
|
||||||
|
}
|
||||||
|
if (!bDepleted && ammoitem.Amount < ammoitem.MaxAmount)
|
||||||
|
{
|
||||||
|
ammoitem.Amount += amount;
|
||||||
|
if (ammoitem.Amount > ammoitem.MaxAmount)
|
||||||
|
{
|
||||||
|
ammoitem.Amount = ammoitem.MaxAmount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Super.CreateCopy (other);
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// ABackpackItem :: HandlePickup
|
||||||
|
//
|
||||||
|
// When the player picks up another backpack, just give them more ammoitem.
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
override bool HandlePickup (Inventory item)
|
||||||
|
{
|
||||||
|
// Since you already have a backpack, that means you already have every
|
||||||
|
// kind of ammo in your inventory, so we don't need to look at the
|
||||||
|
// entire PClass list to discover what kinds of ammo exist, and we don't
|
||||||
|
// have to alter the MaxAmount either.
|
||||||
|
if (item is 'BackpackItem')
|
||||||
|
{
|
||||||
|
for (let probe = Owner.Inv; probe != NULL; probe = probe.Inv)
|
||||||
|
{
|
||||||
|
if (probe.GetParentClass() == 'Ammo')
|
||||||
|
{
|
||||||
|
if (probe.Amount < probe.MaxAmount || sv_unlimited_pickup)
|
||||||
|
{
|
||||||
|
int amount = Ammo(probe).Default.BackpackAmount;
|
||||||
|
// extra ammo in baby mode and nightmare mode
|
||||||
|
if (!bIgnoreSkill)
|
||||||
|
{
|
||||||
|
amount = int(amount * G_SkillPropertyFloat(SKILLP_AmmoFactor));
|
||||||
|
}
|
||||||
|
probe.Amount += amount;
|
||||||
|
if (probe.Amount > probe.MaxAmount && !sv_unlimited_pickup)
|
||||||
|
{
|
||||||
|
probe.Amount = probe.MaxAmount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// The pickup always succeeds, even if you didn't get anything
|
||||||
|
item.bPickupGood = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// ABackpackItem :: CreateTossable
|
||||||
|
//
|
||||||
|
// The tossed backpack must not give out any more ammo, otherwise a player
|
||||||
|
// could cheat by dropping their backpack and picking it up for more ammoitem.
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
override Inventory CreateTossable ()
|
||||||
|
{
|
||||||
|
let pack = BackpackItem(Super.CreateTossable());
|
||||||
|
if (pack != NULL)
|
||||||
|
{
|
||||||
|
pack.bDepleted = true;
|
||||||
|
}
|
||||||
|
return pack;
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// ABackpackItem :: DetachFromOwner
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
override void DetachFromOwner ()
|
||||||
|
{
|
||||||
|
// When removing a backpack, drop the player's ammo maximums to normal
|
||||||
|
|
||||||
|
for (let item = Owner.Inv; item != NULL; item = item.Inv)
|
||||||
|
{
|
||||||
|
if (item is 'Ammo' && item.MaxAmount == Ammo(item).BackpackMaxAmount)
|
||||||
|
{
|
||||||
|
item.MaxAmount = item.Default.MaxAmount;
|
||||||
|
if (item.Amount > item.MaxAmount)
|
||||||
|
{
|
||||||
|
item.Amount = item.MaxAmount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue