diff --git a/src/c_console.cpp b/src/c_console.cpp index b27674044..a9cd97557 100644 --- a/src/c_console.cpp +++ b/src/c_console.cpp @@ -1749,7 +1749,7 @@ void C_MidPrintBold (FFont *font, const char *msg) } } -DEFINE_ACTION_FUNCTION(DObject, C_MidPrint) +DEFINE_ACTION_FUNCTION(_Console, MidPrint) { PARAM_PROLOGUE; PARAM_STRING(font); diff --git a/src/g_inventory/a_weapons.cpp b/src/g_inventory/a_weapons.cpp index 823915aea..bf7f04928 100644 --- a/src/g_inventory/a_weapons.cpp +++ b/src/g_inventory/a_weapons.cpp @@ -249,363 +249,6 @@ void AWeapon::MarkPrecacheSounds() const ReadySound.MarkUsed(); } -//=========================================================================== -// -// AWeapon :: TryPickup -// -// If you can't see the weapon when it's active, then you can't pick it up. -// -//=========================================================================== - -bool AWeapon::TryPickupRestricted (AActor *&toucher) -{ - // Wrong class, but try to pick up for ammo - if (CallShouldStay()) - { // Can't pick up weapons for other classes in coop netplay - return false; - } - - bool gaveSome = (NULL != AddAmmo (toucher, AmmoType1, AmmoGive1)); - gaveSome |= (NULL != AddAmmo (toucher, AmmoType2, AmmoGive2)); - if (gaveSome) - { - GoAwayAndDie (); - } - return gaveSome; -} - - -//=========================================================================== -// -// AWeapon :: TryPickup -// -//=========================================================================== - -bool AWeapon::TryPickup (AActor *&toucher) -{ - FState * ReadyState = FindState(NAME_Ready); - if (ReadyState != NULL && - ReadyState->GetFrame() < sprites[ReadyState->sprite].numframes) - { - return Super::TryPickup (toucher); - } - return false; -} - -//=========================================================================== -// -// AWeapon :: Use -// -// Make the player switch to this weapon. -// -//=========================================================================== - -bool AWeapon::Use (bool pickup) -{ - AWeapon *useweap = this; - - // Powered up weapons cannot be used directly. - if (WeaponFlags & WIF_POWERED_UP) return false; - - // If the player is powered-up, use the alternate version of the - // weapon, if one exists. - if (SisterWeapon != NULL && - SisterWeapon->WeaponFlags & WIF_POWERED_UP && - Owner->FindInventory (PClass::FindActor(NAME_PowerWeaponLevel2), true)) - { - useweap = SisterWeapon; - } - if (Owner->player != NULL && Owner->player->ReadyWeapon != useweap) - { - Owner->player->PendingWeapon = useweap; - } - // Return false so that the weapon is not removed from the inventory. - return false; -} - -//=========================================================================== -// -// AWeapon :: Destroy -// -//=========================================================================== - -void AWeapon::OnDestroy() -{ - AWeapon *sister = SisterWeapon; - - if (sister != NULL) - { - // avoid recursion - sister->SisterWeapon = NULL; - if (sister != this) - { // In case we are our own sister, don't crash. - sister->Destroy(); - } - } - Super::OnDestroy(); -} - -//=========================================================================== -// -// AWeapon :: HandlePickup -// -// Try to leach ammo from the weapon if you have it already. -// -//=========================================================================== - -bool AWeapon::HandlePickup (AInventory *item) -{ - if (item->GetClass() == GetClass()) - { - if (static_cast(item)->PickupForAmmo (this)) - { - item->ItemFlags |= IF_PICKUPGOOD; - } - if (MaxAmount > 1) //[SP] If amountAmmo1 != NULL) oldamount1 = ownedWeapon->Ammo1->Amount; - if (ownedWeapon->Ammo2 != NULL) oldamount2 = ownedWeapon->Ammo2->Amount; - - if (AmmoGive1 > 0) gotstuff = AddExistingAmmo (ownedWeapon->Ammo1, AmmoGive1); - if (AmmoGive2 > 0) gotstuff |= AddExistingAmmo (ownedWeapon->Ammo2, AmmoGive2); - - AActor *Owner = ownedWeapon->Owner; - if (gotstuff && Owner != NULL && Owner->player != NULL) - { - if (ownedWeapon->Ammo1 != NULL && oldamount1 == 0) - { - static_cast(Owner)->CheckWeaponSwitch(ownedWeapon->Ammo1->GetClass()); - } - else if (ownedWeapon->Ammo2 != NULL && oldamount2 == 0) - { - static_cast(Owner)->CheckWeaponSwitch(ownedWeapon->Ammo2->GetClass()); - } - } - } - return gotstuff; -} - -//=========================================================================== -// -// AWeapon :: CreateCopy -// -//=========================================================================== - -AInventory *AWeapon::CreateCopy (AActor *other) -{ - AWeapon *copy = static_cast(Super::CreateCopy (other)); - if (copy != this) - { - copy->AmmoGive1 = AmmoGive1; - copy->AmmoGive2 = AmmoGive2; - } - return copy; -} - -//=========================================================================== -// -// AWeapon :: CreateTossable -// -// A weapon that's tossed out should contain no ammo, so you can't cheat -// by dropping it and then picking it back up. -// -//=========================================================================== - -AInventory *AWeapon::CreateTossable () -{ - // Only drop the weapon that is meant to be placed in a level. That is, - // only drop the weapon that normally gives you ammo. - if (SisterWeapon != NULL && - ((AWeapon*)GetDefault())->AmmoGive1 == 0 && - ((AWeapon*)GetDefault())->AmmoGive2 == 0 && - (((AWeapon*)SisterWeapon->GetDefault())->AmmoGive1 > 0 || - ((AWeapon*)SisterWeapon->GetDefault())->AmmoGive2 > 0)) - { - return SisterWeapon->CallCreateTossable (); - } - AWeapon *copy = static_cast (Super::CreateTossable ()); - - if (copy != NULL) - { - // If this weapon has a sister, remove it from the inventory too. - if (SisterWeapon != NULL) - { - SisterWeapon->SisterWeapon = NULL; - SisterWeapon->Destroy (); - } - // To avoid exploits, the tossed weapon must not have any ammo. - copy->AmmoGive1 = 0; - copy->AmmoGive2 = 0; - } - return copy; -} - -//=========================================================================== -// -// AWeapon :: AttachToOwner -// -//=========================================================================== - -void AWeapon::AttachToOwner (AActor *other) -{ - Super::AttachToOwner (other); - - Ammo1 = AddAmmo (Owner, AmmoType1, AmmoGive1); - Ammo2 = AddAmmo (Owner, AmmoType2, AmmoGive2); - SisterWeapon = AddWeapon (SisterWeaponType); - if (Owner->player != NULL) - { - if (!Owner->player->userinfo.GetNeverSwitch() && !(WeaponFlags & WIF_NO_AUTO_SWITCH)) - { - Owner->player->PendingWeapon = this; - } - if (Owner->player->mo == players[consoleplayer].camera) - { - StatusBar->ReceivedWeapon (this); - } - } - GivenAsMorphWeapon = false; // will be set explicitly by morphing code -} - -//=========================================================================== -// -// AWeapon :: AddAmmo -// -// Give some ammo to the owner, even if it's just 0. -// -//=========================================================================== - -AInventory *AWeapon::AddAmmo (AActor *other, PClassActor *ammotype, int amount) -{ - AInventory *ammo; - - if (ammotype == NULL) - { - return NULL; - } - - // [BC] This behavior is from the original Doom. Give 5/2 times as much ammo when - // we pick up a weapon in deathmatch. - if (( deathmatch ) && ( gameinfo.gametype & GAME_DoomChex )) - amount = amount * 5 / 2; - - // extra ammo in baby mode and nightmare mode - if (!(this->ItemFlags&IF_IGNORESKILL)) - { - amount = int(amount * G_SkillProperty(SKILLP_AmmoFactor)); - } - ammo = other->FindInventory (ammotype); - if (ammo == NULL) - { - ammo = static_cast(Spawn (ammotype)); - ammo->Amount = MIN (amount, ammo->MaxAmount); - ammo->AttachToOwner (other); - } - else if (ammo->Amount < ammo->MaxAmount) - { - ammo->Amount += amount; - if (ammo->Amount > ammo->MaxAmount) - { - ammo->Amount = ammo->MaxAmount; - } - } - return ammo; -} - -//=========================================================================== -// -// AWeapon :: AddExistingAmmo -// -// Give the owner some more ammo he already has. -// -//=========================================================================== -EXTERN_CVAR(Bool, sv_unlimited_pickup) - -bool AWeapon::AddExistingAmmo (AInventory *ammo, int amount) -{ - if (ammo != NULL && (ammo->Amount < ammo->MaxAmount || sv_unlimited_pickup)) - { - // extra ammo in baby mode and nightmare mode - if (!(ItemFlags&IF_IGNORESKILL)) - { - amount = int(amount * G_SkillProperty(SKILLP_AmmoFactor)); - } - ammo->Amount += amount; - if (ammo->Amount > ammo->MaxAmount && !sv_unlimited_pickup) - { - ammo->Amount = ammo->MaxAmount; - } - return true; - } - return false; -} - -//=========================================================================== -// -// AWeapon :: AddWeapon -// -// Give the owner a weapon if they don't have it already. -// -//=========================================================================== - -AWeapon *AWeapon::AddWeapon (PClassWeapon *weapontype) -{ - AWeapon *weap; - - if (weapontype == NULL || !weapontype->IsDescendantOf(RUNTIME_CLASS(AWeapon))) - { - return NULL; - } - weap = static_cast(Owner->FindInventory (weapontype)); - if (weap == NULL) - { - weap = static_cast(Spawn (weapontype)); - weap->AttachToOwner (Owner); - } - return weap; -} - -//=========================================================================== -// -// AWeapon :: ShouldStay -// -//=========================================================================== - -bool AWeapon::ShouldStay () -{ - if (((multiplayer && - (!deathmatch && !alwaysapplydmflags)) || (dmflags & DF_WEAPONS_STAY)) && - !(flags & MF_DROPPED)) - { - return true; - } - return false; -} - //=========================================================================== // // AWeapon :: CheckAmmo @@ -781,49 +424,6 @@ void AWeapon::PostMorphWeapon () pspr->SetState(GetUpState()); } -//=========================================================================== -// -// AWeapon :: EndPowerUp -// -// The Tome of Power just expired. -// -//=========================================================================== - -void AWeapon::EndPowerup () -{ - if (SisterWeapon != NULL && WeaponFlags&WIF_POWERED_UP) - { - if (GetReadyState() != SisterWeapon->GetReadyState()) - { - if (Owner->player->PendingWeapon == NULL || - Owner->player->PendingWeapon == WP_NOCHANGE) - Owner->player->PendingWeapon = SisterWeapon; - } - else - { - DPSprite *psp = Owner->player->FindPSprite(PSP_WEAPON); - if (psp != nullptr && psp->GetCaller() == Owner->player->ReadyWeapon) - { - // If the weapon changes but the state does not, we have to manually change the PSprite's caller here. - psp->SetCaller(SisterWeapon); - Owner->player->ReadyWeapon = SisterWeapon; - } - else - { - // Something went wrong. Initiate a regular weapon change. - Owner->player->PendingWeapon = SisterWeapon; - } - } - } -} - -DEFINE_ACTION_FUNCTION(AWeapon, EndPowerup) -{ - PARAM_SELF_PROLOGUE(AWeapon); - self->EndPowerup(); - return 0; -} - //=========================================================================== // // AWeapon :: GetUpState diff --git a/src/g_inventory/a_weapons.h b/src/g_inventory/a_weapons.h index 504529805..21eaf9b89 100644 --- a/src/g_inventory/a_weapons.h +++ b/src/g_inventory/a_weapons.h @@ -136,17 +136,7 @@ public: virtual void MarkPrecacheSounds() const; virtual void Serialize(FSerializer &arc) override; - virtual bool ShouldStay () override; - virtual void AttachToOwner (AActor *other) override; - virtual bool HandlePickup (AInventory *item) override; - virtual AInventory *CreateCopy (AActor *other) override; - virtual AInventory *CreateTossable () override; - virtual bool TryPickup (AActor *&toucher) override; - virtual bool TryPickupRestricted (AActor *&toucher) override; - virtual bool Use (bool pickup) override; - virtual void OnDestroy() override; - bool PickupForAmmo(AWeapon *ownedWeapon); void PostMorphWeapon(); // scripted virtuals. @@ -158,9 +148,6 @@ public: FState *GetStateForButtonName (FName button); - - virtual void EndPowerup (); - enum { PrimaryFire, @@ -180,10 +167,6 @@ public: BobInverseSmooth }; -protected: - AInventory *AddAmmo (AActor *other, PClassActor *ammotype, int amount); - bool AddExistingAmmo (AInventory *ammo, int amount); - AWeapon *AddWeapon (PClassWeapon *weapon); }; enum diff --git a/src/g_shared/shared_sbar.cpp b/src/g_shared/shared_sbar.cpp index f8ed4a94b..8719a7833 100644 --- a/src/g_shared/shared_sbar.cpp +++ b/src/g_shared/shared_sbar.cpp @@ -1673,6 +1673,15 @@ void DBaseStatusBar::ReceivedWeapon (AWeapon *weapon) { } +DEFINE_ACTION_FUNCTION(_StatusBar, ReceivedWeapon) +{ + PARAM_PROLOGUE; + PARAM_POINTER(w, AWeapon); + StatusBar->ReceivedWeapon(w); + return 0; +} + + void DBaseStatusBar::SerializeMessages(FSerializer &arc) { arc.Array("hudmessages", Messages, 3, true); diff --git a/src/gi.cpp b/src/gi.cpp index 6c7349592..8d8ff9da7 100644 --- a/src/gi.cpp +++ b/src/gi.cpp @@ -49,6 +49,7 @@ DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, backpacktype) DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, Armor2Percent) DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, ArmorIcon1) DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, ArmorIcon2) +DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, gametype) const char *GameNames[17] = diff --git a/src/gl/dynlights/a_dynlight.cpp b/src/gl/dynlights/a_dynlight.cpp index e717ae00e..30537a4d2 100644 --- a/src/gl/dynlights/a_dynlight.cpp +++ b/src/gl/dynlights/a_dynlight.cpp @@ -209,6 +209,7 @@ void ADynamicLight::Activate(AActor *activator) m_cycler.SetCycleType(CYCLE_Sin); m_currentRadius = m_cycler.GetVal(); } + assert(m_currentRadius > 0); } diff --git a/src/gl/dynlights/gl_dynlight.cpp b/src/gl/dynlights/gl_dynlight.cpp index ddc560b28..641878979 100644 --- a/src/gl/dynlights/gl_dynlight.cpp +++ b/src/gl/dynlights/gl_dynlight.cpp @@ -137,7 +137,7 @@ public: void SetHalo(bool halo) { m_halo = halo; } protected: FName m_Name; - unsigned char m_Args[5]; + int m_Args[5]; double m_Param; DVector3 m_Pos; ELightType m_type; @@ -159,7 +159,7 @@ FLightDefaults::FLightDefaults(FName name, ELightType type) m_type = type; m_Pos.Zero(); - memset(m_Args, 0, 5); + memset(m_Args, 0, sizeof(m_Args)); m_Param = 0; m_subtractive = false; @@ -1195,8 +1195,8 @@ void gl_SetActorLights(AActor *actor) for(;countdynamiclights.Size();count++) { - actor->dynamiclights[count]->flags2|=MF2_DORMANT; - memset(actor->dynamiclights[count]->args, 0, sizeof(actor->args)); + actor->dynamiclights[count]->flags2 |= MF2_DORMANT; + memset(actor->dynamiclights[count]->args, 0, 3*sizeof(actor->args[0])); } All.Unclock(); } diff --git a/src/p_states.cpp b/src/p_states.cpp index 87a1bae2f..09591d70f 100644 --- a/src/p_states.cpp +++ b/src/p_states.cpp @@ -40,6 +40,8 @@ #include "c_dispatch.h" #include "v_text.h" #include "thingdef.h" +#include "r_state.h" + // stores indices for symbolic state labels for some old-style DECORATE functions. FStateLabelStorage StateLabels; @@ -1092,3 +1094,9 @@ DEFINE_ACTION_FUNCTION(FState, DistanceTo) } ACTION_RETURN_INT(retv); } + +DEFINE_ACTION_FUNCTION(FState, ValidateSpriteFrame) +{ + PARAM_SELF_STRUCT_PROLOGUE(FState); + ACTION_RETURN_BOOL(self->Frame < sprites[self->sprite].numframes); +} \ No newline at end of file diff --git a/src/p_user.cpp b/src/p_user.cpp index 8f2840c3d..af1fbbf2d 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -643,6 +643,11 @@ DEFINE_ACTION_FUNCTION(_PlayerInfo, GetUserName) ACTION_RETURN_STRING(self->userinfo.GetName()); } +DEFINE_ACTION_FUNCTION(_PlayerInfo, GetNeverSwitch) +{ + PARAM_SELF_STRUCT_PROLOGUE(player_t); + ACTION_RETURN_BOOL(self->userinfo.GetNeverSwitch()); +} //=========================================================================== // diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index fe32fbb3e..4e41fce14 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -2359,7 +2359,6 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx) ExpEmit FxAssign::Emit(VMFunctionBuilder *build) { static const BYTE loadops[] = { OP_LK, OP_LKF, OP_LKS, OP_LKP }; - assert(ValueType == Base->ValueType); assert(ValueType->GetRegType() == Right->ValueType->GetRegType()); ExpEmit pointer = Base->Emit(build); diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 2cf48363b..d5e58f653 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -40,6 +40,7 @@ struct Screen native struct Console native { native static void HideConsole(); + native static void MidPrint(string fontname, string textlabel, bool bold = false); // always uses the stringtable. } struct DamageTypeDefinition native @@ -54,6 +55,7 @@ struct GameInfoStruct native native double Armor2Percent; native String ArmorIcon1; native String ArmorIcon2; + native int gametype; } class Object native @@ -65,12 +67,10 @@ class Object native native static double G_SkillPropertyFloat(int p); native static vector3, int G_PickDeathmatchStart(); native static vector3, int G_PickPlayerStart(int pnum, int flags = 0); - native static int GameType(); native static void S_Sound (Sound sound_id, int channel, float volume = 1, float attenuation = ATTN_NORM); native static void S_PauseSound (bool notmusic, bool notsfx); native static void S_ResumeSound (bool notsfx); native static bool S_ChangeMusic(String music_name, int order = 0, bool looping = true, bool force = false); - native static void C_MidPrint(string fontname, string textlabel, bool bold = false); // always uses the stringtable. native static uint BAM(double angle); native static void SetMusicVolume(float vol); @@ -241,6 +241,7 @@ struct State native native bool bDehacked; native int DistanceTo(state other); + native bool ValidateSpriteFrame(); } struct F3DFloor native diff --git a/wadsrc/static/zscript/compatibility.txt b/wadsrc/static/zscript/compatibility.txt index 9334bd619..752de8016 100644 --- a/wadsrc/static/zscript/compatibility.txt +++ b/wadsrc/static/zscript/compatibility.txt @@ -1,4 +1,18 @@ -// This file contains compatibility wrappers for DECORATE functions with bad parameters. +// This file contains compatibility wrappers for DECORATE functions with bad parameters or other things that were refactored since the first release. + +extend class Object +{ + deprecated static int GameType() // deprecated for 2.4.x + { + return gameinfo.gametype; + } + + deprecated static void C_MidPrint(string fontname, string textlabel, bool bold = false) // deprecated for 2.4.x + { + return Console.MidPrint(fontname, textlabel, bold); + } + +} extend class Actor { @@ -16,3 +30,9 @@ extend class StateProvider } } +// this is just a placeholder until the statusbar gets properly exported. +struct StatusBar native +{ + native static void ReceivedWeapon(Weapon weap); +} + diff --git a/wadsrc/static/zscript/hexen/boostarmor.txt b/wadsrc/static/zscript/hexen/boostarmor.txt index f8c797c99..4ed7c7f80 100644 --- a/wadsrc/static/zscript/hexen/boostarmor.txt +++ b/wadsrc/static/zscript/hexen/boostarmor.txt @@ -26,7 +26,7 @@ class ArtiBoostArmor : Inventory { int count = 0; - if (gametype() == GAME_Hexen) + if (gameinfo.gametype == GAME_Hexen) { HexenArmor armor; diff --git a/wadsrc/static/zscript/inventory/inv_misc.txt b/wadsrc/static/zscript/inventory/inv_misc.txt index 9f13ab957..441566786 100644 --- a/wadsrc/static/zscript/inventory/inv_misc.txt +++ b/wadsrc/static/zscript/inventory/inv_misc.txt @@ -124,7 +124,7 @@ class PuzzleItem : Inventory Owner.A_PlaySound ("*puzzfail", CHAN_VOICE); if (Owner.CheckLocalView (consoleplayer)) { - C_MidPrint ("SmallFont", PuzzFailMessage, true); + Console.MidPrint ("SmallFont", PuzzFailMessage, true); } return false; } diff --git a/wadsrc/static/zscript/inventory/weapons.txt b/wadsrc/static/zscript/inventory/weapons.txt index cd558308d..5634c4c49 100644 --- a/wadsrc/static/zscript/inventory/weapons.txt +++ b/wadsrc/static/zscript/inventory/weapons.txt @@ -11,14 +11,14 @@ class Weapon : StateProvider native const ZOOM_NOSCALETURNING = 2; native uint WeaponFlags; - native class AmmoType1, AmmoType2; // Types of ammo used by this weapon + native class AmmoType1, AmmoType2; // Types of ammo used by self weapon native int AmmoGive1, AmmoGive2; // Amount of each ammo to get when picking up weapon - native int MinAmmo1, MinAmmo2; // Minimum ammo needed to switch to this weapon + native int MinAmmo1, MinAmmo2; // Minimum ammo needed to switch to self weapon native int AmmoUse1, AmmoUse2; // How much ammo to use with each shot native int Kickback; native float YAdjust; // For viewing the weapon fullscreen (visual only so no need to be a double) native sound UpSound, ReadySound; // Sounds when coming up and idle - native class SisterWeaponType; // Another weapon to pick up with this one + native class SisterWeaponType; // Another weapon to pick up with self one native class ProjectileType; // Projectile used by primary attack native class AltProjectileType; // Projectile used by alternate attack native int SelectionOrder; // Lower-numbered weapons get picked first @@ -33,7 +33,7 @@ class Weapon : StateProvider native native float FOVScale; native int Crosshair; // 0 to use player's crosshair native bool GivenAsMorphWeapon; - native bool bAltFire; // Set when this weapon's alternate fire is used. + native bool bAltFire; // Set when self weapon's alternate fire is used. native readonly bool bDehAmmo; Default @@ -55,7 +55,6 @@ class Weapon : StateProvider native native bool CheckAmmo(int fireMode, bool autoSwitch, bool requireAmmo = false, int ammocount = -1); native bool DepleteAmmo(bool altFire, bool checkEnough = true, int ammouse = -1); - native virtual void EndPowerup(); virtual State GetReadyState () { @@ -248,6 +247,398 @@ class Weapon : StateProvider native player.ReadyWeapon.Crosshair = xhair; } } + + //=========================================================================== + // + // AWeapon :: TryPickup + // + // If you can't see the weapon when it's active, then you can't pick it up. + // + //=========================================================================== + + override bool TryPickupRestricted (in out Actor toucher) + { + // Wrong class, but try to pick up for ammo + if (ShouldStay()) + { // Can't pick up weapons for other classes in coop netplay + return false; + } + + bool gaveSome = (NULL != AddAmmo (toucher, AmmoType1, AmmoGive1)); + gaveSome |= (NULL != AddAmmo (toucher, AmmoType2, AmmoGive2)); + if (gaveSome) + { + GoAwayAndDie (); + } + return gaveSome; + } + + //=========================================================================== + // + // AWeapon :: TryPickup + // + //=========================================================================== + + override bool TryPickup (in out Actor toucher) + { + State ReadyState = FindState('Ready'); + if (ReadyState != NULL && ReadyState.ValidateSpriteFrame()) + { + return Super.TryPickup (toucher); + } + return false; + } + + //=========================================================================== + // + // AWeapon :: Use + // + // Make the player switch to self weapon. + // + //=========================================================================== + + override bool Use (bool pickup) + { + Weapon useweap = self; + + // Powered up weapons cannot be used directly. + if (bPowered_Up) return false; + + // If the player is powered-up, use the alternate version of the + // weapon, if one exists. + if (SisterWeapon != NULL && + SisterWeapon.bPowered_Up && + Owner.FindInventory ("PowerWeaponLevel2", true)) + { + useweap = SisterWeapon; + } + if (Owner.player != NULL && Owner.player.ReadyWeapon != useweap) + { + Owner.player.PendingWeapon = useweap; + } + // Return false so that the weapon is not removed from the inventory. + return false; + } + + //=========================================================================== + // + // AWeapon :: Destroy + // + //=========================================================================== + + override void OnDestroy() + { + let sister = SisterWeapon; + + if (sister != NULL) + { + // avoid recursion + sister.SisterWeapon = NULL; + if (sister != self) + { // In case we are our own sister, don't crash. + sister.Destroy(); + } + } + Super.OnDestroy(); + } + + + //=========================================================================== + // + // AWeapon :: HandlePickup + // + // Try to leach ammo from the weapon if you have it already. + // + //=========================================================================== + + override bool HandlePickup (Inventory item) + { + if (item.GetClass() == GetClass()) + { + if (Weapon(item).PickupForAmmo (self)) + { + item.bPickupGood = true; + } + if (MaxAmount > 1) //[SP] If amount 0) gotstuff = AddExistingAmmo (ownedWeapon.Ammo1, AmmoGive1); + if (AmmoGive2 > 0) gotstuff |= AddExistingAmmo (ownedWeapon.Ammo2, AmmoGive2); + + let Owner = ownedWeapon.Owner; + if (gotstuff && Owner != NULL && Owner.player != NULL) + { + if (ownedWeapon.Ammo1 != NULL && oldamount1 == 0) + { + PlayerPawn(Owner).CheckWeaponSwitch(ownedWeapon.Ammo1.GetClass()); + } + else if (ownedWeapon.Ammo2 != NULL && oldamount2 == 0) + { + PlayerPawn(Owner).CheckWeaponSwitch(ownedWeapon.Ammo2.GetClass()); + } + } + } + return gotstuff; + } + + //=========================================================================== + // + // AWeapon :: CreateCopy + // + //=========================================================================== + + override Inventory CreateCopy (Actor other) + { + let copy = Weapon(Super.CreateCopy (other)); + if (copy != self && copy != null) + { + copy.AmmoGive1 = AmmoGive1; + copy.AmmoGive2 = AmmoGive2; + } + return copy; + } + + //=========================================================================== + // + // AWeapon :: CreateTossable + // + // A weapon that's tossed out should contain no ammo, so you can't cheat + // by dropping it and then picking it back up. + // + //=========================================================================== + + override Inventory CreateTossable () + { + // Only drop the weapon that is meant to be placed in a level. That is, + // only drop the weapon that normally gives you ammo. + if (SisterWeapon != NULL && + Default.AmmoGive1 == 0 && Default.AmmoGive2 == 0 && + (SisterWeapon.Default.AmmoGive1 > 0 || SisterWeapon.Default.AmmoGive2 > 0)) + { + return SisterWeapon.CreateTossable (); + } + let copy = Weapon(Super.CreateTossable ()); + + if (copy != NULL) + { + // If self weapon has a sister, remove it from the inventory too. + if (SisterWeapon != NULL) + { + SisterWeapon.SisterWeapon = NULL; + SisterWeapon.Destroy (); + } + // To avoid exploits, the tossed weapon must not have any ammo. + copy.AmmoGive1 = 0; + copy.AmmoGive2 = 0; + } + return copy; + } + + //=========================================================================== + // + // AWeapon :: AttachToOwner + // + //=========================================================================== + + override void AttachToOwner (Actor other) + { + Super.AttachToOwner (other); + + Ammo1 = AddAmmo (Owner, AmmoType1, AmmoGive1); + Ammo2 = AddAmmo (Owner, AmmoType2, AmmoGive2); + SisterWeapon = AddWeapon (SisterWeaponType); + if (Owner.player != NULL) + { + if (!Owner.player.GetNeverSwitch() && !bNo_Auto_Switch) + { + Owner.player.PendingWeapon = self; + } + if (Owner.player.mo == players[consoleplayer].camera) + { + StatusBar.ReceivedWeapon (self); + } + } + GivenAsMorphWeapon = false; // will be set explicitly by morphing code + } + + //=========================================================================== + // + // AWeapon :: AddAmmo + // + // Give some ammo to the owner, even if it's just 0. + // + //=========================================================================== + + protected Ammo AddAmmo (Actor other, Class ammotype, int amount) + { + Ammo ammoitem; + + if (ammotype == NULL) + { + return NULL; + } + + // [BC] This behavior is from the original Doom. Give 5/2 times as much ammoitem when + // we pick up a weapon in deathmatch. + if (( deathmatch ) && ( gameinfo.gametype & GAME_DoomChex )) + amount = amount * 5 / 2; + + // extra ammoitem in baby mode and nightmare mode + if (!bIgnoreSkill) + { + amount = int(amount * G_SkillPropertyFloat(SKILLP_AmmoFactor)); + } + ammoitem = Ammo(other.FindInventory (ammotype)); + if (ammoitem == NULL) + { + ammoitem = Ammo(Spawn (ammotype)); + ammoitem.Amount = MIN (amount, ammoitem.MaxAmount); + ammoitem.AttachToOwner (other); + } + else if (ammoitem.Amount < ammoitem.MaxAmount) + { + ammoitem.Amount += amount; + if (ammoitem.Amount > ammoitem.MaxAmount) + { + ammoitem.Amount = ammoitem.MaxAmount; + } + } + return ammoitem; + } + + //=========================================================================== + // + // AWeapon :: AddExistingAmmo + // + // Give the owner some more ammo he already has. + // + //=========================================================================== + + protected bool AddExistingAmmo (Inventory ammo, int amount) + { + if (ammo != NULL && (ammo.Amount < ammo.MaxAmount || sv_unlimited_pickup)) + { + // extra ammo in baby mode and nightmare mode + if (!bIgnoreSkill) + { + amount = int(amount * G_SkillPropertyFloat(SKILLP_AmmoFactor)); + } + ammo.Amount += amount; + if (ammo.Amount > ammo.MaxAmount && !sv_unlimited_pickup) + { + ammo.Amount = ammo.MaxAmount; + } + return true; + } + return false; + } + + //=========================================================================== + // + // AWeapon :: AddWeapon + // + // Give the owner a weapon if they don't have it already. + // + //=========================================================================== + + protected Weapon AddWeapon (Class weapontype) + { + Weapon weap; + + if (weapontype == NULL) + { + return NULL; + } + weap = Weapon(Owner.FindInventory (weapontype)); + if (weap == NULL) + { + weap = Weapon(Spawn (weapontype)); + weap.AttachToOwner (Owner); + } + return weap; + } + + //=========================================================================== + // + // AWeapon :: ShouldStay + // + //=========================================================================== + + override bool ShouldStay () + { + if (((multiplayer && + (!deathmatch && !alwaysapplydmflags)) || sv_weaponstay) && + !bDropped) + { + return true; + } + return false; + } + + + //=========================================================================== + // + // AWeapon :: EndPowerUp + // + // The Tome of Power just expired. + // + //=========================================================================== + + virtual void EndPowerup () + { + let player = Owner.player; + if (SisterWeapon != NULL && bPowered_Up) + { + if (GetReadyState() != SisterWeapon.GetReadyState()) + { + if (player.PendingWeapon == NULL || player.PendingWeapon == WP_NOCHANGE) + player.PendingWeapon = SisterWeapon; + } + else + { + let psp = player.FindPSprite(PSP_WEAPON); + if (psp != null && psp.Caller == player.ReadyWeapon) + { + // If the weapon changes but the state does not, we have to manually change the PSprite's caller here. + psp.Caller = SisterWeapon; + player.ReadyWeapon = SisterWeapon; + } + else + { + // Something went wrong. Initiate a regular weapon change. + player.PendingWeapon = SisterWeapon; + } + } + } + } + + } class WeaponGiver : Weapon @@ -276,7 +667,7 @@ class WeaponGiver : Weapon master = weap = Weapon(Spawn(di.Name)); if (weap != NULL) { - weap.bAlwaysPickup = false; // use the flag of this item only. + weap.bAlwaysPickup = false; // use the flag of self item only. weap.bDropped = bDropped; // If our ammo gives are non-negative, transfer them to the real weapon. diff --git a/wadsrc/static/zscript/raven/minotaur.txt b/wadsrc/static/zscript/raven/minotaur.txt index 06bb6daae..d45ce03f6 100644 --- a/wadsrc/static/zscript/raven/minotaur.txt +++ b/wadsrc/static/zscript/raven/minotaur.txt @@ -252,8 +252,7 @@ class Minotaur : Actor { Class type; - //if (gameinfo.gametype == GAME_Heretic) - if (gametype() == GAME_Heretic) + if (gameinfo.gametype == GAME_Heretic) { type = "PhoenixPuff"; } diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index e90f85a78..73b00a269 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -308,6 +308,7 @@ userinfo_t userinfo; native void SetLogNumber (int text); native void SetLogText (String text); native String GetUserName(); + native bool GetNeverSwitch(); native void DropWeapon(); native void BringUpWeapon(); diff --git a/wadsrc/static/zscript/shared/player_cheat.txt b/wadsrc/static/zscript/shared/player_cheat.txt index b88c387a1..b8c24b30f 100644 --- a/wadsrc/static/zscript/shared/player_cheat.txt +++ b/wadsrc/static/zscript/shared/player_cheat.txt @@ -123,7 +123,7 @@ extend class PlayerPawn if (giveall || name ~== "armor") { - if (GameType() != GAME_Hexen) + if (gameinfo.gametype != GAME_Hexen) { let armoritem = BasicArmorPickup(Spawn("BasicArmorPickup")); armoritem.SaveAmount = 100*deh.BlueAC; diff --git a/wadsrc/static/zscript/shared/teleport.txt b/wadsrc/static/zscript/shared/teleport.txt index acf4a6d75..dd43bb1fa 100644 --- a/wadsrc/static/zscript/shared/teleport.txt +++ b/wadsrc/static/zscript/shared/teleport.txt @@ -27,7 +27,7 @@ class TeleportFog : Actor { Super.PostBeginPlay (); A_PlaySound ("misc/teleport", CHAN_BODY); - switch (gametype()) + switch (gameinfo.gametype) { case GAME_Hexen: case GAME_Heretic: diff --git a/wadsrc/static/zscript/strife/alienspectres.txt b/wadsrc/static/zscript/strife/alienspectres.txt index d65142582..d17d91eb2 100644 --- a/wadsrc/static/zscript/strife/alienspectres.txt +++ b/wadsrc/static/zscript/strife/alienspectres.txt @@ -108,13 +108,13 @@ class AlienSpectre1 : SpectralMonster } else if (cls == "AlienSpectre2") { - C_MidPrint("SmallFont", "$TXT_KILLED_BISHOP"); + Console.MidPrint("SmallFont", "$TXT_KILLED_BISHOP"); log = 74; player.GiveInventoryType ("QuestItem21"); } else if (cls == "AlienSpectre3") { - C_MidPrint("SmallFont", "$TXT_KILLED_ORACLE"); + Console.MidPrint("SmallFont", "$TXT_KILLED_ORACLE"); // If there are any Oracles still alive, kill them. ThinkerIterator it = ThinkerIterator.Create("Oracle"); Actor oracle; @@ -144,7 +144,7 @@ class AlienSpectre1 : SpectralMonster } else if (cls == "AlienSpectre4") { - C_MidPrint("SmallFont", "$TXT_KILLED_MACIL"); + Console.MidPrint("SmallFont", "$TXT_KILLED_MACIL"); player.GiveInventoryType ("QuestItem24"); if (player.FindInventory ("QuestItem25") == null) { // Richter has taken over. Macil is a snake. @@ -157,7 +157,7 @@ class AlienSpectre1 : SpectralMonster } else if (cls == "AlienSpectre5") { - C_MidPrint("SmallFont", "$TXT_KILLED_LOREMASTER"); + Console.MidPrint("SmallFont", "$TXT_KILLED_LOREMASTER"); player.GiveInventoryType ("QuestItem26"); if (!multiplayer) diff --git a/wadsrc/static/zscript/strife/strifeitems.txt b/wadsrc/static/zscript/strife/strifeitems.txt index 4368564cd..970478cae 100644 --- a/wadsrc/static/zscript/strife/strifeitems.txt +++ b/wadsrc/static/zscript/strife/strifeitems.txt @@ -531,7 +531,7 @@ class Scanner : PowerupGiver { if (Owner.CheckLocalView (consoleplayer)) { - C_MidPrint("SmallFont", "$TXT_NEEDMAP"); + Console.MidPrint("SmallFont", "$TXT_NEEDMAP"); } return false; } diff --git a/wadsrc/static/zscript/strife/thingstoblowup.txt b/wadsrc/static/zscript/strife/thingstoblowup.txt index 5e5bfac21..bb268838c 100644 --- a/wadsrc/static/zscript/strife/thingstoblowup.txt +++ b/wadsrc/static/zscript/strife/thingstoblowup.txt @@ -32,7 +32,7 @@ extend class Actor if (msg != msgid) // if both are identical there was no message of this name in the stringtable. { - C_MidPrint ("SmallFont", msg); + Console.MidPrint ("SmallFont", msg); } }