This commit is contained in:
Rachael Alexanderson 2017-01-19 11:58:53 -05:00
commit 8a198591f4
30 changed files with 748 additions and 775 deletions

View file

@ -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_PROLOGUE;
PARAM_STRING(font); PARAM_STRING(font);

View file

@ -2109,6 +2109,11 @@ static int RemoveClass(const PClass *cls)
player = true; player = true;
continue; continue;
} }
// [SP] Don't remove owned inventory objects.
if (static_cast<AInventory *>(actor)->Owner != NULL)
{
continue;
}
removecount++; removecount++;
actor->ClearCounters(); actor->ClearCounters();
actor->Destroy(); actor->Destroy();

View file

@ -249,363 +249,6 @@ void AWeapon::MarkPrecacheSounds() const
ReadySound.MarkUsed(); 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<AWeapon *>(item)->PickupForAmmo (this))
{
item->ItemFlags |= IF_PICKUPGOOD;
}
if (MaxAmount > 1) //[SP] If amount<maxamount do another pickup test of the weapon itself!
{
return Super::HandlePickup (item);
}
return true;
}
return false;
}
//===========================================================================
//
// AWeapon :: PickupForAmmo
//
// The player already has this weapon, so try to pick it up for ammo.
//
//===========================================================================
bool AWeapon::PickupForAmmo (AWeapon *ownedWeapon)
{
bool gotstuff = false;
// Don't take ammo if the weapon sticks around.
if (!CallShouldStay ())
{
int oldamount1 = 0;
int oldamount2 = 0;
if (ownedWeapon->Ammo1 != 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<APlayerPawn *>(Owner)->CheckWeaponSwitch(ownedWeapon->Ammo1->GetClass());
}
else if (ownedWeapon->Ammo2 != NULL && oldamount2 == 0)
{
static_cast<APlayerPawn *>(Owner)->CheckWeaponSwitch(ownedWeapon->Ammo2->GetClass());
}
}
}
return gotstuff;
}
//===========================================================================
//
// AWeapon :: CreateCopy
//
//===========================================================================
AInventory *AWeapon::CreateCopy (AActor *other)
{
AWeapon *copy = static_cast<AWeapon*>(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<AWeapon *> (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<AInventory *>(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<AWeapon *>(Owner->FindInventory (weapontype));
if (weap == NULL)
{
weap = static_cast<AWeapon *>(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 // AWeapon :: CheckAmmo
@ -781,49 +424,6 @@ void AWeapon::PostMorphWeapon ()
pspr->SetState(GetUpState()); 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 // 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<PClassWeapon>(PClass::FindClass(di->Name));
if (ti != NULL)
{
if (master == NULL)
{
master = weap = static_cast<AWeapon*>(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<AWeapon*>(master);
bool res = weap->CallTryPickup(toucher);
if (res)
{
GoAwayAndDie();
master = NULL;
}
return res;
}
}
return false;
}
/* Weapon slots ***********************************************************/ /* Weapon slots ***********************************************************/
//=========================================================================== //===========================================================================
@ -2079,48 +1620,3 @@ PClassWeapon *Net_ReadWeapon(BYTE **stream)
return Weapons_ntoh[index]; 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;
}

View file

@ -136,17 +136,7 @@ public:
virtual void MarkPrecacheSounds() const; virtual void MarkPrecacheSounds() const;
virtual void Serialize(FSerializer &arc) override; 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(); void PostMorphWeapon();
// scripted virtuals. // scripted virtuals.
@ -158,9 +148,6 @@ public:
FState *GetStateForButtonName (FName button); FState *GetStateForButtonName (FName button);
virtual void EndPowerup ();
enum enum
{ {
PrimaryFire, PrimaryFire,
@ -180,10 +167,6 @@ public:
BobInverseSmooth BobInverseSmooth
}; };
protected:
AInventory *AddAmmo (AActor *other, PClassActor *ammotype, int amount);
bool AddExistingAmmo (AInventory *ammo, int amount);
AWeapon *AddWeapon (PClassWeapon *weapon);
}; };
enum enum
@ -217,14 +200,3 @@ enum
WIF_BOT_BFG = 1<<28, // this is a BFG 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;
};

View file

@ -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) void DBaseStatusBar::SerializeMessages(FSerializer &arc)
{ {
arc.Array("hudmessages", Messages, 3, true); arc.Array("hudmessages", Messages, 3, true);

View file

@ -49,6 +49,7 @@ DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, backpacktype)
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, Armor2Percent) DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, Armor2Percent)
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, ArmorIcon1) DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, ArmorIcon1)
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, ArmorIcon2) DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, ArmorIcon2)
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, gametype)
const char *GameNames[17] = const char *GameNames[17] =

