- scriptified BasicArmorBonus.

This commit is contained in:
Christoph Oelckers 2017-01-18 20:23:13 +01:00
parent 87b9b6111d
commit 2dd6fb9595
13 changed files with 180 additions and 265 deletions

View file

@ -1963,11 +1963,10 @@ static int PatchMisc (int dummy)
armor->SavePercent = deh.BlueAC == 1 ? 0.33335 : 0.5;
}
ABasicArmorBonus *barmor;
barmor = static_cast<ABasicArmorBonus *> (GetDefaultByName ("ArmorBonus"));
auto barmor = GetDefaultByName ("ArmorBonus");
if (barmor!=NULL)
{
barmor->MaxSaveAmount = deh.MaxArmor;
barmor->IntVar("MaxSaveAmount") = deh.MaxArmor;
}
AInventory *health;

View file

@ -177,11 +177,6 @@ public:
};
class APlayerChunk : public APlayerPawn
{
DECLARE_CLASS (APlayerChunk, APlayerPawn)
};
//
// PlayerPawn flags
//

View file

@ -48,7 +48,6 @@
IMPLEMENT_CLASS(AArmor, false, false)
IMPLEMENT_CLASS(ABasicArmor, false, false)
IMPLEMENT_CLASS(ABasicArmorPickup, false, false)
IMPLEMENT_CLASS(ABasicArmorBonus, false, false)
IMPLEMENT_CLASS(AHexenArmor, false, false)
//===========================================================================
@ -133,34 +132,6 @@ AInventory *ABasicArmor::CreateCopy (AActor *other)
return copy;
}
//===========================================================================
//
// ABasicArmor :: HandlePickup
//
//===========================================================================
bool ABasicArmor::HandlePickup (AInventory *item)
{
if (item->GetClass() == RUNTIME_CLASS(ABasicArmor))
{
// You shouldn't be picking up BasicArmor anyway.
return true;
}
if (item->IsKindOf(RUNTIME_CLASS(ABasicArmorBonus)) && !(item->ItemFlags & IF_IGNORESKILL))
{
ABasicArmorBonus *armor = static_cast<ABasicArmorBonus*>(item);
armor->SaveAmount = int(armor->SaveAmount * G_SkillProperty(SKILLP_ArmorFactor));
}
else if (item->IsKindOf(RUNTIME_CLASS(ABasicArmorPickup)) && !(item->ItemFlags & IF_IGNORESKILL))
{
ABasicArmorPickup *armor = static_cast<ABasicArmorPickup*>(item);
armor->SaveAmount = int(armor->SaveAmount * G_SkillProperty(SKILLP_ArmorFactor));
}
return false;
}
//===========================================================================
//
// ABasicArmor :: AbsorbDamage
@ -205,7 +176,7 @@ void ABasicArmor::AbsorbDamage (int damage, FName damageType, int &newdamage)
AInventory *probe = Owner->Inventory;
while (probe != NULL)
{
if (probe->IsKindOf (RUNTIME_CLASS(ABasicArmorPickup)))
if (probe->IsKindOf (PClass::FindActor(NAME_BasicArmorPickup)))
{
ABasicArmorPickup *inInv = static_cast<ABasicArmorPickup*>(probe);
if (best == NULL || best->SavePercent < inInv->SavePercent)
@ -339,126 +310,6 @@ bool ABasicArmorPickup::Use (bool pickup)
return true;
}
//===========================================================================
//
//
// BasicArmorBonus
//
//
//===========================================================================
DEFINE_FIELD(ABasicArmorBonus, SavePercent)
DEFINE_FIELD(ABasicArmorBonus, MaxSaveAmount)
DEFINE_FIELD(ABasicArmorBonus, MaxAbsorb)
DEFINE_FIELD(ABasicArmorBonus, MaxFullAbsorb)
DEFINE_FIELD(ABasicArmorBonus, SaveAmount)
DEFINE_FIELD(ABasicArmorBonus, BonusCount)
DEFINE_FIELD(ABasicArmorBonus, BonusMax)
//===========================================================================
//
// ABasicArmorBonus :: Serialize
//
//===========================================================================
void ABasicArmorBonus::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
auto def = (ABasicArmorBonus *)GetDefault();
arc("savepercent", SavePercent, def->SavePercent)
("saveamount", SaveAmount, def->SaveAmount)
("maxsaveamount", MaxSaveAmount, def->MaxSaveAmount)
("bonuscount", BonusCount, def->BonusCount)
("bonusmax", BonusMax, def->BonusMax)
("maxabsorb", MaxAbsorb, def->MaxAbsorb)
("maxfullabsorb", MaxFullAbsorb, def->MaxFullAbsorb);
}
//===========================================================================
//
// ABasicArmorBonus :: CreateCopy
//
//===========================================================================
AInventory *ABasicArmorBonus::CreateCopy (AActor *other)
{
ABasicArmorBonus *copy = static_cast<ABasicArmorBonus *> (Super::CreateCopy (other));
if (!(ItemFlags & IF_IGNORESKILL))
{
SaveAmount = int(SaveAmount * G_SkillProperty(SKILLP_ArmorFactor));
}
copy->SavePercent = SavePercent;
copy->SaveAmount = SaveAmount;
copy->MaxSaveAmount = MaxSaveAmount;
copy->BonusCount = BonusCount;
copy->BonusMax = BonusMax;
copy->MaxAbsorb = MaxAbsorb;
copy->MaxFullAbsorb = MaxFullAbsorb;
return copy;
}
//===========================================================================
//
// ABasicArmorBonus :: Use
//
// Tries to add to the amount of BasicArmor a player has.
//
//===========================================================================
bool ABasicArmorBonus::Use (bool pickup)
{
ABasicArmor *armor = Owner->FindInventory<ABasicArmor> ();
bool result = false;
if (armor == NULL)
{
armor = Spawn<ABasicArmor> ();
armor->BecomeItem ();
armor->Amount = 0;
armor->MaxAmount = MaxSaveAmount;
Owner->AddInventory (armor);
}
if (BonusCount > 0 && armor->BonusCount < BonusMax)
{
armor->BonusCount = MIN (armor->BonusCount + BonusCount, BonusMax);
result = true;
}
int saveAmount = MIN (SaveAmount, MaxSaveAmount);
if (saveAmount <= 0)
{ // If it can't give you anything, it's as good as used.
return BonusCount > 0 ? result : true;
}
// If you already have more armor than this item can give you, you can't
// use it.
if (armor->Amount >= MaxSaveAmount + armor->BonusCount)
{
return result;
}
if (armor->Amount <= 0)
{ // Should never be less than 0, but might as well check anyway
armor->Amount = 0;
armor->Icon = Icon;
armor->SavePercent = SavePercent;
armor->MaxAbsorb = MaxAbsorb;
armor->ArmorType = this->GetClass()->TypeName;
armor->MaxFullAbsorb = MaxFullAbsorb;
armor->ActualSaveAmount = MaxSaveAmount;
}
armor->Amount = MIN(armor->Amount + saveAmount, MaxSaveAmount + armor->BonusCount);
armor->MaxAmount = MAX (armor->MaxAmount, MaxSaveAmount);
return true;
}
//===========================================================================
//
//

View file

@ -19,7 +19,6 @@ public:
virtual void Serialize(FSerializer &arc) override;
virtual void Tick () override;
virtual AInventory *CreateCopy (AActor *other) override;
virtual bool HandlePickup (AInventory *item) override;
virtual void AbsorbDamage (int damage, FName damageType, int &newdamage) override;
int AbsorbCount;
@ -47,25 +46,6 @@ public:
int SaveAmount;
};
// BasicArmorBonus adds to the armor you have.
class ABasicArmorBonus : public AArmor
{
DECLARE_CLASS (ABasicArmorBonus, AArmor)
public:
virtual void Serialize(FSerializer &arc) override;
virtual AInventory *CreateCopy (AActor *other) override;
virtual bool Use (bool pickup) override;
double SavePercent; // The default, for when you don't already have armor
int MaxSaveAmount;
int MaxAbsorb;
int MaxFullAbsorb;
int SaveAmount;
int BonusCount;
int BonusMax;
};
// Hexen armor consists of four separate armor types plus a conceptual armor
// type (the player himself) that work together as a single armor.
class AHexenArmor : public AArmor

View file

@ -318,7 +318,7 @@ void cht_DoCheat (player_t *player, int cheat)
case CHT_RESSURECT:
if (player->playerstate != PST_LIVE && player->mo != nullptr)
{
if (player->mo->IsKindOf(RUNTIME_CLASS(APlayerChunk)))
if (player->mo->IsKindOf(PClass::FindActor("PlayerChunk")))
{
Printf("Unable to resurrect. Player is no longer connected to its body.\n");
}

View file

@ -83,6 +83,13 @@ xx(PointPuller)
xx(UpperStackLookOnly)
xx(LowerStackLookOnly)
xx(BasicArmorBonus)
xx(BasicArmorPickup)
xx(SaveAmount)
xx(SavePercent)
xx(MaxAbsorb)
xx(MaxFullAbsorb)
xx(BulletPuff)
xx(StrifePuff)
xx(MaulerPuff)

View file

@ -2059,7 +2059,7 @@ DEFINE_ACTION_FUNCTION(AStateProvider, A_CustomPunch)
PARAM_FLOAT_DEF (range);
PARAM_FLOAT_DEF (lifesteal);
PARAM_INT_DEF (lifestealmax);
PARAM_CLASS_DEF (armorbonustype, ABasicArmorBonus);
PARAM_CLASS_DEF (armorbonustype, AActor);
PARAM_SOUND_DEF (MeleeSound);
PARAM_SOUND_DEF (MissSound);
@ -2107,18 +2107,17 @@ DEFINE_ACTION_FUNCTION(AStateProvider, A_CustomPunch)
{
if (armorbonustype == NULL)
{
armorbonustype = dyn_cast<ABasicArmorBonus::MetaClass>(PClass::FindClass("ArmorBonus"));
armorbonustype = PClass::FindActor("ArmorBonus");
}
if (armorbonustype != NULL)
{
assert(armorbonustype->IsDescendantOf(RUNTIME_CLASS(ABasicArmorBonus)));
ABasicArmorBonus *armorbonus = static_cast<ABasicArmorBonus *>(Spawn(armorbonustype));
armorbonus->SaveAmount *= int(actualdamage * lifesteal);
armorbonus->MaxSaveAmount = lifestealmax <= 0 ? armorbonus->MaxSaveAmount : lifestealmax;
auto armorbonus = Spawn(armorbonustype);
armorbonus->IntVar(NAME_SaveAmount) *= int(actualdamage * lifesteal);
if (lifestealmax > 0) armorbonus->IntVar("MaxSaveAmount") = lifestealmax;
armorbonus->flags |= MF_DROPPED;
armorbonus->ClearCounters();
if (!armorbonus->CallTryPickup(self))
if (!static_cast<AInventory*>(armorbonus)->CallTryPickup(self))
{
armorbonus->Destroy ();
}

View file

@ -790,13 +790,9 @@ bool AActor::GiveInventory(PClassInventory *type, int amount, bool givecheat)
item->ClearCounters();
if (!givecheat || amount > 0)
{
if (type->IsDescendantOf (RUNTIME_CLASS(ABasicArmorPickup)))
if (type->IsDescendantOf (PClass::FindActor(NAME_BasicArmorPickup)) || type->IsDescendantOf(PClass::FindActor(NAME_BasicArmorBonus)))
{
static_cast<ABasicArmorPickup*>(item)->SaveAmount *= amount;
}
else if (type->IsDescendantOf (RUNTIME_CLASS(ABasicArmorBonus)))
{
static_cast<ABasicArmorBonus*>(item)->SaveAmount *= amount;
item->IntVar(NAME_SaveAmount) *= amount;
}
else
{

View file

@ -659,8 +659,6 @@ IMPLEMENT_POINTERS_START(APlayerPawn)
IMPLEMENT_POINTER(FlechetteType)
IMPLEMENT_POINTERS_END
IMPLEMENT_CLASS(APlayerChunk, false, false)
void APlayerPawn::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
@ -1700,13 +1698,13 @@ DEFINE_ACTION_FUNCTION(AActor, A_PlayerScream)
DEFINE_ACTION_FUNCTION(AActor, A_SkullPop)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_CLASS_DEF(spawntype, APlayerChunk);
PARAM_CLASS_DEF(spawntype, APlayerPawn);
APlayerPawn *mo;
player_t *player;
// [GRB] Parameterized version
if (spawntype == NULL || !spawntype->IsDescendantOf(RUNTIME_CLASS(APlayerChunk)))
if (spawntype == NULL || !spawntype->IsDescendantOf(PClass::FindActor("PlayerChunk")))
{
spawntype = dyn_cast<PClassPlayerPawn>(PClass::FindClass("BloodySkull"));
if (spawntype == NULL)
@ -2203,7 +2201,7 @@ void P_DeathThink (player_t *player)
player->TickPSprites();
player->onground = (player->mo->Z() <= player->mo->floorz);
if (player->mo->IsKindOf (RUNTIME_CLASS(APlayerChunk)))
if (player->mo->IsKindOf (PClass::FindActor("PlayerChunk")))
{ // Flying bloody skull or flying ice chunk
player->viewheight = 6;
player->deltaviewheight = 0;

View file

@ -1723,33 +1723,6 @@ DEFINE_CLASS_PROPERTY(forbiddento, Ssssssssssssssssssss, Inventory)
}
}
//==========================================================================
//
//==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(armor, maxsaveamount, I, BasicArmorBonus)
{
PROP_INT_PARM(i, 0);
defaults->MaxSaveAmount = i;
}
//==========================================================================
//
//==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(armor, maxbonus, I, BasicArmorBonus)
{
PROP_INT_PARM(i, 0);
defaults->BonusCount = i;
}
//==========================================================================
//
//==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(armor, maxbonusmax, I, BasicArmorBonus)
{
PROP_INT_PARM(i, 0);
defaults->BonusMax = i;
}
//==========================================================================
//
//==========================================================================
@ -1758,13 +1731,9 @@ DEFINE_CLASS_PROPERTY(saveamount, I, Armor)
PROP_INT_PARM(i, 0);
// Special case here because this property has to work for 2 unrelated classes
if (info->IsDescendantOf(RUNTIME_CLASS(ABasicArmorPickup)))
if (info->IsDescendantOf(PClass::FindActor(NAME_BasicArmorPickup)) || info->IsDescendantOf(PClass::FindActor(NAME_BasicArmorBonus)))
{
((ABasicArmorPickup*)defaults)->SaveAmount=i;
}
else if (info->IsDescendantOf(RUNTIME_CLASS(ABasicArmorBonus)))
{
((ABasicArmorBonus*)defaults)->SaveAmount=i;
defaults->IntVar(NAME_SaveAmount)=i;
}
else
{
@ -1781,13 +1750,9 @@ DEFINE_CLASS_PROPERTY(savepercent, F, Armor)
i = clamp(i, 0., 100.)/100.;
// Special case here because this property has to work for 2 unrelated classes
if (info->IsDescendantOf(RUNTIME_CLASS(ABasicArmorPickup)))
if (info->IsDescendantOf(PClass::FindActor(NAME_BasicArmorPickup)) || info->IsDescendantOf(PClass::FindActor(NAME_BasicArmorBonus)))
{
((ABasicArmorPickup*)defaults)->SavePercent = i;
}
else if (info->IsDescendantOf(RUNTIME_CLASS(ABasicArmorBonus)))
{
((ABasicArmorBonus*)defaults)->SavePercent = i;
defaults->FloatVar(NAME_SavePercent) = i;
}
else
{
@ -1803,13 +1768,9 @@ DEFINE_CLASS_PROPERTY(maxabsorb, I, Armor)
PROP_INT_PARM(i, 0);
// Special case here because this property has to work for 2 unrelated classes
if (info->IsDescendantOf(RUNTIME_CLASS(ABasicArmorPickup)))
if (info->IsDescendantOf(PClass::FindActor(NAME_BasicArmorPickup)) || info->IsDescendantOf(PClass::FindActor(NAME_BasicArmorBonus)))
{
((ABasicArmorPickup*)defaults)->MaxAbsorb = i;
}
else if (info->IsDescendantOf(RUNTIME_CLASS(ABasicArmorBonus)))
{
((ABasicArmorBonus*)defaults)->MaxAbsorb = i;
defaults->IntVar(NAME_MaxAbsorb) = i;
}
else
{
@ -1825,13 +1786,9 @@ DEFINE_CLASS_PROPERTY(maxfullabsorb, I, Armor)
PROP_INT_PARM(i, 0);
// Special case here because this property has to work for 2 unrelated classes
if (info->IsDescendantOf(RUNTIME_CLASS(ABasicArmorPickup)))
if (info->IsDescendantOf(PClass::FindActor(NAME_BasicArmorPickup)) || info->IsDescendantOf(PClass::FindActor(NAME_BasicArmorBonus)))
{
((ABasicArmorPickup*)defaults)->MaxFullAbsorb = i;
}
else if (info->IsDescendantOf(RUNTIME_CLASS(ABasicArmorBonus)))
{
((ABasicArmorBonus*)defaults)->MaxFullAbsorb = i;
defaults->IntVar(NAME_MaxFullAbsorb) = i;
}
else
{

View file

@ -1380,16 +1380,24 @@ bool ZCCCompiler::CompileProperties(PClass *type, TArray<ZCC_Property *> &Proper
TArray<PField *> fields;
ZCC_Identifier *id = (ZCC_Identifier *)p->Body;
do
if (FName(p->NodeName) == FName("prefix") && Wads.GetLumpFile(Lump) == 0)
{
auto f = dyn_cast<PField>(type->Symbols.FindSymbol(id->Id, true));
if (f == nullptr)
// only for internal definitions: Allow setting a prefix. This is only for compatiblity with the old DECORATE property parser, but not for general use.
prefix = id->Id;
}
else
{
do
{
Error(id, "Variable %s not found in %s", FName(id->Id).GetChars(), type->TypeName.GetChars());
}
fields.Push(f);
id = (ZCC_Identifier*)id->SiblingNext;
} while (id != p->Body);
auto f = dyn_cast<PField>(type->Symbols.FindSymbol(id->Id, true));
if (f == nullptr)
{
Error(id, "Variable %s not found in %s", FName(id->Id).GetChars(), type->TypeName.GetChars());
}
fields.Push(f);
id = (ZCC_Identifier*)id->SiblingNext;
} while (id != p->Body);
}
FString qualifiedname;
// Store the full qualified name and prepend some 'garbage' to the name so that no conflicts with other symbol types can happen.

View file

@ -21,17 +21,55 @@ class BasicArmor : Armor native
{
+Inventory.KEEPDEPLETED
}
//===========================================================================
//
// ABasicArmor :: HandlePickup
//
//===========================================================================
override bool HandlePickup (Inventory item)
{
if (item.GetClass() == "BasicArmor")
{
// You shouldn't be picking up BasicArmor anyway.
return true;
}
if (!item.bIgnoreSkill)
{
if (item is "BasicArmorBonus")
{
let armor = BasicArmorBonus(item);
armor.SaveAmount = int(armor.SaveAmount * G_SkillPropertyFloat(SKILLP_ArmorFactor));
}
else if (item is "BasicArmorPickup")
{
let armor = BasicArmorPickup(item);
armor.SaveAmount = int(armor.SaveAmount * G_SkillPropertyFloat(SKILLP_ArmorFactor));
}
}
return false;
}
}
class BasicArmorBonus : Armor native
class BasicArmorBonus : Armor
{
native double SavePercent; // The default, for when you don't already have armor
native int MaxSaveAmount;
native int MaxAbsorb;
native int MaxFullAbsorb;
native int SaveAmount;
native int BonusCount;
native int BonusMax;
double SavePercent; // The default, for when you don't already have armor
int MaxSaveAmount;
int MaxAbsorb;
int MaxFullAbsorb;
int SaveAmount;
int BonusCount;
int BonusMax;
property prefix: Armor;
property MaxSaveAmount: MaxSaveAmount;
property SaveAmount : SaveAmount;
property SavePercent: SavePercent;
property MaxAbsorb: MaxAbsorb;
property MaxFullAbsorb: MaxFullAbsorb;
property MaxBonus: BonusCount;
property MaxBonusMax: BonusMax;
Default
{
@ -40,6 +78,93 @@ class BasicArmorBonus : Armor native
Inventory.MaxAmount 0;
Armor.SavePercent 33.335;
}
//===========================================================================
//
// ABasicArmorBonus :: CreateCopy
//
//===========================================================================
override Inventory CreateCopy (Actor other)
{
let copy = BasicArmorBonus(Super.CreateCopy (other));
if (!bIgnoreSkill)
{
SaveAmount = int(SaveAmount * G_SkillPropertyFloat(SKILLP_ArmorFactor));
}
copy.SavePercent = SavePercent;
copy.SaveAmount = SaveAmount;
copy.MaxSaveAmount = MaxSaveAmount;
copy.BonusCount = BonusCount;
copy.BonusMax = BonusMax;
copy.MaxAbsorb = MaxAbsorb;
copy.MaxFullAbsorb = MaxFullAbsorb;
return copy;
}
//===========================================================================
//
// ABasicArmorBonus :: Use
//
// Tries to add to the amount of BasicArmor a player has.
//
//===========================================================================
override bool Use (bool pickup)
{
let armor = BasicArmor(Owner.FindInventory("BasicArmor"));
bool result = false;
// This should really never happen but let's be prepared for a broken inventory.
if (armor == NULL)
{
armor = BasicArmor(Spawn("BasicArmor"));
armor.BecomeItem ();
armor.Amount = 0;
armor.MaxAmount = MaxSaveAmount;
Owner.AddInventory (armor);
}
if (BonusCount > 0 && armor.BonusCount < BonusMax)
{
armor.BonusCount = min(armor.BonusCount + BonusCount, BonusMax);
result = true;
}
int saveAmount = min(SaveAmount, MaxSaveAmount);
if (saveAmount <= 0)
{ // If it can't give you anything, it's as good as used.
return BonusCount > 0 ? result : true;
}
// If you already have more armor than this item can give you, you can't
// use it.
if (armor.Amount >= MaxSaveAmount + armor.BonusCount)
{
return result;
}
if (armor.Amount <= 0)
{ // Should never be less than 0, but might as well check anyway
armor.Amount = 0;
armor.Icon = Icon;
armor.SavePercent = clamp(SavePercent, 0, 100);
armor.MaxAbsorb = MaxAbsorb;
armor.ArmorType = GetClassName();
armor.MaxFullAbsorb = MaxFullAbsorb;
armor.ActualSaveAmount = MaxSaveAmount;
}
armor.Amount = min(armor.Amount + saveAmount, MaxSaveAmount + armor.BonusCount);
armor.MaxAmount = max(armor.MaxAmount, MaxSaveAmount);
return true;
}
}
class BasicArmorPickup : Armor native

View file

@ -138,7 +138,7 @@ class PlayerPawn : Actor native
native void CheckWeaponSwitch(class<Inventory> item);
}
class PlayerChunk : PlayerPawn native
class PlayerChunk : PlayerPawn
{
Default
{