diff --git a/src/c_console.cpp b/src/c_console.cpp index 2c08d11ae..b9996dcd8 100644 --- a/src/c_console.cpp +++ b/src/c_console.cpp @@ -1753,7 +1753,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/d_net.cpp b/src/d_net.cpp index c47ae6bd1..d9eca7a43 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -2109,6 +2109,11 @@ static int RemoveClass(const PClass *cls) player = true; continue; } + // [SP] Don't remove owned inventory objects. + if (static_cast(actor)->Owner != NULL) + { + continue; + } removecount++; actor->ClearCounters(); actor->Destroy(); diff --git a/src/g_inventory/a_weapons.cpp b/src/g_inventory/a_weapons.cpp index 1b7745979..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 @@ -936,65 +536,6 @@ FState *AWeapon::GetStateForButtonName (FName button) } -/* Weapon giver ***********************************************************/ - -IMPLEMENT_CLASS(AWeaponGiver, false, false) - -DEFINE_FIELD(AWeaponGiver, DropAmmoFactor); - -void AWeaponGiver::Serialize(FSerializer &arc) -{ - Super::Serialize(arc); - auto def = (AWeaponGiver *)GetDefault(); - arc("dropammofactor", DropAmmoFactor, def->DropAmmoFactor); -} - -bool AWeaponGiver::TryPickup(AActor *&toucher) -{ - DDropItem *di = GetDropItems(); - AWeapon *weap; - - if (di != NULL) - { - PClassWeapon *ti = dyn_cast(PClass::FindClass(di->Name)); - if (ti != NULL) - { - if (master == NULL) - { - master = weap = static_cast(Spawn(di->Name)); - if (weap != NULL) - { - weap->ItemFlags &= ~IF_ALWAYSPICKUP; // use the flag of this item only. - weap->flags = (weap->flags & ~MF_DROPPED) | (this->flags & MF_DROPPED); - - // If our ammo gives are non-negative, transfer them to the real weapon. - if (AmmoGive1 >= 0) weap->AmmoGive1 = AmmoGive1; - if (AmmoGive2 >= 0) weap->AmmoGive2 = AmmoGive2; - - // If DropAmmoFactor is non-negative, modify the given ammo amounts. - if (DropAmmoFactor > 0) - { - weap->AmmoGive1 = int(weap->AmmoGive1 * DropAmmoFactor); - weap->AmmoGive2 = int(weap->AmmoGive2 * DropAmmoFactor); - } - weap->BecomeItem(); - } - else return false; - } - - weap = barrier_cast(master); - bool res = weap->CallTryPickup(toucher); - if (res) - { - GoAwayAndDie(); - master = NULL; - } - return res; - } - } - return false; -} - /* Weapon slots ***********************************************************/ //=========================================================================== @@ -2079,48 +1620,3 @@ PClassWeapon *Net_ReadWeapon(BYTE **stream) return Weapons_ntoh[index]; } -//=========================================================================== -// -// A_ZoomFactor -// -//=========================================================================== - -DEFINE_ACTION_FUNCTION(AWeapon, A_ZoomFactor) -{ - PARAM_ACTION_PROLOGUE(AActor); - PARAM_FLOAT_DEF(zoom); - PARAM_INT_DEF(flags); - - if (self->player != NULL && self->player->ReadyWeapon != NULL) - { - zoom = 1 / clamp(zoom, 0.1, 50.0); - if (flags & 1) - { // Make the zoom instant. - self->player->FOV = float(self->player->DesiredFOV * zoom); - } - if (flags & 2) - { // Disable pitch/yaw scaling. - zoom = -zoom; - } - self->player->ReadyWeapon->FOVScale = float(zoom); - } - return 0; -} - -//=========================================================================== -// -// A_SetCrosshair -// -//=========================================================================== - -DEFINE_ACTION_FUNCTION(AWeapon, A_SetCrosshair) -{ - PARAM_ACTION_PROLOGUE(AActor); - PARAM_INT(xhair); - - if (self->player != NULL && self->player->ReadyWeapon != NULL) - { - self->player->ReadyWeapon->Crosshair = xhair; - } - return 0; -} diff --git a/src/g_inventory/a_weapons.h b/src/g_inventory/a_weapons.h index ed18df421..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 @@ -217,14 +200,3 @@ enum WIF_BOT_BFG = 1<<28, // this is a BFG }; -class AWeaponGiver : public AWeapon -{ - DECLARE_CLASS (AWeaponGiver, AWeapon) - -public: - virtual bool TryPickup(AActor *&toucher) override; - virtual void Serialize(FSerializer &arc) override; - - double DropAmmoFactor; -}; - 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 acc23d955..4180f272f 100644 --- a/src/gl/dynlights/a_dynlight.cpp +++ b/src/gl/dynlights/a_dynlight.cpp @@ -208,6 +208,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/namedef.h b/src/namedef.h index b730e93aa..20953a8fe 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -185,6 +185,7 @@ xx(PuzzleItemNumber) xx(HealthPickup) xx(autousemode) xx(Ammo) +xx(WeaponGiver) xx(PowerTargeter) xx(PowerInvulnerable) xx(PowerStrength) diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index e4a902b44..bb90e976f 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -3248,9 +3248,9 @@ void ModifyDropAmount(AInventory *inv, int dropamount) inv->Amount = amount; inv->ItemFlags |= flagmask; } - else if (inv->IsKindOf (RUNTIME_CLASS(AWeaponGiver))) + else if (inv->IsKindOf (PClass::FindActor(NAME_WeaponGiver))) { - static_cast(inv)->DropAmmoFactor = dropammofactor; + inv->FloatVar("AmmoFactor") = dropammofactor; inv->ItemFlags |= flagmask; } else if (inv->IsKindOf (RUNTIME_CLASS(AWeapon))) diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index 4128dca12..7a8c85ed1 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -36,7 +36,6 @@ // MACROS ------------------------------------------------------------------ #define LOWERSPEED 6. -#define RAISESPEED 6. // TYPES ------------------------------------------------------------------- @@ -511,6 +510,13 @@ void P_BringUpWeapon (player_t *player) } } +DEFINE_ACTION_FUNCTION(_PlayerInfo, BringUpWeapon) +{ + PARAM_SELF_STRUCT_PROLOGUE(player_t); + P_BringUpWeapon(self); + return 0; +} + //--------------------------------------------------------------------------- // // PROC P_FireWeapon @@ -607,6 +613,12 @@ void P_DropWeapon (player_t *player) } } +DEFINE_ACTION_FUNCTION(_PlayerInfo, DropWeapon) +{ + PARAM_SELF_STRUCT_PROLOGUE(player_t); + P_DropWeapon(self); + return 0; +} //============================================================================ // // P_BobWeapon @@ -1003,40 +1015,6 @@ void A_ReFire(AActor *self, FState *state) } } -DEFINE_ACTION_FUNCTION(AStateProvider, A_ClearReFire) -{ - PARAM_ACTION_PROLOGUE(AStateProvider); - player_t *player = self->player; - - if (NULL != player) - { - player->refire = 0; - } - return 0; -} - -//--------------------------------------------------------------------------- -// -// PROC A_CheckReload -// -// Present in Doom, but unused. Also present in Strife, and actually used. -// This and what I call A_XBowReFire are actually the same thing in Strife, -// not two separate functions as I have them here. -// -//--------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AStateProvider, A_CheckReload) -{ - PARAM_ACTION_PROLOGUE(AStateProvider); - - if (self->player != NULL) - { - self->player->ReadyWeapon->CheckAmmo ( - self->player->ReadyWeapon->bAltFire ? AWeapon::AltFire - : AWeapon::PrimaryFire, true); - } - return 0; -} //--------------------------------------------------------------------------- // @@ -1272,95 +1250,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_OverlayRenderStyle) return 0; } -//--------------------------------------------------------------------------- -// -// PROC A_Lower -// -//--------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AStateProvider, A_Lower) -{ - PARAM_ACTION_PROLOGUE(AStateProvider); - - player_t *player = self->player; - DPSprite *psp; - - if (nullptr == player) - { - return 0; - } - if (nullptr == player->ReadyWeapon) - { - P_BringUpWeapon(player); - return 0; - } - psp = player->GetPSprite(PSP_WEAPON); - if (player->morphTics || player->cheats & CF_INSTANTWEAPSWITCH) - { - psp->y = WEAPONBOTTOM; - } - else - { - psp->y += LOWERSPEED; - } - if (psp->y < WEAPONBOTTOM) - { // Not lowered all the way yet - return 0; - } - if (player->playerstate == PST_DEAD) - { // Player is dead, so don't bring up a pending weapon - // Player is dead, so keep the weapon off screen - P_SetPsprite(player, PSP_FLASH, nullptr); - psp->SetState(player->ReadyWeapon->FindState(NAME_DeadLowered)); - return 0; - } - // [RH] Clear the flash state. Only needed for Strife. - P_SetPsprite(player, PSP_FLASH, nullptr); - P_BringUpWeapon (player); - return 0; -} - -//--------------------------------------------------------------------------- -// -// PROC A_Raise -// -//--------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AStateProvider, A_Raise) -{ - PARAM_ACTION_PROLOGUE(AStateProvider); - - if (self == nullptr) - { - return 0; - } - player_t *player = self->player; - DPSprite *psp; - - if (nullptr == player) - { - return 0; - } - if (player->PendingWeapon != WP_NOCHANGE) - { - P_DropWeapon(player); - return 0; - } - if (player->ReadyWeapon == nullptr) - { - return 0; - } - psp = player->GetPSprite(PSP_WEAPON); - psp->y -= RAISESPEED; - if (psp->y > WEAPONTOP) - { // Not raised all the way yet - return 0; - } - psp->y = WEAPONTOP; - psp->SetState(player->ReadyWeapon->GetReadyState()); - return 0; -} - //--------------------------------------------------------------------------- // // PROC A_Overlay @@ -1430,47 +1319,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_ClearOverlays) ACTION_RETURN_INT(count); } -// -// A_GunFlash -// -enum GF_Flags -{ - GFF_NOEXTCHANGE = 1, -}; - -DEFINE_ACTION_FUNCTION(AStateProvider, A_GunFlash) -{ - PARAM_ACTION_PROLOGUE(AStateProvider); - PARAM_STATE_ACTION_DEF(flash); - PARAM_INT_DEF(flags); - - player_t *player = self->player; - - if (nullptr == player) - { - return 0; - } - if (!(flags & GFF_NOEXTCHANGE)) - { - player->mo->PlayAttacking2 (); - } - if (flash == nullptr) - { - if (player->ReadyWeapon->bAltFire) - { - flash = player->ReadyWeapon->FindState(NAME_AltFlash); - } - if (flash == nullptr) - { - flash = player->ReadyWeapon->FindState(NAME_Flash); - } - } - P_SetPsprite(player, PSP_FLASH, flash); - return 0; -} - - - // // WEAPON ATTACKS // @@ -1516,20 +1364,6 @@ DEFINE_ACTION_FUNCTION(AActor, BulletSlope) ACTION_RETURN_FLOAT(P_BulletSlope(self, t, aimflags).Degrees); } - -AActor *P_AimTarget(AActor *mo) -{ - FTranslatedLineTarget t; - P_BulletSlope(mo, &t, ALF_PORTALRESTRICT); - return t.linetarget; -} - -DEFINE_ACTION_FUNCTION(AActor, AimTarget) -{ - PARAM_SELF_PROLOGUE(AActor); - ACTION_RETURN_OBJECT(P_AimTarget(self)); -} - //------------------------------------------------------------------------ // // PROC P_SetupPsprites 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 aabf9f959..633cc7f6e 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.txt b/wadsrc/static/zscript.txt index 6f0e3a516..7cd9722bc 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -8,6 +8,7 @@ #include "zscript/inventory/inventory.txt" #include "zscript/inventory/inv_misc.txt" +#include "zscript/inventory/stateprovider.txt" #include "zscript/inventory/weapons.txt" #include "zscript/inventory/weaponpiece.txt" #include "zscript/inventory/armor.txt" diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index f8ee566d9..1e3c6fad0 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -373,7 +373,7 @@ class Actor : Thinker native native void SetXYZ(vector3 newpos); native Actor GetPointer(int aaptr); native double BulletSlope(out FTranslatedLineTarget pLineTarget = null, int aimflags = 0); - native Actor AimTarget(); + native bool CheckMissileSpawn(double maxdist); native bool CheckPosition(Vector2 pos, bool actorsonly = false, FCheckPosition tm = null); native bool TestMobjLocation(); @@ -693,6 +693,12 @@ class Actor : Thinker native return true; } + Actor AimTarget() + { + FTranslatedLineTarget t; + BulletSlope(t, ALF_PORTALRESTRICT); + return t.linetarget; + } native void A_Face(Actor faceto, double max_turn = 0, double max_pitch = 270, double ang_offset = 0, double pitch_offset = 0, int flags = 0, double z_ofs = 0); 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/inventory.txt b/wadsrc/static/zscript/inventory/inventory.txt index 2b0d6d0c7..ea76ab1d9 100644 --- a/wadsrc/static/zscript/inventory/inventory.txt +++ b/wadsrc/static/zscript/inventory/inventory.txt @@ -194,25 +194,6 @@ class Inventory : Actor native } -class StateProvider : Inventory native -{ - action native state A_JumpIfNoAmmo(statelabel label); - action native void A_CustomPunch(int damage, bool norandom = false, int flags = CPF_USEAMMO, class pufftype = "BulletPuff", double range = 0, double lifesteal = 0, int lifestealmax = 0, class armorbonustype = "ArmorBonus", sound MeleeSound = 0, sound MissSound = ""); - action native void A_FireBullets(double spread_xy, double spread_z, int numbullets, int damageperbullet, class pufftype = "BulletPuff", int flags = 1, double range = 0, class missile = null, double Spawnheight = 32, double Spawnofs_xy = 0); - action native void A_FireProjectile(class missiletype, double angle = 0, bool useammo = true, double spawnofs_xy = 0, double spawnheight = 0, int flags = 0, double pitch = 0); - action native void A_RailAttack(int damage, int spawnofs_xy = 0, bool useammo = true, color color1 = 0, color color2 = 0, int flags = 0, double maxdiff = 0, class pufftype = "BulletPuff", double spread_xy = 0, double spread_z = 0, double range = 0, int duration = 0, double sparsity = 1.0, double driftspeed = 1.0, class spawnclass = "none", double spawnofs_z = 0, int spiraloffset = 270, int limit = 0); - action native void A_WeaponReady(int flags = 0); - action native void A_Lower(); - action native void A_Raise(); - - action native void A_ReFire(statelabel flash = null); - action native void A_ClearReFire(); - action native void A_CheckReload(); - action native void A_GunFlash(statelabel flash = null, int flags = 0); - action native state A_CheckForReload(int counter, statelabel label, bool dontincrement = false); - action native void A_ResetReloadCounter(); -} - class DehackedPickup : Inventory native { } @@ -221,11 +202,3 @@ class FakeInventory : Inventory native { native bool Respawnable; } - -class CustomInventory : StateProvider native -{ - Default - { - DefaultStateUsage SUF_ACTOR|SUF_OVERLAY|SUF_ITEM; - } -} diff --git a/wadsrc/static/zscript/inventory/stateprovider.txt b/wadsrc/static/zscript/inventory/stateprovider.txt new file mode 100644 index 000000000..fe5d39bac --- /dev/null +++ b/wadsrc/static/zscript/inventory/stateprovider.txt @@ -0,0 +1,39 @@ + +class StateProvider : Inventory native +{ + action native state A_JumpIfNoAmmo(statelabel label); + action native void A_CustomPunch(int damage, bool norandom = false, int flags = CPF_USEAMMO, class pufftype = "BulletPuff", double range = 0, double lifesteal = 0, int lifestealmax = 0, class armorbonustype = "ArmorBonus", sound MeleeSound = 0, sound MissSound = ""); + action native void A_FireBullets(double spread_xy, double spread_z, int numbullets, int damageperbullet, class pufftype = "BulletPuff", int flags = 1, double range = 0, class missile = null, double Spawnheight = 32, double Spawnofs_xy = 0); + action native void A_FireProjectile(class missiletype, double angle = 0, bool useammo = true, double spawnofs_xy = 0, double spawnheight = 0, int flags = 0, double pitch = 0); + action native void A_RailAttack(int damage, int spawnofs_xy = 0, bool useammo = true, color color1 = 0, color color2 = 0, int flags = 0, double maxdiff = 0, class pufftype = "BulletPuff", double spread_xy = 0, double spread_z = 0, double range = 0, int duration = 0, double sparsity = 1.0, double driftspeed = 1.0, class spawnclass = "none", double spawnofs_z = 0, int spiraloffset = 270, int limit = 0); + action native void A_WeaponReady(int flags = 0); + + action native void A_ReFire(statelabel flash = null); + action native state A_CheckForReload(int counter, statelabel label, bool dontincrement = false); + action native void A_ResetReloadCounter(); +} + +class CustomInventory : StateProvider native +{ + Default + { + DefaultStateUsage SUF_ACTOR|SUF_OVERLAY|SUF_ITEM; + } + + //--------------------------------------------------------------------------- + // + // + //--------------------------------------------------------------------------- + + action void A_ClearReFire() + { + if (NULL != player) player.refire = 0; + } + + + // This is only here, because these functions were originally exported on Inventory, despite only working for weapons, so this is here to satisfy some potential old mods having called it through CustomInventory. + deprecated action void A_GunFlash(statelabel flash = null, int flags = 0) {} + deprecated action void A_Lower() {} + deprecated action void A_Raise() {} + deprecated action void A_CheckReload() {} +} diff --git a/wadsrc/static/zscript/inventory/weapons.txt b/wadsrc/static/zscript/inventory/weapons.txt index 303dc6aa9..5634c4c49 100644 --- a/wadsrc/static/zscript/inventory/weapons.txt +++ b/wadsrc/static/zscript/inventory/weapons.txt @@ -7,15 +7,18 @@ class Weapon : StateProvider native EitherFire }; + const ZOOM_INSTANT = 1; + 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 @@ -30,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 @@ -52,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 () { @@ -85,23 +87,621 @@ class Weapon : StateProvider native return s; } - native action void A_ZoomFactor(double scale = 1, int flags = 0); - native action void A_SetCrosshair(int xhair); - const ZOOM_INSTANT = 1; - const ZOOM_NOSCALETURNING = 2; + action void A_GunFlash(statelabel flashlabel = null, int flags = 0) + { + let player = player; + + if (null == player || player.ReadyWeapon == null) + { + return; + } + if (!(flags & GFF_NOEXTCHANGE)) + { + player.mo.PlayAttacking2 (); + } + if (flashlabel == null) + { + if (player.ReadyWeapon.bAltFire) + { + flashlabel = 'AltFlash'; + } + if (flashlabel == null) + { + flashlabel = 'Flash'; + } + } + player.SetPsprite(PSP_FLASH, player.ReadyWeapon.FindState(flashlabel)); + } + //--------------------------------------------------------------------------- + // + // PROC A_Lower + // + //--------------------------------------------------------------------------- + + action void A_Lower(int lowerspeed = 6) + { + let player = player; + + if (null == player) + { + return; + } + if (null == player.ReadyWeapon) + { + player.BringUpWeapon(); + return; + } + let psp = player.GetPSprite(PSP_WEAPON); + if (player.morphTics || player.cheats & CF_INSTANTWEAPSWITCH) + { + psp.y = WEAPONBOTTOM; + } + else + { + psp.y += lowerspeed; + } + if (psp.y < WEAPONBOTTOM) + { // Not lowered all the way yet + return; + } + if (player.playerstate == PST_DEAD) + { // Player is dead, so don't bring up a pending weapon + // Player is dead, so keep the weapon off screen + player.SetPsprite(PSP_FLASH, null); + psp.SetState(player.ReadyWeapon.FindState('DeadLowered')); + return; + } + // [RH] Clear the flash state. Only needed for Strife. + player.SetPsprite(PSP_FLASH, null); + player.BringUpWeapon (); + return; + } + + //--------------------------------------------------------------------------- + // + // PROC A_Raise + // + //--------------------------------------------------------------------------- + + action void A_Raise(int raisespeed = 6) + { + let player = player; + + if (null == player) + { + return; + } + if (player.PendingWeapon != WP_NOCHANGE) + { + player.DropWeapon(); + return; + } + if (player.ReadyWeapon == null) + { + return; + } + let psp = player.GetPSprite(PSP_WEAPON); + psp.y -= raisespeed; + if (psp.y > WEAPONTOP) + { // Not raised all the way yet + return; + } + psp.y = WEAPONTOP; + psp.SetState(player.ReadyWeapon.GetReadyState()); + return; + } + + //--------------------------------------------------------------------------- + // + // PROC A_CheckReload + // + // Present in Doom, but unused. Also present in Strife, and actually used. + // + //--------------------------------------------------------------------------- + + action void A_CheckReload() + { + let player = self.player; + if (player != NULL) + { + player.ReadyWeapon.CheckAmmo (player.ReadyWeapon.bAltFire ? Weapon.AltFire : Weapon.PrimaryFire, true); + } + } + + //=========================================================================== + // + // A_ZoomFactor + // + //=========================================================================== + + action void A_ZoomFactor(double zoom = 1, int flags = 0) + { + let player = self.player; + if (player != NULL && player.ReadyWeapon != NULL) + { + zoom = 1 / clamp(zoom, 0.1, 50.0); + if (flags & 1) + { // Make the zoom instant. + self.player.FOV = self.player.DesiredFOV * zoom; + } + if (flags & 2) + { // Disable pitch/yaw scaling. + zoom = -zoom; + } + self.player.ReadyWeapon.FOVScale = zoom; + } + } + + //=========================================================================== + // + // A_SetCrosshair + // + //=========================================================================== + + action void A_SetCrosshair(int xhair) + { + let player = self.player; + if (player != NULL && player.ReadyWeapon != NULL) + { + 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 native +class WeaponGiver : Weapon { - - native double DropAmmoFactor; + double AmmoFactor; Default { Weapon.AmmoGive1 -1; Weapon.AmmoGive2 -1; } + + override bool TryPickup(in out Actor toucher) + { + DropItem di = GetDropItems(); + Weapon weap; + + if (di != NULL) + { + Class ti = di.Name; + if (ti != NULL) + { + if (master == NULL) + { + // save the spawned weapon in 'master' to avoid constant respawning if it cannot be picked up. + master = weap = Weapon(Spawn(di.Name)); + if (weap != NULL) + { + 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. + if (AmmoGive1 >= 0) weap.AmmoGive1 = AmmoGive1; + if (AmmoGive2 >= 0) weap.AmmoGive2 = AmmoGive2; + + // If AmmoFactor is non-negative, modify the given ammo amounts. + if (AmmoFactor > 0) + { + weap.AmmoGive1 = int(weap.AmmoGive1 * AmmoFactor); + weap.AmmoGive2 = int(weap.AmmoGive2 * AmmoFactor); + } + weap.BecomeItem(); + } + else return false; + } + + weap = Weapon(master); + bool res = false; + if (weap != null) + { + res = weap.CallTryPickup(toucher); + if (res) + { + GoAwayAndDie(); + master = NULL; + } + } + return res; + } + } + return false; + } + } struct WeaponSlots native 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 830247c08..c111de21c 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -214,7 +214,7 @@ struct PlayerInfo native // this is what internally is known as player_t native uint original_oldbuttons; native readonly Class cls; native float DesiredFOV; - native readonly float FOV; + native float FOV; native double viewz; native double viewheight; native double deltaviewheight; @@ -310,5 +310,8 @@ 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); } }