View file

@ -208,6 +208,7 @@ void ADynamicLight::Activate(AActor *activator)
m_cycler.SetCycleType(CYCLE_Sin); m_cycler.SetCycleType(CYCLE_Sin);
m_currentRadius = m_cycler.GetVal(); m_currentRadius = m_cycler.GetVal();
} }
assert(m_currentRadius > 0);
} }

View file

@ -137,7 +137,7 @@ public:
void SetHalo(bool halo) { m_halo = halo; } void SetHalo(bool halo) { m_halo = halo; }
protected: protected:
FName m_Name; FName m_Name;
unsigned char m_Args[5]; int m_Args[5];
double m_Param; double m_Param;
DVector3 m_Pos; DVector3 m_Pos;
ELightType m_type; ELightType m_type;
@ -159,7 +159,7 @@ FLightDefaults::FLightDefaults(FName name, ELightType type)
m_type = type; m_type = type;
m_Pos.Zero(); m_Pos.Zero();
memset(m_Args, 0, 5); memset(m_Args, 0, sizeof(m_Args));
m_Param = 0; m_Param = 0;
m_subtractive = false; m_subtractive = false;
@ -1196,7 +1196,7 @@ void gl_SetActorLights(AActor *actor)
for(;count<actor->dynamiclights.Size();count++) for(;count<actor->dynamiclights.Size();count++)
{ {
actor->dynamiclights[count]->flags2 |= MF2_DORMANT; actor->dynamiclights[count]->flags2 |= MF2_DORMANT;
memset(actor->dynamiclights[count]->args, 0, sizeof(actor->args)); memset(actor->dynamiclights[count]->args, 0, 3*sizeof(actor->args[0]));
} }
All.Unclock(); All.Unclock();
} }

View file

@ -185,6 +185,7 @@ xx(PuzzleItemNumber)
xx(HealthPickup) xx(HealthPickup)
xx(autousemode) xx(autousemode)
xx(Ammo) xx(Ammo)
xx(WeaponGiver)
xx(PowerTargeter) xx(PowerTargeter)
xx(PowerInvulnerable) xx(PowerInvulnerable)
xx(PowerStrength) xx(PowerStrength)

View file

@ -3248,9 +3248,9 @@ void ModifyDropAmount(AInventory *inv, int dropamount)
inv->Amount = amount; inv->Amount = amount;
inv->ItemFlags |= flagmask; inv->ItemFlags |= flagmask;
} }
else if (inv->IsKindOf (RUNTIME_CLASS(AWeaponGiver))) else if (inv->IsKindOf (PClass::FindActor(NAME_WeaponGiver)))
{ {
static_cast<AWeaponGiver *>(inv)->DropAmmoFactor = dropammofactor; inv->FloatVar("AmmoFactor") = dropammofactor;
inv->ItemFlags |= flagmask; inv->ItemFlags |= flagmask;
} }
else if (inv->IsKindOf (RUNTIME_CLASS(AWeapon))) else if (inv->IsKindOf (RUNTIME_CLASS(AWeapon)))

View file

@ -36,7 +36,6 @@
// MACROS ------------------------------------------------------------------ // MACROS ------------------------------------------------------------------
#define LOWERSPEED 6. #define LOWERSPEED 6.
#define RAISESPEED 6.
// TYPES ------------------------------------------------------------------- // 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 // 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 // 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; 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 // PROC A_Overlay
@ -1430,47 +1319,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_ClearOverlays)
ACTION_RETURN_INT(count); 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 // WEAPON ATTACKS
// //
@ -1516,20 +1364,6 @@ DEFINE_ACTION_FUNCTION(AActor, BulletSlope)
ACTION_RETURN_FLOAT(P_BulletSlope(self, t, aimflags).Degrees); 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 // PROC P_SetupPsprites

View file

@ -40,6 +40,8 @@
#include "c_dispatch.h" #include "c_dispatch.h"
#include "v_text.h" #include "v_text.h"
#include "thingdef.h" #include "thingdef.h"
#include "r_state.h"
// stores indices for symbolic state labels for some old-style DECORATE functions. // stores indices for symbolic state labels for some old-style DECORATE functions.
FStateLabelStorage StateLabels; FStateLabelStorage StateLabels;
@ -1092,3 +1094,9 @@ DEFINE_ACTION_FUNCTION(FState, DistanceTo)
} }
ACTION_RETURN_INT(retv); ACTION_RETURN_INT(retv);
} }
DEFINE_ACTION_FUNCTION(FState, ValidateSpriteFrame)
{
PARAM_SELF_STRUCT_PROLOGUE(FState);
ACTION_RETURN_BOOL(self->Frame < sprites[self->sprite].numframes);
}

View file

@ -643,6 +643,11 @@ DEFINE_ACTION_FUNCTION(_PlayerInfo, GetUserName)
ACTION_RETURN_STRING(self->userinfo.GetName()); ACTION_RETURN_STRING(self->userinfo.GetName());
} }
DEFINE_ACTION_FUNCTION(_PlayerInfo, GetNeverSwitch)
{
PARAM_SELF_STRUCT_PROLOGUE(player_t);
ACTION_RETURN_BOOL(self->userinfo.GetNeverSwitch());
}
//=========================================================================== //===========================================================================
// //

View file

@ -2359,7 +2359,6 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx)
ExpEmit FxAssign::Emit(VMFunctionBuilder *build) ExpEmit FxAssign::Emit(VMFunctionBuilder *build)
{ {
static const BYTE loadops[] = { OP_LK, OP_LKF, OP_LKS, OP_LKP }; static const BYTE loadops[] = { OP_LK, OP_LKF, OP_LKS, OP_LKP };
assert(ValueType == Base->ValueType);
assert(ValueType->GetRegType() == Right->ValueType->GetRegType()); assert(ValueType->GetRegType() == Right->ValueType->GetRegType());
ExpEmit pointer = Base->Emit(build); ExpEmit pointer = Base->Emit(build);

View file

@ -8,6 +8,7 @@
#include "zscript/inventory/inventory.txt" #include "zscript/inventory/inventory.txt"
#include "zscript/inventory/inv_misc.txt" #include "zscript/inventory/inv_misc.txt"
#include "zscript/inventory/stateprovider.txt"
#include "zscript/inventory/weapons.txt" #include "zscript/inventory/weapons.txt"
#include "zscript/inventory/weaponpiece.txt" #include "zscript/inventory/weaponpiece.txt"
#include "zscript/inventory/armor.txt" #include "zscript/inventory/armor.txt"

View file

@ -373,7 +373,7 @@ class Actor : Thinker native
native void SetXYZ(vector3 newpos); native void SetXYZ(vector3 newpos);
native Actor GetPointer(int aaptr); native Actor GetPointer(int aaptr);
native double BulletSlope(out FTranslatedLineTarget pLineTarget = null, int aimflags = 0); native double BulletSlope(out FTranslatedLineTarget pLineTarget = null, int aimflags = 0);
native Actor AimTarget();
native bool CheckMissileSpawn(double maxdist); native bool CheckMissileSpawn(double maxdist);
native bool CheckPosition(Vector2 pos, bool actorsonly = false, FCheckPosition tm = null); native bool CheckPosition(Vector2 pos, bool actorsonly = false, FCheckPosition tm = null);
native bool TestMobjLocation(); native bool TestMobjLocation();
@ -693,6 +693,12 @@ class Actor : Thinker native
return true; 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); 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);

