mirror of https://github.com/ZDoom/qzdoom.git
- scriptified the health items.
This commit is contained in:
parent
917b36c6ae
commit
9f9cea4b4a
|
@ -37,114 +37,7 @@
|
||||||
#include "a_morph.h"
|
#include "a_morph.h"
|
||||||
#include "a_health.h"
|
#include "a_health.h"
|
||||||
#include "serializer.h"
|
#include "serializer.h"
|
||||||
|
#include "p_local.h"
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// FUNC P_GiveBody
|
|
||||||
//
|
|
||||||
// Returns false if the body isn't needed at all.
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
bool P_GiveBody (AActor *actor, int num, int max)
|
|
||||||
{
|
|
||||||
if (actor->health <= 0 || (actor->player != NULL && actor->player->playerstate == PST_DEAD))
|
|
||||||
{ // Do not heal dead things.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
player_t *player = actor->player;
|
|
||||||
|
|
||||||
num = clamp(num, -65536, 65536); // prevent overflows for bad values
|
|
||||||
if (player != NULL)
|
|
||||||
{
|
|
||||||
// Max is 0 by default, preserving default behavior for P_GiveBody()
|
|
||||||
// calls while supporting AHealth.
|
|
||||||
if (max <= 0)
|
|
||||||
{
|
|
||||||
max = static_cast<APlayerPawn*>(actor)->GetMaxHealth() + player->mo->stamina;
|
|
||||||
// [MH] First step in predictable generic morph effects
|
|
||||||
if (player->morphTics)
|
|
||||||
{
|
|
||||||
if (player->MorphStyle & MORPH_FULLHEALTH)
|
|
||||||
{
|
|
||||||
if (!(player->MorphStyle & MORPH_ADDSTAMINA))
|
|
||||||
{
|
|
||||||
max -= player->mo->stamina;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else // old health behaviour
|
|
||||||
{
|
|
||||||
max = MAXMORPHHEALTH;
|
|
||||||
if (player->MorphStyle & MORPH_ADDSTAMINA)
|
|
||||||
{
|
|
||||||
max += player->mo->stamina;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// [RH] For Strife: A negative body sets you up with a percentage
|
|
||||||
// of your full health.
|
|
||||||
if (num < 0)
|
|
||||||
{
|
|
||||||
num = max * -num / 100;
|
|
||||||
if (player->health < num)
|
|
||||||
{
|
|
||||||
player->health = num;
|
|
||||||
actor->health = num;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (num > 0)
|
|
||||||
{
|
|
||||||
if (player->health < max)
|
|
||||||
{
|
|
||||||
num = int(num * G_SkillProperty(SKILLP_HealthFactor));
|
|
||||||
if (num < 1) num = 1;
|
|
||||||
player->health += num;
|
|
||||||
if (player->health > max)
|
|
||||||
{
|
|
||||||
player->health = max;
|
|
||||||
}
|
|
||||||
actor->health = player->health;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Parameter value for max is ignored on monsters, preserving original
|
|
||||||
// behaviour on AHealth as well as on existing calls to P_GiveBody().
|
|
||||||
max = actor->SpawnHealth();
|
|
||||||
if (num < 0)
|
|
||||||
{
|
|
||||||
num = max * -num / 100;
|
|
||||||
if (actor->health < num)
|
|
||||||
{
|
|
||||||
actor->health = num;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (actor->health < max)
|
|
||||||
{
|
|
||||||
actor->health += num;
|
|
||||||
if (actor->health > max)
|
|
||||||
{
|
|
||||||
actor->health = max;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(AActor, GiveBody)
|
|
||||||
{
|
|
||||||
PARAM_SELF_PROLOGUE(AActor);
|
|
||||||
PARAM_INT(num);
|
|
||||||
PARAM_INT_DEF(max);
|
|
||||||
ACTION_RETURN_BOOL(P_GiveBody(self, num, max));
|
|
||||||
}
|
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
|
@ -155,6 +48,8 @@ DEFINE_ACTION_FUNCTION(AActor, GiveBody)
|
||||||
IMPLEMENT_CLASS(PClassHealth, false, false)
|
IMPLEMENT_CLASS(PClassHealth, false, false)
|
||||||
IMPLEMENT_CLASS(AHealth, false, false)
|
IMPLEMENT_CLASS(AHealth, false, false)
|
||||||
DEFINE_FIELD(AHealth, PrevHealth)
|
DEFINE_FIELD(AHealth, PrevHealth)
|
||||||
|
DEFINE_FIELD(PClassHealth, LowHealth)
|
||||||
|
DEFINE_FIELD(PClassHealth, LowHealthMessage)
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
|
@ -184,108 +79,10 @@ void PClassHealth::DeriveData(PClass *newclass)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// AHealth :: PickupMessage
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
FString AHealth::PickupMessage ()
|
|
||||||
{
|
|
||||||
int threshold = GetClass()->LowHealth;
|
|
||||||
|
|
||||||
if (PrevHealth < threshold)
|
|
||||||
{
|
|
||||||
FString message = GetClass()->LowHealthMessage;
|
|
||||||
|
|
||||||
if (message.IsNotEmpty())
|
|
||||||
{
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Super::PickupMessage();
|
|
||||||
}
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// AHealth :: TryPickup
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
bool AHealth::TryPickup (AActor *&other)
|
|
||||||
{
|
|
||||||
PrevHealth = other->player != NULL ? other->player->health : other->health;
|
|
||||||
|
|
||||||
// P_GiveBody adds one new feature, applied only if it is possible to pick up negative health:
|
|
||||||
// Negative values are treated as positive percentages, ie Amount -100 means 100% health, ignoring max amount.
|
|
||||||
if (P_GiveBody(other, Amount, MaxAmount))
|
|
||||||
{
|
|
||||||
GoAwayAndDie();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
IMPLEMENT_CLASS(AHealthPickup, false, false)
|
IMPLEMENT_CLASS(AHealthPickup, false, false)
|
||||||
|
|
||||||
DEFINE_FIELD(AHealthPickup, autousemode)
|
DEFINE_FIELD(AHealthPickup, autousemode)
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// AHealthPickup :: CreateCopy
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
AInventory *AHealthPickup::CreateCopy (AActor *other)
|
|
||||||
{
|
|
||||||
AInventory *copy = Super::CreateCopy (other);
|
|
||||||
copy->health = health;
|
|
||||||
return copy;
|
|
||||||
}
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// AHealthPickup :: CreateTossable
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
AInventory *AHealthPickup::CreateTossable ()
|
|
||||||
{
|
|
||||||
AInventory *copy = Super::CreateTossable ();
|
|
||||||
if (copy != NULL)
|
|
||||||
{
|
|
||||||
copy->health = health;
|
|
||||||
}
|
|
||||||
return copy;
|
|
||||||
}
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// AHealthPickup :: HandlePickup
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
bool AHealthPickup::HandlePickup (AInventory *item)
|
|
||||||
{
|
|
||||||
// HealthPickups that are the same type but have different health amounts
|
|
||||||
// do not count as the same item.
|
|
||||||
if (item->health == health)
|
|
||||||
{
|
|
||||||
return Super::HandlePickup (item);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// AHealthPickup :: Use
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
bool AHealthPickup::Use (bool pickup)
|
|
||||||
{
|
|
||||||
return P_GiveBody (Owner, health, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
// AHealthPickup :: Serialize
|
// AHealthPickup :: Serialize
|
||||||
|
|
|
@ -21,8 +21,6 @@ class AHealth : public AInventory
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int PrevHealth;
|
int PrevHealth;
|
||||||
virtual bool TryPickup (AActor *&other) override;
|
|
||||||
virtual FString PickupMessage () override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// HealthPickup is some item that gives the player health when used.
|
// HealthPickup is some item that gives the player health when used.
|
||||||
|
@ -32,11 +30,6 @@ class AHealthPickup : public AInventory
|
||||||
public:
|
public:
|
||||||
int autousemode;
|
int autousemode;
|
||||||
|
|
||||||
|
|
||||||
virtual void Serialize(FSerializer &arc) override;
|
virtual void Serialize(FSerializer &arc) override;
|
||||||
virtual AInventory *CreateCopy (AActor *other) override;
|
|
||||||
virtual AInventory *CreateTossable () override;
|
|
||||||
virtual bool HandlePickup (AInventory *item) override;
|
|
||||||
virtual bool Use (bool pickup) override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
110
src/p_mobj.cpp
110
src/p_mobj.cpp
|
@ -73,6 +73,7 @@
|
||||||
#include "a_ammo.h"
|
#include "a_ammo.h"
|
||||||
#include "a_health.h"
|
#include "a_health.h"
|
||||||
#include "g_levellocals.h"
|
#include "g_levellocals.h"
|
||||||
|
#include "a_morph.h"
|
||||||
|
|
||||||
// MACROS ------------------------------------------------------------------
|
// MACROS ------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -1318,6 +1319,115 @@ DEFINE_ACTION_FUNCTION(AActor, ObtainInventory)
|
||||||
self->ObtainInventory(other);
|
self->ObtainInventory(other);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// FUNC P_GiveBody
|
||||||
|
//
|
||||||
|
// Returns false if the body isn't needed at all.
|
||||||
|
//
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool P_GiveBody(AActor *actor, int num, int max)
|
||||||
|
{
|
||||||
|
if (actor->health <= 0 || (actor->player != NULL && actor->player->playerstate == PST_DEAD))
|
||||||
|
{ // Do not heal dead things.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
player_t *player = actor->player;
|
||||||
|
|
||||||
|
num = clamp(num, -65536, 65536); // prevent overflows for bad values
|
||||||
|
if (player != NULL)
|
||||||
|
{
|
||||||
|
// Max is 0 by default, preserving default behavior for P_GiveBody()
|
||||||
|
// calls while supporting AHealth.
|
||||||
|
if (max <= 0)
|
||||||
|
{
|
||||||
|
max = static_cast<APlayerPawn*>(actor)->GetMaxHealth() + player->mo->stamina;
|
||||||
|
// [MH] First step in predictable generic morph effects
|
||||||
|
if (player->morphTics)
|
||||||
|
{
|
||||||
|
if (player->MorphStyle & MORPH_FULLHEALTH)
|
||||||
|
{
|
||||||
|
if (!(player->MorphStyle & MORPH_ADDSTAMINA))
|
||||||
|
{
|
||||||
|
max -= player->mo->stamina;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // old health behaviour
|
||||||
|
{
|
||||||
|
max = MAXMORPHHEALTH;
|
||||||
|
if (player->MorphStyle & MORPH_ADDSTAMINA)
|
||||||
|
{
|
||||||
|
max += player->mo->stamina;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// [RH] For Strife: A negative body sets you up with a percentage
|
||||||
|
// of your full health.
|
||||||
|
if (num < 0)
|
||||||
|
{
|
||||||
|
num = max * -num / 100;
|
||||||
|
if (player->health < num)
|
||||||
|
{
|
||||||
|
player->health = num;
|
||||||
|
actor->health = num;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (num > 0)
|
||||||
|
{
|
||||||
|
if (player->health < max)
|
||||||
|
{
|
||||||
|
num = int(num * G_SkillProperty(SKILLP_HealthFactor));
|
||||||
|
if (num < 1) num = 1;
|
||||||
|
player->health += num;
|
||||||
|
if (player->health > max)
|
||||||
|
{
|
||||||
|
player->health = max;
|
||||||
|
}
|
||||||
|
actor->health = player->health;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Parameter value for max is ignored on monsters, preserving original
|
||||||
|
// behaviour on AHealth as well as on existing calls to P_GiveBody().
|
||||||
|
max = actor->SpawnHealth();
|
||||||
|
if (num < 0)
|
||||||
|
{
|
||||||
|
num = max * -num / 100;
|
||||||
|
if (actor->health < num)
|
||||||
|
{
|
||||||
|
actor->health = num;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (actor->health < max)
|
||||||
|
{
|
||||||
|
actor->health += num;
|
||||||
|
if (actor->health > max)
|
||||||
|
{
|
||||||
|
actor->health = max;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(AActor, GiveBody)
|
||||||
|
{
|
||||||
|
PARAM_SELF_PROLOGUE(AActor);
|
||||||
|
PARAM_INT(num);
|
||||||
|
PARAM_INT_DEF(max);
|
||||||
|
ACTION_RETURN_BOOL(P_GiveBody(self, num, max));
|
||||||
|
}
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
//
|
//
|
||||||
// AActor :: CheckLocalView
|
// AActor :: CheckLocalView
|
||||||
|
|
|
@ -7526,6 +7526,13 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
||||||
|
|
||||||
else if (Self->ValueType == TypeString)
|
else if (Self->ValueType == TypeString)
|
||||||
{
|
{
|
||||||
|
if (MethodName == NAME_Length) // This is an intrinsic because a dedicated opcode exists for it.
|
||||||
|
{
|
||||||
|
auto x = new FxStrLen(Self);
|
||||||
|
Self = nullptr;
|
||||||
|
delete this;
|
||||||
|
return x->Resolve(ctx);
|
||||||
|
}
|
||||||
// same for String methods. It also uses a hidden struct type to define them.
|
// same for String methods. It also uses a hidden struct type to define them.
|
||||||
Self->ValueType = TypeStringStruct;
|
Self->ValueType = TypeStringStruct;
|
||||||
}
|
}
|
||||||
|
@ -8735,6 +8742,39 @@ ExpEmit FxVectorBuiltin::Emit(VMFunctionBuilder *build)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
|
FxStrLen::FxStrLen(FxExpression *self)
|
||||||
|
:FxExpression(EFX_StrLen, self->ScriptPosition)
|
||||||
|
{
|
||||||
|
Self = self;
|
||||||
|
}
|
||||||
|
|
||||||
|
FxStrLen::~FxStrLen()
|
||||||
|
{
|
||||||
|
SAFE_DELETE(Self);
|
||||||
|
}
|
||||||
|
|
||||||
|
FxExpression *FxStrLen::Resolve(FCompileContext &ctx)
|
||||||
|
{
|
||||||
|
SAFE_RESOLVE(Self, ctx);
|
||||||
|
assert(Self->ValueType == TypeString);
|
||||||
|
ValueType = TypeUInt32;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpEmit FxStrLen::Emit(VMFunctionBuilder *build)
|
||||||
|
{
|
||||||
|
ExpEmit to(build, REGT_INT);
|
||||||
|
ExpEmit op = Self->Emit(build);
|
||||||
|
build->Emit(OP_LENS, to.RegNum, op.RegNum);
|
||||||
|
op.Free(build);
|
||||||
|
return to;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
FxGetClass::FxGetClass(FxExpression *self)
|
FxGetClass::FxGetClass(FxExpression *self)
|
||||||
:FxExpression(EFX_GetClass, self->ScriptPosition)
|
:FxExpression(EFX_GetClass, self->ScriptPosition)
|
||||||
{
|
{
|
||||||
|
@ -8774,7 +8814,7 @@ ExpEmit FxGetClass::Emit(VMFunctionBuilder *build)
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
FxGetParentClass::FxGetParentClass(FxExpression *self)
|
FxGetParentClass::FxGetParentClass(FxExpression *self)
|
||||||
:FxExpression(EFX_GetClass, self->ScriptPosition)
|
:FxExpression(EFX_GetParentClass, self->ScriptPosition)
|
||||||
{
|
{
|
||||||
Self = self;
|
Self = self;
|
||||||
}
|
}
|
||||||
|
|
|
@ -289,6 +289,8 @@ enum EFxType
|
||||||
EFX_CVar,
|
EFX_CVar,
|
||||||
EFX_NamedNode,
|
EFX_NamedNode,
|
||||||
EFX_GetClass,
|
EFX_GetClass,
|
||||||
|
EFX_GetParentClass,
|
||||||
|
EFX_StrLen,
|
||||||
EFX_ColorLiteral,
|
EFX_ColorLiteral,
|
||||||
EFX_GetDefaultByType,
|
EFX_GetDefaultByType,
|
||||||
EFX_COUNT
|
EFX_COUNT
|
||||||
|
@ -1571,6 +1573,24 @@ public:
|
||||||
ExpEmit Emit(VMFunctionBuilder *build);
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FxVectorBuiltin
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
class FxStrLen : public FxExpression
|
||||||
|
{
|
||||||
|
FxExpression *Self;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
FxStrLen(FxExpression *self);
|
||||||
|
~FxStrLen();
|
||||||
|
FxExpression *Resolve(FCompileContext&);
|
||||||
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
|
};
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// FxGetClass
|
// FxGetClass
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "zscript/inventory/weapons.txt"
|
#include "zscript/inventory/weapons.txt"
|
||||||
#include "zscript/inventory/armor.txt"
|
#include "zscript/inventory/armor.txt"
|
||||||
#include "zscript/inventory/ammo.txt"
|
#include "zscript/inventory/ammo.txt"
|
||||||
|
#include "zscript/inventory/health.txt"
|
||||||
#include "zscript/inventory/powerups.txt"
|
#include "zscript/inventory/powerups.txt"
|
||||||
|
|
||||||
#include "zscript/shared/player.txt"
|
#include "zscript/shared/player.txt"
|
||||||
|
|
|
@ -1,3 +1,37 @@
|
||||||
|
/*
|
||||||
|
** a_ammo.cpp
|
||||||
|
** Implements ammo and backpack items.
|
||||||
|
**
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
** Copyright 2000-2016 Randy Heit
|
||||||
|
** Copyright 2006-2017 Cheistoph Oelckers
|
||||||
|
** All rights reserved.
|
||||||
|
**
|
||||||
|
** Redistribution and use in source and binary forms, with or without
|
||||||
|
** modification, are permitted provided that the following conditions
|
||||||
|
** are met:
|
||||||
|
**
|
||||||
|
** 1. Redistributions of source code must retain the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer.
|
||||||
|
** 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer in the
|
||||||
|
** documentation and/or other materials provided with the distribution.
|
||||||
|
** 3. The name of the author may not be used to endorse or promote products
|
||||||
|
** derived from this software without specific prior written permission.
|
||||||
|
**
|
||||||
|
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
|
||||||
class Ammo : Inventory native
|
class Ammo : Inventory native
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,159 @@
|
||||||
|
/*
|
||||||
|
** a_health.cpp
|
||||||
|
** All health items
|
||||||
|
**
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
** Copyright 2000-2016 Randy Heit
|
||||||
|
** Copyright 2006-2017 Cheistoph Oelckers
|
||||||
|
** All rights reserved.
|
||||||
|
**
|
||||||
|
** Redistribution and use in source and binary forms, with or without
|
||||||
|
** modification, are permitted provided that the following conditions
|
||||||
|
** are met:
|
||||||
|
**
|
||||||
|
** 1. Redistributions of source code must retain the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer.
|
||||||
|
** 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer in the
|
||||||
|
** documentation and/or other materials provided with the distribution.
|
||||||
|
** 3. The name of the author may not be used to endorse or promote products
|
||||||
|
** derived from this software without specific prior written permission.
|
||||||
|
**
|
||||||
|
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Health : Inventory native
|
||||||
|
{
|
||||||
|
native int PrevHealth;
|
||||||
|
native meta int LowHealth;
|
||||||
|
native meta String LowHealthMessage;
|
||||||
|
|
||||||
|
Default
|
||||||
|
{
|
||||||
|
Inventory.Amount 1;
|
||||||
|
Inventory.MaxAmount 0;
|
||||||
|
Inventory.PickupSound "misc/health_pkup";
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// AHealth :: PickupMessage
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
override String PickupMessage ()
|
||||||
|
{
|
||||||
|
if (PrevHealth < LowHealth)
|
||||||
|
{
|
||||||
|
String message = LowHealthMessage;
|
||||||
|
|
||||||
|
if (message.Length() != 0)
|
||||||
|
{
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Super.PickupMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// TryPickup
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
override bool TryPickup (in out Actor other)
|
||||||
|
{
|
||||||
|
PrevHealth = other.player != NULL ? other.player.health : other.health;
|
||||||
|
|
||||||
|
// P_GiveBody adds one new feature, applied only if it is possible to pick up negative health:
|
||||||
|
// Negative values are treated as positive percentages, ie Amount -100 means 100% health, ignoring max amount.
|
||||||
|
if (other.GiveBody(Amount, MaxAmount))
|
||||||
|
{
|
||||||
|
GoAwayAndDie();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class HealthPickup : Inventory native
|
||||||
|
{
|
||||||
|
native int autousemode;
|
||||||
|
|
||||||
|
Default
|
||||||
|
{
|
||||||
|
Inventory.DefMaxAmount;
|
||||||
|
+INVENTORY.INVBAR
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// CreateCopy
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
override Inventory CreateCopy (Actor other)
|
||||||
|
{
|
||||||
|
Inventory copy = Super.CreateCopy (other);
|
||||||
|
copy.health = health;
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// CreateTossable
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
override Inventory CreateTossable ()
|
||||||
|
{
|
||||||
|
Inventory copy = Super.CreateTossable ();
|
||||||
|
if (copy != NULL)
|
||||||
|
{
|
||||||
|
copy.health = health;
|
||||||
|
}
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// HandlePickup
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
override bool HandlePickup (Inventory item)
|
||||||
|
{
|
||||||
|
// HealthPickups that are the same type but have different health amounts
|
||||||
|
// do not count as the same item.
|
||||||
|
if (item.health == health)
|
||||||
|
{
|
||||||
|
return Super.HandlePickup (item);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// Use
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
override bool Use (bool pickup)
|
||||||
|
{
|
||||||
|
return Owner.GiveBody (health, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -19,6 +19,8 @@ class ScoreItem : Inventory
|
||||||
class Health : Inventory native
|
class Health : Inventory native
|
||||||
{
|
{
|
||||||
native int PrevHealth;
|
native int PrevHealth;
|
||||||
|
native meta int LowHealth;
|
||||||
|
native meta String LowHealthMessage;
|
||||||
|
|
||||||
Default
|
Default
|
||||||
{
|
{
|
||||||
|
@ -26,6 +28,47 @@ class Health : Inventory native
|
||||||
Inventory.MaxAmount 0;
|
Inventory.MaxAmount 0;
|
||||||
Inventory.PickupSound "misc/health_pkup";
|
Inventory.PickupSound "misc/health_pkup";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// AHealth :: PickupMessage
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
override String PickupMessage ()
|
||||||
|
{
|
||||||
|
if (PrevHealth < LowHealth)
|
||||||
|
{
|
||||||
|
String message = LowHealthMessage;
|
||||||
|
|
||||||
|
if (message.Length() != 0)
|
||||||
|
{
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Super.PickupMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// TryPickup
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
override bool TryPickup (in out Actor other)
|
||||||
|
{
|
||||||
|
PrevHealth = other.player != NULL ? other.player.health : other.health;
|
||||||
|
|
||||||
|
// P_GiveBody adds one new feature, applied only if it is possible to pick up negative health:
|
||||||
|
// Negative values are treated as positive percentages, ie Amount -100 means 100% health, ignoring max amount.
|
||||||
|
if (other.GiveBody(Amount, MaxAmount))
|
||||||
|
{
|
||||||
|
GoAwayAndDie();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class HealthPickup : Inventory native
|
class HealthPickup : Inventory native
|
||||||
|
@ -37,6 +80,65 @@ class HealthPickup : Inventory native
|
||||||
Inventory.DefMaxAmount;
|
Inventory.DefMaxAmount;
|
||||||
+INVENTORY.INVBAR
|
+INVENTORY.INVBAR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// CreateCopy
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
override Inventory CreateCopy (Actor other)
|
||||||
|
{
|
||||||
|
Inventory copy = Super.CreateCopy (other);
|
||||||
|
copy.health = health;
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// CreateTossable
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
override Inventory CreateTossable ()
|
||||||
|
{
|
||||||
|
Inventory copy = Super.CreateTossable ();
|
||||||
|
if (copy != NULL)
|
||||||
|
{
|
||||||
|
copy.health = health;
|
||||||
|
}
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// HandlePickup
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
override bool HandlePickup (Inventory item)
|
||||||
|
{
|
||||||
|
// HealthPickups that are the same type but have different health amounts
|
||||||
|
// do not count as the same item.
|
||||||
|
if (item.health == health)
|
||||||
|
{
|
||||||
|
return Super.HandlePickup (item);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// Use
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
override bool Use (bool pickup)
|
||||||
|
{
|
||||||
|
return Owner.GiveBody (health, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class Key : Inventory native
|
class Key : Inventory native
|
||||||
|
@ -55,7 +157,7 @@ class MapRevealer : Inventory
|
||||||
{
|
{
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
// AMapRevealer :: TryPickup
|
// AMapRevealer . TryPickup
|
||||||
//
|
//
|
||||||
// A MapRevealer reveals the whole map for the player who picks it up.
|
// A MapRevealer reveals the whole map for the player who picks it up.
|
||||||
// The MapRevealer doesn't actually go in your inventory. Instead, it sets
|
// The MapRevealer doesn't actually go in your inventory. Instead, it sets
|
||||||
|
|
Loading…
Reference in New Issue