gzdoom/src/g_shared/a_weaponpiece.cpp

204 lines
4.8 KiB
C++
Raw Normal View History

#include "a_pickups.h"
#include "a_weaponpiece.h"
#include "doomstat.h"
2008-09-15 00:47:31 +00:00
#include "farchive.h"
IMPLEMENT_CLASS(PClassWeaponPiece)
IMPLEMENT_CLASS (AWeaponHolder)
void PClassWeaponPiece::ReplaceClassRef(PClass *oldclass, PClass *newclass)
{
Super::ReplaceClassRef(oldclass, newclass);
AWeaponPiece *def = (AWeaponPiece*)Defaults;
if (def != NULL)
{
if (def->WeaponClass == oldclass) def->WeaponClass = static_cast<PClassWeapon *>(newclass);
}
}
2008-09-15 00:47:31 +00:00
void AWeaponHolder::Serialize (FArchive &arc)
{
Super::Serialize(arc);
arc << PieceMask << PieceWeapon;
}
IMPLEMENT_POINTY_CLASS (AWeaponPiece)
DECLARE_POINTER (FullWeapon)
END_POINTERS
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;
}
//==========================================================================
//
// 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;
}
//==========================================================================
//
// TryPickupWeaponPiece
//
//==========================================================================
bool AWeaponPiece::TryPickup (AActor *&toucher)
{
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));
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));
// 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 ()
{
if (FullWeapon)
{
return FullWeapon->PickupMessage();
}
else
{
return Super::PickupMessage();
}
}
//===========================================================================
//
// DoPlayPickupSound
//
// Plays a sound when this actor is picked up.
//
//===========================================================================
void AWeaponPiece::PlayPickupSound (AActor *toucher)
{
if (FullWeapon)
{
FullWeapon->PlayPickupSound(toucher);
}
else
{
Super::PlayPickupSound(toucher);
}
}