View file

@ -40,6 +40,7 @@ struct Screen native
struct Console native struct Console native
{ {
native static void HideConsole(); native static void HideConsole();
native static void MidPrint(string fontname, string textlabel, bool bold = false); // always uses the stringtable.
} }
struct DamageTypeDefinition native struct DamageTypeDefinition native
@ -54,6 +55,7 @@ struct GameInfoStruct native
native double Armor2Percent; native double Armor2Percent;
native String ArmorIcon1; native String ArmorIcon1;
native String ArmorIcon2; native String ArmorIcon2;
native int gametype;
} }
class Object native class Object native
@ -65,12 +67,10 @@ class Object native
native static double G_SkillPropertyFloat(int p); native static double G_SkillPropertyFloat(int p);
native static vector3, int G_PickDeathmatchStart(); native static vector3, int G_PickDeathmatchStart();
native static vector3, int G_PickPlayerStart(int pnum, int flags = 0); 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_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_PauseSound (bool notmusic, bool notsfx);
native static void S_ResumeSound (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 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 uint BAM(double angle);
native static void SetMusicVolume(float vol); native static void SetMusicVolume(float vol);
@ -241,6 +241,7 @@ struct State native
native bool bDehacked; native bool bDehacked;
native int DistanceTo(state other); native int DistanceTo(state other);
native bool ValidateSpriteFrame();
} }
struct F3DFloor native struct F3DFloor native

View file

@ -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 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);
}

View file

