mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-24 13:01:47 +00:00
- scriptified a large part of the weapon code.
This commit is contained in:
parent
3b55406302
commit
19b1c10ba8
22 changed files with 462 additions and 444 deletions
|
@ -1749,7 +1749,7 @@ void C_MidPrintBold (FFont *font, const char *msg)
|
|||
}
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DObject, C_MidPrint)
|
||||
DEFINE_ACTION_FUNCTION(_Console, MidPrint)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_STRING(font);
|
||||
|
|
|
@ -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<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
|
||||
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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] =
|
||||
|
|
|
@ -209,6 +209,7 @@ void ADynamicLight::Activate(AActor *activator)
|
|||
m_cycler.SetCycleType(CYCLE_Sin);
|
||||
m_currentRadius = m_cycler.GetVal();
|
||||
}
|
||||
assert(m_currentRadius > 0);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
@ -1196,7 +1196,7 @@ void gl_SetActorLights(AActor *actor)
|
|||
for(;count<actor->dynamiclights.Size();count++)
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ class ArtiBoostArmor : Inventory
|
|||
{
|
||||
int count = 0;
|
||||
|
||||
if (gametype() == GAME_Hexen)
|
||||
if (gameinfo.gametype == GAME_Hexen)
|
||||
{
|
||||
HexenArmor armor;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -11,14 +11,14 @@ class Weapon : StateProvider native
|
|||
const ZOOM_NOSCALETURNING = 2;
|
||||
|
||||
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 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<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> AltProjectileType; // Projectile used by alternate attack
|
||||
native int SelectionOrder; // Lower-numbered weapons get picked first
|
||||
|
@ -33,7 +33,7 @@ class Weapon : StateProvider native
|
|||
native float FOVScale;
|
||||
native int Crosshair; // 0 to use player's crosshair
|
||||
native bool GivenAsMorphWeapon;
|
||||
native bool bAltFire; // Set when this weapon's alternate fire is used.
|
||||
native bool bAltFire; // Set when self weapon's alternate fire is used.
|
||||
native readonly bool bDehAmmo;
|
||||
|
||||
Default
|
||||
|
@ -55,7 +55,6 @@ class Weapon : StateProvider native
|
|||
|
||||
native bool CheckAmmo(int fireMode, bool autoSwitch, bool requireAmmo = false, int ammocount = -1);
|
||||
native bool DepleteAmmo(bool altFire, bool checkEnough = true, int ammouse = -1);
|
||||
native virtual void EndPowerup();
|
||||
|
||||
virtual State GetReadyState ()
|
||||
{
|
||||
|
@ -248,6 +247,398 @@ class Weapon : StateProvider native
|
|||
player.ReadyWeapon.Crosshair = xhair;
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// AWeapon :: TryPickup
|
||||
//
|
||||
// If you can't see the weapon when it's active, then you can't pick it up.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
override bool TryPickupRestricted (in out Actor toucher)
|
||||
{
|
||||
// Wrong class, but try to pick up for ammo
|
||||
if (ShouldStay())
|
||||
{ // Can't pick up weapons for other classes in coop netplay
|
||||
return false;
|
||||
}
|
||||
|
||||
bool gaveSome = (NULL != AddAmmo (toucher, AmmoType1, AmmoGive1));
|
||||
gaveSome |= (NULL != AddAmmo (toucher, AmmoType2, AmmoGive2));
|
||||
if (gaveSome)
|
||||
{
|
||||
GoAwayAndDie ();
|
||||
}
|
||||
return gaveSome;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// AWeapon :: TryPickup
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
override bool TryPickup (in out Actor toucher)
|
||||
{
|
||||
State ReadyState = FindState('Ready');
|
||||
if (ReadyState != NULL && ReadyState.ValidateSpriteFrame())
|
||||
{
|
||||
return Super.TryPickup (toucher);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// AWeapon :: Use
|
||||
//
|
||||
// Make the player switch to self weapon.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
override bool Use (bool pickup)
|
||||
{
|
||||
Weapon useweap = self;
|
||||
|
||||
// Powered up weapons cannot be used directly.
|
||||
if (bPowered_Up) return false;
|
||||
|
||||
// If the player is powered-up, use the alternate version of the
|
||||
// weapon, if one exists.
|
||||
if (SisterWeapon != NULL &&
|
||||
SisterWeapon.bPowered_Up &&
|
||||
Owner.FindInventory ("PowerWeaponLevel2", true))
|
||||
{
|
||||
useweap = SisterWeapon;
|
||||
}
|
||||
if (Owner.player != NULL && Owner.player.ReadyWeapon != useweap)
|
||||
{
|
||||
Owner.player.PendingWeapon = useweap;
|
||||
}
|
||||
// Return false so that the weapon is not removed from the inventory.
|
||||
return false;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// AWeapon :: Destroy
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
override void OnDestroy()
|
||||
{
|
||||
let sister = SisterWeapon;
|
||||
|
||||
if (sister != NULL)
|
||||
{
|
||||
// avoid recursion
|
||||
sister.SisterWeapon = NULL;
|
||||
if (sister != self)
|
||||
{ // In case we are our own sister, don't crash.
|
||||
sister.Destroy();
|
||||
}
|
||||
}
|
||||
Super.OnDestroy();
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// AWeapon :: HandlePickup
|
||||
//
|
||||
// Try to leach ammo from the weapon if you have it already.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
override bool HandlePickup (Inventory item)
|
||||
{
|
||||
if (item.GetClass() == GetClass())
|
||||
{
|
||||
if (Weapon(item).PickupForAmmo (self))
|
||||
{
|
||||
item.bPickupGood = true;
|
||||
}
|
||||
if (MaxAmount > 1) //[SP] If amount<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
|
||||
|
@ -276,7 +667,7 @@ class WeaponGiver : Weapon
|
|||
master = weap = Weapon(Spawn(di.Name));
|
||||
if (weap != NULL)
|
||||
{
|
||||
weap.bAlwaysPickup = false; // use the flag of this item only.
|
||||
weap.bAlwaysPickup = false; // use the flag of self item only.
|
||||
weap.bDropped = bDropped;
|
||||
|
||||
// If our ammo gives are non-negative, transfer them to the real weapon.
|
||||
|
|
|
@ -252,8 +252,7 @@ class Minotaur : Actor
|
|||
{
|
||||
Class<Actor> type;
|
||||
|
||||
//if (gameinfo.gametype == GAME_Heretic)
|
||||
if (gametype() == GAME_Heretic)
|
||||
if (gameinfo.gametype == GAME_Heretic)
|
||||
{
|
||||
type = "PhoenixPuff";
|
||||
}
|
||||
|
|
|
@ -308,6 +308,7 @@ userinfo_t userinfo;
|
|||
native void SetLogNumber (int text);
|
||||
native void SetLogText (String text);
|
||||
native String GetUserName();
|
||||
native bool GetNeverSwitch();
|
||||
native void DropWeapon();
|
||||
native void BringUpWeapon();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -531,7 +531,7 @@ class Scanner : PowerupGiver
|
|||
{
|
||||
if (Owner.CheckLocalView (consoleplayer))
|
||||
{
|
||||
C_MidPrint("SmallFont", "$TXT_NEEDMAP");
|
||||
Console.MidPrint("SmallFont", "$TXT_NEEDMAP");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue