2006-02-24 04:48:15 +00:00
|
|
|
#include "a_pickups.h"
|
|
|
|
#include "a_weaponpiece.h"
|
|
|
|
#include "doomstat.h"
|
2008-09-15 00:47:31 +00:00
|
|
|
#include "farchive.h"
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2008-08-09 11:35:42 +00:00
|
|
|
IMPLEMENT_CLASS (AWeaponHolder)
|
2008-03-12 02:56:11 +00:00
|
|
|
|
2008-09-15 00:47:31 +00:00
|
|
|
void AWeaponHolder::Serialize (FArchive &arc)
|
|
|
|
{
|
|
|
|
Super::Serialize(arc);
|
|
|
|
arc << PieceMask << PieceWeapon;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-03-12 02:56:11 +00:00
|
|
|
IMPLEMENT_POINTY_CLASS (AWeaponPiece)
|
|
|
|
DECLARE_POINTER (FullWeapon)
|
|
|
|
END_POINTERS
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
|
|
|
|
void AWeaponPiece::Serialize (FArchive &arc)
|
|
|
|
{
|
|
|
|
Super::Serialize (arc);
|
- Fixed: ActorFlagSetOrReset() wasn't receiving the + or - character from
ParseActorProperties().
- Fixed: The decorate FindFlag() function returned flags from ActorFlags
instead of the passed flags set.
- Fixed: The CHT_CHAINSAW, CHT_POWER, CHT_HEALTH, and CHT_RESSURECT needed
NULL player->mo checks.
- Fixed: The "give all" command didn't give the backpack in Doom, and it
must give the backpack before giving ammo.
- Fixed: P_SetPsprite() must not call the action function if the player is
not attached to an actor. This can happen, for instance, if the level is
destroyed while the player is holding a powered-up Phoenix Rod. As part
of its EndPowerup() function, it sets the psprite to the regular version,
but the player actor has already been destroyed.
- Fixed: FinishThingdef() needs to check for valid names, because weapons
could have inherited valid pointers from their superclass.
- Fixed: fuglyname didn't work.
- Fixed: Redefining $ambient sounds leaked memory.
- Added Jim's crashcatcher.c fix for better shell support.
- VC7.1 seems to have no trouble distinguishing between passing a (const
TypeInfo *) reference to operator<< and the generic, templated (object *)
version, so a few places that can benefit from it now use it. I believe
VC6 had problems with this, which is why I didn't do it all along. The
function's implementation was also moved out of dobject.cpp and into
farchive.cpp.
- Fixed: UnpackPixels() unpacked all chunks in a byte, which is wrong for the
last byte in a row if the image width is not an even multiple of the number
pixels per byte.
- Fixed: P_TranslateLineDef() should only clear monster activation for secret
useable lines, not crossable lines.
- Fixed: Some leftover P_IsHostile() calls still needed to be rewritten.
- Fixed: AWeaponHolder::Serialize() wrote the class type in all circumstances.
SVN r20 (trunk)
2006-03-14 06:11:39 +00:00
|
|
|
arc << WeaponClass << FullWeapon << PieceValue;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
2011-09-23 08:23:51 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// TryPickupWeaponPiece
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
bool AWeaponPiece::TryPickupRestricted (AActor *&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;
|
|
|
|
}
|
|
|
|
|
|
|
|
AWeapon * Defaults=(AWeapon*)GetDefaultByType(WeaponClass);
|
|
|
|
|
|
|
|
bool gaveSome = !!(toucher->GiveAmmo (Defaults->AmmoType1, Defaults->AmmoGive1) +
|
|
|
|
toucher->GiveAmmo (Defaults->AmmoType2, Defaults->AmmoGive2));
|
|
|
|
|
|
|
|
if (gaveSome)
|
|
|
|
{
|
|
|
|
GoAwayAndDie ();
|
|
|
|
}
|
|
|
|
return gaveSome;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// TryPickupWeaponPiece
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
2008-09-13 22:08:41 +00:00
|
|
|
bool AWeaponPiece::TryPickup (AActor *&toucher)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
AInventory * inv;
|
|
|
|
AWeaponHolder * hold=NULL;
|
|
|
|
bool shouldStay = PrivateShouldStay ();
|
|
|
|
int gaveAmmo;
|
|
|
|
AWeapon * Defaults=(AWeapon*)GetDefaultByType(WeaponClass);
|
|
|
|
|
|
|
|
FullWeapon=NULL;
|
|
|
|
for(inv=toucher->Inventory;inv;inv=inv->Inventory)
|
|
|
|
{
|
|
|
|
if (inv->IsKindOf(RUNTIME_CLASS(AWeaponHolder)))
|
|
|
|
{
|
|
|
|
hold=static_cast<AWeaponHolder*>(inv);
|
|
|
|
|
|
|
|
if (hold->PieceWeapon==WeaponClass) break;
|
|
|
|
hold=NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!hold)
|
|
|
|
{
|
2006-07-16 09:10:45 +00:00
|
|
|
hold=static_cast<AWeaponHolder*>(Spawn(RUNTIME_CLASS(AWeaponHolder), 0, 0, 0, NO_REPLACE));
|
2006-02-24 04:48:15 +00:00
|
|
|
hold->BecomeItem();
|
|
|
|
hold->AttachToOwner(toucher);
|
|
|
|
hold->PieceMask=0;
|
|
|
|
hold->PieceWeapon=WeaponClass;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (shouldStay)
|
|
|
|
{
|
|
|
|
// Cooperative net-game
|
|
|
|
if (hold->PieceMask & PieceValue)
|
|
|
|
{
|
|
|
|
// Already has the piece
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
toucher->GiveAmmo (Defaults->AmmoType1, Defaults->AmmoGive1);
|
|
|
|
toucher->GiveAmmo (Defaults->AmmoType2, Defaults->AmmoGive2);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{ // Deathmatch or singleplayer game
|
|
|
|
gaveAmmo = toucher->GiveAmmo (Defaults->AmmoType1, Defaults->AmmoGive1) +
|
|
|
|
toucher->GiveAmmo (Defaults->AmmoType2, Defaults->AmmoGive2);
|
|
|
|
|
|
|
|
if (hold->PieceMask & PieceValue)
|
|
|
|
{
|
|
|
|
// Already has the piece, check if mana needed
|
|
|
|
if (!gaveAmmo) return false;
|
|
|
|
GoAwayAndDie();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
hold->PieceMask |= PieceValue;
|
|
|
|
|
|
|
|
// Check if weapon assembled
|
|
|
|
if (hold->PieceMask== (1<<Defaults->health)-1)
|
|
|
|
{
|
|
|
|
if (!toucher->FindInventory (WeaponClass))
|
|
|
|
{
|
2006-07-16 09:10:45 +00:00
|
|
|
FullWeapon= static_cast<AWeapon*>(Spawn(WeaponClass, 0, 0, 0, NO_REPLACE));
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
// The weapon itself should not give more ammo to the player!
|
|
|
|
FullWeapon->AmmoGive1=0;
|
|
|
|
FullWeapon->AmmoGive2=0;
|
|
|
|
FullWeapon->AttachToOwner(toucher);
|
|
|
|
FullWeapon->AmmoGive1=Defaults->AmmoGive1;
|
|
|
|
FullWeapon->AmmoGive2=Defaults->AmmoGive2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
GoAwayAndDie();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool AWeaponPiece::ShouldStay ()
|
|
|
|
{
|
|
|
|
return PrivateShouldStay ();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool AWeaponPiece::PrivateShouldStay ()
|
|
|
|
{
|
|
|
|
// We want a weapon piece to behave like a weapon, so follow the exact
|
|
|
|
// same logic as weapons when deciding whether or not to stay.
|
|
|
|
if (((multiplayer &&
|
|
|
|
(!deathmatch && !alwaysapplydmflags)) || (dmflags & DF_WEAPONS_STAY)) &&
|
|
|
|
!(flags&MF_DROPPED))
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
//
|
|
|
|
// PickupMessage
|
|
|
|
//
|
|
|
|
// Returns the message to print when this actor is picked up.
|
|
|
|
//
|
|
|
|
//===========================================================================
|
|
|
|
|
|
|
|
const char *AWeaponPiece::PickupMessage ()
|
|
|
|
{
|
2006-06-17 20:29:41 +00:00
|
|
|
if (FullWeapon)
|
|
|
|
{
|
|
|
|
return FullWeapon->PickupMessage();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return Super::PickupMessage();
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
//
|
|
|
|
// DoPlayPickupSound
|
|
|
|
//
|
|
|
|
// Plays a sound when this actor is picked up.
|
|
|
|
//
|
|
|
|
//===========================================================================
|
|
|
|
|
|
|
|
void AWeaponPiece::PlayPickupSound (AActor *toucher)
|
|
|
|
{
|
2008-09-12 01:12:40 +00:00
|
|
|
if (FullWeapon)
|
|
|
|
{
|
|
|
|
FullWeapon->PlayPickupSound(toucher);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Super::PlayPickupSound(toucher);
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|