@ -26,7 +26,7 @@ class ArtiBoostArmor : Inventory
{ {
int count = 0; int count = 0;
if (gametype() == GAME_Hexen) if (gameinfo.gametype == GAME_Hexen)
{ {
HexenArmor armor; HexenArmor armor;

View file

@ -124,7 +124,7 @@ class PuzzleItem : Inventory
Owner.A_PlaySound ("*puzzfail", CHAN_VOICE); Owner.A_PlaySound ("*puzzfail", CHAN_VOICE);
if (Owner.CheckLocalView (consoleplayer)) if (Owner.CheckLocalView (consoleplayer))
{ {
C_MidPrint ("SmallFont", PuzzFailMessage, true); Console.MidPrint ("SmallFont", PuzzFailMessage, true);
} }
return false; return false;
} }

View file

@ -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<Actor> pufftype = "BulletPuff", double range = 0, double lifesteal = 0, int lifestealmax = 0, class<BasicArmorBonus> armorbonustype = "ArmorBonus", sound MeleeSound = 0, sound MissSound = "");
action native void A_FireBullets(double spread_xy, double spread_z, int numbullets, int damageperbullet, class<Actor> pufftype = "BulletPuff", int flags = 1, double range = 0, class<Actor> missile = null, double Spawnheight = 32, double Spawnofs_xy = 0);
action native void A_FireProjectile(class<Actor> 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<Actor> 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<Actor> 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 class DehackedPickup : Inventory native
{ {
} }
@ -221,11 +202,3 @@ class FakeInventory : Inventory native
{ {
native bool Respawnable; native bool Respawnable;
} }
class CustomInventory : StateProvider native
{
Default
{
DefaultStateUsage SUF_ACTOR|SUF_OVERLAY|SUF_ITEM;
}
}

View file

@ -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<Actor> pufftype = "BulletPuff", double range = 0, double lifesteal = 0, int lifestealmax = 0, class<BasicArmorBonus> armorbonustype = "ArmorBonus", sound MeleeSound = 0, sound MissSound = "");
action native void A_FireBullets(double spread_xy, double spread_z, int numbullets, int damageperbullet, class<Actor> pufftype = "BulletPuff", int flags = 1, double range = 0, class<Actor> missile = null, double Spawnheight = 32, double Spawnofs_xy = 0);
action native void A_FireProjectile(class<Actor> 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<Actor> 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<Actor> 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() {}
}

View file

@ -7,15 +7,18 @@ class Weapon : StateProvider native
EitherFire EitherFire
}; };
const ZOOM_INSTANT = 1;
const ZOOM_NOSCALETURNING = 2;
native uint WeaponFlags; native uint WeaponFlags;
native class<Ammo> AmmoType1, AmmoType2; // Types of ammo used by this weapon native class<Ammo> 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 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 AmmoUse1, AmmoUse2; // How much ammo to use with each shot
native int Kickback; native int Kickback;
native float YAdjust; // For viewing the weapon fullscreen (visual only so no need to be a double) 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 sound UpSound, ReadySound; // Sounds when coming up and idle
native class<Weapon> SisterWeaponType; // Another weapon to pick up with this one native class<Weapon> SisterWeaponType; // Another weapon to pick up with self one
native class<Actor> ProjectileType; // Projectile used by primary attack native class<Actor> ProjectileType; // Projectile used by primary attack
native class<Actor> AltProjectileType; // Projectile used by alternate attack native class<Actor> AltProjectileType; // Projectile used by alternate attack
native int SelectionOrder; // Lower-numbered weapons get picked first native int SelectionOrder; // Lower-numbered weapons get picked first
@ -30,7 +33,7 @@ class Weapon : StateProvider native
native float FOVScale; native float FOVScale;
native int Crosshair; // 0 to use player's crosshair native int Crosshair; // 0 to use player's crosshair
native bool GivenAsMorphWeapon; 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; native readonly bool bDehAmmo;
Default Default
@ -52,7 +55,6 @@ class Weapon : StateProvider native
native bool CheckAmmo(int fireMode, bool autoSwitch, bool requireAmmo = false, int ammocount = -1); 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 bool DepleteAmmo(bool altFire, bool checkEnough = true, int ammouse = -1);
native virtual void EndPowerup();
virtual State GetReadyState () virtual State GetReadyState ()
{ {
@ -85,23 +87,621 @@ class Weapon : StateProvider native
return s; return s;
} }
native action void A_ZoomFactor(double scale = 1, int flags = 0); action void A_GunFlash(statelabel flashlabel = null, int flags = 0)
native action void A_SetCrosshair(int xhair); {
const ZOOM_INSTANT = 1; let player = player;
const ZOOM_NOSCALETURNING = 2;
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<maxamount do another pickup test of the weapon itself!
{
return Super.HandlePickup (item);
}
return true;
}
return false;
}
//===========================================================================
//
// AWeapon :: PickupForAmmo
//
// The player already has self weapon, so try to pick it up for ammo.
//
//===========================================================================
protected bool PickupForAmmo (Weapon ownedWeapon)
{
bool gotstuff = false;
// Don't take ammo if the weapon sticks around.
if (!ShouldStay ())
{
int oldamount1 = 0;
int oldamount2 = 0;
if (ownedWeapon.Ammo1 != 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);
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<Ammo> 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<Weapon> 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
{ {
double AmmoFactor;
native double DropAmmoFactor;
Default Default
{ {
Weapon.AmmoGive1 -1; Weapon.AmmoGive1 -1;
Weapon.AmmoGive2 -1; Weapon.AmmoGive2 -1;
} }
override bool TryPickup(in out Actor toucher)
{
DropItem di = GetDropItems();
Weapon weap;
if (di != NULL)
{
Class<Weapon> 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 struct WeaponSlots native

View file

@ -252,8 +252,7 @@ class Minotaur : Actor
{ {
Class<Actor> type; Class<Actor> type;
//if (gameinfo.gametype == GAME_Heretic) if (gameinfo.gametype == GAME_Heretic)
if (gametype() == GAME_Heretic)
{ {
type = "PhoenixPuff"; type = "PhoenixPuff";
} }

View file

@ -214,7 +214,7 @@ struct PlayerInfo native // this is what internally is known as player_t
native uint original_oldbuttons; native uint original_oldbuttons;
native readonly Class<PlayerPawn> cls; native readonly Class<PlayerPawn> cls;
native float DesiredFOV; native float DesiredFOV;
native readonly float FOV; native float FOV;
native double viewz; native double viewz;
native double viewheight; native double viewheight;
native double deltaviewheight; native double deltaviewheight;
@ -310,5 +310,8 @@ userinfo_t userinfo;
native void SetLogNumber (int text); native void SetLogNumber (int text);
native void SetLogText (String text); native void SetLogText (String text);
native String GetUserName(); native String GetUserName();
native bool GetNeverSwitch();
native void DropWeapon();
native void BringUpWeapon();
} }

View file

@ -123,7 +123,7 @@ extend class PlayerPawn
if (giveall || name ~== "armor") if (giveall || name ~== "armor")
{ {
if (GameType() != GAME_Hexen) if (gameinfo.gametype != GAME_Hexen)
{ {
let armoritem = BasicArmorPickup(Spawn("BasicArmorPickup")); let armoritem = BasicArmorPickup(Spawn("BasicArmorPickup"));
armoritem.SaveAmount = 100*deh.BlueAC; armoritem.SaveAmount = 100*deh.BlueAC;

View file

@ -27,7 +27,7 @@ class TeleportFog : Actor
{ {
Super.PostBeginPlay (); Super.PostBeginPlay ();
A_PlaySound ("misc/teleport", CHAN_BODY); A_PlaySound ("misc/teleport", CHAN_BODY);
switch (gametype()) switch (gameinfo.gametype)
{ {
case GAME_Hexen: case GAME_Hexen:
case GAME_Heretic: case GAME_Heretic:

View file

@ -108,13 +108,13 @@ class AlienSpectre1 : SpectralMonster
} }
else if (cls == "AlienSpectre2") else if (cls == "AlienSpectre2")
{ {
C_MidPrint("SmallFont", "$TXT_KILLED_BISHOP"); Console.MidPrint("SmallFont", "$TXT_KILLED_BISHOP");
log = 74; log = 74;
player.GiveInventoryType ("QuestItem21"); player.GiveInventoryType ("QuestItem21");
} }
else if (cls == "AlienSpectre3") 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. // If there are any Oracles still alive, kill them.
ThinkerIterator it = ThinkerIterator.Create("Oracle"); ThinkerIterator it = ThinkerIterator.Create("Oracle");
Actor oracle; Actor oracle;
@ -144,7 +144,7 @@ class AlienSpectre1 : SpectralMonster
} }
else if (cls == "AlienSpectre4") else if (cls == "AlienSpectre4")
{ {
C_MidPrint("SmallFont", "$TXT_KILLED_MACIL"); Console.MidPrint("SmallFont", "$TXT_KILLED_MACIL");
player.GiveInventoryType ("QuestItem24"); player.GiveInventoryType ("QuestItem24");
if (player.FindInventory ("QuestItem25") == null) if (player.FindInventory ("QuestItem25") == null)
{ // Richter has taken over. Macil is a snake. { // Richter has taken over. Macil is a snake.
@ -157,7 +157,7 @@ class AlienSpectre1 : SpectralMonster
} }
else if (cls == "AlienSpectre5") else if (cls == "AlienSpectre5")
{ {
C_MidPrint("SmallFont", "$TXT_KILLED_LOREMASTER"); Console.MidPrint("SmallFont", "$TXT_KILLED_LOREMASTER");
player.GiveInventoryType ("QuestItem26"); player.GiveInventoryType ("QuestItem26");
if (!multiplayer) if (!multiplayer)

View file

@ -531,7 +531,7 @@ class Scanner : PowerupGiver
{ {
if (Owner.CheckLocalView (consoleplayer)) if (Owner.CheckLocalView (consoleplayer))
{ {
C_MidPrint("SmallFont", "$TXT_NEEDMAP"); Console.MidPrint("SmallFont", "$TXT_NEEDMAP");
} }
return false; return false;
} }

View file

@ -32,7 +32,7 @@ extend class Actor
if (msg != msgid) // if both are identical there was no message of this name in the stringtable. 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);
} }
} }