diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 05dd7d708..5c4c79f1b 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,6 @@ August 7, 2008 (Changes by Graf Zahl) +- Added Gez's dropammofactor submission with some necessary changes. Also merged + redundant ammo multiplication code from P_DropItem and ADehackedPickup::TryPickup. - Fixed. The Firedemon was missing a game filter. August 7, 2008 (SBARINfO update) diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 7b3c0c065..e4d9df5ba 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -2603,6 +2603,8 @@ void FinishDehPatch () } } +void ModifyDropAmount(AInventory *inv, int dropamount); + bool ADehackedPickup::TryPickup (AActor *toucher) { const PClass *type = DetermineType (); @@ -2618,18 +2620,10 @@ bool ADehackedPickup::TryPickup (AActor *toucher) RealPickup->flags &= ~MF_DROPPED; } // If this item has been dropped by a monster the - // amount of ammo this gives must be halved. + // amount of ammo this gives must be adjusted. if (droppedbymonster) { - if (RealPickup->IsKindOf(RUNTIME_CLASS(AWeapon))) - { - static_cast(RealPickup)->AmmoGive1 /= 2; - static_cast(RealPickup)->AmmoGive2 /= 2; - } - else if (RealPickup->IsKindOf(RUNTIME_CLASS(AAmmo))) - { - RealPickup->Amount /= 2; - } + ModifyDropAmount(RealPickup, 0); } if (!RealPickup->TryPickup (toucher)) { diff --git a/src/g_level.cpp b/src/g_level.cpp index a36c20840..5d41a6a9a 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -3232,6 +3232,7 @@ static void ParseSkill (FScanner &sc) skill.AmmoFactor = FRACUNIT; skill.DoubleAmmoFactor = 2*FRACUNIT; + skill.DropAmmoFactor = -1; skill.DamageFactor = FRACUNIT; skill.FastMonsters = false; skill.DisableCheats = false; @@ -3262,6 +3263,11 @@ static void ParseSkill (FScanner &sc) sc.MustGetFloat (); skill.DoubleAmmoFactor = FLOAT2FIXED(sc.Float); } + else if (sc.Compare ("dropammofactor")) + { + sc.MustGetFloat (); + skill.DropAmmoFactor = FLOAT2FIXED(sc.Float); + } else if (sc.Compare ("damagefactor")) { sc.MustGetFloat (); @@ -3387,6 +3393,9 @@ int G_SkillProperty(ESkillProperty prop) } return AllSkills[gameskill].AmmoFactor; + case SKILLP_DropAmmoFactor: + return AllSkills[gameskill].DropAmmoFactor; + case SKILLP_DamageFactor: return AllSkills[gameskill].DamageFactor; @@ -3437,6 +3446,7 @@ FSkillInfo &FSkillInfo::operator=(const FSkillInfo &other) Name = other.Name; AmmoFactor = other.AmmoFactor; DoubleAmmoFactor = other.DoubleAmmoFactor; + DropAmmoFactor = other.DropAmmoFactor; DamageFactor = other.DamageFactor; FastMonsters = other.FastMonsters; DisableCheats = other.DisableCheats; diff --git a/src/g_level.h b/src/g_level.h index 6da01a8f7..bfa4c8a20 100644 --- a/src/g_level.h +++ b/src/g_level.h @@ -406,6 +406,7 @@ void G_WriteSnapshots (FILE *file); enum ESkillProperty { SKILLP_AmmoFactor, + SKILLP_DropAmmoFactor, SKILLP_DamageFactor, SKILLP_FastMonsters, SKILLP_Respawn, @@ -424,7 +425,7 @@ typedef TMap SkillMenuNames; struct FSkillInfo { FName Name; - fixed_t AmmoFactor, DoubleAmmoFactor; + fixed_t AmmoFactor, DoubleAmmoFactor, DropAmmoFactor; fixed_t DamageFactor; bool FastMonsters; bool DisableCheats; diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 835f54c20..a624404d7 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -573,7 +573,7 @@ void FBehavior::StaticLoadDefaultModules () FBehavior *FBehavior::StaticLoadModule (int lumpnum, FileReader * fr, int len) { - if (lumpnum == -1) return; + if (lumpnum == -1) return NULL; for (unsigned int i = 0; i < StaticModules.Size(); ++i) { diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 49a953180..7e5a1b587 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -2378,14 +2378,64 @@ void A_XXScream (AActor *actor) } } +//--------------------------------------------------------------------------- +// +// Modifies the drop amount of this item according to the current skill's +// settings (also called by ADehackedPickup::TryPickup) +// +//--------------------------------------------------------------------------- +void ModifyDropAmount(AInventory *inv, int dropamount) +{ + int flagmask = IF_IGNORESKILL; + fixed_t dropammofactor = G_SkillProperty(SKILLP_DropAmmoFactor); + // Default drop amount is half of regular amount * regular ammo multiplication + if (dropammofactor == -1) + { + dropammofactor = FRACUNIT/2; + flagmask = 0; + } + + if (dropamount > 0) + { + if (flagmask != 0 && inv->IsKindOf(RUNTIME_CLASS(AAmmo))) + { + inv->Amount = FixedMul(dropamount, dropammofactor); + inv->ItemFlags |= IF_IGNORESKILL; + } + else + { + inv->Amount = dropamount; + } + } + else if (inv->IsKindOf (RUNTIME_CLASS(AAmmo))) + { + // Half ammo when dropped by bad guys. + inv->Amount = inv->GetClass()->Meta.GetMetaInt (AIMETA_DropAmount, MAX(1, FixedMul(inv->Amount, dropammofactor))); + inv->ItemFlags|=flagmask; + } + else if (inv->IsKindOf (RUNTIME_CLASS(AWeapon))) + { + // The same goes for ammo from a weapon. + static_cast(inv)->AmmoGive1 = FixedMul(static_cast(inv)->AmmoGive1, dropammofactor); + static_cast(inv)->AmmoGive2 = FixedMul(static_cast(inv)->AmmoGive2, dropammofactor); + inv->ItemFlags|=flagmask; + } + else if (inv->IsKindOf (RUNTIME_CLASS(ADehackedPickup))) + { + // For weapons and ammo modified by Dehacked we need to flag the item. + static_cast(inv)->droppedbymonster = true; + } +} + //--------------------------------------------------------------------------- // // PROC P_DropItem // //--------------------------------------------------------------------------- + CVAR(Int, sv_dropstyle, 0, CVAR_SERVERINFO | CVAR_ARCHIVE); -AInventory *P_DropItem (AActor *source, const PClass *type, int special, int chance) +AInventory *P_DropItem (AActor *source, const PClass *type, int dropamount, int chance) { if (type != NULL && pr_dropitem() <= chance) { @@ -2413,36 +2463,18 @@ AInventory *P_DropItem (AActor *source, const PClass *type, int special, int cha if (mo->IsKindOf (RUNTIME_CLASS(AInventory))) { AInventory * inv = static_cast(mo); - if (special > 0) - { - inv->Amount = special; - } - else if (mo->IsKindOf (RUNTIME_CLASS(AAmmo))) - { - // Half ammo when dropped by bad guys. - inv->Amount = inv->GetClass()->Meta.GetMetaInt (AIMETA_DropAmount, MAX(1, inv->Amount / 2 )); - } - else if (mo->IsKindOf (RUNTIME_CLASS(AWeapon))) - { - // The same goes for ammo from a weapon. - static_cast(mo)->AmmoGive1 /= 2; - static_cast(mo)->AmmoGive2 /= 2; - } - else if (mo->IsKindOf (RUNTIME_CLASS(ADehackedPickup))) - { - // For weapons and ammo modified by Dehacked we need to flag the item. - static_cast(mo)->droppedbymonster = true; - } + ModifyDropAmount(inv, dropamount); if (inv->SpecialDropAction (source)) { return NULL; } + return inv; } if (!(i_compatflags & COMPATF_NOTOSSDROPS)) { P_TossItem (mo); } - return static_cast(mo); + // we can't really return an AInventory pointer to a non-inventory item here, can we? } return NULL; } diff --git a/src/sc_man.cpp b/src/sc_man.cpp index 137b79634..5f1b05e76 100644 --- a/src/sc_man.cpp +++ b/src/sc_man.cpp @@ -179,6 +179,7 @@ void FScanner::OpenFile (const char *name) ScriptBuffer = FString((const char *)filebuf, filesize); delete[] filebuf; ScriptName = name; // This is used for error messages so the full file name is preferable + LumpNum = -1; PrepareScript (); } @@ -196,6 +197,7 @@ void FScanner::OpenMem (const char *name, char *buffer, int size) Close (); ScriptBuffer = FString(buffer, size); ScriptName = name; + LumpNum = -1; PrepareScript (); } @@ -215,6 +217,7 @@ void FScanner :: OpenLumpNum (int lump) ScriptBuffer = mem.GetString(); } ScriptName = Wads.GetLumpFullPath(lump); + LumpNum = lump; PrepareScript (); } diff --git a/src/sc_man.h b/src/sc_man.h index a7ed75f02..81061b9c9 100644 --- a/src/sc_man.h +++ b/src/sc_man.h @@ -70,6 +70,7 @@ public: int Line; bool End; bool Crossed; + int LumpNum; protected: void PrepareScript(); diff --git a/src/thingdef/thingdef.cpp b/src/thingdef/thingdef.cpp index 868b5b6af..d11913bb7 100644 --- a/src/thingdef/thingdef.cpp +++ b/src/thingdef/thingdef.cpp @@ -165,6 +165,11 @@ static void ParseActionDef (FScanner &sc, PClass *cls) AFuncDesc *afd; FName funcname; FString args; + + if (sc.LumpNum == -1 || Wads.GetLumpFile(sc.LumpNum) > 0) + { + sc.ScriptError ("action functions can only be imported by internal class and actor definitions!"); + } sc.MustGetToken(TK_Native); sc.MustGetToken(TK_Identifier);