mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-28 23:11:58 +00:00
This commit is contained in:
commit
9333ce1888
63 changed files with 1354 additions and 1931 deletions
|
@ -1195,11 +1195,9 @@ set (PCH_SOURCES
|
||||||
w_wad.cpp
|
w_wad.cpp
|
||||||
wi_stuff.cpp
|
wi_stuff.cpp
|
||||||
zstrformat.cpp
|
zstrformat.cpp
|
||||||
g_inventory/a_ammo.cpp
|
|
||||||
g_inventory/a_armor.cpp
|
g_inventory/a_armor.cpp
|
||||||
g_inventory/a_keys.cpp
|
g_inventory/a_keys.cpp
|
||||||
g_inventory/a_pickups.cpp
|
g_inventory/a_pickups.cpp
|
||||||
g_inventory/a_weaponpiece.cpp
|
|
||||||
g_inventory/a_weapons.cpp
|
g_inventory/a_weapons.cpp
|
||||||
g_strife/strife_sbar.cpp
|
g_strife/strife_sbar.cpp
|
||||||
g_shared/a_action.cpp
|
g_shared/a_action.cpp
|
||||||
|
|
|
@ -721,7 +721,7 @@ public:
|
||||||
|
|
||||||
// Finds the first item of a particular type.
|
// Finds the first item of a particular type.
|
||||||
AInventory *FindInventory (PClassActor *type, bool subclass=false);
|
AInventory *FindInventory (PClassActor *type, bool subclass=false);
|
||||||
AInventory *FindInventory (FName type);
|
AInventory *FindInventory (FName type, bool subclass = false);
|
||||||
template<class T> T *FindInventory ()
|
template<class T> T *FindInventory ()
|
||||||
{
|
{
|
||||||
return static_cast<T *> (FindInventory (RUNTIME_TEMPLATE_CLASS(T)));
|
return static_cast<T *> (FindInventory (RUNTIME_TEMPLATE_CLASS(T)));
|
||||||
|
|
|
@ -2740,8 +2740,8 @@ void AM_drawKeys ()
|
||||||
mpoint_t p;
|
mpoint_t p;
|
||||||
DAngle angle;
|
DAngle angle;
|
||||||
|
|
||||||
TThinkerIterator<AKey> it;
|
TThinkerIterator<AInventory> it(NAME_Key);
|
||||||
AKey *key;
|
AInventory *key;
|
||||||
|
|
||||||
while ((key = it.Next()) != NULL)
|
while ((key = it.Next()) != NULL)
|
||||||
{
|
{
|
||||||
|
@ -2853,7 +2853,7 @@ void AM_drawThings ()
|
||||||
// Find the key's own color.
|
// Find the key's own color.
|
||||||
// Only works correctly if single-key locks have lower numbers than any-key locks.
|
// Only works correctly if single-key locks have lower numbers than any-key locks.
|
||||||
// That is the case for all default keys, however.
|
// That is the case for all default keys, however.
|
||||||
if (t->IsKindOf(RUNTIME_CLASS(AKey)))
|
if (t->IsKindOf(PClass::FindActor(NAME_Key)))
|
||||||
{
|
{
|
||||||
if (G_SkillProperty(SKILLP_EasyKey))
|
if (G_SkillProperty(SKILLP_EasyKey))
|
||||||
{
|
{
|
||||||
|
@ -2863,7 +2863,7 @@ void AM_drawThings ()
|
||||||
else if (am_showkeys)
|
else if (am_showkeys)
|
||||||
{
|
{
|
||||||
int P_GetMapColorForKey (AInventory * key);
|
int P_GetMapColorForKey (AInventory * key);
|
||||||
int c = P_GetMapColorForKey(static_cast<AKey *>(t));
|
int c = P_GetMapColorForKey(static_cast<AInventory *>(t));
|
||||||
|
|
||||||
if (c >= 0) color.FromRGB(RPART(c), GPART(c), BPART(c));
|
if (c >= 0) color.FromRGB(RPART(c), GPART(c), BPART(c));
|
||||||
else color = AMColors[AMColors.ThingColor_CountItem];
|
else color = AMColors[AMColors.ThingColor_CountItem];
|
||||||
|
@ -3048,7 +3048,7 @@ void AM_Drawer ()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bool allmap = (level.flags2 & LEVEL2_ALLMAP) != 0;
|
bool allmap = (level.flags2 & LEVEL2_ALLMAP) != 0;
|
||||||
bool allthings = allmap && players[consoleplayer].mo->FindInventory(PClass::FindActor(NAME_PowerScanner), true) != nullptr;
|
bool allthings = allmap && players[consoleplayer].mo->FindInventory(NAME_PowerScanner, true) != nullptr;
|
||||||
|
|
||||||
if (am_portaloverlay)
|
if (am_portaloverlay)
|
||||||
{
|
{
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
#include "d_event.h"
|
#include "d_event.h"
|
||||||
#include "d_player.h"
|
#include "d_player.h"
|
||||||
#include "vectors.h"
|
#include "vectors.h"
|
||||||
#include "a_ammo.h"
|
|
||||||
|
|
||||||
static FRandom pr_botmove ("BotMove");
|
static FRandom pr_botmove ("BotMove");
|
||||||
|
|
||||||
|
@ -346,12 +345,12 @@ void DBot::WhatToGet (AActor *item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (item->IsKindOf (RUNTIME_CLASS(AAmmo)))
|
else if (item->IsKindOf (PClass::FindActor(NAME_Ammo)))
|
||||||
{
|
{
|
||||||
AAmmo *ammo = static_cast<AAmmo *> (item);
|
auto ac = PClass::FindActor(NAME_Ammo);
|
||||||
PClassActor *parent = ammo->GetParentAmmo ();
|
auto parent = item->GetClass();
|
||||||
AInventory *holdingammo = player->mo->FindInventory (parent);
|
while (parent->ParentClass != ac) parent = (PClassActor*)(parent->ParentClass);
|
||||||
|
AInventory *holdingammo = player->mo->FindInventory(parent);
|
||||||
if (holdingammo != NULL && holdingammo->Amount >= holdingammo->MaxAmount)
|
if (holdingammo != NULL && holdingammo->Amount >= holdingammo->MaxAmount)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -31,7 +31,6 @@
|
||||||
#include "templates.h"
|
#include "templates.h"
|
||||||
#include "d_net.h"
|
#include "d_net.h"
|
||||||
#include "d_event.h"
|
#include "d_event.h"
|
||||||
#include "a_armor.h"
|
|
||||||
|
|
||||||
#define QUEUESIZE 128
|
#define QUEUESIZE 128
|
||||||
#define MESSAGESIZE 128
|
#define MESSAGESIZE 128
|
||||||
|
@ -434,7 +433,7 @@ static bool DoSubstitution (FString &out, const char *in)
|
||||||
{
|
{
|
||||||
if (strnicmp(a, "armor", 5) == 0)
|
if (strnicmp(a, "armor", 5) == 0)
|
||||||
{
|
{
|
||||||
AInventory *armor = player->mo->FindInventory<ABasicArmor>();
|
AInventory *armor = player->mo->FindInventory(NAME_BasicArmor);
|
||||||
out.AppendFormat("%d", armor != NULL ? armor->Amount : 0);
|
out.AppendFormat("%d", armor != NULL ? armor->Amount : 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,8 +74,6 @@
|
||||||
#include "info.h"
|
#include "info.h"
|
||||||
#include "v_text.h"
|
#include "v_text.h"
|
||||||
#include "vmbuilder.h"
|
#include "vmbuilder.h"
|
||||||
#include "a_armor.h"
|
|
||||||
#include "a_ammo.h"
|
|
||||||
|
|
||||||
// [SO] Just the way Randy said to do it :)
|
// [SO] Just the way Randy said to do it :)
|
||||||
// [RH] Made this CVAR_SERVERINFO
|
// [RH] Made this CVAR_SERVERINFO
|
||||||
|
@ -1536,7 +1534,7 @@ static int PatchSprite (int sprNum)
|
||||||
static int PatchAmmo (int ammoNum)
|
static int PatchAmmo (int ammoNum)
|
||||||
{
|
{
|
||||||
PClassActor *ammoType = NULL;
|
PClassActor *ammoType = NULL;
|
||||||
AAmmo *defaultAmmo = NULL;
|
AInventory *defaultAmmo = NULL;
|
||||||
int result;
|
int result;
|
||||||
int oldclip;
|
int oldclip;
|
||||||
int dummy;
|
int dummy;
|
||||||
|
@ -1549,7 +1547,7 @@ static int PatchAmmo (int ammoNum)
|
||||||
ammoType = AmmoNames[ammoNum];
|
ammoType = AmmoNames[ammoNum];
|
||||||
if (ammoType != NULL)
|
if (ammoType != NULL)
|
||||||
{
|
{
|
||||||
defaultAmmo = (AAmmo *)GetDefaultByType (ammoType);
|
defaultAmmo = (AInventory*)GetDefaultByType (ammoType);
|
||||||
if (defaultAmmo != NULL)
|
if (defaultAmmo != NULL)
|
||||||
{
|
{
|
||||||
max = &defaultAmmo->MaxAmount;
|
max = &defaultAmmo->MaxAmount;
|
||||||
|
@ -1575,8 +1573,8 @@ static int PatchAmmo (int ammoNum)
|
||||||
// Calculate the new backpack-given amounts for this ammo.
|
// Calculate the new backpack-given amounts for this ammo.
|
||||||
if (ammoType != NULL)
|
if (ammoType != NULL)
|
||||||
{
|
{
|
||||||
defaultAmmo->BackpackMaxAmount = defaultAmmo->MaxAmount * 2;
|
defaultAmmo->IntVar("BackpackMaxAmount") = defaultAmmo->MaxAmount * 2;
|
||||||
defaultAmmo->BackpackAmount = defaultAmmo->Amount;
|
defaultAmmo->IntVar("BackpackAmount") = defaultAmmo->Amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fix per-ammo/max-ammo amounts for descendants of the base ammo class
|
// Fix per-ammo/max-ammo amounts for descendants of the base ammo class
|
||||||
|
@ -1591,7 +1589,7 @@ static int PatchAmmo (int ammoNum)
|
||||||
|
|
||||||
if (type->IsDescendantOf (ammoType))
|
if (type->IsDescendantOf (ammoType))
|
||||||
{
|
{
|
||||||
defaultAmmo = (AAmmo *)GetDefaultByType (type);
|
defaultAmmo = (AInventory *)GetDefaultByType (type);
|
||||||
defaultAmmo->MaxAmount = *max;
|
defaultAmmo->MaxAmount = *max;
|
||||||
defaultAmmo->Amount = Scale (defaultAmmo->Amount, *per, oldclip);
|
defaultAmmo->Amount = Scale (defaultAmmo->Amount, *per, oldclip);
|
||||||
}
|
}
|
||||||
|
@ -1673,7 +1671,7 @@ static int PatchWeapon (int weapNum)
|
||||||
info->AmmoType1 = (PClassInventory*)AmmoNames[val];
|
info->AmmoType1 = (PClassInventory*)AmmoNames[val];
|
||||||
if (info->AmmoType1 != NULL)
|
if (info->AmmoType1 != NULL)
|
||||||
{
|
{
|
||||||
info->AmmoGive1 = ((AAmmo*)GetDefaultByType (info->AmmoType1))->Amount * 2;
|
info->AmmoGive1 = ((AInventory*)GetDefaultByType (info->AmmoType1))->Amount * 2;
|
||||||
if (info->AmmoUse1 == 0)
|
if (info->AmmoUse1 == 0)
|
||||||
{
|
{
|
||||||
info->AmmoUse1 = 1;
|
info->AmmoUse1 = 1;
|
||||||
|
@ -1949,26 +1947,24 @@ static int PatchMisc (int dummy)
|
||||||
|
|
||||||
// Update default item properties by patching the affected items
|
// Update default item properties by patching the affected items
|
||||||
// Note: This won't have any effect on DECORATE derivates of these items!
|
// Note: This won't have any effect on DECORATE derivates of these items!
|
||||||
ABasicArmorPickup *armor;
|
|
||||||
|
|
||||||
armor = static_cast<ABasicArmorPickup *> (GetDefaultByName ("GreenArmor"));
|
auto armor = GetDefaultByName ("GreenArmor");
|
||||||
if (armor!=NULL)
|
if (armor!=NULL)
|
||||||
{
|
{
|
||||||
armor->SaveAmount = 100 * deh.GreenAC;
|
armor->IntVar(NAME_SaveAmount) = 100 * deh.GreenAC;
|
||||||
armor->SavePercent = deh.GreenAC == 1 ? 0.33335 : 0.5;
|
armor->FloatVar(NAME_SavePercent) = deh.GreenAC == 1 ? 0.33335 : 0.5;
|
||||||
}
|
}
|
||||||
armor = static_cast<ABasicArmorPickup *> (GetDefaultByName ("BlueArmor"));
|
armor = GetDefaultByName ("BlueArmor");
|
||||||
if (armor!=NULL)
|
if (armor!=NULL)
|
||||||
{
|
{
|
||||||
armor->SaveAmount = 100 * deh.BlueAC;
|
armor->IntVar(NAME_SaveAmount) = 100 * deh.BlueAC;
|
||||||
armor->SavePercent = deh.BlueAC == 1 ? 0.33335 : 0.5;
|
armor->FloatVar(NAME_SavePercent) = deh.BlueAC == 1 ? 0.33335 : 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
ABasicArmorBonus *barmor;
|
auto barmor = GetDefaultByName ("ArmorBonus");
|
||||||
barmor = static_cast<ABasicArmorBonus *> (GetDefaultByName ("ArmorBonus"));
|
|
||||||
if (barmor!=NULL)
|
if (barmor!=NULL)
|
||||||
{
|
{
|
||||||
barmor->MaxSaveAmount = deh.MaxArmor;
|
barmor->IntVar("MaxSaveAmount") = deh.MaxArmor;
|
||||||
}
|
}
|
||||||
|
|
||||||
AInventory *health;
|
AInventory *health;
|
||||||
|
@ -2930,7 +2926,7 @@ static bool LoadDehSupp ()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto cls = PClass::FindActor(sc.String);
|
auto cls = PClass::FindActor(sc.String);
|
||||||
if (cls == NULL || !cls->IsDescendantOf(RUNTIME_CLASS(AAmmo)))
|
if (cls == NULL || !cls->IsDescendantOf(PClass::FindActor(NAME_Ammo)))
|
||||||
{
|
{
|
||||||
sc.ScriptError("Unknown ammo type '%s'", sc.String);
|
sc.ScriptError("Unknown ammo type '%s'", sc.String);
|
||||||
}
|
}
|
||||||
|
@ -3184,7 +3180,7 @@ bool ADehackedPickup::ShouldRespawn ()
|
||||||
void ADehackedPickup::PlayPickupSound (AActor *toucher)
|
void ADehackedPickup::PlayPickupSound (AActor *toucher)
|
||||||
{
|
{
|
||||||
if (RealPickup != nullptr)
|
if (RealPickup != nullptr)
|
||||||
RealPickup->PlayPickupSound (toucher);
|
RealPickup->CallPlayPickupSound (toucher);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ADehackedPickup::DoPickupSpecial (AActor *toucher)
|
void ADehackedPickup::DoPickupSpecial (AActor *toucher)
|
||||||
|
|
|
@ -177,11 +177,6 @@ public:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class APlayerChunk : public APlayerPawn
|
|
||||||
{
|
|
||||||
DECLARE_CLASS (APlayerChunk, APlayerPawn)
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// PlayerPawn flags
|
// PlayerPawn flags
|
||||||
//
|
//
|
||||||
|
|
|
@ -571,7 +571,7 @@ DEFINE_ACTION_FUNCTION(DObject, GetClassName)
|
||||||
void *DObject::ScriptVar(FName field, PType *type)
|
void *DObject::ScriptVar(FName field, PType *type)
|
||||||
{
|
{
|
||||||
auto sym = dyn_cast<PField>(GetClass()->Symbols.FindSymbol(field, true));
|
auto sym = dyn_cast<PField>(GetClass()->Symbols.FindSymbol(field, true));
|
||||||
if (sym && sym->Type == type)
|
if (sym && (sym->Type == type || type == nullptr))
|
||||||
{
|
{
|
||||||
return (((char*)this) + sym->Offset);
|
return (((char*)this) + sym->Offset);
|
||||||
}
|
}
|
||||||
|
|
|
@ -482,6 +482,7 @@ public:
|
||||||
PalEntry &ColorVar(FName field);
|
PalEntry &ColorVar(FName field);
|
||||||
FName &NameVar(FName field);
|
FName &NameVar(FName field);
|
||||||
double &FloatVar(FName field);
|
double &FloatVar(FName field);
|
||||||
|
template<class T> T*& PointerVar(FName field);
|
||||||
|
|
||||||
// If you need to replace one object with another and want to
|
// If you need to replace one object with another and want to
|
||||||
// change any pointers from the old object to the new object,
|
// change any pointers from the old object to the new object,
|
||||||
|
|
|
@ -45,7 +45,6 @@
|
||||||
#include "autosegs.h"
|
#include "autosegs.h"
|
||||||
#include "v_text.h"
|
#include "v_text.h"
|
||||||
#include "a_pickups.h"
|
#include "a_pickups.h"
|
||||||
#include "a_weaponpiece.h"
|
|
||||||
#include "d_player.h"
|
#include "d_player.h"
|
||||||
#include "doomerrors.h"
|
#include "doomerrors.h"
|
||||||
#include "fragglescript/t_fs.h"
|
#include "fragglescript/t_fs.h"
|
||||||
|
|
|
@ -1093,5 +1093,9 @@ inline double &DObject::FloatVar(FName field)
|
||||||
return *(double*)ScriptVar(field, TypeFloat64);
|
return *(double*)ScriptVar(field, TypeFloat64);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
inline T *&DObject::PointerVar(FName field)
|
||||||
|
{
|
||||||
|
return *(T**)ScriptVar(field, nullptr); // pointer check is more tricky and for the handful of uses in the DECORATE parser not worth the hassle.
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -69,7 +69,6 @@
|
||||||
#include "p_setup.h"
|
#include "p_setup.h"
|
||||||
#include "p_spec.h"
|
#include "p_spec.h"
|
||||||
#include "r_utility.h"
|
#include "r_utility.h"
|
||||||
#include "a_ammo.h"
|
|
||||||
#include "math/cmath.h"
|
#include "math/cmath.h"
|
||||||
#include "g_levellocals.h"
|
#include "g_levellocals.h"
|
||||||
|
|
||||||
|
@ -2478,14 +2477,7 @@ static void FS_TakeInventory (AActor *actor, const char * type, int amount)
|
||||||
// If it's not ammo, destroy it. Ammo needs to stick around, even
|
// If it's not ammo, destroy it. Ammo needs to stick around, even
|
||||||
// when it's zero for the benefit of the weapons that use it and
|
// when it's zero for the benefit of the weapons that use it and
|
||||||
// to maintain the maximum ammo amounts a backpack might have given.
|
// to maintain the maximum ammo amounts a backpack might have given.
|
||||||
if (item->GetClass()->ParentClass != RUNTIME_CLASS(AAmmo))
|
item->DepleteOrDestroy();
|
||||||
{
|
|
||||||
item->Destroy ();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
item->Amount = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2628,7 +2620,7 @@ void FParser::SF_MaxPlayerAmmo()
|
||||||
if(amount < 0) amount = 0;
|
if(amount < 0) amount = 0;
|
||||||
if (!iammo)
|
if (!iammo)
|
||||||
{
|
{
|
||||||
iammo = static_cast<AAmmo *>(Spawn (ammotype));
|
iammo = static_cast<AInventory *>(Spawn (ammotype));
|
||||||
iammo->Amount = 0;
|
iammo->Amount = 0;
|
||||||
iammo->AttachToOwner (players[playernum].mo);
|
iammo->AttachToOwner (players[playernum].mo);
|
||||||
}
|
}
|
||||||
|
@ -2644,13 +2636,13 @@ void FParser::SF_MaxPlayerAmmo()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
((AAmmo*)iammo)->BackpackMaxAmount=amount;
|
iammo->IntVar("BackpackMaxAmount") = amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
t_return.type = svt_int;
|
t_return.type = svt_int;
|
||||||
AInventory * iammo = players[playernum].mo->FindInventory(ammotype);
|
AInventory * iammo = players[playernum].mo->FindInventory(ammotype);
|
||||||
if (iammo) t_return.value.i = iammo->MaxAmount;
|
if (iammo) t_return.value.i = iammo->MaxAmount;
|
||||||
else t_return.value.i = ((AAmmo*)GetDefaultByType(ammotype))->MaxAmount;
|
else t_return.value.i = ((AInventory*)GetDefaultByType(ammotype))->MaxAmount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -447,7 +447,7 @@ CCMD (use)
|
||||||
{
|
{
|
||||||
if (argv.argc() > 1 && who != NULL)
|
if (argv.argc() > 1 && who != NULL)
|
||||||
{
|
{
|
||||||
SendItemUse = who->FindInventory(PClass::FindActor(argv[1]));
|
SendItemUse = who->FindInventory(argv[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -468,7 +468,7 @@ CCMD (drop)
|
||||||
{
|
{
|
||||||
if (argv.argc() > 1 && who != NULL)
|
if (argv.argc() > 1 && who != NULL)
|
||||||
{
|
{
|
||||||
SendItemDrop = who->FindInventory(PClass::FindActor(argv[1]));
|
SendItemDrop = who->FindInventory(argv[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -513,7 +513,7 @@ CCMD (select)
|
||||||
{
|
{
|
||||||
if (argv.argc() > 1)
|
if (argv.argc() > 1)
|
||||||
{
|
{
|
||||||
AInventory *item = who->FindInventory(PClass::FindActor(argv[1]));
|
AInventory *item = who->FindInventory(argv[1]);
|
||||||
if (item != NULL)
|
if (item != NULL)
|
||||||
{
|
{
|
||||||
who->InvSel = item;
|
who->InvSel = item;
|
||||||
|
|
|
@ -1,91 +0,0 @@
|
||||||
/*
|
|
||||||
** a_ammo.cpp
|
|
||||||
** Implements ammo and backpack items.
|
|
||||||
**
|
|
||||||
**---------------------------------------------------------------------------
|
|
||||||
** Copyright 2000-2016 Randy Heit
|
|
||||||
** Copyright 2006-2016 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.
|
|
||||||
**---------------------------------------------------------------------------
|
|
||||||
**
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "c_dispatch.h"
|
|
||||||
#include "d_player.h"
|
|
||||||
#include "serializer.h"
|
|
||||||
|
|
||||||
IMPLEMENT_CLASS(AAmmo, false, false)
|
|
||||||
|
|
||||||
DEFINE_FIELD(AAmmo, BackpackAmount)
|
|
||||||
DEFINE_FIELD(AAmmo, BackpackMaxAmount)
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// AAmmo :: Serialize
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
void AAmmo::Serialize(FSerializer &arc)
|
|
||||||
{
|
|
||||||
Super::Serialize (arc);
|
|
||||||
auto def = (AAmmo*)GetDefault();
|
|
||||||
arc("backpackamount", BackpackAmount, def->BackpackAmount)
|
|
||||||
("backpackmaxamount", BackpackMaxAmount, def->BackpackMaxAmount);
|
|
||||||
}
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// AAmmo :: GetParentAmmo
|
|
||||||
//
|
|
||||||
// Returns the least-derived ammo type that this ammo is a descendant of.
|
|
||||||
// That is, if this ammo is an immediate subclass of Ammo, then this ammo's
|
|
||||||
// type is returned. If this ammo's superclass is not Ammo, then this
|
|
||||||
// function travels up the inheritance chain until it finds a type that is
|
|
||||||
// an immediate subclass of Ammo and returns that.
|
|
||||||
//
|
|
||||||
// The intent of this is that all unique ammo types will be immediate
|
|
||||||
// subclasses of Ammo. To make different pickups with different ammo amounts,
|
|
||||||
// you subclass the type of ammo you want a different amount for and edit
|
|
||||||
// that.
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
PClassActor *AAmmo::GetParentAmmo () const
|
|
||||||
{
|
|
||||||
PClass *type = GetClass();
|
|
||||||
|
|
||||||
while (type->ParentClass != RUNTIME_CLASS(AAmmo) && type->ParentClass != NULL)
|
|
||||||
{
|
|
||||||
type = type->ParentClass;
|
|
||||||
}
|
|
||||||
return static_cast<PClassActor *>(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(AAmmo, GetParentAmmo)
|
|
||||||
{
|
|
||||||
PARAM_SELF_PROLOGUE(AAmmo);
|
|
||||||
ACTION_RETURN_OBJECT(self->GetParentAmmo());
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
#pragma once
|
|
||||||
#include "a_pickups.h"
|
|
||||||
|
|
||||||
class AAmmo : public AInventory
|
|
||||||
{
|
|
||||||
DECLARE_CLASS (AAmmo, AInventory)
|
|
||||||
public:
|
|
||||||
|
|
||||||
virtual void Serialize(FSerializer &arc) override;
|
|
||||||
PClassActor *GetParentAmmo () const;
|
|
||||||
|
|
||||||
int BackpackAmount, BackpackMaxAmount, DropAmount;
|
|
||||||
};
|
|
||||||
|
|
|
@ -1,644 +0,0 @@
|
||||||
/*
|
|
||||||
** a_armor.cpp
|
|
||||||
** Implements all variations of armor objects
|
|
||||||
**
|
|
||||||
**---------------------------------------------------------------------------
|
|
||||||
** Copyright 2002-2016 Randy Heit
|
|
||||||
** Copyright 2006-2016 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.
|
|
||||||
**---------------------------------------------------------------------------
|
|
||||||
**
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include "info.h"
|
|
||||||
#include "gi.h"
|
|
||||||
#include "a_pickups.h"
|
|
||||||
#include "a_armor.h"
|
|
||||||
#include "templates.h"
|
|
||||||
#include "g_level.h"
|
|
||||||
#include "d_player.h"
|
|
||||||
#include "serializer.h"
|
|
||||||
#include "cmdlib.h"
|
|
||||||
|
|
||||||
IMPLEMENT_CLASS(AArmor, false, false)
|
|
||||||
IMPLEMENT_CLASS(ABasicArmor, false, false)
|
|
||||||
IMPLEMENT_CLASS(ABasicArmorPickup, false, false)
|
|
||||||
IMPLEMENT_CLASS(ABasicArmorBonus, false, false)
|
|
||||||
IMPLEMENT_CLASS(AHexenArmor, false, false)
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// BasicArmor
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
DEFINE_FIELD(ABasicArmor, AbsorbCount)
|
|
||||||
DEFINE_FIELD(ABasicArmor, SavePercent)
|
|
||||||
DEFINE_FIELD(ABasicArmor, MaxAbsorb)
|
|
||||||
DEFINE_FIELD(ABasicArmor, MaxFullAbsorb)
|
|
||||||
DEFINE_FIELD(ABasicArmor, BonusCount)
|
|
||||||
DEFINE_FIELD(ABasicArmor, ArmorType)
|
|
||||||
DEFINE_FIELD(ABasicArmor, ActualSaveAmount)
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// ABasicArmor :: Serialize
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
void ABasicArmor::Serialize(FSerializer &arc)
|
|
||||||
{
|
|
||||||
Super::Serialize (arc);
|
|
||||||
auto def = (ABasicArmor *)GetDefault();
|
|
||||||
arc("savepercent", SavePercent, def->SavePercent)
|
|
||||||
("bonuscount", BonusCount, def->BonusCount)
|
|
||||||
("maxabsorb", MaxAbsorb, def->MaxAbsorb)
|
|
||||||
("maxfullabsorb", MaxFullAbsorb, def->MaxFullAbsorb)
|
|
||||||
("absorbcount", AbsorbCount, def->AbsorbCount)
|
|
||||||
("armortype", ArmorType, def->ArmorType)
|
|
||||||
("actualsaveamount", ActualSaveAmount, def->ActualSaveAmount);
|
|
||||||
}
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// ABasicArmor :: Tick
|
|
||||||
//
|
|
||||||
// If BasicArmor is given to the player by means other than a
|
|
||||||
// BasicArmorPickup, then it may not have an icon set. Fix that here.
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
void ABasicArmor::Tick ()
|
|
||||||
{
|
|
||||||
Super::Tick ();
|
|
||||||
AbsorbCount = 0;
|
|
||||||
if (!Icon.isValid())
|
|
||||||
{
|
|
||||||
FString icon = gameinfo.ArmorIcon1;
|
|
||||||
|
|
||||||
if (SavePercent >= gameinfo.Armor2Percent && gameinfo.ArmorIcon2.Len() != 0)
|
|
||||||
icon = gameinfo.ArmorIcon2;
|
|
||||||
|
|
||||||
if (icon[0] != 0)
|
|
||||||
Icon = TexMan.CheckForTexture (icon, FTexture::TEX_Any);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// ABasicArmor :: CreateCopy
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
AInventory *ABasicArmor::CreateCopy (AActor *other)
|
|
||||||
{
|
|
||||||
// BasicArmor that is in use is stored in the inventory as BasicArmor.
|
|
||||||
// BasicArmor that is in reserve is not.
|
|
||||||
ABasicArmor *copy = Spawn<ABasicArmor> ();
|
|
||||||
copy->SavePercent = SavePercent != 0 ? SavePercent : 0.33335; // slightly more than 1/3 to avoid roundoff errors.
|
|
||||||
copy->Amount = Amount;
|
|
||||||
copy->MaxAmount = MaxAmount;
|
|
||||||
copy->Icon = Icon;
|
|
||||||
copy->BonusCount = BonusCount;
|
|
||||||
copy->ArmorType = ArmorType;
|
|
||||||
copy->ActualSaveAmount = ActualSaveAmount;
|
|
||||||
GoAwayAndDie ();
|
|
||||||
return copy;
|
|
||||||
}
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// ABasicArmor :: HandlePickup
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
bool ABasicArmor::HandlePickup (AInventory *item)
|
|
||||||
{
|
|
||||||
if (item->GetClass() == RUNTIME_CLASS(ABasicArmor))
|
|
||||||
{
|
|
||||||
// You shouldn't be picking up BasicArmor anyway.
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (item->IsKindOf(RUNTIME_CLASS(ABasicArmorBonus)) && !(item->ItemFlags & IF_IGNORESKILL))
|
|
||||||
{
|
|
||||||
ABasicArmorBonus *armor = static_cast<ABasicArmorBonus*>(item);
|
|
||||||
|
|
||||||
armor->SaveAmount = int(armor->SaveAmount * G_SkillProperty(SKILLP_ArmorFactor));
|
|
||||||
}
|
|
||||||
else if (item->IsKindOf(RUNTIME_CLASS(ABasicArmorPickup)) && !(item->ItemFlags & IF_IGNORESKILL))
|
|
||||||
{
|
|
||||||
ABasicArmorPickup *armor = static_cast<ABasicArmorPickup*>(item);
|
|
||||||
|
|
||||||
armor->SaveAmount = int(armor->SaveAmount * G_SkillProperty(SKILLP_ArmorFactor));
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// ABasicArmor :: AbsorbDamage
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
void ABasicArmor::AbsorbDamage (int damage, FName damageType, int &newdamage)
|
|
||||||
{
|
|
||||||
int saved;
|
|
||||||
|
|
||||||
if (!DamageTypeDefinition::IgnoreArmor(damageType))
|
|
||||||
{
|
|
||||||
int full = MAX(0, MaxFullAbsorb - AbsorbCount);
|
|
||||||
if (damage < full)
|
|
||||||
{
|
|
||||||
saved = damage;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
saved = full + int((damage - full) * SavePercent);
|
|
||||||
if (MaxAbsorb > 0 && saved + AbsorbCount > MaxAbsorb)
|
|
||||||
{
|
|
||||||
saved = MAX(0, MaxAbsorb - AbsorbCount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Amount < saved)
|
|
||||||
{
|
|
||||||
saved = Amount;
|
|
||||||
}
|
|
||||||
newdamage -= saved;
|
|
||||||
Amount -= saved;
|
|
||||||
AbsorbCount += saved;
|
|
||||||
if (Amount == 0)
|
|
||||||
{
|
|
||||||
// The armor has become useless
|
|
||||||
SavePercent = 0;
|
|
||||||
ArmorType = NAME_None; // Not NAME_BasicArmor.
|
|
||||||
// Now see if the player has some more armor in their inventory
|
|
||||||
// and use it if so. As in Strife, the best armor is used up first.
|
|
||||||
ABasicArmorPickup *best = NULL;
|
|
||||||
AInventory *probe = Owner->Inventory;
|
|
||||||
while (probe != NULL)
|
|
||||||
{
|
|
||||||
if (probe->IsKindOf (RUNTIME_CLASS(ABasicArmorPickup)))
|
|
||||||
{
|
|
||||||
ABasicArmorPickup *inInv = static_cast<ABasicArmorPickup*>(probe);
|
|
||||||
if (best == NULL || best->SavePercent < inInv->SavePercent)
|
|
||||||
{
|
|
||||||
best = inInv;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
probe = probe->Inventory;
|
|
||||||
}
|
|
||||||
if (best != NULL)
|
|
||||||
{
|
|
||||||
Owner->UseInventory (best);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
damage = newdamage;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Once the armor has absorbed its part of the damage, then apply its damage factor, if any, to the player
|
|
||||||
if ((damage > 0) && (ArmorType != NAME_None)) // BasicArmor is not going to have any damage factor, so skip it.
|
|
||||||
{
|
|
||||||
// This code is taken and adapted from APowerProtection::ModifyDamage().
|
|
||||||
// The differences include not using a default value, and of course the way
|
|
||||||
// the damage factor info is obtained.
|
|
||||||
|
|
||||||
// ApplyDamageFactors(ArmorType, damageType, damage, damage);
|
|
||||||
DmgFactors *df = PClass::FindActor(ArmorType)->DamageFactors;
|
|
||||||
if (df != NULL)
|
|
||||||
{
|
|
||||||
damage = newdamage = df->Apply(damageType, damage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// BasicArmorPickup
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
|
|
||||||
DEFINE_FIELD(ABasicArmorPickup, SavePercent)
|
|
||||||
DEFINE_FIELD(ABasicArmorPickup, MaxAbsorb)
|
|
||||||
DEFINE_FIELD(ABasicArmorPickup, MaxFullAbsorb)
|
|
||||||
DEFINE_FIELD(ABasicArmorPickup, SaveAmount)
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// ABasicArmorPickup :: Serialize
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
void ABasicArmorPickup::Serialize(FSerializer &arc)
|
|
||||||
{
|
|
||||||
Super::Serialize (arc);
|
|
||||||
|
|
||||||
auto def = (ABasicArmorPickup *)GetDefault();
|
|
||||||
arc("savepercent", SavePercent, def->SavePercent)
|
|
||||||
("saveamount", SaveAmount, def->SaveAmount)
|
|
||||||
("maxabsorb", MaxAbsorb, def->MaxAbsorb)
|
|
||||||
("maxfullabsorb", MaxFullAbsorb, def->MaxFullAbsorb);
|
|
||||||
}
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// ABasicArmorPickup :: CreateCopy
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
AInventory *ABasicArmorPickup::CreateCopy (AActor *other)
|
|
||||||
{
|
|
||||||
ABasicArmorPickup *copy = static_cast<ABasicArmorPickup *> (Super::CreateCopy (other));
|
|
||||||
|
|
||||||
if (!(ItemFlags & IF_IGNORESKILL))
|
|
||||||
{
|
|
||||||
SaveAmount = int(SaveAmount * G_SkillProperty(SKILLP_ArmorFactor));
|
|
||||||
}
|
|
||||||
|
|
||||||
copy->SavePercent = SavePercent;
|
|
||||||
copy->SaveAmount = SaveAmount;
|
|
||||||
copy->MaxAbsorb = MaxAbsorb;
|
|
||||||
copy->MaxFullAbsorb = MaxFullAbsorb;
|
|
||||||
|
|
||||||
return copy;
|
|
||||||
}
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// ABasicArmorPickup :: Use
|
|
||||||
//
|
|
||||||
// Either gives you new armor or replaces the armor you already have (if
|
|
||||||
// the SaveAmount is greater than the amount of armor you own). When the
|
|
||||||
// item is auto-activated, it will only be activated if its max amount is 0
|
|
||||||
// or if you have no armor active already.
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
bool ABasicArmorPickup::Use (bool pickup)
|
|
||||||
{
|
|
||||||
ABasicArmor *armor = Owner->FindInventory<ABasicArmor> ();
|
|
||||||
|
|
||||||
if (armor == NULL)
|
|
||||||
{
|
|
||||||
armor = Spawn<ABasicArmor> ();
|
|
||||||
armor->BecomeItem ();
|
|
||||||
Owner->AddInventory (armor);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// If you already have more armor than this item gives you, you can't
|
|
||||||
// use it.
|
|
||||||
if (armor->Amount >= SaveAmount + armor->BonusCount)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// Don't use it if you're picking it up and already have some.
|
|
||||||
if (pickup && armor->Amount > 0 && MaxAmount > 0)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
armor->SavePercent = SavePercent;
|
|
||||||
armor->Amount = SaveAmount + armor->BonusCount;
|
|
||||||
armor->MaxAmount = SaveAmount;
|
|
||||||
armor->Icon = Icon;
|
|
||||||
armor->MaxAbsorb = MaxAbsorb;
|
|
||||||
armor->MaxFullAbsorb = MaxFullAbsorb;
|
|
||||||
armor->ArmorType = this->GetClass()->TypeName;
|
|
||||||
armor->ActualSaveAmount = SaveAmount;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// BasicArmorBonus
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
|
|
||||||
DEFINE_FIELD(ABasicArmorBonus, SavePercent)
|
|
||||||
DEFINE_FIELD(ABasicArmorBonus, MaxSaveAmount)
|
|
||||||
DEFINE_FIELD(ABasicArmorBonus, MaxAbsorb)
|
|
||||||
DEFINE_FIELD(ABasicArmorBonus, MaxFullAbsorb)
|
|
||||||
DEFINE_FIELD(ABasicArmorBonus, SaveAmount)
|
|
||||||
DEFINE_FIELD(ABasicArmorBonus, BonusCount)
|
|
||||||
DEFINE_FIELD(ABasicArmorBonus, BonusMax)
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// ABasicArmorBonus :: Serialize
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
void ABasicArmorBonus::Serialize(FSerializer &arc)
|
|
||||||
{
|
|
||||||
Super::Serialize (arc);
|
|
||||||
auto def = (ABasicArmorBonus *)GetDefault();
|
|
||||||
arc("savepercent", SavePercent, def->SavePercent)
|
|
||||||
("saveamount", SaveAmount, def->SaveAmount)
|
|
||||||
("maxsaveamount", MaxSaveAmount, def->MaxSaveAmount)
|
|
||||||
("bonuscount", BonusCount, def->BonusCount)
|
|
||||||
("bonusmax", BonusMax, def->BonusMax)
|
|
||||||
("maxabsorb", MaxAbsorb, def->MaxAbsorb)
|
|
||||||
("maxfullabsorb", MaxFullAbsorb, def->MaxFullAbsorb);
|
|
||||||
}
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// ABasicArmorBonus :: CreateCopy
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
AInventory *ABasicArmorBonus::CreateCopy (AActor *other)
|
|
||||||
{
|
|
||||||
ABasicArmorBonus *copy = static_cast<ABasicArmorBonus *> (Super::CreateCopy (other));
|
|
||||||
|
|
||||||
if (!(ItemFlags & IF_IGNORESKILL))
|
|
||||||
{
|
|
||||||
SaveAmount = int(SaveAmount * G_SkillProperty(SKILLP_ArmorFactor));
|
|
||||||
}
|
|
||||||
|
|
||||||
copy->SavePercent = SavePercent;
|
|
||||||
copy->SaveAmount = SaveAmount;
|
|
||||||
copy->MaxSaveAmount = MaxSaveAmount;
|
|
||||||
copy->BonusCount = BonusCount;
|
|
||||||
copy->BonusMax = BonusMax;
|
|
||||||
copy->MaxAbsorb = MaxAbsorb;
|
|
||||||
copy->MaxFullAbsorb = MaxFullAbsorb;
|
|
||||||
|
|
||||||
return copy;
|
|
||||||
}
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// ABasicArmorBonus :: Use
|
|
||||||
//
|
|
||||||
// Tries to add to the amount of BasicArmor a player has.
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
bool ABasicArmorBonus::Use (bool pickup)
|
|
||||||
{
|
|
||||||
ABasicArmor *armor = Owner->FindInventory<ABasicArmor> ();
|
|
||||||
bool result = false;
|
|
||||||
|
|
||||||
if (armor == NULL)
|
|
||||||
{
|
|
||||||
armor = Spawn<ABasicArmor> ();
|
|
||||||
armor->BecomeItem ();
|
|
||||||
armor->Amount = 0;
|
|
||||||
armor->MaxAmount = MaxSaveAmount;
|
|
||||||
Owner->AddInventory (armor);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (BonusCount > 0 && armor->BonusCount < BonusMax)
|
|
||||||
{
|
|
||||||
armor->BonusCount = MIN (armor->BonusCount + BonusCount, BonusMax);
|
|
||||||
result = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int saveAmount = MIN (SaveAmount, MaxSaveAmount);
|
|
||||||
|
|
||||||
if (saveAmount <= 0)
|
|
||||||
{ // If it can't give you anything, it's as good as used.
|
|
||||||
return BonusCount > 0 ? result : true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If you already have more armor than this item can give you, you can't
|
|
||||||
// use it.
|
|
||||||
if (armor->Amount >= MaxSaveAmount + armor->BonusCount)
|
|
||||||
{
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (armor->Amount <= 0)
|
|
||||||
{ // Should never be less than 0, but might as well check anyway
|
|
||||||
armor->Amount = 0;
|
|
||||||
armor->Icon = Icon;
|
|
||||||
armor->SavePercent = SavePercent;
|
|
||||||
armor->MaxAbsorb = MaxAbsorb;
|
|
||||||
armor->ArmorType = this->GetClass()->TypeName;
|
|
||||||
armor->MaxFullAbsorb = MaxFullAbsorb;
|
|
||||||
armor->ActualSaveAmount = MaxSaveAmount;
|
|
||||||
}
|
|
||||||
|
|
||||||
armor->Amount = MIN(armor->Amount + saveAmount, MaxSaveAmount + armor->BonusCount);
|
|
||||||
armor->MaxAmount = MAX (armor->MaxAmount, MaxSaveAmount);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// HexenArmor
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
DEFINE_FIELD(AHexenArmor, Slots)
|
|
||||||
DEFINE_FIELD(AHexenArmor, SlotsIncrement)
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// AHexenArmor :: Serialize
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
void AHexenArmor::Serialize(FSerializer &arc)
|
|
||||||
{
|
|
||||||
Super::Serialize (arc);
|
|
||||||
auto def = (AHexenArmor *)GetDefault();
|
|
||||||
arc.Array("slots", Slots, def->Slots, 5, true)
|
|
||||||
.Array("slotsincrement", SlotsIncrement, def->SlotsIncrement, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// AHexenArmor :: CreateCopy
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
AInventory *AHexenArmor::CreateCopy (AActor *other)
|
|
||||||
{
|
|
||||||
// Like BasicArmor, HexenArmor is used in the inventory but not the map.
|
|
||||||
// health is the slot this armor occupies.
|
|
||||||
// Amount is the quantity to give (0 = normal max).
|
|
||||||
AHexenArmor *copy = Spawn<AHexenArmor> ();
|
|
||||||
copy->AddArmorToSlot (other, health, Amount);
|
|
||||||
GoAwayAndDie ();
|
|
||||||
return copy;
|
|
||||||
}
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// AHexenArmor :: CreateTossable
|
|
||||||
//
|
|
||||||
// Since this isn't really a single item, you can't drop it. Ever.
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
AInventory *AHexenArmor::CreateTossable ()
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// AHexenArmor :: HandlePickup
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
bool AHexenArmor::HandlePickup (AInventory *item)
|
|
||||||
{
|
|
||||||
if (item->IsKindOf (RUNTIME_CLASS(AHexenArmor)))
|
|
||||||
{
|
|
||||||
if (AddArmorToSlot (Owner, item->health, item->Amount))
|
|
||||||
{
|
|
||||||
item->ItemFlags |= IF_PICKUPGOOD;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// AHexenArmor :: AddArmorToSlot
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
bool AHexenArmor::AddArmorToSlot (AActor *actor, int slot, int amount)
|
|
||||||
{
|
|
||||||
APlayerPawn *ppawn;
|
|
||||||
double hits;
|
|
||||||
|
|
||||||
if (actor->player != NULL)
|
|
||||||
{
|
|
||||||
ppawn = static_cast<APlayerPawn *>(actor);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ppawn = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (slot < 0 || slot > 3)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (amount <= 0)
|
|
||||||
{
|
|
||||||
hits = SlotsIncrement[slot];
|
|
||||||
if (Slots[slot] < hits)
|
|
||||||
{
|
|
||||||
Slots[slot] = hits;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hits = amount * 5;
|
|
||||||
auto total = Slots[0] + Slots[1] + Slots[2] + Slots[3] + Slots[4];
|
|
||||||
auto max = SlotsIncrement[0] + SlotsIncrement[1] + SlotsIncrement[2] + SlotsIncrement[3] + Slots[4] + 4 * 5;
|
|
||||||
if (total < max)
|
|
||||||
{
|
|
||||||
Slots[slot] += hits;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// AHexenArmor :: AbsorbDamage
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
void AHexenArmor::AbsorbDamage (int damage, FName damageType, int &newdamage)
|
|
||||||
{
|
|
||||||
if (!DamageTypeDefinition::IgnoreArmor(damageType))
|
|
||||||
{
|
|
||||||
double savedPercent = Slots[0] + Slots[1] + Slots[2] + Slots[3] + Slots[4];
|
|
||||||
|
|
||||||
if (savedPercent)
|
|
||||||
{ // armor absorbed some damage
|
|
||||||
if (savedPercent > 100)
|
|
||||||
{
|
|
||||||
savedPercent = 100;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < 4; i++)
|
|
||||||
{
|
|
||||||
if (Slots[i])
|
|
||||||
{
|
|
||||||
// 300 damage always wipes out the armor unless some was added
|
|
||||||
// with the dragon skin bracers.
|
|
||||||
if (damage < 10000)
|
|
||||||
{
|
|
||||||
Slots[i] -= damage * SlotsIncrement[i] / 300.;
|
|
||||||
if (Slots[i] < 2)
|
|
||||||
{
|
|
||||||
Slots[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Slots[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int saved = int(damage * savedPercent / 100.);
|
|
||||||
if (saved > savedPercent*2)
|
|
||||||
{
|
|
||||||
saved = int(savedPercent*2);
|
|
||||||
}
|
|
||||||
newdamage -= saved;
|
|
||||||
damage = newdamage;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// AHexenArmor :: DepleteOrDestroy
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
void AHexenArmor::DepleteOrDestroy()
|
|
||||||
{
|
|
||||||
for (int i = 0; i < 4; i++)
|
|
||||||
{
|
|
||||||
Slots[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,89 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "a_pickups.h"
|
|
||||||
|
|
||||||
// Armor absorbs some damage for the player.
|
|
||||||
class AArmor : public AInventory
|
|
||||||
{
|
|
||||||
DECLARE_CLASS (AArmor, AInventory)
|
|
||||||
};
|
|
||||||
|
|
||||||
// Basic armor absorbs a specific percent of the damage. You should
|
|
||||||
// never pickup a BasicArmor. Instead, you pickup a BasicArmorPickup
|
|
||||||
// or BasicArmorBonus and those gives you BasicArmor when it activates.
|
|
||||||
class ABasicArmor : public AArmor
|
|
||||||
{
|
|
||||||
DECLARE_CLASS (ABasicArmor, AArmor)
|
|
||||||
public:
|
|
||||||
|
|
||||||
virtual void Serialize(FSerializer &arc) override;
|
|
||||||
virtual void Tick () override;
|
|
||||||
virtual AInventory *CreateCopy (AActor *other) override;
|
|
||||||
virtual bool HandlePickup (AInventory *item) override;
|
|
||||||
virtual void AbsorbDamage (int damage, FName damageType, int &newdamage) override;
|
|
||||||
|
|
||||||
int AbsorbCount;
|
|
||||||
double SavePercent;
|
|
||||||
int MaxAbsorb;
|
|
||||||
int MaxFullAbsorb;
|
|
||||||
int BonusCount;
|
|
||||||
FNameNoInit ArmorType;
|
|
||||||
int ActualSaveAmount;
|
|
||||||
};
|
|
||||||
|
|
||||||
// BasicArmorPickup replaces the armor you have.
|
|
||||||
class ABasicArmorPickup : public AArmor
|
|
||||||
{
|
|
||||||
DECLARE_CLASS (ABasicArmorPickup, AArmor)
|
|
||||||
public:
|
|
||||||
|
|
||||||
virtual void Serialize(FSerializer &arc) override;
|
|
||||||
virtual AInventory *CreateCopy (AActor *other) override;
|
|
||||||
virtual bool Use (bool pickup) override;
|
|
||||||
|
|
||||||
double SavePercent;
|
|
||||||
int MaxAbsorb;
|
|
||||||
int MaxFullAbsorb;
|
|
||||||
int SaveAmount;
|
|
||||||
};
|
|
||||||
|
|
||||||
// BasicArmorBonus adds to the armor you have.
|
|
||||||
class ABasicArmorBonus : public AArmor
|
|
||||||
{
|
|
||||||
DECLARE_CLASS (ABasicArmorBonus, AArmor)
|
|
||||||
public:
|
|
||||||
|
|
||||||
virtual void Serialize(FSerializer &arc) override;
|
|
||||||
virtual AInventory *CreateCopy (AActor *other) override;
|
|
||||||
virtual bool Use (bool pickup) override;
|
|
||||||
|
|
||||||
double SavePercent; // The default, for when you don't already have armor
|
|
||||||
int MaxSaveAmount;
|
|
||||||
int MaxAbsorb;
|
|
||||||
int MaxFullAbsorb;
|
|
||||||
int SaveAmount;
|
|
||||||
int BonusCount;
|
|
||||||
int BonusMax;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Hexen armor consists of four separate armor types plus a conceptual armor
|
|
||||||
// type (the player himself) that work together as a single armor.
|
|
||||||
class AHexenArmor : public AArmor
|
|
||||||
{
|
|
||||||
DECLARE_CLASS (AHexenArmor, AArmor)
|
|
||||||
public:
|
|
||||||
|
|
||||||
virtual void Serialize(FSerializer &arc) override;
|
|
||||||
virtual AInventory *CreateCopy (AActor *other) override;
|
|
||||||
virtual AInventory *CreateTossable () override;
|
|
||||||
virtual bool HandlePickup (AInventory *item) override;
|
|
||||||
virtual void AbsorbDamage (int damage, FName damageType, int &newdamage) override;
|
|
||||||
virtual void DepleteOrDestroy() override;
|
|
||||||
|
|
||||||
double Slots[5];
|
|
||||||
double SlotsIncrement[4];
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bool AddArmorToSlot (AActor *actor, int slot, int amount);
|
|
||||||
};
|
|
||||||
|
|
|
@ -51,7 +51,6 @@
|
||||||
//
|
//
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
@ -63,14 +62,10 @@ struct OneKey
|
||||||
int count;
|
int count;
|
||||||
|
|
||||||
bool check(AActor *owner)
|
bool check(AActor *owner)
|
||||||
{
|
|
||||||
if (owner->IsKindOf(RUNTIME_CLASS(AKey)))
|
|
||||||
{
|
{
|
||||||
// P_GetMapColorForKey() checks the key directly
|
// P_GetMapColorForKey() checks the key directly
|
||||||
return owner->IsA(key) || owner->GetSpecies() == key->TypeName;
|
if (owner->IsA(key) || owner->GetSpecies() == key->TypeName) return true;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Other calls check an actor that may have a key in its inventory.
|
// Other calls check an actor that may have a key in its inventory.
|
||||||
AInventory *item;
|
AInventory *item;
|
||||||
|
|
||||||
|
@ -87,7 +82,6 @@ struct OneKey
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
@ -138,9 +132,10 @@ struct Lock
|
||||||
// An empty key list means that any key will do
|
// An empty key list means that any key will do
|
||||||
if (!keylist.Size())
|
if (!keylist.Size())
|
||||||
{
|
{
|
||||||
|
auto kt = PClass::FindActor(NAME_Key);
|
||||||
for (AInventory * item = owner->Inventory; item != NULL; item = item->Inventory)
|
for (AInventory * item = owner->Inventory; item != NULL; item = item->Inventory)
|
||||||
{
|
{
|
||||||
if (item->IsKindOf (RUNTIME_CLASS(AKey)))
|
if (item->IsKindOf (kt))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -192,12 +187,12 @@ static void AddOneKey(Keygroup *keygroup, PClassActor *mi, FScanner &sc)
|
||||||
keygroup->anykeylist.Push (k);
|
keygroup->anykeylist.Push (k);
|
||||||
|
|
||||||
//... but only keys get key numbers!
|
//... but only keys get key numbers!
|
||||||
if (mi->IsDescendantOf(RUNTIME_CLASS(AKey)))
|
if (mi->IsDescendantOf(PClass::FindActor(NAME_Key)))
|
||||||
{
|
{
|
||||||
if (!ignorekey &&
|
if (!ignorekey &&
|
||||||
static_cast<AKey*>(GetDefaultByType(mi))->KeyNumber == 0)
|
GetDefaultByType(mi)->special1 == 0)
|
||||||
{
|
{
|
||||||
static_cast<AKey*>(GetDefaultByType(mi))->KeyNumber=++currentnumber;
|
GetDefaultByType(mi)->special1 = ++currentnumber;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -387,14 +382,15 @@ static void ParseLock(FScanner &sc)
|
||||||
static void ClearLocks()
|
static void ClearLocks()
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
auto kt = PClass::FindActor(NAME_Key);
|
||||||
for(i = 0; i < PClassActor::AllActorClasses.Size(); i++)
|
for(i = 0; i < PClassActor::AllActorClasses.Size(); i++)
|
||||||
{
|
{
|
||||||
if (PClassActor::AllActorClasses[i]->IsDescendantOf(RUNTIME_CLASS(AKey)))
|
if (PClassActor::AllActorClasses[i]->IsDescendantOf(kt))
|
||||||
{
|
{
|
||||||
AKey *key = static_cast<AKey*>(GetDefaultByType(PClassActor::AllActorClasses[i]));
|
auto key = GetDefaultByType(PClassActor::AllActorClasses[i]);
|
||||||
if (key != NULL)
|
if (key != NULL)
|
||||||
{
|
{
|
||||||
key->KeyNumber = 0;
|
key->special1 = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -523,15 +519,6 @@ bool P_CheckKeys (AActor *owner, int keynum, bool remote)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// AKey implementation
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
IMPLEMENT_CLASS(AKey, false, false)
|
|
||||||
DEFINE_FIELD(AKey, KeyNumber)
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// These functions can be used to get color information for
|
// These functions can be used to get color information for
|
||||||
|
|
|
@ -1,14 +1,8 @@
|
||||||
#ifndef A_KEYS_H
|
#ifndef A_KEYS_H
|
||||||
#define A_KEYS_H
|
#define A_KEYS_H
|
||||||
|
|
||||||
#include "a_pickups.h"
|
class AActor;
|
||||||
|
class AInventory;
|
||||||
class AKey : public AInventory
|
|
||||||
{
|
|
||||||
DECLARE_CLASS (AKey, AInventory)
|
|
||||||
public:
|
|
||||||
BYTE KeyNumber;
|
|
||||||
};
|
|
||||||
|
|
||||||
bool P_CheckKeys (AActor *owner, int keynum, bool remote);
|
bool P_CheckKeys (AActor *owner, int keynum, bool remote);
|
||||||
void P_InitKeyMessages ();
|
void P_InitKeyMessages ();
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
#include "p_spec.h"
|
#include "p_spec.h"
|
||||||
#include "serializer.h"
|
#include "serializer.h"
|
||||||
#include "virtual.h"
|
#include "virtual.h"
|
||||||
#include "a_ammo.h"
|
|
||||||
#include "c_functions.h"
|
#include "c_functions.h"
|
||||||
#include "g_levellocals.h"
|
#include "g_levellocals.h"
|
||||||
|
|
||||||
|
@ -80,71 +79,6 @@ void PClassInventory::Finalize(FStateDefinitions &statedef)
|
||||||
((AActor*)Defaults)->flags |= MF_SPECIAL;
|
((AActor*)Defaults)->flags |= MF_SPECIAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// PROC A_RestoreSpecialThing1
|
|
||||||
//
|
|
||||||
// Make a special thing visible again.
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(AInventory, A_RestoreSpecialThing1)
|
|
||||||
{
|
|
||||||
PARAM_SELF_PROLOGUE(AInventory);
|
|
||||||
|
|
||||||
self->renderflags &= ~RF_INVISIBLE;
|
|
||||||
if (self->DoRespawn ())
|
|
||||||
{
|
|
||||||
S_Sound (self, CHAN_VOICE, "misc/spawn", 1, ATTN_IDLE);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// PROC A_RestoreSpecialThing2
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(AInventory, A_RestoreSpecialThing2)
|
|
||||||
{
|
|
||||||
PARAM_SELF_PROLOGUE(AInventory);
|
|
||||||
|
|
||||||
self->flags |= MF_SPECIAL;
|
|
||||||
if (!(self->GetDefault()->flags & MF_NOGRAVITY))
|
|
||||||
{
|
|
||||||
self->flags &= ~MF_NOGRAVITY;
|
|
||||||
}
|
|
||||||
self->SetState (self->SpawnState);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// PROC A_RestoreSpecialDoomThing
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(AInventory, A_RestoreSpecialDoomThing)
|
|
||||||
{
|
|
||||||
PARAM_SELF_PROLOGUE(AInventory);
|
|
||||||
|
|
||||||
self->renderflags &= ~RF_INVISIBLE;
|
|
||||||
self->flags |= MF_SPECIAL;
|
|
||||||
if (!(self->GetDefault()->flags & MF_NOGRAVITY))
|
|
||||||
{
|
|
||||||
self->flags &= ~MF_NOGRAVITY;
|
|
||||||
}
|
|
||||||
if (self->DoRespawn ())
|
|
||||||
{
|
|
||||||
self->SetState (self->SpawnState);
|
|
||||||
S_Sound (self, CHAN_VOICE, "misc/spawn", 1, ATTN_IDLE);
|
|
||||||
Spawn ("ItemFog", self->Pos(), ALLOW_REPLACE);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int AInventory::StaticLastMessageTic;
|
int AInventory::StaticLastMessageTic;
|
||||||
FString AInventory::StaticLastMessage;
|
FString AInventory::StaticLastMessage;
|
||||||
|
|
||||||
|
@ -908,7 +842,7 @@ void AInventory::Touch (AActor *toucher)
|
||||||
// real player to make noise.
|
// real player to make noise.
|
||||||
if (player != NULL)
|
if (player != NULL)
|
||||||
{
|
{
|
||||||
PlayPickupSound (player->mo);
|
CallPlayPickupSound (player->mo);
|
||||||
if (!(ItemFlags & IF_NOSCREENFLASH))
|
if (!(ItemFlags & IF_NOSCREENFLASH))
|
||||||
{
|
{
|
||||||
player->bonuscount = BONUSADD;
|
player->bonuscount = BONUSADD;
|
||||||
|
@ -916,7 +850,7 @@ void AInventory::Touch (AActor *toucher)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PlayPickupSound (toucher);
|
CallPlayPickupSound (toucher);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1117,19 +1051,10 @@ void AInventory::OnDestroy ()
|
||||||
|
|
||||||
void AInventory::DepleteOrDestroy ()
|
void AInventory::DepleteOrDestroy ()
|
||||||
{
|
{
|
||||||
// If it's not ammo or an internal armor, destroy it.
|
IFVIRTUAL(AInventory, DepleteOrDestroy)
|
||||||
// Ammo needs to stick around, even when it's zero for the benefit
|
|
||||||
// of the weapons that use it and to maintain the maximum ammo
|
|
||||||
// amounts a backpack might have given.
|
|
||||||
// Armor shouldn't be removed because they only work properly when
|
|
||||||
// they are the last items in the inventory.
|
|
||||||
if (ItemFlags & IF_KEEPDEPLETED)
|
|
||||||
{
|
{
|
||||||
Amount = 0;
|
VMValue params[1] = { (DObject*)this };
|
||||||
}
|
GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr);
|
||||||
else
|
|
||||||
{
|
|
||||||
Destroy();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1273,6 +1198,11 @@ bool AInventory::DoRespawn ()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(AInventory, DoRespawn)
|
||||||
|
{
|
||||||
|
PARAM_SELF_PROLOGUE(AInventory);
|
||||||
|
ACTION_RETURN_BOOL(self->DoRespawn());
|
||||||
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
|
@ -1314,29 +1244,7 @@ bool AInventory::TryPickup (AActor *&toucher)
|
||||||
ItemFlags &= ~IF_PICKUPGOOD;
|
ItemFlags &= ~IF_PICKUPGOOD;
|
||||||
GoAwayAndDie ();
|
GoAwayAndDie ();
|
||||||
}
|
}
|
||||||
else if (MaxAmount == 0 && !IsKindOf(RUNTIME_CLASS(AAmmo)))
|
else if (MaxAmount > 0)
|
||||||
{
|
|
||||||
// Special case: If an item's MaxAmount is 0, you can still pick it
|
|
||||||
// up if it is autoactivate-able.
|
|
||||||
if (!(ItemFlags & IF_AUTOACTIVATE))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// The item is placed in the inventory just long enough to be used.
|
|
||||||
toucher->AddInventory (this);
|
|
||||||
bool usegood = CallUse (true);
|
|
||||||
toucher->RemoveInventory (this);
|
|
||||||
|
|
||||||
if (usegood)
|
|
||||||
{
|
|
||||||
GoAwayAndDie ();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
// Add the item to the inventory. It is not already there, or HandlePickup
|
// Add the item to the inventory. It is not already there, or HandlePickup
|
||||||
// would have already taken care of it.
|
// would have already taken care of it.
|
||||||
|
@ -1374,6 +1282,25 @@ bool AInventory::TryPickup (AActor *&toucher)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (ItemFlags & IF_AUTOACTIVATE)
|
||||||
|
{
|
||||||
|
// Special case: If an item's MaxAmount is 0, you can still pick it
|
||||||
|
// up if it is autoactivate-able.
|
||||||
|
|
||||||
|
// The item is placed in the inventory just long enough to be used.
|
||||||
|
toucher->AddInventory(this);
|
||||||
|
bool usegood = CallUse(true);
|
||||||
|
toucher->RemoveInventory(this);
|
||||||
|
|
||||||
|
if (usegood)
|
||||||
|
{
|
||||||
|
GoAwayAndDie();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -82,7 +82,7 @@ public:
|
||||||
|
|
||||||
// virtual methods that only get overridden by special internal classes, like DehackedPickup.
|
// virtual methods that only get overridden by special internal classes, like DehackedPickup.
|
||||||
// There is no need to expose these to scripts.
|
// There is no need to expose these to scripts.
|
||||||
virtual void DepleteOrDestroy ();
|
void DepleteOrDestroy ();
|
||||||
virtual bool ShouldRespawn ();
|
virtual bool ShouldRespawn ();
|
||||||
virtual void DoPickupSpecial (AActor *toucher);
|
virtual void DoPickupSpecial (AActor *toucher);
|
||||||
|
|
||||||
|
|
|
@ -1,258 +0,0 @@
|
||||||
/*
|
|
||||||
** a_weaponpieces.cpp
|
|
||||||
** Implements generic weapon pieces
|
|
||||||
**
|
|
||||||
**---------------------------------------------------------------------------
|
|
||||||
** Copyright 2006-2016 Cheistoph Oelckers
|
|
||||||
** Copyright 2006-2016 Randy Heit
|
|
||||||
** 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.
|
|
||||||
**---------------------------------------------------------------------------
|
|
||||||
**
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "a_pickups.h"
|
|
||||||
#include "a_weaponpiece.h"
|
|
||||||
#include "doomstat.h"
|
|
||||||
#include "serializer.h"
|
|
||||||
|
|
||||||
IMPLEMENT_CLASS(AWeaponHolder, false, false)
|
|
||||||
|
|
||||||
DEFINE_FIELD(AWeaponHolder, PieceMask);
|
|
||||||
DEFINE_FIELD(AWeaponHolder, PieceWeapon);
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
void AWeaponHolder::Serialize(FSerializer &arc)
|
|
||||||
{
|
|
||||||
Super::Serialize(arc);
|
|
||||||
arc("piecemask", PieceMask)
|
|
||||||
("pieceweapon", PieceWeapon);
|
|
||||||
}
|
|
||||||
|
|
||||||
IMPLEMENT_CLASS(AWeaponPiece, false, true)
|
|
||||||
|
|
||||||
IMPLEMENT_POINTERS_START(AWeaponPiece)
|
|
||||||
IMPLEMENT_POINTER(FullWeapon)
|
|
||||||
IMPLEMENT_POINTER(WeaponClass)
|
|
||||||
IMPLEMENT_POINTERS_END
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
void AWeaponPiece::Serialize(FSerializer &arc)
|
|
||||||
{
|
|
||||||
Super::Serialize (arc);
|
|
||||||
auto def = (AWeaponPiece*)GetDefault();
|
|
||||||
arc("weaponclass", WeaponClass, def->WeaponClass)
|
|
||||||
("fullweapon", FullWeapon)
|
|
||||||
("piecevalue", PieceValue, def->PieceValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// TryPickupWeaponPiece
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
bool AWeaponPiece::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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
hold=static_cast<AWeaponHolder*>(Spawn(RUNTIME_CLASS(AWeaponHolder)));
|
|
||||||
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))
|
|
||||||
{
|
|
||||||
FullWeapon= static_cast<AWeapon*>(Spawn(WeaponClass));
|
|
||||||
|
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
FString 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
#pragma once
|
|
||||||
#include "a_pickups.h"
|
|
||||||
#include "a_weapons.h"
|
|
||||||
|
|
||||||
class AWeaponPiece : public AInventory
|
|
||||||
{
|
|
||||||
DECLARE_CLASS (AWeaponPiece, AInventory)
|
|
||||||
HAS_OBJECT_POINTERS
|
|
||||||
protected:
|
|
||||||
bool PrivateShouldStay ();
|
|
||||||
public:
|
|
||||||
|
|
||||||
virtual void Serialize(FSerializer &arc) override;
|
|
||||||
virtual bool TryPickup (AActor *&toucher) override;
|
|
||||||
virtual bool TryPickupRestricted (AActor *&toucher) override;
|
|
||||||
virtual bool ShouldStay () override;
|
|
||||||
virtual FString PickupMessage () override;
|
|
||||||
virtual void PlayPickupSound (AActor *toucher) override;
|
|
||||||
|
|
||||||
int PieceValue;
|
|
||||||
PClassActor *WeaponClass;
|
|
||||||
TObjPtr<AWeapon> FullWeapon;
|
|
||||||
};
|
|
||||||
|
|
||||||
// an internal class to hold the information for player class independent weapon piece handling
|
|
||||||
// [BL] Needs to be available for SBarInfo to check weaponpieces
|
|
||||||
class AWeaponHolder : public AInventory
|
|
||||||
{
|
|
||||||
DECLARE_CLASS (AWeaponHolder, AInventory)
|
|
||||||
|
|
||||||
public:
|
|
||||||
int PieceMask;
|
|
||||||
PClassActor * PieceWeapon;
|
|
||||||
|
|
||||||
|
|
||||||
virtual void Serialize(FSerializer &arc) override;
|
|
||||||
};
|
|
|
@ -54,7 +54,7 @@
|
||||||
#include "serializer.h"
|
#include "serializer.h"
|
||||||
#include "thingdef.h"
|
#include "thingdef.h"
|
||||||
#include "virtual.h"
|
#include "virtual.h"
|
||||||
#include "a_ammo.h"
|
|
||||||
|
|
||||||
#define BONUSADD 6
|
#define BONUSADD 6
|
||||||
|
|
||||||
|
@ -499,9 +499,9 @@ void AWeapon::AttachToOwner (AActor *other)
|
||||||
//
|
//
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
AAmmo *AWeapon::AddAmmo (AActor *other, PClassActor *ammotype, int amount)
|
AInventory *AWeapon::AddAmmo (AActor *other, PClassActor *ammotype, int amount)
|
||||||
{
|
{
|
||||||
AAmmo *ammo;
|
AInventory *ammo;
|
||||||
|
|
||||||
if (ammotype == NULL)
|
if (ammotype == NULL)
|
||||||
{
|
{
|
||||||
|
@ -518,10 +518,10 @@ AAmmo *AWeapon::AddAmmo (AActor *other, PClassActor *ammotype, int amount)
|
||||||
{
|
{
|
||||||
amount = int(amount * G_SkillProperty(SKILLP_AmmoFactor));
|
amount = int(amount * G_SkillProperty(SKILLP_AmmoFactor));
|
||||||
}
|
}
|
||||||
ammo = static_cast<AAmmo *>(other->FindInventory (ammotype));
|
ammo = other->FindInventory (ammotype);
|
||||||
if (ammo == NULL)
|
if (ammo == NULL)
|
||||||
{
|
{
|
||||||
ammo = static_cast<AAmmo *>(Spawn (ammotype));
|
ammo = static_cast<AInventory *>(Spawn (ammotype));
|
||||||
ammo->Amount = MIN (amount, ammo->MaxAmount);
|
ammo->Amount = MIN (amount, ammo->MaxAmount);
|
||||||
ammo->AttachToOwner (other);
|
ammo->AttachToOwner (other);
|
||||||
}
|
}
|
||||||
|
@ -545,7 +545,7 @@ AAmmo *AWeapon::AddAmmo (AActor *other, PClassActor *ammotype, int amount)
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
EXTERN_CVAR(Bool, sv_unlimited_pickup)
|
EXTERN_CVAR(Bool, sv_unlimited_pickup)
|
||||||
|
|
||||||
bool AWeapon::AddExistingAmmo (AAmmo *ammo, int amount)
|
bool AWeapon::AddExistingAmmo (AInventory *ammo, int amount)
|
||||||
{
|
{
|
||||||
if (ammo != NULL && (ammo->Amount < ammo->MaxAmount || sv_unlimited_pickup))
|
if (ammo != NULL && (ammo->Amount < ammo->MaxAmount || sv_unlimited_pickup))
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "a_ammo.h"
|
#include "a_pickups.h"
|
||||||
|
|
||||||
class PClassWeapon;
|
class PClassWeapon;
|
||||||
class AWeapon;
|
class AWeapon;
|
||||||
|
|
||||||
|
@ -126,7 +125,7 @@ public:
|
||||||
float BobRangeX, BobRangeY; // [XA] Bobbing range. Defines how far a weapon bobs in either direction.
|
float BobRangeX, BobRangeY; // [XA] Bobbing range. Defines how far a weapon bobs in either direction.
|
||||||
|
|
||||||
// In-inventory instance variables
|
// In-inventory instance variables
|
||||||
TObjPtr<AAmmo> Ammo1, Ammo2;
|
TObjPtr<AInventory> Ammo1, Ammo2;
|
||||||
TObjPtr<AWeapon> SisterWeapon;
|
TObjPtr<AWeapon> SisterWeapon;
|
||||||
float FOVScale;
|
float FOVScale;
|
||||||
int Crosshair; // 0 to use player's crosshair
|
int Crosshair; // 0 to use player's crosshair
|
||||||
|
@ -182,8 +181,8 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
AAmmo *AddAmmo (AActor *other, PClassActor *ammotype, int amount);
|
AInventory *AddAmmo (AActor *other, PClassActor *ammotype, int amount);
|
||||||
bool AddExistingAmmo (AAmmo *ammo, int amount);
|
bool AddExistingAmmo (AInventory *ammo, int amount);
|
||||||
AWeapon *AddWeapon (PClassWeapon *weapon);
|
AWeapon *AddWeapon (PClassWeapon *weapon);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
#include "serializer.h"
|
#include "serializer.h"
|
||||||
#include "p_enemy.h"
|
#include "p_enemy.h"
|
||||||
#include "d_player.h"
|
#include "d_player.h"
|
||||||
#include "a_armor.h"
|
|
||||||
#include "r_data/sprites.h"
|
#include "r_data/sprites.h"
|
||||||
#include "g_levellocals.h"
|
#include "g_levellocals.h"
|
||||||
#include "virtual.h"
|
#include "virtual.h"
|
||||||
|
@ -137,7 +136,7 @@ bool P_MorphPlayer (player_t *activator, player_t *p, PClassPlayerPawn *spawntyp
|
||||||
for (item = morphed->Inventory; item != nullptr; )
|
for (item = morphed->Inventory; item != nullptr; )
|
||||||
{
|
{
|
||||||
AInventory *next = item->Inventory;
|
AInventory *next = item->Inventory;
|
||||||
if (item->IsKindOf (RUNTIME_CLASS(AArmor)))
|
if (item->IsKindOf (PClass::FindActor(NAME_Armor)))
|
||||||
{
|
{
|
||||||
item->DepleteOrDestroy();
|
item->DepleteOrDestroy();
|
||||||
}
|
}
|
||||||
|
@ -364,10 +363,11 @@ bool P_UndoPlayerMorph (player_t *activator, player_t *player, int unmorphflag,
|
||||||
}
|
}
|
||||||
pmo->Destroy ();
|
pmo->Destroy ();
|
||||||
// Restore playerclass armor to its normal amount.
|
// Restore playerclass armor to its normal amount.
|
||||||
AHexenArmor *hxarmor = mo->FindInventory<AHexenArmor>();
|
auto hxarmor = mo->FindInventory(NAME_HexenArmor);
|
||||||
if (hxarmor != nullptr)
|
if (hxarmor != nullptr)
|
||||||
{
|
{
|
||||||
hxarmor->Slots[4] = mo->GetClass()->HexenArmor[0];
|
double *Slots = (double*)hxarmor->ScriptVar(NAME_Slots, nullptr);
|
||||||
|
Slots[4] = mo->GetClass()->HexenArmor[0];
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -294,7 +294,6 @@ int FindMugShotStateIndex(FName state);
|
||||||
// Base Status Bar ----------------------------------------------------------
|
// Base Status Bar ----------------------------------------------------------
|
||||||
|
|
||||||
class FTexture;
|
class FTexture;
|
||||||
class AAmmo;
|
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -395,7 +394,7 @@ protected:
|
||||||
|
|
||||||
void RefreshBackground () const;
|
void RefreshBackground () const;
|
||||||
|
|
||||||
void GetCurrentAmmo (AAmmo *&ammo1, AAmmo *&ammo2, int &ammocount1, int &ammocount2) const;
|
void GetCurrentAmmo (AInventory *&ammo1, AInventory *&ammo2, int &ammocount1, int &ammocount2) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AInventory *ValidateInvFirst (int numVisible) const;
|
AInventory *ValidateInvFirst (int numVisible) const;
|
||||||
|
|
|
@ -45,20 +45,17 @@
|
||||||
#include "st_stuff.h"
|
#include "st_stuff.h"
|
||||||
#include "m_swap.h"
|
#include "m_swap.h"
|
||||||
#include "a_keys.h"
|
#include "a_keys.h"
|
||||||
#include "a_armor.h"
|
|
||||||
#include "templates.h"
|
#include "templates.h"
|
||||||
#include "i_system.h"
|
#include "i_system.h"
|
||||||
#include "sbarinfo.h"
|
#include "sbarinfo.h"
|
||||||
#include "gi.h"
|
#include "gi.h"
|
||||||
#include "r_data/r_translate.h"
|
#include "r_data/r_translate.h"
|
||||||
#include "a_weaponpiece.h"
|
|
||||||
#include "g_level.h"
|
#include "g_level.h"
|
||||||
#include "v_palette.h"
|
#include "v_palette.h"
|
||||||
#include "p_acs.h"
|
#include "p_acs.h"
|
||||||
#include "gstrings.h"
|
#include "gstrings.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "cmdlib.h"
|
#include "cmdlib.h"
|
||||||
#include "a_ammo.h"
|
|
||||||
#include "g_levellocals.h"
|
#include "g_levellocals.h"
|
||||||
|
|
||||||
#define ARTIFLASH_OFFSET (statusBar->invBarOffset+6)
|
#define ARTIFLASH_OFFSET (statusBar->invBarOffset+6)
|
||||||
|
@ -1069,7 +1066,7 @@ public:
|
||||||
|
|
||||||
//prepare ammo counts
|
//prepare ammo counts
|
||||||
GetCurrentAmmo(ammo1, ammo2, ammocount1, ammocount2);
|
GetCurrentAmmo(ammo1, ammo2, ammocount1, ammocount2);
|
||||||
armor = CPlayer->mo->FindInventory<ABasicArmor>();
|
armor = CPlayer->mo->FindInventory(NAME_BasicArmor);
|
||||||
|
|
||||||
if(state != HUD_AltHud)
|
if(state != HUD_AltHud)
|
||||||
{
|
{
|
||||||
|
@ -1517,9 +1514,9 @@ public:
|
||||||
return translationtables[TRANSLATION_Players][int(CPlayer - players)];
|
return translationtables[TRANSLATION_Players][int(CPlayer - players)];
|
||||||
}
|
}
|
||||||
|
|
||||||
AAmmo *ammo1, *ammo2;
|
AInventory *ammo1, *ammo2;
|
||||||
int ammocount1, ammocount2;
|
int ammocount1, ammocount2;
|
||||||
ABasicArmor *armor;
|
AInventory *armor;
|
||||||
FImageCollection Images;
|
FImageCollection Images;
|
||||||
unsigned int invBarOffset;
|
unsigned int invBarOffset;
|
||||||
|
|
||||||
|
|
|
@ -244,31 +244,31 @@ class CommandDrawImage : public SBarInfoCommandFlowControl
|
||||||
texture = TexMan(statusBar->CPlayer->mo->ScoreIcon);
|
texture = TexMan(statusBar->CPlayer->mo->ScoreIcon);
|
||||||
else if(type == AMMO1)
|
else if(type == AMMO1)
|
||||||
{
|
{
|
||||||
AAmmo *ammo = statusBar->ammo1;
|
auto ammo = statusBar->ammo1;
|
||||||
if(ammo != NULL)
|
if(ammo != NULL)
|
||||||
GetIcon(ammo);
|
GetIcon(ammo);
|
||||||
}
|
}
|
||||||
else if(type == AMMO2)
|
else if(type == AMMO2)
|
||||||
{
|
{
|
||||||
AAmmo *ammo = statusBar->ammo2;
|
auto ammo = statusBar->ammo2;
|
||||||
if(ammo != NULL)
|
if(ammo != NULL)
|
||||||
GetIcon(ammo);
|
GetIcon(ammo);
|
||||||
}
|
}
|
||||||
else if(type == ARMOR)
|
else if(type == ARMOR)
|
||||||
{
|
{
|
||||||
ABasicArmor *armor = statusBar->armor;
|
auto armor = statusBar->armor;
|
||||||
if(armor != NULL && armor->Amount != 0)
|
if(armor != NULL && armor->Amount != 0)
|
||||||
GetIcon(armor);
|
GetIcon(armor);
|
||||||
}
|
}
|
||||||
else if(type == WEAPONICON)
|
else if(type == WEAPONICON)
|
||||||
{
|
{
|
||||||
AWeapon *weapon = statusBar->CPlayer->ReadyWeapon;
|
auto weapon = statusBar->CPlayer->ReadyWeapon;
|
||||||
if(weapon != NULL)
|
if(weapon != NULL)
|
||||||
GetIcon(weapon);
|
GetIcon(weapon);
|
||||||
}
|
}
|
||||||
else if(type == SIGIL)
|
else if(type == SIGIL)
|
||||||
{
|
{
|
||||||
AInventory *item = statusBar->CPlayer->mo->FindInventory(PClass::FindActor(NAME_Sigil));
|
auto item = statusBar->CPlayer->mo->FindInventory(NAME_Sigil);
|
||||||
if (item != NULL)
|
if (item != NULL)
|
||||||
texture = TexMan(item->Icon);
|
texture = TexMan(item->Icon);
|
||||||
}
|
}
|
||||||
|
@ -276,13 +276,15 @@ class CommandDrawImage : public SBarInfoCommandFlowControl
|
||||||
{
|
{
|
||||||
int armorType = type - HEXENARMOR_ARMOR;
|
int armorType = type - HEXENARMOR_ARMOR;
|
||||||
|
|
||||||
AHexenArmor *harmor = statusBar->CPlayer->mo->FindInventory<AHexenArmor>();
|
auto harmor = statusBar->CPlayer->mo->FindInventory(NAME_HexenArmor);
|
||||||
if (harmor != NULL)
|
if (harmor != NULL)
|
||||||
{
|
{
|
||||||
if (harmor->Slots[armorType] > 0 && harmor->SlotsIncrement[armorType] > 0)
|
double *Slots = (double*)harmor->ScriptVar(NAME_Slots, nullptr);
|
||||||
|
double *SlotsIncrement = (double*)harmor->ScriptVar(NAME_SlotsIncrement, nullptr);
|
||||||
|
if (Slots[armorType] > 0 && SlotsIncrement[armorType] > 0)
|
||||||
{
|
{
|
||||||
//combine the alpha values
|
//combine the alpha values
|
||||||
alpha *= MIN(1., harmor->Slots[armorType] / harmor->SlotsIncrement[armorType]);
|
alpha *= MIN(1., Slots[armorType] / SlotsIncrement[armorType]);
|
||||||
texture = statusBar->Images[image];
|
texture = statusBar->Images[image];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -416,10 +418,10 @@ class CommandDrawSwitchableImage : public CommandDrawImage
|
||||||
for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
|
for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
|
||||||
{
|
{
|
||||||
PClassActor *cls = PClassActor::AllActorClasses[i];
|
PClassActor *cls = PClassActor::AllActorClasses[i];
|
||||||
if (cls->IsDescendantOf(RUNTIME_CLASS(AKey)))
|
if (cls->IsDescendantOf(PClass::FindActor(NAME_Key)))
|
||||||
{
|
{
|
||||||
AKey *key = (AKey *)GetDefaultByType(cls);
|
auto key = GetDefaultByType(cls);
|
||||||
if (key->KeyNumber == keynum)
|
if (key->special1 == keynum)
|
||||||
return cls->TypeName;
|
return cls->TypeName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -554,9 +556,9 @@ class CommandDrawSwitchableImage : public CommandDrawImage
|
||||||
|
|
||||||
for(AInventory *item = statusBar->CPlayer->mo->Inventory;item != NULL;item = item->Inventory)
|
for(AInventory *item = statusBar->CPlayer->mo->Inventory;item != NULL;item = item->Inventory)
|
||||||
{
|
{
|
||||||
if(item->IsKindOf(RUNTIME_CLASS(AKey)))
|
if(item->IsKindOf(PClass::FindActor(NAME_Key)))
|
||||||
{
|
{
|
||||||
int keynum = static_cast<AKey *>(item)->KeyNumber;
|
int keynum = item->special1;
|
||||||
if(keynum)
|
if(keynum)
|
||||||
{
|
{
|
||||||
if(keynum == conditionalValue[0])
|
if(keynum == conditionalValue[0])
|
||||||
|
@ -592,11 +594,11 @@ class CommandDrawSwitchableImage : public CommandDrawImage
|
||||||
}
|
}
|
||||||
else if(condition == ARMORTYPE)
|
else if(condition == ARMORTYPE)
|
||||||
{
|
{
|
||||||
ABasicArmor *armor = (ABasicArmor *) statusBar->CPlayer->mo->FindInventory(NAME_BasicArmor);
|
auto armor = statusBar->CPlayer->mo->FindInventory(NAME_BasicArmor);
|
||||||
if(armor != NULL)
|
if(armor != NULL)
|
||||||
{
|
{
|
||||||
bool matches1 = armor->ArmorType.GetIndex() == armorType[0] && EvaluateOperation(conditionalOperator[0], conditionalValue[0], armor->Amount);
|
bool matches1 = armor->NameVar(NAME_ArmorType).GetIndex() == armorType[0] && EvaluateOperation(conditionalOperator[0], conditionalValue[0], armor->Amount);
|
||||||
bool matches2 = armor->ArmorType.GetIndex() == armorType[1] && EvaluateOperation(conditionalOperator[1], conditionalValue[1], armor->Amount);
|
bool matches2 = armor->NameVar(NAME_ArmorType).GetIndex() == armorType[1] && EvaluateOperation(conditionalOperator[1], conditionalValue[1], armor->Amount);
|
||||||
|
|
||||||
drawAlt = 1;
|
drawAlt = 1;
|
||||||
if(conditionAnd)
|
if(conditionAnd)
|
||||||
|
@ -614,12 +616,12 @@ class CommandDrawSwitchableImage : public CommandDrawImage
|
||||||
}
|
}
|
||||||
else //check the inventory items and draw selected sprite
|
else //check the inventory items and draw selected sprite
|
||||||
{
|
{
|
||||||
AInventory* item = statusBar->CPlayer->mo->FindInventory(PClass::FindActor(inventoryItem[0]));
|
AInventory* item = statusBar->CPlayer->mo->FindInventory(inventoryItem[0]);
|
||||||
if(item == NULL || !EvaluateOperation(conditionalOperator[0], conditionalValue[0], item->Amount))
|
if(item == NULL || !EvaluateOperation(conditionalOperator[0], conditionalValue[0], item->Amount))
|
||||||
drawAlt = 1;
|
drawAlt = 1;
|
||||||
if(conditionAnd)
|
if(conditionAnd)
|
||||||
{
|
{
|
||||||
item = statusBar->CPlayer->mo->FindInventory(PClass::FindActor(inventoryItem[1]));
|
item = statusBar->CPlayer->mo->FindInventory(inventoryItem[1]);
|
||||||
bool secondCondition = item != NULL && EvaluateOperation(conditionalOperator[1], conditionalValue[1], item->Amount);
|
bool secondCondition = item != NULL && EvaluateOperation(conditionalOperator[1], conditionalValue[1], item->Amount);
|
||||||
if((item != NULL && secondCondition) && drawAlt == 0) //both
|
if((item != NULL && secondCondition) && drawAlt == 0) //both
|
||||||
{
|
{
|
||||||
|
@ -1076,10 +1078,10 @@ class CommandDrawNumber : public CommandDrawString
|
||||||
if(!parenthesized || !sc.CheckToken(TK_StringConst))
|
if(!parenthesized || !sc.CheckToken(TK_StringConst))
|
||||||
sc.MustGetToken(TK_Identifier);
|
sc.MustGetToken(TK_Identifier);
|
||||||
inventoryItem = PClass::FindActor(sc.String);
|
inventoryItem = PClass::FindActor(sc.String);
|
||||||
if(inventoryItem == NULL || !RUNTIME_CLASS(AAmmo)->IsAncestorOf(inventoryItem)) //must be a kind of ammo
|
if(inventoryItem == NULL || !PClass::FindActor(NAME_Ammo)->IsAncestorOf(inventoryItem)) //must be a kind of ammo
|
||||||
{
|
{
|
||||||
sc.ScriptMessage("'%s' is not a type of ammo.", sc.String);
|
sc.ScriptMessage("'%s' is not a type of ammo.", sc.String);
|
||||||
inventoryItem = RUNTIME_CLASS(AAmmo);
|
inventoryItem = PClass::FindActor(NAME_Ammo);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(parenthesized) sc.MustGetToken(')');
|
if(parenthesized) sc.MustGetToken(')');
|
||||||
|
@ -1092,10 +1094,10 @@ class CommandDrawNumber : public CommandDrawString
|
||||||
if(!parenthesized || !sc.CheckToken(TK_StringConst))
|
if(!parenthesized || !sc.CheckToken(TK_StringConst))
|
||||||
sc.MustGetToken(TK_Identifier);
|
sc.MustGetToken(TK_Identifier);
|
||||||
inventoryItem = PClass::FindActor(sc.String);
|
inventoryItem = PClass::FindActor(sc.String);
|
||||||
if(inventoryItem == NULL || !RUNTIME_CLASS(AAmmo)->IsAncestorOf(inventoryItem)) //must be a kind of ammo
|
if(inventoryItem == NULL || !PClass::FindActor(NAME_Ammo)->IsAncestorOf(inventoryItem)) //must be a kind of ammo
|
||||||
{
|
{
|
||||||
sc.ScriptMessage("'%s' is not a type of ammo.", sc.String);
|
sc.ScriptMessage("'%s' is not a type of ammo.", sc.String);
|
||||||
inventoryItem = RUNTIME_CLASS(AAmmo);
|
inventoryItem = PClass::FindActor(NAME_Ammo);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(parenthesized) sc.MustGetToken(')');
|
if(parenthesized) sc.MustGetToken(')');
|
||||||
|
@ -1409,16 +1411,16 @@ class CommandDrawNumber : public CommandDrawString
|
||||||
case SAVEPERCENT:
|
case SAVEPERCENT:
|
||||||
{
|
{
|
||||||
double add = 0;
|
double add = 0;
|
||||||
AHexenArmor *harmor = statusBar->CPlayer->mo->FindInventory<AHexenArmor>();
|
auto harmor = statusBar->CPlayer->mo->FindInventory(NAME_HexenArmor);
|
||||||
if(harmor != NULL)
|
if(harmor != NULL)
|
||||||
{
|
{
|
||||||
add = harmor->Slots[0] + harmor->Slots[1] +
|
double *Slots = (double*)harmor->ScriptVar(NAME_Slots, nullptr);
|
||||||
harmor->Slots[2] + harmor->Slots[3] + harmor->Slots[4];
|
add = Slots[0] + Slots[1] + Slots[2] + Slots[3] + Slots[4];
|
||||||
}
|
}
|
||||||
//Hexen counts basic armor also so we should too.
|
//Hexen counts basic armor also so we should too.
|
||||||
if(statusBar->armor != NULL)
|
if(statusBar->armor != NULL)
|
||||||
{
|
{
|
||||||
add += statusBar->armor->SavePercent * 100;
|
add += statusBar->armor->FloatVar(NAME_SavePercent) * 100;
|
||||||
}
|
}
|
||||||
if(value == ARMORCLASS)
|
if(value == ARMORCLASS)
|
||||||
add /= 5;
|
add /= 5;
|
||||||
|
@ -1435,7 +1437,7 @@ class CommandDrawNumber : public CommandDrawString
|
||||||
{
|
{
|
||||||
// num = statusBar.CPlayer.mo.GetEffectTicsForItem(inventoryItem) / TICRATE + 1;
|
// num = statusBar.CPlayer.mo.GetEffectTicsForItem(inventoryItem) / TICRATE + 1;
|
||||||
static VMFunction *func = nullptr;
|
static VMFunction *func = nullptr;
|
||||||
if (func == nullptr) func = static_cast<PFunction*>(RUNTIME_CLASS(APlayerPawn)->Symbols.FindSymbol("GetEffectTicsForItem", false))->Variants[0].Implementation;
|
if (func == nullptr) func = PClass::FindFunction(NAME_PlayerPawn, "GetEffectTicsForItem");
|
||||||
VMValue params[] = { statusBar->CPlayer->mo, inventoryItem };
|
VMValue params[] = { statusBar->CPlayer->mo, inventoryItem };
|
||||||
int retv;
|
int retv;
|
||||||
VMReturn ret(&retv);
|
VMReturn ret(&retv);
|
||||||
|
@ -1474,7 +1476,7 @@ class CommandDrawNumber : public CommandDrawString
|
||||||
num = 0;
|
num = 0;
|
||||||
for(AInventory *item = statusBar->CPlayer->mo->Inventory;item != NULL;item = item->Inventory)
|
for(AInventory *item = statusBar->CPlayer->mo->Inventory;item != NULL;item = item->Inventory)
|
||||||
{
|
{
|
||||||
if(item->IsKindOf(RUNTIME_CLASS(AKey)))
|
if(item->IsKindOf(PClass::FindActor(NAME_Key)))
|
||||||
num++;
|
num++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -2429,7 +2431,7 @@ class CommandDrawKeyBar : public SBarInfoCommand
|
||||||
int rowWidth = 0;
|
int rowWidth = 0;
|
||||||
for(unsigned int i = 0;i < number+keyOffset;i++)
|
for(unsigned int i = 0;i < number+keyOffset;i++)
|
||||||
{
|
{
|
||||||
while(!item->Icon.isValid() || !item->IsKindOf(RUNTIME_CLASS(AKey)))
|
while(!item->Icon.isValid() || !item->IsKindOf(PClass::FindActor(NAME_Key)))
|
||||||
{
|
{
|
||||||
item = item->Inventory;
|
item = item->Inventory;
|
||||||
if(item == NULL)
|
if(item == NULL)
|
||||||
|
@ -2630,10 +2632,10 @@ class CommandDrawBar : public SBarInfoCommand
|
||||||
sc.MustGetToken(TK_Identifier);
|
sc.MustGetToken(TK_Identifier);
|
||||||
type = AMMO;
|
type = AMMO;
|
||||||
data.inventoryItem = PClass::FindActor(sc.String);
|
data.inventoryItem = PClass::FindActor(sc.String);
|
||||||
if(data.inventoryItem == NULL || !RUNTIME_CLASS(AAmmo)->IsAncestorOf(data.inventoryItem)) //must be a kind of ammo
|
if(data.inventoryItem == NULL || !PClass::FindActor(NAME_Ammo)->IsAncestorOf(data.inventoryItem)) //must be a kind of ammo
|
||||||
{
|
{
|
||||||
sc.ScriptMessage("'%s' is not a type of ammo.", sc.String);
|
sc.ScriptMessage("'%s' is not a type of ammo.", sc.String);
|
||||||
data.inventoryItem = RUNTIME_CLASS(AAmmo);
|
data.inventoryItem = PClass::FindActor(NAME_Ammo);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(parenthesized) sc.MustGetToken(')');
|
if(parenthesized) sc.MustGetToken(')');
|
||||||
|
@ -2825,8 +2827,10 @@ class CommandDrawBar : public SBarInfoCommand
|
||||||
break;
|
break;
|
||||||
case POWERUPTIME:
|
case POWERUPTIME:
|
||||||
{
|
{
|
||||||
|
// [value, max] = statusBar.CPlayer.mo.GetEffectTicsForItem(inventoryItem);
|
||||||
|
// value++; max++;
|
||||||
static VMFunction *func = nullptr;
|
static VMFunction *func = nullptr;
|
||||||
if (func == nullptr) func = static_cast<PFunction*>(RUNTIME_CLASS(APlayerPawn)->Symbols.FindSymbol("GetEffectTicsForItem", false))->Variants[0].Implementation;
|
if (func == nullptr) func = PClass::FindFunction(NAME_PlayerPawn, "GetEffectTicsForItem");
|
||||||
VMValue params[] = { statusBar->CPlayer->mo, data.inventoryItem };
|
VMValue params[] = { statusBar->CPlayer->mo, data.inventoryItem };
|
||||||
VMReturn ret[2];
|
VMReturn ret[2];
|
||||||
int ival;
|
int ival;
|
||||||
|
@ -2840,16 +2844,17 @@ class CommandDrawBar : public SBarInfoCommand
|
||||||
case SAVEPERCENT:
|
case SAVEPERCENT:
|
||||||
{
|
{
|
||||||
double add = 0;
|
double add = 0;
|
||||||
AHexenArmor *harmor = statusBar->CPlayer->mo->FindInventory<AHexenArmor>();
|
auto harmor = statusBar->CPlayer->mo->FindInventory(NAME_HexenArmor);
|
||||||
if(harmor != NULL)
|
if (harmor != NULL)
|
||||||
{
|
{
|
||||||
add = harmor->Slots[0] + harmor->Slots[1] +
|
double *Slots = (double*)harmor->ScriptVar(NAME_Slots, nullptr);
|
||||||
harmor->Slots[2] + harmor->Slots[3] + harmor->Slots[4];
|
add = Slots[0] + Slots[1] + Slots[2] + Slots[3] + Slots[4];
|
||||||
}
|
}
|
||||||
|
|
||||||
//Hexen counts basic armor also so we should too.
|
//Hexen counts basic armor also so we should too.
|
||||||
if(statusBar->armor != NULL)
|
if(statusBar->armor != NULL)
|
||||||
{
|
{
|
||||||
add += statusBar->armor->SavePercent * 100;
|
add += statusBar->armor->FloatVar(NAME_SavePercent) * 100;
|
||||||
}
|
}
|
||||||
value = int(add);
|
value = int(add);
|
||||||
max = 100;
|
max = 100;
|
||||||
|
@ -3143,12 +3148,12 @@ class CommandHasWeaponPiece : public SBarInfoCommandFlowControl
|
||||||
|
|
||||||
for(AInventory *inv = statusBar->CPlayer->mo->Inventory;inv != NULL;inv=inv->Inventory)
|
for(AInventory *inv = statusBar->CPlayer->mo->Inventory;inv != NULL;inv=inv->Inventory)
|
||||||
{
|
{
|
||||||
if(inv->IsKindOf(RUNTIME_CLASS(AWeaponHolder)))
|
auto hc = PClass::FindActor("WeaponHolder");
|
||||||
|
if(inv->IsKindOf(hc))
|
||||||
{
|
{
|
||||||
AWeaponHolder *hold = static_cast<AWeaponHolder*>(inv);
|
if(inv->PointerVar<PClass>("PieceWeapon") == weapon)
|
||||||
if(hold->PieceWeapon == weapon)
|
|
||||||
{
|
{
|
||||||
SetTruth(0 != (hold->PieceMask & (1 << (piece-1))), block, statusBar);
|
SetTruth(0 != (inv->IntVar("PieceMask") & (1 << (piece-1))), block, statusBar);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3312,10 +3317,10 @@ class CommandWeaponAmmo : public SBarInfoNegatableFlowControl
|
||||||
for(int i = 0;i < 2;i++)
|
for(int i = 0;i < 2;i++)
|
||||||
{
|
{
|
||||||
ammo[i] = PClass::FindClass(sc.String);
|
ammo[i] = PClass::FindClass(sc.String);
|
||||||
if(ammo[i] == NULL || !RUNTIME_CLASS(AAmmo)->IsAncestorOf(ammo[i])) //must be a kind of ammo
|
if(ammo[i] == NULL || !PClass::FindActor(NAME_Ammo)->IsAncestorOf(ammo[i])) //must be a kind of ammo
|
||||||
{
|
{
|
||||||
sc.ScriptMessage("'%s' is not a type of ammo.", sc.String);
|
sc.ScriptMessage("'%s' is not a type of ammo.", sc.String);
|
||||||
ammo[i] = RUNTIME_CLASS(AAmmo);
|
ammo[i] = PClass::FindActor(NAME_Ammo);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(sc.CheckToken(TK_OrOr))
|
if(sc.CheckToken(TK_OrOr))
|
||||||
|
@ -3689,3 +3694,5 @@ SBarInfoCommand *SBarInfoCommandFlowControl::NextCommand(FScanner &sc)
|
||||||
sc.MustGetToken('}');
|
sc.MustGetToken('}');
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -43,8 +43,6 @@
|
||||||
#include "c_cvars.h"
|
#include "c_cvars.h"
|
||||||
#include "w_wad.h"
|
#include "w_wad.h"
|
||||||
#include "a_keys.h"
|
#include "a_keys.h"
|
||||||
#include "a_armor.h"
|
|
||||||
#include "a_ammo.h"
|
|
||||||
#include "sbar.h"
|
#include "sbar.h"
|
||||||
#include "sc_man.h"
|
#include "sc_man.h"
|
||||||
#include "templates.h"
|
#include "templates.h"
|
||||||
|
@ -298,7 +296,7 @@ static void DrawHealth(player_t *CPlayer, int x, int y)
|
||||||
|
|
||||||
const bool haveBerserk = hud_berserk_health
|
const bool haveBerserk = hud_berserk_health
|
||||||
&& nullptr != berserkpic
|
&& nullptr != berserkpic
|
||||||
&& nullptr != CPlayer->mo->FindInventory(PClass::FindActor(NAME_PowerStrength));
|
&& nullptr != CPlayer->mo->FindInventory(NAME_PowerStrength);
|
||||||
|
|
||||||
DrawImageToBox(haveBerserk ? berserkpic : healthpic, x, y, 31, 17);
|
DrawImageToBox(haveBerserk ? berserkpic : healthpic, x, y, 31, 17);
|
||||||
DrawHudNumber(HudFont, fontcolor, health, x + 33, y + 17);
|
DrawHudNumber(HudFont, fontcolor, health, x + 33, y + 17);
|
||||||
|
@ -311,14 +309,15 @@ static void DrawHealth(player_t *CPlayer, int x, int y)
|
||||||
//
|
//
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
static void DrawArmor(ABasicArmor * barmor, AHexenArmor * harmor, int x, int y)
|
static void DrawArmor(AInventory * barmor, AInventory * harmor, int x, int y)
|
||||||
{
|
{
|
||||||
int ap = 0;
|
int ap = 0;
|
||||||
int bestslot = 4;
|
int bestslot = 4;
|
||||||
|
|
||||||
if (harmor)
|
if (harmor)
|
||||||
{
|
{
|
||||||
auto ac = (harmor->Slots[0] + harmor->Slots[1] + harmor->Slots[2] + harmor->Slots[3] + harmor->Slots[4]);
|
double *Slots = (double*)harmor->ScriptVar(NAME_Slots, nullptr);
|
||||||
|
auto ac = (Slots[0] + Slots[1] + Slots[2] + Slots[3] + Slots[4]);
|
||||||
ap += int(ac);
|
ap += int(ac);
|
||||||
|
|
||||||
if (ac)
|
if (ac)
|
||||||
|
@ -327,7 +326,7 @@ static void DrawArmor(ABasicArmor * barmor, AHexenArmor * harmor, int x, int y)
|
||||||
bestslot = 0;
|
bestslot = 0;
|
||||||
for (int i = 1; i < 4; ++i)
|
for (int i = 1; i < 4; ++i)
|
||||||
{
|
{
|
||||||
if (harmor->Slots[i] > harmor->Slots[bestslot])
|
if (Slots[i] > Slots[bestslot])
|
||||||
{
|
{
|
||||||
bestslot = i;
|
bestslot = i;
|
||||||
}
|
}
|
||||||
|
@ -386,9 +385,9 @@ static TArray<PClassActor *> KeyTypes, UnassignedKeyTypes;
|
||||||
|
|
||||||
static int ktcmp(const void * a, const void * b)
|
static int ktcmp(const void * a, const void * b)
|
||||||
{
|
{
|
||||||
AKey *key1 = (AKey*)GetDefaultByType ( *(PClassActor **)a );
|
auto key1 = GetDefaultByType ( *(PClassActor **)a );
|
||||||
AKey *key2 = (AKey*)GetDefaultByType ( *(PClassActor **)b );
|
auto key2 = GetDefaultByType ( *(PClassActor **)b );
|
||||||
return key1->KeyNumber - key2->KeyNumber;
|
return key1->special1 - key2->special1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SetKeyTypes()
|
static void SetKeyTypes()
|
||||||
|
@ -396,13 +395,14 @@ static void SetKeyTypes()
|
||||||
for(unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); i++)
|
for(unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); i++)
|
||||||
{
|
{
|
||||||
PClass *ti = PClassActor::AllActorClasses[i];
|
PClass *ti = PClassActor::AllActorClasses[i];
|
||||||
|
auto kt = PClass::FindActor(NAME_Key);
|
||||||
|
|
||||||
if (ti->IsDescendantOf(RUNTIME_CLASS(AKey)))
|
if (ti->IsDescendantOf(kt))
|
||||||
{
|
{
|
||||||
PClassActor *tia = static_cast<PClassActor *>(ti);
|
PClassActor *tia = static_cast<PClassActor *>(ti);
|
||||||
AKey *key = (AKey*)GetDefaultByType(tia);
|
AInventory *key = (AInventory*)(GetDefaultByType(tia));
|
||||||
|
|
||||||
if (key->Icon.isValid() && key->KeyNumber>0)
|
if (key->Icon.isValid() && key->special1 > 0)
|
||||||
{
|
{
|
||||||
KeyTypes.Push(tia);
|
KeyTypes.Push(tia);
|
||||||
}
|
}
|
||||||
|
@ -419,8 +419,7 @@ static void SetKeyTypes()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Don't leave the list empty
|
// Don't leave the list empty
|
||||||
PClassActor *ti = RUNTIME_CLASS(AKey);
|
KeyTypes.Push(PClass::FindActor(NAME_Key));
|
||||||
KeyTypes.Push(ti);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -527,7 +526,7 @@ static void AddAmmoToList(AWeapon * weapdef)
|
||||||
PClassInventory * ti = i==0? weapdef->AmmoType1 : weapdef->AmmoType2;
|
PClassInventory * ti = i==0? weapdef->AmmoType1 : weapdef->AmmoType2;
|
||||||
if (ti)
|
if (ti)
|
||||||
{
|
{
|
||||||
AAmmo * ammodef=(AAmmo*)GetDefaultByType(ti);
|
auto ammodef=(AInventory*)GetDefaultByType(ti);
|
||||||
|
|
||||||
if (ammodef && !(ammodef->ItemFlags&IF_INVBAR))
|
if (ammodef && !(ammodef->ItemFlags&IF_INVBAR))
|
||||||
{
|
{
|
||||||
|
@ -561,9 +560,9 @@ static void GetAmmoTextLengths(player_t *CPlayer, int& ammocur, int& ammomax)
|
||||||
{
|
{
|
||||||
for (auto type : orderedammos)
|
for (auto type : orderedammos)
|
||||||
{
|
{
|
||||||
AAmmo * ammoitem = static_cast<AAmmo*>(CPlayer->mo->FindInventory(type));
|
auto ammoitem = CPlayer->mo->FindInventory(type);
|
||||||
AAmmo * inv = nullptr == ammoitem
|
auto inv = nullptr == ammoitem
|
||||||
? static_cast<AAmmo*>(GetDefaultByType(type))
|
? static_cast<AInventory*>(GetDefaultByType(type))
|
||||||
: ammoitem;
|
: ammoitem;
|
||||||
assert(nullptr != inv);
|
assert(nullptr != inv);
|
||||||
|
|
||||||
|
@ -648,9 +647,9 @@ static int DrawAmmo(player_t *CPlayer, int x, int y)
|
||||||
{
|
{
|
||||||
|
|
||||||
PClassInventory * type = orderedammos[i];
|
PClassInventory * type = orderedammos[i];
|
||||||
AAmmo * ammoitem = (AAmmo*)CPlayer->mo->FindInventory(type);
|
auto ammoitem = CPlayer->mo->FindInventory(type);
|
||||||
|
|
||||||
AAmmo * inv = ammoitem? ammoitem : (AAmmo*)GetDefaultByType(orderedammos[i]);
|
auto inv = ammoitem? ammoitem : (AInventory*)GetDefaultByType(orderedammos[i]);
|
||||||
FTextureID AltIcon = GetHUDIcon(type);
|
FTextureID AltIcon = GetHUDIcon(type);
|
||||||
FTextureID icon = !AltIcon.isNull()? AltIcon : inv->Icon;
|
FTextureID icon = !AltIcon.isNull()? AltIcon : inv->Icon;
|
||||||
if (!icon.isValid()) continue;
|
if (!icon.isValid()) continue;
|
||||||
|
@ -1142,8 +1141,7 @@ void DrawHUD()
|
||||||
DrawFrags(CPlayer, 5, hudheight-70);
|
DrawFrags(CPlayer, 5, hudheight-70);
|
||||||
}
|
}
|
||||||
DrawHealth(CPlayer, 5, hudheight-45);
|
DrawHealth(CPlayer, 5, hudheight-45);
|
||||||
DrawArmor(CPlayer->mo->FindInventory<ABasicArmor>(),
|
DrawArmor(CPlayer->mo->FindInventory(NAME_BasicArmor), CPlayer->mo->FindInventory(NAME_HexenArmor), 5, hudheight-20);
|
||||||
CPlayer->mo->FindInventory<AHexenArmor>(), 5, hudheight-20);
|
|
||||||
i=DrawKeys(CPlayer, hudwidth-4, hudheight-10);
|
i=DrawKeys(CPlayer, hudwidth-4, hudheight-10);
|
||||||
i=DrawAmmo(CPlayer, hudwidth-5, i);
|
i=DrawAmmo(CPlayer, hudwidth-5, i);
|
||||||
if (hud_showweapons) DrawWeapons(CPlayer, hudwidth - 5, i);
|
if (hud_showweapons) DrawWeapons(CPlayer, hudwidth - 5, i);
|
||||||
|
|
|
@ -1794,7 +1794,7 @@ AInventory *DBaseStatusBar::ValidateInvFirst (int numVisible) const
|
||||||
//
|
//
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
void DBaseStatusBar::GetCurrentAmmo (AAmmo *&ammo1, AAmmo *&ammo2, int &ammocount1, int &ammocount2) const
|
void DBaseStatusBar::GetCurrentAmmo (AInventory *&ammo1, AInventory *&ammo2, int &ammocount1, int &ammocount2) const
|
||||||
{
|
{
|
||||||
if (CPlayer->ReadyWeapon != NULL)
|
if (CPlayer->ReadyWeapon != NULL)
|
||||||
{
|
{
|
||||||
|
|
|
@ -12,8 +12,6 @@
|
||||||
#include "m_swap.h"
|
#include "m_swap.h"
|
||||||
#include "templates.h"
|
#include "templates.h"
|
||||||
#include "a_keys.h"
|
#include "a_keys.h"
|
||||||
#include "a_armor.h"
|
|
||||||
#include "a_ammo.h"
|
|
||||||
#include "gi.h"
|
#include "gi.h"
|
||||||
#include "g_level.h"
|
#include "g_level.h"
|
||||||
#include "colormatcher.h"
|
#include "colormatcher.h"
|
||||||
|
@ -257,7 +255,7 @@ public:
|
||||||
item != NULL;
|
item != NULL;
|
||||||
item = item->Inventory)
|
item = item->Inventory)
|
||||||
{
|
{
|
||||||
if (item->IsKindOf (RUNTIME_CLASS(AKey)))
|
if (item->IsKindOf (PClass::FindActor(NAME_Key)))
|
||||||
{
|
{
|
||||||
if (i == KeyPopPos)
|
if (i == KeyPopPos)
|
||||||
{
|
{
|
||||||
|
@ -404,7 +402,7 @@ private:
|
||||||
DrawImage (&HealthBar, 49, 7);
|
DrawImage (&HealthBar, 49, 7);
|
||||||
|
|
||||||
// Armor
|
// Armor
|
||||||
item = CPlayer->mo->FindInventory<ABasicArmor>();
|
item = CPlayer->mo->FindInventory(NAME_BasicArmor);
|
||||||
if (item != NULL && item->Amount > 0)
|
if (item != NULL && item->Amount > 0)
|
||||||
{
|
{
|
||||||
DrawImage (TexMan(item->Icon), 2, 9);
|
DrawImage (TexMan(item->Icon), 2, 9);
|
||||||
|
@ -412,7 +410,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ammo
|
// Ammo
|
||||||
AAmmo *ammo1, *ammo2;
|
AInventory *ammo1, *ammo2;
|
||||||
int ammocount1, ammocount2;
|
int ammocount1, ammocount2;
|
||||||
|
|
||||||
GetCurrentAmmo (ammo1, ammo2, ammocount1, ammocount2);
|
GetCurrentAmmo (ammo1, ammo2, ammocount1, ammocount2);
|
||||||
|
@ -432,7 +430,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sigil
|
// Sigil
|
||||||
item = CPlayer->mo->FindInventory(PClass::FindActor(NAME_Sigil));
|
item = CPlayer->mo->FindInventory(NAME_Sigil);
|
||||||
if (item != NULL)
|
if (item != NULL)
|
||||||
{
|
{
|
||||||
DrawImage (TexMan(item->Icon), 253, 7);
|
DrawImage (TexMan(item->Icon), 253, 7);
|
||||||
|
@ -469,7 +467,7 @@ private:
|
||||||
TAG_DONE);
|
TAG_DONE);
|
||||||
|
|
||||||
// Draw armor
|
// Draw armor
|
||||||
ABasicArmor *armor = CPlayer->mo->FindInventory<ABasicArmor>();
|
auto armor = CPlayer->mo->FindInventory(NAME_BasicArmor);
|
||||||
if (armor != NULL && armor->Amount != 0)
|
if (armor != NULL && armor->Amount != 0)
|
||||||
{
|
{
|
||||||
DrINumberOuter (armor->Amount, 35, -10, false, 7);
|
DrINumberOuter (armor->Amount, 35, -10, false, 7);
|
||||||
|
@ -480,7 +478,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw ammo
|
// Draw ammo
|
||||||
AAmmo *ammo1, *ammo2;
|
AInventory *ammo1, *ammo2;
|
||||||
int ammocount1, ammocount2;
|
int ammocount1, ammocount2;
|
||||||
|
|
||||||
GetCurrentAmmo (ammo1, ammo2, ammocount1, ammocount2);
|
GetCurrentAmmo (ammo1, ammo2, ammocount1, ammocount2);
|
||||||
|
@ -629,7 +627,7 @@ private:
|
||||||
i < endpos && item != NULL;
|
i < endpos && item != NULL;
|
||||||
item = item->Inventory)
|
item = item->Inventory)
|
||||||
{
|
{
|
||||||
if (!item->IsKindOf (RUNTIME_CLASS(AKey)))
|
if (!item->IsKindOf (PClass::FindActor(NAME_Key)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (i < pos)
|
if (i < pos)
|
||||||
|
@ -674,7 +672,7 @@ private:
|
||||||
item != NULL;
|
item != NULL;
|
||||||
item = item->Inventory)
|
item = item->Inventory)
|
||||||
{
|
{
|
||||||
if (item->IsKindOf (RUNTIME_CLASS(AKey)))
|
if (item->IsKindOf (PClass::FindActor(NAME_Key)))
|
||||||
{
|
{
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,8 @@ gameinfo_t gameinfo;
|
||||||
|
|
||||||
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, backpacktype)
|
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, ArmorIcon2)
|
||||||
|
|
||||||
|
|
||||||
const char *GameNames[17] =
|
const char *GameNames[17] =
|
||||||
|
|
|
@ -109,49 +109,6 @@ DEFINE_CLASS_PROPERTY(type, S, DynamicLight)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
IMPLEMENT_CLASS(ADynamicLight, false, false)
|
IMPLEMENT_CLASS(ADynamicLight, false, false)
|
||||||
IMPLEMENT_CLASS(AVavoomLight, false, false)
|
|
||||||
IMPLEMENT_CLASS(AVavoomLightWhite, false, false)
|
|
||||||
IMPLEMENT_CLASS(AVavoomLightColor, false, false)
|
|
||||||
|
|
||||||
void AVavoomLight::BeginPlay ()
|
|
||||||
{
|
|
||||||
// This must not call Super::BeginPlay!
|
|
||||||
ChangeStatNum(STAT_DLIGHT);
|
|
||||||
if (Sector) AddZ(-Sector->floorplane.ZatPoint(this), false);
|
|
||||||
lighttype = PointLight;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AVavoomLightWhite::BeginPlay ()
|
|
||||||
{
|
|
||||||
m_Radius[0] = args[0] * 4;
|
|
||||||
args[LIGHT_RED] = 128;
|
|
||||||
args[LIGHT_GREEN] = 128;
|
|
||||||
args[LIGHT_BLUE] = 128;
|
|
||||||
|
|
||||||
if (gl.legacyMode && (flags4 & MF4_ATTENUATE))
|
|
||||||
{
|
|
||||||
m_Radius[0] = m_Radius[0] * 2 / 3;
|
|
||||||
}
|
|
||||||
Super::BeginPlay();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AVavoomLightColor::BeginPlay ()
|
|
||||||
{
|
|
||||||
int l_args[5];
|
|
||||||
memcpy(l_args, args, sizeof(l_args));
|
|
||||||
memset(args, 0, sizeof(args));
|
|
||||||
m_Radius[0] = l_args[0] * 4;
|
|
||||||
args[LIGHT_RED] = l_args[1] >> 1;
|
|
||||||
args[LIGHT_GREEN] = l_args[2] >> 1;
|
|
||||||
args[LIGHT_BLUE] = l_args[3] >> 1;
|
|
||||||
|
|
||||||
if (gl.legacyMode && (flags4 & MF4_ATTENUATE))
|
|
||||||
{
|
|
||||||
m_Radius[0] = m_Radius[0] * 2 / 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
Super::BeginPlay();
|
|
||||||
}
|
|
||||||
|
|
||||||
static FRandom randLight;
|
static FRandom randLight;
|
||||||
|
|
||||||
|
@ -173,8 +130,7 @@ void ADynamicLight::Serialize(FSerializer &arc)
|
||||||
arc("lightflags", lightflags, def->lightflags)
|
arc("lightflags", lightflags, def->lightflags)
|
||||||
("lighttype", lighttype, def->lighttype)
|
("lighttype", lighttype, def->lighttype)
|
||||||
("tickcount", m_tickCount, def->m_tickCount)
|
("tickcount", m_tickCount, def->m_tickCount)
|
||||||
("currentradius", m_currentRadius, def->m_currentRadius)
|
("currentradius", m_currentRadius, def->m_currentRadius);
|
||||||
.Array("lightradius", m_Radius, def->m_Radius, 2);
|
|
||||||
|
|
||||||
if (lighttype == PulseLight)
|
if (lighttype == PulseLight)
|
||||||
arc("lastupdate", m_lastUpdate, def->m_lastUpdate)
|
arc("lastupdate", m_lastUpdate, def->m_lastUpdate)
|
||||||
|
@ -201,15 +157,13 @@ void ADynamicLight::BeginPlay()
|
||||||
//Super::BeginPlay();
|
//Super::BeginPlay();
|
||||||
ChangeStatNum(STAT_DLIGHT);
|
ChangeStatNum(STAT_DLIGHT);
|
||||||
|
|
||||||
m_Radius[0] = args[LIGHT_INTENSITY];
|
|
||||||
m_Radius[1] = args[LIGHT_SECONDARY_INTENSITY];
|
|
||||||
specialf1 = DAngle(double(SpawnAngle)).Normalized360().Degrees;
|
specialf1 = DAngle(double(SpawnAngle)).Normalized360().Degrees;
|
||||||
visibletoplayer = true;
|
visibletoplayer = true;
|
||||||
|
|
||||||
if (gl.legacyMode && (flags4 & MF4_ATTENUATE))
|
if (gl.legacyMode && (flags4 & MF4_ATTENUATE))
|
||||||
{
|
{
|
||||||
m_Radius[0] = m_Radius[0] * 2 / 3;
|
args[LIGHT_INTENSITY] = args[LIGHT_INTENSITY] * 2 / 3;
|
||||||
m_Radius[1] = m_Radius[1] * 2 / 3;
|
args[LIGHT_SECONDARY_INTENSITY] = args[LIGHT_SECONDARY_INTENSITY] * 2 / 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,7 +195,7 @@ void ADynamicLight::Activate(AActor *activator)
|
||||||
//Super::Activate(activator);
|
//Super::Activate(activator);
|
||||||
flags2&=~MF2_DORMANT;
|
flags2&=~MF2_DORMANT;
|
||||||
|
|
||||||
m_currentRadius = float(m_Radius[0]);
|
m_currentRadius = float(args[LIGHT_INTENSITY]);
|
||||||
m_tickCount = 0;
|
m_tickCount = 0;
|
||||||
|
|
||||||
if (lighttype == PulseLight)
|
if (lighttype == PulseLight)
|
||||||
|
@ -249,7 +203,7 @@ void ADynamicLight::Activate(AActor *activator)
|
||||||
float pulseTime = specialf1 / TICRATE;
|
float pulseTime = specialf1 / TICRATE;
|
||||||
|
|
||||||
m_lastUpdate = level.maptime;
|
m_lastUpdate = level.maptime;
|
||||||
m_cycler.SetParams(float(m_Radius[1]), float(m_Radius[0]), pulseTime);
|
m_cycler.SetParams(float(args[LIGHT_SECONDARY_INTENSITY]), float(args[LIGHT_INTENSITY]), pulseTime);
|
||||||
m_cycler.ShouldCycle(true);
|
m_cycler.ShouldCycle(true);
|
||||||
m_cycler.SetCycleType(CYCLE_Sin);
|
m_cycler.SetCycleType(CYCLE_Sin);
|
||||||
m_currentRadius = m_cycler.GetVal();
|
m_currentRadius = m_cycler.GetVal();
|
||||||
|
@ -309,22 +263,22 @@ void ADynamicLight::Tick()
|
||||||
BYTE rnd = randLight();
|
BYTE rnd = randLight();
|
||||||
float pct = specialf1 / 360.f;
|
float pct = specialf1 / 360.f;
|
||||||
|
|
||||||
m_currentRadius = float(m_Radius[rnd >= pct * 255]);
|
m_currentRadius = float(args[LIGHT_INTENSITY + (rnd >= pct * 255)]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case RandomFlickerLight:
|
case RandomFlickerLight:
|
||||||
{
|
{
|
||||||
int flickerRange = m_Radius[1] - m_Radius[0];
|
int flickerRange = args[LIGHT_SECONDARY_INTENSITY] - args[LIGHT_INTENSITY];
|
||||||
float amt = randLight() / 255.f;
|
float amt = randLight() / 255.f;
|
||||||
|
|
||||||
if (m_tickCount > specialf1)
|
if (m_tickCount > specialf1)
|
||||||
{
|
{
|
||||||
m_tickCount = 0;
|
m_tickCount = 0;
|
||||||
}
|
}
|
||||||
if (m_tickCount++ == 0 || m_currentRadius > m_Radius[1])
|
if (m_tickCount++ == 0 || m_currentRadius > args[LIGHT_SECONDARY_INTENSITY])
|
||||||
{
|
{
|
||||||
m_currentRadius = float(m_Radius[0] + (amt * flickerRange));
|
m_currentRadius = float(args[LIGHT_INTENSITY] + (amt * flickerRange));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -342,14 +296,14 @@ void ADynamicLight::Tick()
|
||||||
|
|
||||||
case RandomColorFlickerLight:
|
case RandomColorFlickerLight:
|
||||||
{
|
{
|
||||||
int flickerRange = m_Radius[1] - m_Radius[0];
|
int flickerRange = args[LIGHT_SECONDARY_INTENSITY] - args[LIGHT_INTENSITY];
|
||||||
float amt = randLight() / 255.f;
|
float amt = randLight() / 255.f;
|
||||||
|
|
||||||
m_tickCount++;
|
m_tickCount++;
|
||||||
|
|
||||||
if (m_tickCount > specialf1)
|
if (m_tickCount > specialf1)
|
||||||
{
|
{
|
||||||
m_currentRadius = m_Radius[0] + (amt * flickerRange);
|
m_currentRadius = args[LIGHT_INTENSITY] + (amt * flickerRange);
|
||||||
m_tickCount = 0;
|
m_tickCount = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -371,7 +325,7 @@ void ADynamicLight::Tick()
|
||||||
}
|
}
|
||||||
|
|
||||||
case PointLight:
|
case PointLight:
|
||||||
m_currentRadius = float(m_Radius[0]);
|
m_currentRadius = float(args[LIGHT_INTENSITY]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
UpdateLocation();
|
UpdateLocation();
|
||||||
|
@ -423,7 +377,7 @@ void ADynamicLight::UpdateLocation()
|
||||||
|
|
||||||
if (lighttype == FlickerLight || lighttype == RandomFlickerLight || lighttype == PulseLight)
|
if (lighttype == FlickerLight || lighttype == RandomFlickerLight || lighttype == PulseLight)
|
||||||
{
|
{
|
||||||
intensity = float(MAX(m_Radius[0], m_Radius[1]));
|
intensity = float(MAX(args[LIGHT_INTENSITY], args[LIGHT_SECONDARY_INTENSITY]));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -178,8 +178,8 @@ void FLightDefaults::ApplyProperties(ADynamicLight * light) const
|
||||||
light->SetOffset(m_Pos);
|
light->SetOffset(m_Pos);
|
||||||
light->halo = m_halo;
|
light->halo = m_halo;
|
||||||
for (int a = 0; a < 3; a++) light->args[a] = clamp<int>((int)(m_Args[a]), 0, 255);
|
for (int a = 0; a < 3; a++) light->args[a] = clamp<int>((int)(m_Args[a]), 0, 255);
|
||||||
light->m_Radius[0] = int(m_Args[LIGHT_INTENSITY]);
|
light->args[LIGHT_INTENSITY] = int(m_Args[LIGHT_INTENSITY]);
|
||||||
light->m_Radius[1] = int(m_Args[LIGHT_SECONDARY_INTENSITY]);
|
light->args[LIGHT_SECONDARY_INTENSITY] = int(m_Args[LIGHT_SECONDARY_INTENSITY]);
|
||||||
light->flags4 &= ~(MF4_ADDITIVE | MF4_SUBTRACTIVE | MF4_DONTLIGHTSELF);
|
light->flags4 &= ~(MF4_ADDITIVE | MF4_SUBTRACTIVE | MF4_DONTLIGHTSELF);
|
||||||
if (m_subtractive) light->flags4 |= MF4_SUBTRACTIVE;
|
if (m_subtractive) light->flags4 |= MF4_SUBTRACTIVE;
|
||||||
if (m_additive) light->flags4 |= MF4_ADDITIVE;
|
if (m_additive) light->flags4 |= MF4_ADDITIVE;
|
||||||
|
@ -190,7 +190,7 @@ void FLightDefaults::ApplyProperties(ADynamicLight * light) const
|
||||||
float pulseTime = float(m_Param / TICRATE);
|
float pulseTime = float(m_Param / TICRATE);
|
||||||
|
|
||||||
light->m_lastUpdate = level.maptime;
|
light->m_lastUpdate = level.maptime;
|
||||||
light->m_cycler.SetParams(float(light->m_Radius[1]), float(light->m_Radius[0]), pulseTime, oldtype == PulseLight);
|
light->m_cycler.SetParams(float(light->args[LIGHT_SECONDARY_INTENSITY]), float(light->args[LIGHT_INTENSITY]), pulseTime, oldtype == PulseLight);
|
||||||
light->m_cycler.ShouldCycle(true);
|
light->m_cycler.ShouldCycle(true);
|
||||||
light->m_cycler.SetCycleType(CYCLE_Sin);
|
light->m_cycler.SetCycleType(CYCLE_Sin);
|
||||||
light->m_currentRadius = light->m_cycler.GetVal();
|
light->m_currentRadius = light->m_cycler.GetVal();
|
||||||
|
|
|
@ -135,7 +135,6 @@ protected:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int m_tickCount;
|
int m_tickCount;
|
||||||
int m_Radius[2];
|
|
||||||
BYTE lightflags;
|
BYTE lightflags;
|
||||||
BYTE lighttype;
|
BYTE lighttype;
|
||||||
bool owned;
|
bool owned;
|
||||||
|
@ -147,28 +146,6 @@ public:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class AVavoomLight : public ADynamicLight
|
|
||||||
{
|
|
||||||
DECLARE_CLASS (AVavoomLight, ADynamicLight)
|
|
||||||
public:
|
|
||||||
virtual void BeginPlay();
|
|
||||||
};
|
|
||||||
|
|
||||||
class AVavoomLightWhite : public AVavoomLight
|
|
||||||
{
|
|
||||||
DECLARE_CLASS (AVavoomLightWhite, AVavoomLight)
|
|
||||||
public:
|
|
||||||
virtual void BeginPlay();
|
|
||||||
};
|
|
||||||
|
|
||||||
class AVavoomLightColor : public AVavoomLight
|
|
||||||
{
|
|
||||||
DECLARE_CLASS (AVavoomLightColor, AVavoomLight)
|
|
||||||
public:
|
|
||||||
void BeginPlay();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
STAT_DLIGHT=64
|
STAT_DLIGHT=64
|
||||||
|
|
|
@ -758,6 +758,14 @@ bool DamageTypeDefinition::IgnoreArmor(FName type)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(_DamageTypeDefinition, IgnoreArmor)
|
||||||
|
{
|
||||||
|
PARAM_PROLOGUE;
|
||||||
|
PARAM_NAME(type);
|
||||||
|
ACTION_RETURN_BOOL(DamageTypeDefinition::IgnoreArmor(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// DamageTypeDefinition :: ApplyMobjDamageFactor
|
// DamageTypeDefinition :: ApplyMobjDamageFactor
|
||||||
|
|
|
@ -226,10 +226,12 @@ public:
|
||||||
NoArmor = false;
|
NoArmor = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DamageTypeDefinition *Get(FName type);
|
|
||||||
static bool IgnoreArmor(FName type);
|
static bool IgnoreArmor(FName type);
|
||||||
static double GetMobjDamageFactor(FName type, DmgFactors const * const factors);
|
|
||||||
static int ApplyMobjDamageFactor(int damage, FName type, DmgFactors const * const factors);
|
static int ApplyMobjDamageFactor(int damage, FName type, DmgFactors const * const factors);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static double GetMobjDamageFactor(FName type, DmgFactors const * const factors);
|
||||||
|
static DamageTypeDefinition *Get(FName type);
|
||||||
};
|
};
|
||||||
|
|
||||||
class DDropItem;
|
class DDropItem;
|
||||||
|
|
|
@ -47,8 +47,6 @@
|
||||||
#include "serializer.h"
|
#include "serializer.h"
|
||||||
#include "r_utility.h"
|
#include "r_utility.h"
|
||||||
#include "a_morph.h"
|
#include "a_morph.h"
|
||||||
#include "a_armor.h"
|
|
||||||
#include "a_ammo.h"
|
|
||||||
#include "g_levellocals.h"
|
#include "g_levellocals.h"
|
||||||
#include "virtual.h"
|
#include "virtual.h"
|
||||||
|
|
||||||
|
@ -267,7 +265,7 @@ void cht_DoCheat (player_t *player, int cheat)
|
||||||
}
|
}
|
||||||
else if (player->mo != NULL && player->health >= 0)
|
else if (player->mo != NULL && player->health >= 0)
|
||||||
{
|
{
|
||||||
item = player->mo->FindInventory(PClass::FindActor(BeholdPowers[i]));
|
item = player->mo->FindInventory(BeholdPowers[i]);
|
||||||
if (item == NULL)
|
if (item == NULL)
|
||||||
{
|
{
|
||||||
if (i != 0)
|
if (i != 0)
|
||||||
|
@ -319,7 +317,7 @@ void cht_DoCheat (player_t *player, int cheat)
|
||||||
case CHT_RESSURECT:
|
case CHT_RESSURECT:
|
||||||
if (player->playerstate != PST_LIVE && player->mo != nullptr)
|
if (player->playerstate != PST_LIVE && player->mo != nullptr)
|
||||||
{
|
{
|
||||||
if (player->mo->IsKindOf(RUNTIME_CLASS(APlayerChunk)))
|
if (player->mo->IsKindOf(PClass::FindActor("PlayerChunk")))
|
||||||
{
|
{
|
||||||
Printf("Unable to resurrect. Player is no longer connected to its body.\n");
|
Printf("Unable to resurrect. Player is no longer connected to its body.\n");
|
||||||
}
|
}
|
||||||
|
@ -488,7 +486,7 @@ void cht_DoCheat (player_t *player, int cheat)
|
||||||
int oldpieces = 1;
|
int oldpieces = 1;
|
||||||
ret.IntAt(&oldpieces);
|
ret.IntAt(&oldpieces);
|
||||||
GlobalVMStack.Call(gsp, params, 1, &ret, 1, nullptr);
|
GlobalVMStack.Call(gsp, params, 1, &ret, 1, nullptr);
|
||||||
item = player->mo->FindInventory(PClass::FindActor(NAME_Sigil));
|
item = player->mo->FindInventory(NAME_Sigil);
|
||||||
|
|
||||||
if (item != NULL)
|
if (item != NULL)
|
||||||
{
|
{
|
||||||
|
|
|
@ -83,6 +83,20 @@ xx(PointPuller)
|
||||||
xx(UpperStackLookOnly)
|
xx(UpperStackLookOnly)
|
||||||
xx(LowerStackLookOnly)
|
xx(LowerStackLookOnly)
|
||||||
|
|
||||||
|
xx(BasicArmorBonus)
|
||||||
|
xx(BasicArmorPickup)
|
||||||
|
xx(SaveAmount)
|
||||||
|
xx(SavePercent)
|
||||||
|
xx(MaxAbsorb)
|
||||||
|
xx(MaxFullAbsorb)
|
||||||
|
xx(MaxAmount)
|
||||||
|
xx(ActualSaveAmount)
|
||||||
|
xx(ArmorType)
|
||||||
|
xx(HexenArmor)
|
||||||
|
xx(Slots)
|
||||||
|
xx(SlotsIncrement)
|
||||||
|
|
||||||
|
|
||||||
xx(BulletPuff)
|
xx(BulletPuff)
|
||||||
xx(StrifePuff)
|
xx(StrifePuff)
|
||||||
xx(MaulerPuff)
|
xx(MaulerPuff)
|
||||||
|
@ -716,6 +730,8 @@ xx(BlendColor)
|
||||||
xx(Strength)
|
xx(Strength)
|
||||||
xx(Mode)
|
xx(Mode)
|
||||||
xx(PowerupType)
|
xx(PowerupType)
|
||||||
|
xx(PlayerPawn)
|
||||||
|
xx(Key)
|
||||||
|
|
||||||
// Decorate compatibility functions
|
// Decorate compatibility functions
|
||||||
xx(BuiltinTypeCheck)
|
xx(BuiltinTypeCheck)
|
||||||
|
|
|
@ -83,8 +83,6 @@
|
||||||
#include "serializer.h"
|
#include "serializer.h"
|
||||||
#include "thingdef.h"
|
#include "thingdef.h"
|
||||||
#include "a_pickups.h"
|
#include "a_pickups.h"
|
||||||
#include "a_armor.h"
|
|
||||||
#include "a_ammo.h"
|
|
||||||
#include "r_data/colormaps.h"
|
#include "r_data/colormaps.h"
|
||||||
#include "g_levellocals.h"
|
#include "g_levellocals.h"
|
||||||
#include "stats.h"
|
#include "stats.h"
|
||||||
|
@ -4956,8 +4954,8 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FName p(FBehavior::StaticLookupString(args[0]));
|
FName p(FBehavior::StaticLookupString(args[0]));
|
||||||
ABasicArmor * armor = (ABasicArmor *) players[args[1]].mo->FindInventory(NAME_BasicArmor);
|
auto armor = players[args[1]].mo->FindInventory(NAME_BasicArmor);
|
||||||
if (armor && armor->ArmorType == p) return armor->Amount;
|
if (armor && armor->NameVar(NAME_ArmorType) == p) return armor->Amount;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -4966,29 +4964,29 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args)
|
||||||
{
|
{
|
||||||
if (activator == NULL || activator->player == NULL) return 0;
|
if (activator == NULL || activator->player == NULL) return 0;
|
||||||
|
|
||||||
ABasicArmor * equippedarmor = (ABasicArmor *) activator->FindInventory(NAME_BasicArmor);
|
auto equippedarmor = activator->FindInventory(NAME_BasicArmor);
|
||||||
|
|
||||||
if (equippedarmor && equippedarmor->Amount != 0)
|
if (equippedarmor && equippedarmor->Amount != 0)
|
||||||
{
|
{
|
||||||
switch(args[0])
|
switch(args[0])
|
||||||
{
|
{
|
||||||
case ARMORINFO_CLASSNAME:
|
case ARMORINFO_CLASSNAME:
|
||||||
return GlobalACSStrings.AddString(equippedarmor->ArmorType.GetChars());
|
return GlobalACSStrings.AddString(equippedarmor->NameVar(NAME_ArmorType).GetChars());
|
||||||
|
|
||||||
case ARMORINFO_SAVEAMOUNT:
|
case ARMORINFO_SAVEAMOUNT:
|
||||||
return equippedarmor->MaxAmount;
|
return equippedarmor->IntVar(NAME_MaxAmount);
|
||||||
|
|
||||||
case ARMORINFO_SAVEPERCENT:
|
case ARMORINFO_SAVEPERCENT:
|
||||||
return DoubleToACS(equippedarmor->SavePercent);
|
return DoubleToACS(equippedarmor->FloatVar(NAME_SavePercent));
|
||||||
|
|
||||||
case ARMORINFO_MAXABSORB:
|
case ARMORINFO_MAXABSORB:
|
||||||
return equippedarmor->MaxAbsorb;
|
return equippedarmor->IntVar(NAME_MaxAbsorb);
|
||||||
|
|
||||||
case ARMORINFO_MAXFULLABSORB:
|
case ARMORINFO_MAXFULLABSORB:
|
||||||
return equippedarmor->MaxFullAbsorb;
|
return equippedarmor->IntVar(NAME_MaxFullAbsorb);
|
||||||
|
|
||||||
case ARMORINFO_ACTUALSAVEAMOUNT:
|
case ARMORINFO_ACTUALSAVEAMOUNT:
|
||||||
return equippedarmor->ActualSaveAmount;
|
return equippedarmor->IntVar(NAME_ActualSaveAmount);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -8236,7 +8234,7 @@ scriptwait:
|
||||||
case PCD_PLAYERARMORPOINTS:
|
case PCD_PLAYERARMORPOINTS:
|
||||||
if (activator)
|
if (activator)
|
||||||
{
|
{
|
||||||
ABasicArmor *armor = activator->FindInventory<ABasicArmor>();
|
auto armor = activator->FindInventory(NAME_BasicArmor);
|
||||||
PushToStack (armor ? armor->Amount : 0);
|
PushToStack (armor ? armor->Amount : 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -8683,7 +8681,7 @@ scriptwait:
|
||||||
{
|
{
|
||||||
AInventory *sigil;
|
AInventory *sigil;
|
||||||
|
|
||||||
if (activator == NULL || (sigil = activator->FindInventory(PClass::FindActor(NAME_Sigil))) == NULL)
|
if (activator == NULL || (sigil = activator->FindInventory(NAME_Sigil)) == NULL)
|
||||||
{
|
{
|
||||||
PushToStack (0);
|
PushToStack (0);
|
||||||
}
|
}
|
||||||
|
@ -8700,7 +8698,7 @@ scriptwait:
|
||||||
PClass *type = PClass::FindClass (FBehavior::StaticLookupString (STACK(1)));
|
PClass *type = PClass::FindClass (FBehavior::StaticLookupString (STACK(1)));
|
||||||
AInventory *item;
|
AInventory *item;
|
||||||
|
|
||||||
if (type != NULL && type->ParentClass == RUNTIME_CLASS(AAmmo))
|
if (type != NULL && type->ParentClass == PClass::FindActor(NAME_Ammo))
|
||||||
{
|
{
|
||||||
item = activator->FindInventory (static_cast<PClassActor *>(type));
|
item = activator->FindInventory (static_cast<PClassActor *>(type));
|
||||||
if (item != NULL)
|
if (item != NULL)
|
||||||
|
@ -8729,7 +8727,7 @@ scriptwait:
|
||||||
PClassActor *type = PClass::FindActor (FBehavior::StaticLookupString (STACK(2)));
|
PClassActor *type = PClass::FindActor (FBehavior::StaticLookupString (STACK(2)));
|
||||||
AInventory *item;
|
AInventory *item;
|
||||||
|
|
||||||
if (type != NULL && type->ParentClass == RUNTIME_CLASS(AAmmo))
|
if (type != NULL && type->ParentClass == PClass::FindActor(NAME_Ammo))
|
||||||
{
|
{
|
||||||
item = activator->FindInventory (type);
|
item = activator->FindInventory (type);
|
||||||
if (item != NULL)
|
if (item != NULL)
|
||||||
|
|
|
@ -78,7 +78,6 @@
|
||||||
#include "v_text.h"
|
#include "v_text.h"
|
||||||
#include "thingdef.h"
|
#include "thingdef.h"
|
||||||
#include "math/cmath.h"
|
#include "math/cmath.h"
|
||||||
#include "a_armor.h"
|
|
||||||
#include "g_levellocals.h"
|
#include "g_levellocals.h"
|
||||||
|
|
||||||
AActor *SingleActorFromTID(int tid, AActor *defactor);
|
AActor *SingleActorFromTID(int tid, AActor *defactor);
|
||||||
|
@ -2059,7 +2058,7 @@ DEFINE_ACTION_FUNCTION(AStateProvider, A_CustomPunch)
|
||||||
PARAM_FLOAT_DEF (range);
|
PARAM_FLOAT_DEF (range);
|
||||||
PARAM_FLOAT_DEF (lifesteal);
|
PARAM_FLOAT_DEF (lifesteal);
|
||||||
PARAM_INT_DEF (lifestealmax);
|
PARAM_INT_DEF (lifestealmax);
|
||||||
PARAM_CLASS_DEF (armorbonustype, ABasicArmorBonus);
|
PARAM_CLASS_DEF (armorbonustype, AActor);
|
||||||
PARAM_SOUND_DEF (MeleeSound);
|
PARAM_SOUND_DEF (MeleeSound);
|
||||||
PARAM_SOUND_DEF (MissSound);
|
PARAM_SOUND_DEF (MissSound);
|
||||||
|
|
||||||
|
@ -2107,18 +2106,17 @@ DEFINE_ACTION_FUNCTION(AStateProvider, A_CustomPunch)
|
||||||
{
|
{
|
||||||
if (armorbonustype == NULL)
|
if (armorbonustype == NULL)
|
||||||
{
|
{
|
||||||
armorbonustype = dyn_cast<ABasicArmorBonus::MetaClass>(PClass::FindClass("ArmorBonus"));
|
armorbonustype = PClass::FindActor("ArmorBonus");
|
||||||
}
|
}
|
||||||
if (armorbonustype != NULL)
|
if (armorbonustype != NULL)
|
||||||
{
|
{
|
||||||
assert(armorbonustype->IsDescendantOf(RUNTIME_CLASS(ABasicArmorBonus)));
|
auto armorbonus = Spawn(armorbonustype);
|
||||||
ABasicArmorBonus *armorbonus = static_cast<ABasicArmorBonus *>(Spawn(armorbonustype));
|
armorbonus->IntVar(NAME_SaveAmount) *= int(actualdamage * lifesteal);
|
||||||
armorbonus->SaveAmount *= int(actualdamage * lifesteal);
|
if (lifestealmax > 0) armorbonus->IntVar("MaxSaveAmount") = lifestealmax;
|
||||||
armorbonus->MaxSaveAmount = lifestealmax <= 0 ? armorbonus->MaxSaveAmount : lifestealmax;
|
|
||||||
armorbonus->flags |= MF_DROPPED;
|
armorbonus->flags |= MF_DROPPED;
|
||||||
armorbonus->ClearCounters();
|
armorbonus->ClearCounters();
|
||||||
|
|
||||||
if (!armorbonus->CallTryPickup(self))
|
if (!static_cast<AInventory*>(armorbonus)->CallTryPickup(self))
|
||||||
{
|
{
|
||||||
armorbonus->Destroy ();
|
armorbonus->Destroy ();
|
||||||
}
|
}
|
||||||
|
|
|
@ -642,7 +642,7 @@ static void TakeStrifeItem (player_t *player, PClassActor *itemtype, int amount)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Don't take keys.
|
// Don't take keys.
|
||||||
if (itemtype->IsDescendantOf (RUNTIME_CLASS(AKey)))
|
if (itemtype->IsDescendantOf (PClass::FindActor(NAME_Key)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Don't take the sigil.
|
// Don't take the sigil.
|
||||||
|
|
|
@ -51,7 +51,6 @@
|
||||||
#include "p_spec.h"
|
#include "p_spec.h"
|
||||||
#include "p_checkposition.h"
|
#include "p_checkposition.h"
|
||||||
#include "math/cmath.h"
|
#include "math/cmath.h"
|
||||||
#include "a_ammo.h"
|
|
||||||
#include "g_levellocals.h"
|
#include "g_levellocals.h"
|
||||||
|
|
||||||
#include "gi.h"
|
#include "gi.h"
|
||||||
|
@ -3228,7 +3227,7 @@ void ModifyDropAmount(AInventory *inv, int dropamount)
|
||||||
|
|
||||||
if (dropamount > 0)
|
if (dropamount > 0)
|
||||||
{
|
{
|
||||||
if (flagmask != 0 && inv->IsKindOf(RUNTIME_CLASS(AAmmo)))
|
if (flagmask != 0 && inv->IsKindOf(PClass::FindActor(NAME_Ammo)))
|
||||||
{
|
{
|
||||||
inv->Amount = int(dropamount * dropammofactor);
|
inv->Amount = int(dropamount * dropammofactor);
|
||||||
inv->ItemFlags |= IF_IGNORESKILL;
|
inv->ItemFlags |= IF_IGNORESKILL;
|
||||||
|
@ -3238,10 +3237,10 @@ void ModifyDropAmount(AInventory *inv, int dropamount)
|
||||||
inv->Amount = dropamount;
|
inv->Amount = dropamount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (inv->IsKindOf (RUNTIME_CLASS(AAmmo)))
|
else if (inv->IsKindOf (PClass::FindActor(NAME_Ammo)))
|
||||||
{
|
{
|
||||||
// Half ammo when dropped by bad guys.
|
// Half ammo when dropped by bad guys.
|
||||||
int amount = static_cast<AAmmo *>(inv)->DropAmount;
|
int amount = inv->IntVar("DropAmount");
|
||||||
if (amount <= 0)
|
if (amount <= 0)
|
||||||
{
|
{
|
||||||
amount = MAX(1, int(inv->Amount * dropammofactor));
|
amount = MAX(1, int(inv->Amount * dropammofactor));
|
||||||
|
|
|
@ -1456,7 +1456,7 @@ void P_SetRenderSector()
|
||||||
segs[i].PartnerSeg = segs[i].PartnerSeg->PartnerSeg = nullptr;
|
segs[i].PartnerSeg = segs[i].PartnerSeg->PartnerSeg = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
for (i = 0; i < numsegs; i++)
|
for (i = 0; i < numsegs; i++)
|
||||||
{
|
{
|
||||||
if (segs[i].PartnerSeg != nullptr && segs[i].PartnerSeg->PartnerSeg != &segs[i])
|
if (segs[i].PartnerSeg != nullptr && segs[i].PartnerSeg->PartnerSeg != &segs[i])
|
||||||
|
@ -1464,7 +1464,6 @@ void P_SetRenderSector()
|
||||||
segs[i].PartnerSeg = nullptr;
|
segs[i].PartnerSeg = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// look up sector number for each subsector
|
// look up sector number for each subsector
|
||||||
for (i = 0; i < numsubsectors; i++)
|
for (i = 0; i < numsubsectors; i++)
|
||||||
|
|
|
@ -2883,7 +2883,7 @@ FUNC(LS_SetPlayerProperty)
|
||||||
{ // Take power from activator
|
{ // Take power from activator
|
||||||
if (power != 4)
|
if (power != 4)
|
||||||
{
|
{
|
||||||
AInventory *item = it->FindInventory(PClass::FindActor(powers[power]), true);
|
AInventory *item = it->FindInventory(powers[power], true);
|
||||||
if (item != NULL)
|
if (item != NULL)
|
||||||
{
|
{
|
||||||
item->Destroy ();
|
item->Destroy ();
|
||||||
|
|
|
@ -69,8 +69,6 @@
|
||||||
#include "thingdef.h"
|
#include "thingdef.h"
|
||||||
#include "d_player.h"
|
#include "d_player.h"
|
||||||
#include "virtual.h"
|
#include "virtual.h"
|
||||||
#include "a_armor.h"
|
|
||||||
#include "a_ammo.h"
|
|
||||||
#include "g_levellocals.h"
|
#include "g_levellocals.h"
|
||||||
#include "a_morph.h"
|
#include "a_morph.h"
|
||||||
|
|
||||||
|
@ -791,13 +789,9 @@ bool AActor::GiveInventory(PClassInventory *type, int amount, bool givecheat)
|
||||||
item->ClearCounters();
|
item->ClearCounters();
|
||||||
if (!givecheat || amount > 0)
|
if (!givecheat || amount > 0)
|
||||||
{
|
{
|
||||||
if (type->IsDescendantOf (RUNTIME_CLASS(ABasicArmorPickup)))
|
if (type->IsDescendantOf (PClass::FindActor(NAME_BasicArmorPickup)) || type->IsDescendantOf(PClass::FindActor(NAME_BasicArmorBonus)))
|
||||||
{
|
{
|
||||||
static_cast<ABasicArmorPickup*>(item)->SaveAmount *= amount;
|
item->IntVar(NAME_SaveAmount) *= amount;
|
||||||
}
|
|
||||||
else if (type->IsDescendantOf (RUNTIME_CLASS(ABasicArmorBonus)))
|
|
||||||
{
|
|
||||||
static_cast<ABasicArmorBonus*>(item)->SaveAmount *= amount;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -899,14 +893,11 @@ bool AActor::TakeInventory(PClassActor *itemclass, int amount, bool fromdecorate
|
||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item->IsKindOf(RUNTIME_CLASS(AHexenArmor)))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Do not take ammo if the "no take infinite/take as ammo depletion" flag is set
|
// Do not take ammo if the "no take infinite/take as ammo depletion" flag is set
|
||||||
// and infinite ammo is on
|
// and infinite ammo is on
|
||||||
if (notakeinfinite &&
|
if (notakeinfinite &&
|
||||||
((dmflags & DF_INFINITE_AMMO) || (player && player->cheats & CF_INFINITEAMMO)) &&
|
((dmflags & DF_INFINITE_AMMO) || (player && player->cheats & CF_INFINITEAMMO)) &&
|
||||||
item->IsKindOf(RUNTIME_CLASS(AAmmo)))
|
item->IsKindOf(PClass::FindActor(NAME_Ammo)))
|
||||||
{
|
{
|
||||||
// Nothing to do here, except maybe res = false;? Would it make sense?
|
// Nothing to do here, except maybe res = false;? Would it make sense?
|
||||||
result = false;
|
result = false;
|
||||||
|
@ -1098,9 +1089,9 @@ AInventory *AActor::FindInventory (PClassActor *type, bool subclass)
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
AInventory *AActor::FindInventory (FName type)
|
AInventory *AActor::FindInventory (FName type, bool subclass)
|
||||||
{
|
{
|
||||||
return FindInventory(PClass::FindActor(type));
|
return FindInventory(PClass::FindActor(type), subclass);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(AActor, FindInventory)
|
DEFINE_ACTION_FUNCTION(AActor, FindInventory)
|
||||||
|
@ -1171,7 +1162,7 @@ bool AActor::GiveAmmo (PClassInventory *type, int amount)
|
||||||
DEFINE_ACTION_FUNCTION(AActor, GiveAmmo)
|
DEFINE_ACTION_FUNCTION(AActor, GiveAmmo)
|
||||||
{
|
{
|
||||||
PARAM_SELF_PROLOGUE(AActor);
|
PARAM_SELF_PROLOGUE(AActor);
|
||||||
PARAM_CLASS(type, AAmmo);
|
PARAM_CLASS(type, AInventory);
|
||||||
PARAM_INT(amount);
|
PARAM_INT(amount);
|
||||||
ACTION_RETURN_BOOL(self->GiveAmmo(type, amount));
|
ACTION_RETURN_BOOL(self->GiveAmmo(type, amount));
|
||||||
}
|
}
|
||||||
|
@ -1212,12 +1203,7 @@ void AActor::ClearInventory()
|
||||||
if (!(inv->ItemFlags & IF_UNDROPPABLE))
|
if (!(inv->ItemFlags & IF_UNDROPPABLE))
|
||||||
{
|
{
|
||||||
inv->DepleteOrDestroy();
|
inv->DepleteOrDestroy();
|
||||||
}
|
if (!(inv->ObjectFlags & OF_EuthanizeMe)) invp = &inv->Inventory; // was only depleted so advance the pointer manually.
|
||||||
else if (inv->GetClass() == RUNTIME_CLASS(AHexenArmor))
|
|
||||||
{
|
|
||||||
AHexenArmor *harmor = static_cast<AHexenArmor *> (inv);
|
|
||||||
harmor->Slots[3] = harmor->Slots[2] = harmor->Slots[1] = harmor->Slots[0] = 0;
|
|
||||||
invp = &inv->Inventory;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -5711,7 +5697,7 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position)
|
||||||
}
|
}
|
||||||
if (dmflags & DF_NO_ARMOR)
|
if (dmflags & DF_NO_ARMOR)
|
||||||
{
|
{
|
||||||
if (i->IsDescendantOf (RUNTIME_CLASS(AArmor)))
|
if (i->IsDescendantOf (PClass::FindActor(NAME_Armor)))
|
||||||
return NULL;
|
return NULL;
|
||||||
if (i->TypeName == NAME_Megasphere)
|
if (i->TypeName == NAME_Megasphere)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -237,7 +237,7 @@ DPSprite *player_t::GetPSprite(PSPLayers layer)
|
||||||
{
|
{
|
||||||
if (mo != nullptr)
|
if (mo != nullptr)
|
||||||
{
|
{
|
||||||
newcaller = mo->FindInventory(PClass::FindActor(NAME_PowerTargeter), true);
|
newcaller = mo->FindInventory(NAME_PowerTargeter, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (layer == PSP_STRIFEHANDS)
|
else if (layer == PSP_STRIFEHANDS)
|
||||||
|
|
|
@ -59,8 +59,6 @@
|
||||||
#include "a_morph.h"
|
#include "a_morph.h"
|
||||||
#include "p_spec.h"
|
#include "p_spec.h"
|
||||||
#include "virtual.h"
|
#include "virtual.h"
|
||||||
#include "a_armor.h"
|
|
||||||
#include "a_ammo.h"
|
|
||||||
#include "g_levellocals.h"
|
#include "g_levellocals.h"
|
||||||
|
|
||||||
static FRandom pr_skullpop ("SkullPop");
|
static FRandom pr_skullpop ("SkullPop");
|
||||||
|
@ -660,8 +658,6 @@ IMPLEMENT_POINTERS_START(APlayerPawn)
|
||||||
IMPLEMENT_POINTER(FlechetteType)
|
IMPLEMENT_POINTER(FlechetteType)
|
||||||
IMPLEMENT_POINTERS_END
|
IMPLEMENT_POINTERS_END
|
||||||
|
|
||||||
IMPLEMENT_CLASS(APlayerChunk, false, false)
|
|
||||||
|
|
||||||
void APlayerPawn::Serialize(FSerializer &arc)
|
void APlayerPawn::Serialize(FSerializer &arc)
|
||||||
{
|
{
|
||||||
Super::Serialize (arc);
|
Super::Serialize (arc);
|
||||||
|
@ -1076,12 +1072,12 @@ void APlayerPawn::GiveDeathmatchInventory()
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
|
for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
|
||||||
{
|
{
|
||||||
if (PClassActor::AllActorClasses[i]->IsDescendantOf (RUNTIME_CLASS(AKey)))
|
if (PClassActor::AllActorClasses[i]->IsDescendantOf (PClass::FindActor(NAME_Key)))
|
||||||
{
|
{
|
||||||
AKey *key = (AKey *)GetDefaultByType (PClassActor::AllActorClasses[i]);
|
AInventory *key = (AInventory*)GetDefaultByType (PClassActor::AllActorClasses[i]);
|
||||||
if (key->KeyNumber != 0)
|
if (key->special1 != 0)
|
||||||
{
|
{
|
||||||
key = static_cast<AKey *>(Spawn(static_cast<PClassActor *>(PClassActor::AllActorClasses[i])));
|
key = (AInventory*)Spawn(PClassActor::AllActorClasses[i]);
|
||||||
if (!key->CallTryPickup (this))
|
if (!key->CallTryPickup (this))
|
||||||
{
|
{
|
||||||
key->Destroy ();
|
key->Destroy ();
|
||||||
|
@ -1134,7 +1130,7 @@ void APlayerPawn::FilterCoopRespawnInventory (APlayerPawn *oldplayer)
|
||||||
|
|
||||||
if ((dmflags & DF_COOP_LOSE_KEYS) &&
|
if ((dmflags & DF_COOP_LOSE_KEYS) &&
|
||||||
defitem == NULL &&
|
defitem == NULL &&
|
||||||
item->IsKindOf(RUNTIME_CLASS(AKey)))
|
item->IsKindOf(PClass::FindActor(NAME_Key)))
|
||||||
{
|
{
|
||||||
item->Destroy();
|
item->Destroy();
|
||||||
}
|
}
|
||||||
|
@ -1145,23 +1141,22 @@ void APlayerPawn::FilterCoopRespawnInventory (APlayerPawn *oldplayer)
|
||||||
item->Destroy();
|
item->Destroy();
|
||||||
}
|
}
|
||||||
else if ((dmflags & DF_COOP_LOSE_ARMOR) &&
|
else if ((dmflags & DF_COOP_LOSE_ARMOR) &&
|
||||||
item->IsKindOf(RUNTIME_CLASS(AArmor)))
|
item->IsKindOf(PClass::FindActor(NAME_Armor)))
|
||||||
{
|
{
|
||||||
if (defitem == NULL)
|
if (defitem == NULL)
|
||||||
{
|
{
|
||||||
item->Destroy();
|
item->Destroy();
|
||||||
}
|
}
|
||||||
else if (item->IsKindOf(RUNTIME_CLASS(ABasicArmor)))
|
else if (item->IsKindOf(PClass::FindActor(NAME_BasicArmor)))
|
||||||
{
|
{
|
||||||
static_cast<ABasicArmor*>(item)->SavePercent = static_cast<ABasicArmor*>(defitem)->SavePercent;
|
item->IntVar(NAME_SavePercent) = defitem->IntVar(NAME_SavePercent);
|
||||||
item->Amount = defitem->Amount;
|
item->Amount = defitem->Amount;
|
||||||
}
|
}
|
||||||
else if (item->IsKindOf(RUNTIME_CLASS(AHexenArmor)))
|
else if (item->IsKindOf(PClass::FindActor(NAME_HexenArmor)))
|
||||||
{
|
{
|
||||||
static_cast<AHexenArmor*>(item)->Slots[0] = static_cast<AHexenArmor*>(defitem)->Slots[0];
|
double *SlotsTo = (double*)item->ScriptVar(NAME_Slots, nullptr);
|
||||||
static_cast<AHexenArmor*>(item)->Slots[1] = static_cast<AHexenArmor*>(defitem)->Slots[1];
|
double *SlotsFrom = (double*)defitem->ScriptVar(NAME_Slots, nullptr);
|
||||||
static_cast<AHexenArmor*>(item)->Slots[2] = static_cast<AHexenArmor*>(defitem)->Slots[2];
|
memcpy(SlotsTo, SlotsFrom, 4 * sizeof(double));
|
||||||
static_cast<AHexenArmor*>(item)->Slots[3] = static_cast<AHexenArmor*>(defitem)->Slots[3];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ((dmflags & DF_COOP_LOSE_POWERUPS) &&
|
else if ((dmflags & DF_COOP_LOSE_POWERUPS) &&
|
||||||
|
@ -1171,7 +1166,7 @@ void APlayerPawn::FilterCoopRespawnInventory (APlayerPawn *oldplayer)
|
||||||
item->Destroy();
|
item->Destroy();
|
||||||
}
|
}
|
||||||
else if ((dmflags & (DF_COOP_LOSE_AMMO | DF_COOP_HALVE_AMMO)) &&
|
else if ((dmflags & (DF_COOP_LOSE_AMMO | DF_COOP_HALVE_AMMO)) &&
|
||||||
item->IsKindOf(RUNTIME_CLASS(AAmmo)))
|
item->IsKindOf(PClass::FindActor(NAME_Ammo)))
|
||||||
{
|
{
|
||||||
if (defitem == NULL)
|
if (defitem == NULL)
|
||||||
{
|
{
|
||||||
|
@ -1367,21 +1362,22 @@ void APlayerPawn::GiveDefaultInventory ()
|
||||||
// it provides player class based protection that should not affect
|
// it provides player class based protection that should not affect
|
||||||
// any other protection item.
|
// any other protection item.
|
||||||
PClassPlayerPawn *myclass = GetClass();
|
PClassPlayerPawn *myclass = GetClass();
|
||||||
GiveInventoryType(RUNTIME_CLASS(AHexenArmor));
|
GiveInventoryType(PClass::FindActor(NAME_HexenArmor));
|
||||||
AHexenArmor *harmor = FindInventory<AHexenArmor>();
|
auto harmor = FindInventory(NAME_HexenArmor);
|
||||||
harmor->Slots[4] = myclass->HexenArmor[0];
|
|
||||||
|
double *Slots = (double*)harmor->ScriptVar(NAME_Slots, nullptr);
|
||||||
|
double *SlotsIncrement = (double*)harmor->ScriptVar(NAME_SlotsIncrement, nullptr);
|
||||||
|
Slots[4] = myclass->HexenArmor[0];
|
||||||
for (int i = 0; i < 4; ++i)
|
for (int i = 0; i < 4; ++i)
|
||||||
{
|
{
|
||||||
harmor->SlotsIncrement[i] = myclass->HexenArmor[i + 1];
|
SlotsIncrement[i] = myclass->HexenArmor[i + 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
// BasicArmor must come right after that. It should not affect any
|
// BasicArmor must come right after that. It should not affect any
|
||||||
// other protection item as well but needs to process the damage
|
// other protection item as well but needs to process the damage
|
||||||
// before the HexenArmor does.
|
// before the HexenArmor does.
|
||||||
ABasicArmor *barmor = Spawn<ABasicArmor> ();
|
auto barmor = (AInventory*)Spawn(NAME_BasicArmor);
|
||||||
barmor->BecomeItem ();
|
barmor->BecomeItem ();
|
||||||
barmor->SavePercent = 0;
|
|
||||||
barmor->Amount = 0;
|
|
||||||
AddInventory (barmor);
|
AddInventory (barmor);
|
||||||
|
|
||||||
// Now add the items from the DECORATE definition
|
// Now add the items from the DECORATE definition
|
||||||
|
@ -1701,13 +1697,13 @@ DEFINE_ACTION_FUNCTION(AActor, A_PlayerScream)
|
||||||
DEFINE_ACTION_FUNCTION(AActor, A_SkullPop)
|
DEFINE_ACTION_FUNCTION(AActor, A_SkullPop)
|
||||||
{
|
{
|
||||||
PARAM_SELF_PROLOGUE(AActor);
|
PARAM_SELF_PROLOGUE(AActor);
|
||||||
PARAM_CLASS_DEF(spawntype, APlayerChunk);
|
PARAM_CLASS_DEF(spawntype, APlayerPawn);
|
||||||
|
|
||||||
APlayerPawn *mo;
|
APlayerPawn *mo;
|
||||||
player_t *player;
|
player_t *player;
|
||||||
|
|
||||||
// [GRB] Parameterized version
|
// [GRB] Parameterized version
|
||||||
if (spawntype == NULL || !spawntype->IsDescendantOf(RUNTIME_CLASS(APlayerChunk)))
|
if (spawntype == NULL || !spawntype->IsDescendantOf(PClass::FindActor("PlayerChunk")))
|
||||||
{
|
{
|
||||||
spawntype = dyn_cast<PClassPlayerPawn>(PClass::FindClass("BloodySkull"));
|
spawntype = dyn_cast<PClassPlayerPawn>(PClass::FindClass("BloodySkull"));
|
||||||
if (spawntype == NULL)
|
if (spawntype == NULL)
|
||||||
|
@ -2205,7 +2201,7 @@ void P_DeathThink (player_t *player)
|
||||||
player->TickPSprites();
|
player->TickPSprites();
|
||||||
|
|
||||||
player->onground = (player->mo->Z() <= player->mo->floorz);
|
player->onground = (player->mo->Z() <= player->mo->floorz);
|
||||||
if (player->mo->IsKindOf (RUNTIME_CLASS(APlayerChunk)))
|
if (player->mo->IsKindOf (PClass::FindActor("PlayerChunk")))
|
||||||
{ // Flying bloody skull or flying ice chunk
|
{ // Flying bloody skull or flying ice chunk
|
||||||
player->viewheight = 6;
|
player->viewheight = 6;
|
||||||
player->deltaviewheight = 0;
|
player->deltaviewheight = 0;
|
||||||
|
|
|
@ -56,7 +56,7 @@
|
||||||
#include "m_argv.h"
|
#include "m_argv.h"
|
||||||
#include "p_local.h"
|
#include "p_local.h"
|
||||||
#include "doomerrors.h"
|
#include "doomerrors.h"
|
||||||
#include "a_weaponpiece.h"
|
#include "a_weapons.h"
|
||||||
#include "p_conversation.h"
|
#include "p_conversation.h"
|
||||||
#include "v_text.h"
|
#include "v_text.h"
|
||||||
#include "thingdef.h"
|
#include "thingdef.h"
|
||||||
|
|
|
@ -46,7 +46,6 @@
|
||||||
#include "templates.h"
|
#include "templates.h"
|
||||||
#include "r_defs.h"
|
#include "r_defs.h"
|
||||||
#include "a_pickups.h"
|
#include "a_pickups.h"
|
||||||
#include "a_armor.h"
|
|
||||||
#include "s_sound.h"
|
#include "s_sound.h"
|
||||||
#include "cmdlib.h"
|
#include "cmdlib.h"
|
||||||
#include "p_lnspec.h"
|
#include "p_lnspec.h"
|
||||||
|
@ -67,9 +66,7 @@
|
||||||
#include "teaminfo.h"
|
#include "teaminfo.h"
|
||||||
#include "v_video.h"
|
#include "v_video.h"
|
||||||
#include "r_data/colormaps.h"
|
#include "r_data/colormaps.h"
|
||||||
#include "a_weaponpiece.h"
|
|
||||||
#include "vmbuilder.h"
|
#include "vmbuilder.h"
|
||||||
#include "a_ammo.h"
|
|
||||||
#include "a_keys.h"
|
#include "a_keys.h"
|
||||||
#include "g_levellocals.h"
|
#include "g_levellocals.h"
|
||||||
|
|
||||||
|
@ -98,9 +95,9 @@ static PClassActor *FindClassTentative(const char *name, PClass *ancestor, bool
|
||||||
}
|
}
|
||||||
return static_cast<PClassActor *>(cls);
|
return static_cast<PClassActor *>(cls);
|
||||||
}
|
}
|
||||||
static AAmmo::MetaClass *FindClassTentativeAmmo(const char *name, bool optional = false)
|
static AInventory::MetaClass *FindClassTentativeAmmo(const char *name, bool optional = false)
|
||||||
{
|
{
|
||||||
return static_cast<AAmmo::MetaClass *>(FindClassTentative(name, RUNTIME_CLASS(AAmmo), optional));
|
return static_cast<PClassInventory *>(FindClassTentative(name, PClass::FindActor(NAME_Ammo), optional));
|
||||||
}
|
}
|
||||||
static AWeapon::MetaClass *FindClassTentativeWeapon(const char *name, bool optional = false)
|
static AWeapon::MetaClass *FindClassTentativeWeapon(const char *name, bool optional = false)
|
||||||
{
|
{
|
||||||
|
@ -465,23 +462,6 @@ static bool PointerCheck(PType *symtype, PType *checktype)
|
||||||
return symptype != nullptr && checkptype != nullptr && symptype->ClassRestriction->IsDescendantOf(checkptype->ClassRestriction);
|
return symptype != nullptr && checkptype != nullptr && symptype->ClassRestriction->IsDescendantOf(checkptype->ClassRestriction);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *ScriptVar(DObject *obj, PClass *cls, FName field, PType *type)
|
|
||||||
{
|
|
||||||
auto sym = dyn_cast<PField>(cls->Symbols.FindSymbol(field, true));
|
|
||||||
if (sym && (sym->Type == type || PointerCheck(sym->Type, type)))
|
|
||||||
{
|
|
||||||
return (((char*)obj) + sym->Offset);
|
|
||||||
}
|
|
||||||
I_Error("Variable %s of type %s not found in %s\n", field.GetChars(), type->DescriptiveName(), cls->TypeName.GetChars());
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
T &TypedScriptVar(DObject *obj, PClass *cls, FName field, PType *type)
|
|
||||||
{
|
|
||||||
return *(T*)ScriptVar(obj, cls, field, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// Info Property handlers
|
// Info Property handlers
|
||||||
|
@ -1742,149 +1722,6 @@ DEFINE_CLASS_PROPERTY(forbiddento, Ssssssssssssssssssss, Inventory)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
DEFINE_CLASS_PROPERTY(backpackamount, I, Ammo)
|
|
||||||
{
|
|
||||||
PROP_INT_PARM(i, 0);
|
|
||||||
defaults->BackpackAmount = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
DEFINE_CLASS_PROPERTY(backpackmaxamount, I, Ammo)
|
|
||||||
{
|
|
||||||
PROP_INT_PARM(i, 0);
|
|
||||||
defaults->BackpackMaxAmount = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
DEFINE_CLASS_PROPERTY(dropamount, I, Ammo)
|
|
||||||
{
|
|
||||||
PROP_INT_PARM(i, 0);
|
|
||||||
defaults->DropAmount = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
DEFINE_CLASS_PROPERTY_PREFIX(armor, maxsaveamount, I, BasicArmorBonus)
|
|
||||||
{
|
|
||||||
PROP_INT_PARM(i, 0);
|
|
||||||
defaults->MaxSaveAmount = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
DEFINE_CLASS_PROPERTY_PREFIX(armor, maxbonus, I, BasicArmorBonus)
|
|
||||||
{
|
|
||||||
PROP_INT_PARM(i, 0);
|
|
||||||
defaults->BonusCount = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
DEFINE_CLASS_PROPERTY_PREFIX(armor, maxbonusmax, I, BasicArmorBonus)
|
|
||||||
{
|
|
||||||
PROP_INT_PARM(i, 0);
|
|
||||||
defaults->BonusMax = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
DEFINE_CLASS_PROPERTY(saveamount, I, Armor)
|
|
||||||
{
|
|
||||||
PROP_INT_PARM(i, 0);
|
|
||||||
|
|
||||||
// Special case here because this property has to work for 2 unrelated classes
|
|
||||||
if (info->IsDescendantOf(RUNTIME_CLASS(ABasicArmorPickup)))
|
|
||||||
{
|
|
||||||
((ABasicArmorPickup*)defaults)->SaveAmount=i;
|
|
||||||
}
|
|
||||||
else if (info->IsDescendantOf(RUNTIME_CLASS(ABasicArmorBonus)))
|
|
||||||
{
|
|
||||||
((ABasicArmorBonus*)defaults)->SaveAmount=i;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
I_Error("\"Armor.SaveAmount\" requires an actor of type \"Armor\"");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
DEFINE_CLASS_PROPERTY(savepercent, F, Armor)
|
|
||||||
{
|
|
||||||
PROP_DOUBLE_PARM(i, 0);
|
|
||||||
|
|
||||||
i = clamp(i, 0., 100.)/100.;
|
|
||||||
// Special case here because this property has to work for 2 unrelated classes
|
|
||||||
if (info->IsDescendantOf(RUNTIME_CLASS(ABasicArmorPickup)))
|
|
||||||
{
|
|
||||||
((ABasicArmorPickup*)defaults)->SavePercent = i;
|
|
||||||
}
|
|
||||||
else if (info->IsDescendantOf(RUNTIME_CLASS(ABasicArmorBonus)))
|
|
||||||
{
|
|
||||||
((ABasicArmorBonus*)defaults)->SavePercent = i;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
I_Error("\"Armor.SavePercent\" requires an actor of type \"Armor\"\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
DEFINE_CLASS_PROPERTY(maxabsorb, I, Armor)
|
|
||||||
{
|
|
||||||
PROP_INT_PARM(i, 0);
|
|
||||||
|
|
||||||
// Special case here because this property has to work for 2 unrelated classes
|
|
||||||
if (info->IsDescendantOf(RUNTIME_CLASS(ABasicArmorPickup)))
|
|
||||||
{
|
|
||||||
((ABasicArmorPickup*)defaults)->MaxAbsorb = i;
|
|
||||||
}
|
|
||||||
else if (info->IsDescendantOf(RUNTIME_CLASS(ABasicArmorBonus)))
|
|
||||||
{
|
|
||||||
((ABasicArmorBonus*)defaults)->MaxAbsorb = i;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
I_Error("\"Armor.MaxAbsorb\" requires an actor of type \"Armor\"\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
DEFINE_CLASS_PROPERTY(maxfullabsorb, I, Armor)
|
|
||||||
{
|
|
||||||
PROP_INT_PARM(i, 0);
|
|
||||||
|
|
||||||
// Special case here because this property has to work for 2 unrelated classes
|
|
||||||
if (info->IsDescendantOf(RUNTIME_CLASS(ABasicArmorPickup)))
|
|
||||||
{
|
|
||||||
((ABasicArmorPickup*)defaults)->MaxFullAbsorb = i;
|
|
||||||
}
|
|
||||||
else if (info->IsDescendantOf(RUNTIME_CLASS(ABasicArmorBonus)))
|
|
||||||
{
|
|
||||||
((ABasicArmorBonus*)defaults)->MaxFullAbsorb = i;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
I_Error("\"Armor.MaxFullAbsorb\" requires an actor of type \"Armor\"\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -2251,24 +2088,6 @@ DEFINE_CLASS_PROPERTY(preferredskin, S, Weapon)
|
||||||
// NoOp - only for Skulltag compatibility
|
// NoOp - only for Skulltag compatibility
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
DEFINE_CLASS_PROPERTY(number, I, WeaponPiece)
|
|
||||||
{
|
|
||||||
PROP_INT_PARM(i, 0);
|
|
||||||
defaults->PieceValue = 1 << (i-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
DEFINE_CLASS_PROPERTY(weapon, S, WeaponPiece)
|
|
||||||
{
|
|
||||||
PROP_STRING_PARM(str, 0);
|
|
||||||
defaults->WeaponClass = FindClassTentativeWeapon(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -2429,7 +2248,7 @@ DEFINE_SCRIPTED_PROPERTY_PREFIX(powerup, type, S, PowerupGiver)
|
||||||
I_Error("Unknown powerup type %s", str);
|
I_Error("Unknown powerup type %s", str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TypedScriptVar<PClassActor*>(defaults, info, NAME_PowerupType, NewClassPointer(RUNTIME_CLASS(AActor))) = cls;
|
defaults->PointerVar<PClassActor>(NAME_PowerupType) = cls;
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -3018,7 +2837,7 @@ DEFINE_CLASS_PROPERTY(unmorphflash, S, MorphProjectile)
|
||||||
DEFINE_SCRIPTED_PROPERTY(playerclass, S, PowerMorph)
|
DEFINE_SCRIPTED_PROPERTY(playerclass, S, PowerMorph)
|
||||||
{
|
{
|
||||||
PROP_STRING_PARM(str, 0);
|
PROP_STRING_PARM(str, 0);
|
||||||
TypedScriptVar<PClassActor*>(defaults, bag.Info, NAME_PlayerClass, NewClassPointer(RUNTIME_CLASS(APlayerPawn))) = FindClassTentativePlayerPawn(str, bag.fromDecorate);
|
defaults->PointerVar<PClassActor>(NAME_PlayerClass) = FindClassTentativePlayerPawn(str, bag.fromDecorate);
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -3027,7 +2846,7 @@ DEFINE_SCRIPTED_PROPERTY(playerclass, S, PowerMorph)
|
||||||
DEFINE_SCRIPTED_PROPERTY(morphstyle, M, PowerMorph)
|
DEFINE_SCRIPTED_PROPERTY(morphstyle, M, PowerMorph)
|
||||||
{
|
{
|
||||||
PROP_INT_PARM(i, 0);
|
PROP_INT_PARM(i, 0);
|
||||||
TypedScriptVar<int>(defaults, bag.Info, NAME_MorphStyle, TypeSInt32) = i;
|
defaults->IntVar(NAME_MorphStyle) = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -3036,7 +2855,7 @@ DEFINE_SCRIPTED_PROPERTY(morphstyle, M, PowerMorph)
|
||||||
DEFINE_SCRIPTED_PROPERTY(morphflash, S, PowerMorph)
|
DEFINE_SCRIPTED_PROPERTY(morphflash, S, PowerMorph)
|
||||||
{
|
{
|
||||||
PROP_STRING_PARM(str, 0);
|
PROP_STRING_PARM(str, 0);
|
||||||
TypedScriptVar<PClassActor*>(defaults, bag.Info, NAME_MorphFlash, NewClassPointer(RUNTIME_CLASS(AActor))) = FindClassTentative(str, RUNTIME_CLASS(AActor), bag.fromDecorate);
|
defaults->PointerVar<PClassActor>(NAME_MorphFlash) = FindClassTentative(str, RUNTIME_CLASS(AActor), bag.fromDecorate);
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -3045,7 +2864,7 @@ DEFINE_SCRIPTED_PROPERTY(morphflash, S, PowerMorph)
|
||||||
DEFINE_SCRIPTED_PROPERTY(unmorphflash, S, PowerMorph)
|
DEFINE_SCRIPTED_PROPERTY(unmorphflash, S, PowerMorph)
|
||||||
{
|
{
|
||||||
PROP_STRING_PARM(str, 0);
|
PROP_STRING_PARM(str, 0);
|
||||||
TypedScriptVar<PClassActor*>(defaults, bag.Info, NAME_UnMorphFlash, NewClassPointer(RUNTIME_CLASS(AActor))) = FindClassTentative(str, RUNTIME_CLASS(AActor), bag.fromDecorate);
|
defaults->PointerVar<PClassActor>(NAME_UnMorphFlash) = FindClassTentative(str, RUNTIME_CLASS(AActor), bag.fromDecorate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1380,6 +1380,13 @@ bool ZCCCompiler::CompileProperties(PClass *type, TArray<ZCC_Property *> &Proper
|
||||||
TArray<PField *> fields;
|
TArray<PField *> fields;
|
||||||
ZCC_Identifier *id = (ZCC_Identifier *)p->Body;
|
ZCC_Identifier *id = (ZCC_Identifier *)p->Body;
|
||||||
|
|
||||||
|
if (FName(p->NodeName) == FName("prefix") && Wads.GetLumpFile(Lump) == 0)
|
||||||
|
{
|
||||||
|
// only for internal definitions: Allow setting a prefix. This is only for compatiblity with the old DECORATE property parser, but not for general use.
|
||||||
|
prefix = id->Id;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
auto f = dyn_cast<PField>(type->Symbols.FindSymbol(id->Id, true));
|
auto f = dyn_cast<PField>(type->Symbols.FindSymbol(id->Id, true));
|
||||||
|
@ -1390,6 +1397,7 @@ bool ZCCCompiler::CompileProperties(PClass *type, TArray<ZCC_Property *> &Proper
|
||||||
fields.Push(f);
|
fields.Push(f);
|
||||||
id = (ZCC_Identifier*)id->SiblingNext;
|
id = (ZCC_Identifier*)id->SiblingNext;
|
||||||
} while (id != p->Body);
|
} while (id != p->Body);
|
||||||
|
}
|
||||||
|
|
||||||
FString qualifiedname;
|
FString qualifiedname;
|
||||||
// Store the full qualified name and prepend some 'garbage' to the name so that no conflicts with other symbol types can happen.
|
// Store the full qualified name and prepend some 'garbage' to the name so that no conflicts with other symbol types can happen.
|
||||||
|
|
|
@ -9,6 +9,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/weapons.txt"
|
#include "zscript/inventory/weapons.txt"
|
||||||
|
#include "zscript/inventory/weaponpiece.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/health.txt"
|
||||||
|
|
|
@ -42,11 +42,18 @@ struct Console native
|
||||||
native static void HideConsole();
|
native static void HideConsole();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct DamageTypeDefinition native
|
||||||
|
{
|
||||||
|
native static bool IgnoreArmor(Name type);
|
||||||
|
}
|
||||||
|
|
||||||
struct GameInfoStruct native
|
struct GameInfoStruct native
|
||||||
{
|
{
|
||||||
// will be extended as needed.
|
// will be extended as needed.
|
||||||
native Name backpacktype;
|
native Name backpacktype;
|
||||||
native double Armor2Percent;
|
native double Armor2Percent;
|
||||||
|
native String ArmorIcon1;
|
||||||
|
native String ArmorIcon2;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Object native
|
class Object native
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
**
|
**
|
||||||
**---------------------------------------------------------------------------
|
**---------------------------------------------------------------------------
|
||||||
** Copyright 2000-2016 Randy Heit
|
** Copyright 2000-2016 Randy Heit
|
||||||
** Copyright 2006-2017 Cheistoph Oelckers
|
** Copyright 2006-2017 Christoph Oelckers
|
||||||
** All rights reserved.
|
** All rights reserved.
|
||||||
**
|
**
|
||||||
** Redistribution and use in source and binary forms, with or without
|
** Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -33,10 +33,15 @@
|
||||||
**
|
**
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class Ammo : Inventory native
|
class Ammo : Inventory
|
||||||
{
|
{
|
||||||
native int BackpackAmount;
|
int BackpackAmount;
|
||||||
native int BackpackMaxAmount;
|
int BackpackMaxAmount;
|
||||||
|
/*meta*/ int DropAmount;
|
||||||
|
|
||||||
|
property BackpackAmount: BackpackAmount;
|
||||||
|
property BackpackMaxAmount: BackpackMaxAmount;
|
||||||
|
property DropAmount: DropAmount;
|
||||||
|
|
||||||
Default
|
Default
|
||||||
{
|
{
|
||||||
|
@ -44,7 +49,33 @@ class Ammo : Inventory native
|
||||||
Inventory.PickupSound "misc/ammo_pkup";
|
Inventory.PickupSound "misc/ammo_pkup";
|
||||||
}
|
}
|
||||||
|
|
||||||
native Class<Actor> GetParentAmmo ();
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// AAmmo :: GetParentAmmo
|
||||||
|
//
|
||||||
|
// Returns the least-derived ammo type that this ammo is a descendant of.
|
||||||
|
// That is, if this ammo is an immediate subclass of Ammo, then this ammo's
|
||||||
|
// type is returned. If this ammo's superclass is not Ammo, then this
|
||||||
|
// function travels up the inheritance chain until it finds a type that is
|
||||||
|
// an immediate subclass of Ammo and returns that.
|
||||||
|
//
|
||||||
|
// The intent of this is that all unique ammo types will be immediate
|
||||||
|
// subclasses of Ammo. To make different pickups with different ammo amounts,
|
||||||
|
// you subclass the type of ammo you want a different amount for and edit
|
||||||
|
// that.
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
Class<Ammo> GetParentAmmo ()
|
||||||
|
{
|
||||||
|
class<Object> type = GetClass();
|
||||||
|
|
||||||
|
while (type.GetParentClass() != "Ammo" && type.GetParentClass() != NULL)
|
||||||
|
{
|
||||||
|
type = type.GetParentClass();
|
||||||
|
}
|
||||||
|
return (class<Ammo>)(type);
|
||||||
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
|
@ -113,7 +144,7 @@ class Ammo : Inventory native
|
||||||
}
|
}
|
||||||
|
|
||||||
let type = GetParentAmmo();
|
let type = GetParentAmmo();
|
||||||
if (GetClass() == type)
|
if (GetClass() != type && type != null)
|
||||||
{
|
{
|
||||||
if (!GoAway ())
|
if (!GoAway ())
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,39 @@
|
||||||
class Armor : Inventory native
|
/*
|
||||||
|
** armor.txt
|
||||||
|
** Implements all variations of armor objects
|
||||||
|
**
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
** Copyright 2002-2016 Randy Heit
|
||||||
|
** Copyright 2006-2017 Christoph 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 Armor : Inventory
|
||||||
{
|
{
|
||||||
Default
|
Default
|
||||||
{
|
{
|
||||||
|
@ -6,32 +41,209 @@ class Armor : Inventory native
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class BasicArmor : Armor native
|
//===========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// BasicArmor
|
||||||
|
//
|
||||||
|
// Basic armor absorbs a specific percent of the damage. You should
|
||||||
|
// never pickup a BasicArmor. Instead, you pickup a BasicArmorPickup
|
||||||
|
// or BasicArmorBonus and those gives you BasicArmor when it activates.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
class BasicArmor : Armor
|
||||||
{
|
{
|
||||||
|
|
||||||
native int AbsorbCount;
|
int AbsorbCount;
|
||||||
native double SavePercent;
|
double SavePercent;
|
||||||
native int MaxAbsorb;
|
int MaxAbsorb;
|
||||||
native int MaxFullAbsorb;
|
int MaxFullAbsorb;
|
||||||
native int BonusCount;
|
int BonusCount;
|
||||||
native Name ArmorType;
|
Name ArmorType;
|
||||||
native int ActualSaveAmount;
|
int ActualSaveAmount;
|
||||||
|
|
||||||
Default
|
Default
|
||||||
{
|
{
|
||||||
|
Inventory.Amount 0;
|
||||||
+Inventory.KEEPDEPLETED
|
+Inventory.KEEPDEPLETED
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// ABasicArmor :: Tick
|
||||||
|
//
|
||||||
|
// If BasicArmor is given to the player by means other than a
|
||||||
|
// BasicArmorPickup, then it may not have an icon set. Fix that here.
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
override void Tick ()
|
||||||
|
{
|
||||||
|
Super.Tick ();
|
||||||
|
AbsorbCount = 0;
|
||||||
|
if (!Icon.isValid())
|
||||||
|
{
|
||||||
|
String icontex = gameinfo.ArmorIcon1;
|
||||||
|
|
||||||
|
if (SavePercent >= gameinfo.Armor2Percent && gameinfo.ArmorIcon2.Length() != 0)
|
||||||
|
icontex = gameinfo.ArmorIcon2;
|
||||||
|
|
||||||
|
if (icontex.Length() != 0)
|
||||||
|
Icon = TexMan.CheckForTexture (icontex, TexMan.TYPE_Any);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// ABasicArmor :: CreateCopy
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
override Inventory CreateCopy (Actor other)
|
||||||
|
{
|
||||||
|
// BasicArmor that is in use is stored in the inventory as BasicArmor.
|
||||||
|
// BasicArmor that is in reserve is not.
|
||||||
|
let copy = BasicArmor(Spawn("BasicArmor"));
|
||||||
|
copy.SavePercent = SavePercent != 0 ? SavePercent : 0.33335; // slightly more than 1/3 to avoid roundoff errors.
|
||||||
|
copy.Amount = Amount;
|
||||||
|
copy.MaxAmount = MaxAmount;
|
||||||
|
copy.Icon = Icon;
|
||||||
|
copy.BonusCount = BonusCount;
|
||||||
|
copy.ArmorType = ArmorType;
|
||||||
|
copy.ActualSaveAmount = ActualSaveAmount;
|
||||||
|
GoAwayAndDie ();
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// ABasicArmor :: HandlePickup
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
override bool HandlePickup (Inventory item)
|
||||||
|
{
|
||||||
|
if (item.GetClass() == "BasicArmor")
|
||||||
|
{
|
||||||
|
// You shouldn't be picking up BasicArmor anyway.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!item.bIgnoreSkill)
|
||||||
|
{
|
||||||
|
if (item is "BasicArmorBonus")
|
||||||
|
{
|
||||||
|
let armor = BasicArmorBonus(item);
|
||||||
|
armor.SaveAmount = int(armor.SaveAmount * G_SkillPropertyFloat(SKILLP_ArmorFactor));
|
||||||
|
}
|
||||||
|
else if (item is "BasicArmorPickup")
|
||||||
|
{
|
||||||
|
let armor = BasicArmorPickup(item);
|
||||||
|
armor.SaveAmount = int(armor.SaveAmount * G_SkillPropertyFloat(SKILLP_ArmorFactor));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// ABasicArmor :: AbsorbDamage
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
override void AbsorbDamage (int damage, Name damageType, out int newdamage)
|
||||||
|
{
|
||||||
|
int saved;
|
||||||
|
|
||||||
|
if (!DamageTypeDefinition.IgnoreArmor(damageType))
|
||||||
|
{
|
||||||
|
int full = MAX(0, MaxFullAbsorb - AbsorbCount);
|
||||||
|
|
||||||
|
if (damage < full)
|
||||||
|
{
|
||||||
|
saved = damage;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
saved = full + int((damage - full) * SavePercent);
|
||||||
|
if (MaxAbsorb > 0 && saved + AbsorbCount > MaxAbsorb)
|
||||||
|
{
|
||||||
|
saved = MAX(0, MaxAbsorb - AbsorbCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Amount < saved)
|
||||||
|
{
|
||||||
|
saved = Amount;
|
||||||
|
}
|
||||||
|
newdamage -= saved;
|
||||||
|
Amount -= saved;
|
||||||
|
AbsorbCount += saved;
|
||||||
|
if (Amount == 0)
|
||||||
|
{
|
||||||
|
// The armor has become useless
|
||||||
|
SavePercent = 0;
|
||||||
|
ArmorType = 'None'; // Not NAME_BasicArmor.
|
||||||
|
// Now see if the player has some more armor in their inventory
|
||||||
|
// and use it if so. As in Strife, the best armor is used up first.
|
||||||
|
BasicArmorPickup best = null;
|
||||||
|
Inventory probe = Owner.Inv;
|
||||||
|
while (probe != null)
|
||||||
|
{
|
||||||
|
let inInv = BasicArmorPickup(probe);
|
||||||
|
if (inInv != null)
|
||||||
|
{
|
||||||
|
if (best == null || best.SavePercent < inInv.SavePercent)
|
||||||
|
{
|
||||||
|
best = inInv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
probe = probe.Inv;
|
||||||
|
}
|
||||||
|
if (best != null)
|
||||||
|
{
|
||||||
|
Owner.UseInventory (best);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
damage = newdamage;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Once the armor has absorbed its part of the damage, then apply its damage factor, if any, to the player
|
||||||
|
if ((damage > 0) && (ArmorType != 'None')) // BasicArmor is not going to have any damage factor, so skip it.
|
||||||
|
{
|
||||||
|
ApplyDamageFactors(ArmorType, damageType, damage, damage);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class BasicArmorBonus : Armor native
|
//===========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// BasicArmorBonus
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
class BasicArmorBonus : Armor
|
||||||
{
|
{
|
||||||
native double SavePercent; // The default, for when you don't already have armor
|
double SavePercent; // The default, for when you don't already have armor
|
||||||
native int MaxSaveAmount;
|
int MaxSaveAmount;
|
||||||
native int MaxAbsorb;
|
int MaxAbsorb;
|
||||||
native int MaxFullAbsorb;
|
int MaxFullAbsorb;
|
||||||
native int SaveAmount;
|
int SaveAmount;
|
||||||
native int BonusCount;
|
int BonusCount;
|
||||||
native int BonusMax;
|
int BonusMax;
|
||||||
|
|
||||||
|
property prefix: Armor;
|
||||||
|
property MaxSaveAmount: MaxSaveAmount;
|
||||||
|
property SaveAmount : SaveAmount;
|
||||||
|
property SavePercent: SavePercent;
|
||||||
|
property MaxAbsorb: MaxAbsorb;
|
||||||
|
property MaxFullAbsorb: MaxFullAbsorb;
|
||||||
|
property MaxBonus: BonusCount;
|
||||||
|
property MaxBonusMax: BonusMax;
|
||||||
|
|
||||||
Default
|
Default
|
||||||
{
|
{
|
||||||
|
@ -40,33 +252,365 @@ class BasicArmorBonus : Armor native
|
||||||
Inventory.MaxAmount 0;
|
Inventory.MaxAmount 0;
|
||||||
Armor.SavePercent 33.335;
|
Armor.SavePercent 33.335;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// ABasicArmorBonus :: CreateCopy
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
override Inventory CreateCopy (Actor other)
|
||||||
|
{
|
||||||
|
let copy = BasicArmorBonus(Super.CreateCopy (other));
|
||||||
|
|
||||||
|
if (!bIgnoreSkill)
|
||||||
|
{
|
||||||
|
SaveAmount = int(SaveAmount * G_SkillPropertyFloat(SKILLP_ArmorFactor));
|
||||||
|
}
|
||||||
|
|
||||||
|
copy.SavePercent = SavePercent;
|
||||||
|
copy.SaveAmount = SaveAmount;
|
||||||
|
copy.MaxSaveAmount = MaxSaveAmount;
|
||||||
|
copy.BonusCount = BonusCount;
|
||||||
|
copy.BonusMax = BonusMax;
|
||||||
|
copy.MaxAbsorb = MaxAbsorb;
|
||||||
|
copy.MaxFullAbsorb = MaxFullAbsorb;
|
||||||
|
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// ABasicArmorBonus :: Use
|
||||||
|
//
|
||||||
|
// Tries to add to the amount of BasicArmor a player has.
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
override bool Use (bool pickup)
|
||||||
|
{
|
||||||
|
let armor = BasicArmor(Owner.FindInventory("BasicArmor"));
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
// This should really never happen but let's be prepared for a broken inventory.
|
||||||
|
if (armor == null)
|
||||||
|
{
|
||||||
|
armor = BasicArmor(Spawn("BasicArmor"));
|
||||||
|
armor.BecomeItem ();
|
||||||
|
armor.Amount = 0;
|
||||||
|
armor.MaxAmount = MaxSaveAmount;
|
||||||
|
Owner.AddInventory (armor);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BonusCount > 0 && armor.BonusCount < BonusMax)
|
||||||
|
{
|
||||||
|
armor.BonusCount = min(armor.BonusCount + BonusCount, BonusMax);
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int saveAmount = min(SaveAmount, MaxSaveAmount);
|
||||||
|
|
||||||
|
if (saveAmount <= 0)
|
||||||
|
{ // If it can't give you anything, it's as good as used.
|
||||||
|
return BonusCount > 0 ? result : true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If you already have more armor than this item can give you, you can't
|
||||||
|
// use it.
|
||||||
|
if (armor.Amount >= MaxSaveAmount + armor.BonusCount)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (armor.Amount <= 0)
|
||||||
|
{ // Should never be less than 0, but might as well check anyway
|
||||||
|
armor.Amount = 0;
|
||||||
|
armor.Icon = Icon;
|
||||||
|
armor.SavePercent = clamp(SavePercent, 0, 100) / 100;
|
||||||
|
armor.MaxAbsorb = MaxAbsorb;
|
||||||
|
armor.ArmorType = GetClassName();
|
||||||
|
armor.MaxFullAbsorb = MaxFullAbsorb;
|
||||||
|
armor.ActualSaveAmount = MaxSaveAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
armor.Amount = min(armor.Amount + saveAmount, MaxSaveAmount + armor.BonusCount);
|
||||||
|
armor.MaxAmount = max(armor.MaxAmount, MaxSaveAmount);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class BasicArmorPickup : Armor native
|
//===========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// BasicArmorPickup
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
class BasicArmorPickup : Armor
|
||||||
{
|
{
|
||||||
|
|
||||||
native double SavePercent;
|
double SavePercent;
|
||||||
native int MaxAbsorb;
|
int MaxAbsorb;
|
||||||
native int MaxFullAbsorb;
|
int MaxFullAbsorb;
|
||||||
native int SaveAmount;
|
int SaveAmount;
|
||||||
|
|
||||||
|
property prefix: Armor;
|
||||||
|
property SaveAmount : SaveAmount;
|
||||||
|
property SavePercent: SavePercent;
|
||||||
|
property MaxAbsorb: MaxAbsorb;
|
||||||
|
property MaxFullAbsorb: MaxFullAbsorb;
|
||||||
|
|
||||||
Default
|
Default
|
||||||
{
|
{
|
||||||
+Inventory.AUTOACTIVATE;
|
+Inventory.AUTOACTIVATE;
|
||||||
Inventory.MaxAmount 0;
|
Inventory.MaxAmount 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// ABasicArmorPickup :: CreateCopy
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
override Inventory CreateCopy (Actor other)
|
||||||
|
{
|
||||||
|
let copy = BasicArmorPickup(Super.CreateCopy (other));
|
||||||
|
|
||||||
|
if (!bIgnoreSkill)
|
||||||
|
{
|
||||||
|
SaveAmount = int(SaveAmount * G_SkillPropertyFloat(SKILLP_ArmorFactor));
|
||||||
|
}
|
||||||
|
|
||||||
|
copy.SavePercent = SavePercent;
|
||||||
|
copy.SaveAmount = SaveAmount;
|
||||||
|
copy.MaxAbsorb = MaxAbsorb;
|
||||||
|
copy.MaxFullAbsorb = MaxFullAbsorb;
|
||||||
|
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// ABasicArmorPickup :: Use
|
||||||
|
//
|
||||||
|
// Either gives you new armor or replaces the armor you already have (if
|
||||||
|
// the SaveAmount is greater than the amount of armor you own). When the
|
||||||
|
// item is auto-activated, it will only be activated if its max amount is 0
|
||||||
|
// or if you have no armor active already.
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
override bool Use (bool pickup)
|
||||||
|
{
|
||||||
|
let armor = BasicArmor(Owner.FindInventory("BasicArmor"));
|
||||||
|
|
||||||
|
// This should really never happen but let's be prepared for a broken inventory.
|
||||||
|
if (armor == null)
|
||||||
|
{
|
||||||
|
armor = BasicArmor(Spawn("BasicArmor"));
|
||||||
|
armor.BecomeItem ();
|
||||||
|
Owner.AddInventory (armor);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If you already have more armor than this item gives you, you can't
|
||||||
|
// use it.
|
||||||
|
if (armor.Amount >= SaveAmount + armor.BonusCount)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Don't use it if you're picking it up and already have some.
|
||||||
|
if (pickup && armor.Amount > 0 && MaxAmount > 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
armor.SavePercent = clamp(SavePercent, 0, 100) / 100;
|
||||||
|
armor.Amount = SaveAmount + armor.BonusCount;
|
||||||
|
armor.MaxAmount = SaveAmount;
|
||||||
|
armor.Icon = Icon;
|
||||||
|
armor.MaxAbsorb = MaxAbsorb;
|
||||||
|
armor.MaxFullAbsorb = MaxFullAbsorb;
|
||||||
|
armor.ArmorType = GetClassName();
|
||||||
|
armor.ActualSaveAmount = SaveAmount;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class HexenArmor : Armor native
|
//===========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// HexenArmor
|
||||||
|
//
|
||||||
|
// Hexen armor consists of four separate armor types plus a conceptual armor
|
||||||
|
// type (the player himself) that work together as a single armor.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
class HexenArmor : Armor
|
||||||
{
|
{
|
||||||
|
|
||||||
native double Slots[5];
|
double Slots[5];
|
||||||
native double SlotsIncrement[4];
|
double SlotsIncrement[4];
|
||||||
|
|
||||||
Default
|
Default
|
||||||
{
|
{
|
||||||
+Inventory.KEEPDEPLETED
|
+Inventory.KEEPDEPLETED
|
||||||
+Inventory.UNDROPPABLE
|
+Inventory.UNTOSSABLE
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// AHexenArmor :: CreateCopy
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
override Inventory CreateCopy (Actor other)
|
||||||
|
{
|
||||||
|
// Like BasicArmor, HexenArmor is used in the inventory but not the map.
|
||||||
|
// health is the slot this armor occupies.
|
||||||
|
// Amount is the quantity to give (0 = normal max).
|
||||||
|
let copy = HexenArmor(Spawn("HexenArmor"));
|
||||||
|
copy.AddArmorToSlot (health, Amount);
|
||||||
|
GoAwayAndDie ();
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// AHexenArmor :: CreateTossable
|
||||||
|
//
|
||||||
|
// Since this isn't really a single item, you can't drop it. Ever.
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
override Inventory CreateTossable ()
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// AHexenArmor :: HandlePickup
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
override bool HandlePickup (Inventory item)
|
||||||
|
{
|
||||||
|
if (item is "HexenArmor")
|
||||||
|
{
|
||||||
|
if (AddArmorToSlot (item.health, item.Amount))
|
||||||
|
{
|
||||||
|
item.bPickupGood = true;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// AHexenArmor :: AddArmorToSlot
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
protected bool AddArmorToSlot (int slot, int amount)
|
||||||
|
{
|
||||||
|
double hits;
|
||||||
|
|
||||||
|
if (slot < 0 || slot > 3)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (amount <= 0)
|
||||||
|
{
|
||||||
|
hits = SlotsIncrement[slot];
|
||||||
|
if (Slots[slot] < hits)
|
||||||
|
{
|
||||||
|
Slots[slot] = hits;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hits = amount * 5;
|
||||||
|
let total = Slots[0] + Slots[1] + Slots[2] + Slots[3] + Slots[4];
|
||||||
|
let max = SlotsIncrement[0] + SlotsIncrement[1] + SlotsIncrement[2] + SlotsIncrement[3] + Slots[4] + 4 * 5;
|
||||||
|
if (total < max)
|
||||||
|
{
|
||||||
|
Slots[slot] += hits;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// AHexenArmor :: AbsorbDamage
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
override void AbsorbDamage (int damage, Name damageType, out int newdamage)
|
||||||
|
{
|
||||||
|
if (!DamageTypeDefinition.IgnoreArmor(damageType))
|
||||||
|
{
|
||||||
|
double savedPercent = Slots[0] + Slots[1] + Slots[2] + Slots[3] + Slots[4];
|
||||||
|
|
||||||
|
if (savedPercent)
|
||||||
|
{ // armor absorbed some damage
|
||||||
|
if (savedPercent > 100)
|
||||||
|
{
|
||||||
|
savedPercent = 100;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
if (Slots[i])
|
||||||
|
{
|
||||||
|
// 300 damage always wipes out the armor unless some was added
|
||||||
|
// with the dragon skin bracers.
|
||||||
|
if (damage < 10000)
|
||||||
|
{
|
||||||
|
Slots[i] -= damage * SlotsIncrement[i] / 300.;
|
||||||
|
if (Slots[i] < 2)
|
||||||
|
{
|
||||||
|
Slots[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Slots[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int saved = int(damage * savedPercent / 100.);
|
||||||
|
if (saved > savedPercent*2)
|
||||||
|
{
|
||||||
|
saved = int(savedPercent*2);
|
||||||
|
}
|
||||||
|
newdamage -= saved;
|
||||||
|
damage = newdamage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// AHexenArmor :: DepleteOrDestroy
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
override void DepleteOrDestroy()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
Slots[i] = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,10 +28,8 @@ class ScoreItem : Inventory
|
||||||
//
|
//
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
class Key : Inventory native
|
class Key : Inventory
|
||||||
{
|
{
|
||||||
native uint8 KeyNumber;
|
|
||||||
|
|
||||||
Default
|
Default
|
||||||
{
|
{
|
||||||
+DONTGIB; // Don't disappear due to a crusher
|
+DONTGIB; // Don't disappear due to a crusher
|
||||||
|
|
|
@ -47,44 +47,12 @@ class Inventory : Actor native
|
||||||
virtual native bool DrawPowerup(int x, int y);
|
virtual native bool DrawPowerup(int x, int y);
|
||||||
virtual native void AbsorbDamage (int damage, Name damageType, out int newdamage);
|
virtual native void AbsorbDamage (int damage, Name damageType, out int newdamage);
|
||||||
|
|
||||||
//===========================================================================
|
native bool DoRespawn();
|
||||||
//
|
|
||||||
// AInventory :: Travelled
|
|
||||||
//
|
|
||||||
// Called when an item in somebody's inventory is carried over to another
|
|
||||||
// map, in case it needs to do special reinitialization.
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
virtual void Travelled() {}
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// AInventory :: DoEffect
|
|
||||||
//
|
|
||||||
// Handles any effect an item might apply to its owner
|
|
||||||
// Normally only used by subclasses of Powerup
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
virtual void DoEffect() {}
|
|
||||||
|
|
||||||
virtual double GetSpeedFactor() { return 1; }
|
|
||||||
virtual bool GetNoTeleportFreeze() { return false; }
|
|
||||||
virtual void ModifyDamage(int damage, Name damageType, out int newdamage, bool passive) {}
|
|
||||||
virtual void AlterWeaponSprite(VisStyle vis, in out int changed) {}
|
|
||||||
virtual void OwnerDied() {}
|
|
||||||
|
|
||||||
native bool GoAway();
|
native bool GoAway();
|
||||||
native void GoAwayAndDie();
|
native void GoAwayAndDie();
|
||||||
native void BecomeItem();
|
native void BecomeItem();
|
||||||
native void BecomePickup();
|
native void BecomePickup();
|
||||||
|
|
||||||
// These are regular functions for the item itself.
|
|
||||||
private native void A_RestoreSpecialDoomThing();
|
|
||||||
private native void A_RestoreSpecialThing1();
|
|
||||||
private native void A_RestoreSpecialThing2();
|
|
||||||
|
|
||||||
// In this case the caller function is more than a simple wrapper around the virtual method and
|
// In this case the caller function is more than a simple wrapper around the virtual method and
|
||||||
// is what must be actually called to pick up an item.
|
// is what must be actually called to pick up an item.
|
||||||
virtual protected native bool TryPickup(in out Actor toucher);
|
virtual protected native bool TryPickup(in out Actor toucher);
|
||||||
|
@ -112,6 +80,118 @@ class Inventory : Actor native
|
||||||
TNT1 A 1;
|
TNT1 A 1;
|
||||||
Stop;
|
Stop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// These are regular functions for the item itself.
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// PROC A_RestoreSpecialThing1
|
||||||
|
//
|
||||||
|
// Make a special thing visible again.
|
||||||
|
//
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void A_RestoreSpecialThing1()
|
||||||
|
{
|
||||||
|
bInvisible = false;
|
||||||
|
if (DoRespawn ())
|
||||||
|
{
|
||||||
|
A_PlaySound ("misc/spawn", CHAN_VOICE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// PROC A_RestoreSpecialThing2
|
||||||
|
//
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void A_RestoreSpecialThing2()
|
||||||
|
{
|
||||||
|
bSpecial = true;
|
||||||
|
if (!Default.bNoGravity)
|
||||||
|
{
|
||||||
|
bNoGravity = false;
|
||||||
|
}
|
||||||
|
SetState (SpawnState);
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// PROC A_RestoreSpecialDoomThing
|
||||||
|
//
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void A_RestoreSpecialDoomThing()
|
||||||
|
{
|
||||||
|
bInvisible = false;
|
||||||
|
bSpecial = true;
|
||||||
|
if (!Default.bNoGravity)
|
||||||
|
{
|
||||||
|
bNoGravity = false;
|
||||||
|
}
|
||||||
|
if (DoRespawn ())
|
||||||
|
{
|
||||||
|
SetState (SpawnState);
|
||||||
|
A_PlaySound ("misc/spawn", CHAN_VOICE);
|
||||||
|
Spawn ("ItemFog", Pos, ALLOW_REPLACE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// AInventory :: DepleteOrDestroy
|
||||||
|
//
|
||||||
|
// If the item is depleted, just change its amount to 0, otherwise it's destroyed.
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
virtual void DepleteOrDestroy ()
|
||||||
|
{
|
||||||
|
// If it's not ammo or an internal armor, destroy it.
|
||||||
|
// Ammo needs to stick around, even when it's zero for the benefit
|
||||||
|
// of the weapons that use it and to maintain the maximum ammo
|
||||||
|
// amounts a backpack might have given.
|
||||||
|
// Armor shouldn't be removed because they only work properly when
|
||||||
|
// they are the last items in the inventory.
|
||||||
|
if (bKeepDepleted)
|
||||||
|
{
|
||||||
|
Amount = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// AInventory :: Travelled
|
||||||
|
//
|
||||||
|
// Called when an item in somebody's inventory is carried over to another
|
||||||
|
// map, in case it needs to do special reinitialization.
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
virtual void Travelled() {}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// AInventory :: DoEffect
|
||||||
|
//
|
||||||
|
// Handles any effect an item might apply to its owner
|
||||||
|
// Normally only used by subclasses of Powerup
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
virtual void DoEffect() {}
|
||||||
|
|
||||||
|
virtual double GetSpeedFactor() { return 1; }
|
||||||
|
virtual bool GetNoTeleportFreeze() { return false; }
|
||||||
|
virtual void ModifyDamage(int damage, Name damageType, out int newdamage, bool passive) {}
|
||||||
|
virtual void AlterWeaponSprite(VisStyle vis, in out int changed) {}
|
||||||
|
virtual void OwnerDied() {}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class StateProvider : Inventory native
|
class StateProvider : Inventory native
|
||||||
|
|
225
wadsrc/static/zscript/inventory/weaponpiece.txt
Normal file
225
wadsrc/static/zscript/inventory/weaponpiece.txt
Normal file
|
@ -0,0 +1,225 @@
|
||||||
|
/*
|
||||||
|
** a_weaponpieces.cpp
|
||||||
|
** Implements generic weapon pieces
|
||||||
|
**
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
** Copyright 2006-2016 Cheistoph Oelckers
|
||||||
|
** Copyright 2006-2016 Randy Heit
|
||||||
|
** 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 WeaponHolder : Inventory
|
||||||
|
{
|
||||||
|
int PieceMask;
|
||||||
|
Class<Weapon> PieceWeapon;
|
||||||
|
|
||||||
|
Default
|
||||||
|
{
|
||||||
|
+NOBLOCKMAP
|
||||||
|
+NOSECTOR
|
||||||
|
+INVENTORY.UNDROPPABLE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class WeaponPiece : Inventory
|
||||||
|
{
|
||||||
|
Default
|
||||||
|
{
|
||||||
|
+WEAPONSPAWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PieceValue;
|
||||||
|
Class<Weapon> WeaponClass;
|
||||||
|
Weapon FullWeapon;
|
||||||
|
|
||||||
|
property number: PieceValue;
|
||||||
|
property weapon: WeaponClass;
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// TryPickupWeaponPiece
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
let Defaults = GetDefaultByType(WeaponClass);
|
||||||
|
|
||||||
|
bool gaveSome = !!(toucher.GiveAmmo (Defaults.AmmoType1, Defaults.AmmoGive1) +
|
||||||
|
toucher.GiveAmmo (Defaults.AmmoType2, Defaults.AmmoGive2));
|
||||||
|
|
||||||
|
if (gaveSome)
|
||||||
|
{
|
||||||
|
GoAwayAndDie ();
|
||||||
|
}
|
||||||
|
return gaveSome;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// TryPickupWeaponPiece
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
override bool TryPickup (in out Actor toucher)
|
||||||
|
{
|
||||||
|
Inventory item;
|
||||||
|
WeaponHolder hold = NULL;
|
||||||
|
bool shouldStay = ShouldStay ();
|
||||||
|
int gaveAmmo;
|
||||||
|
let Defaults = GetDefaultByType(WeaponClass);
|
||||||
|
|
||||||
|
FullWeapon = NULL;
|
||||||
|
for(item=toucher.Inv; item; item=item.Inv)
|
||||||
|
{
|
||||||
|
hold = WeaponHolder(item);
|
||||||
|
if (hold != null)
|
||||||
|
{
|
||||||
|
if (hold.PieceWeapon == WeaponClass)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
hold = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!hold)
|
||||||
|
{
|
||||||
|
hold = WeaponHolder(Spawn("WeaponHolder"));
|
||||||
|
hold.BecomeItem();
|
||||||
|
hold.AttachToOwner(toucher);
|
||||||
|
hold.PieceMask = 0;
|
||||||
|
hold.PieceWeapon = WeaponClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pieceval = 1 << (PieceValue - 1);
|
||||||
|
if (shouldStay)
|
||||||
|
{
|
||||||
|
// Cooperative net-game
|
||||||
|
if (hold.PieceMask & pieceval)
|
||||||
|
{
|
||||||
|
// 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 & pieceval)
|
||||||
|
{
|
||||||
|
// Already has the piece, check if mana needed
|
||||||
|
if (!gaveAmmo) return false;
|
||||||
|
GoAwayAndDie();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hold.PieceMask |= pieceval;
|
||||||
|
|
||||||
|
// Check if weapon assembled
|
||||||
|
if (hold.PieceMask == (1 << Defaults.health) - 1)
|
||||||
|
{
|
||||||
|
if (!toucher.FindInventory (WeaponClass))
|
||||||
|
{
|
||||||
|
FullWeapon= Weapon(Spawn(WeaponClass));
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
override bool ShouldStay ()
|
||||||
|
{
|
||||||
|
// 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.
|
||||||
|
return (((multiplayer &&
|
||||||
|
(!deathmatch && !alwaysapplydmflags)) || sv_weaponstay) && !bDropped);
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// PickupMessage
|
||||||
|
//
|
||||||
|
// Returns the message to print when this actor is picked up.
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
override String PickupMessage ()
|
||||||
|
{
|
||||||
|
if (FullWeapon)
|
||||||
|
{
|
||||||
|
return FullWeapon.PickupMessage();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return Super.PickupMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// DoPlayPickupSound
|
||||||
|
//
|
||||||
|
// Plays a sound when this actor is picked up.
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
override void PlayPickupSound (Actor toucher)
|
||||||
|
{
|
||||||
|
if (FullWeapon)
|
||||||
|
{
|
||||||
|
FullWeapon.PlayPickupSound(toucher);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Super.PlayPickupSound(toucher);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -104,27 +104,6 @@ class WeaponGiver : Weapon native
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class WeaponHolder : Inventory native
|
|
||||||
{
|
|
||||||
native int PieceMask;
|
|
||||||
native Class<Actor> PieceWeapon;
|
|
||||||
|
|
||||||
Default
|
|
||||||
{
|
|
||||||
+NOBLOCKMAP
|
|
||||||
+NOSECTOR
|
|
||||||
+INVENTORY.UNDROPPABLE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class WeaponPiece : Inventory native
|
|
||||||
{
|
|
||||||
Default
|
|
||||||
{
|
|
||||||
+WEAPONSPAWN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct WeaponSlots native
|
struct WeaponSlots native
|
||||||
{
|
{
|
||||||
native bool, int, int LocateWeapon(class<Weapon> weap);
|
native bool, int, int LocateWeapon(class<Weapon> weap);
|
||||||
|
|
|
@ -1,5 +1,28 @@
|
||||||
class DynamicLight : Actor native
|
class DynamicLight : Actor native
|
||||||
{
|
{
|
||||||
|
enum EArgs
|
||||||
|
{
|
||||||
|
LIGHT_RED = 0,
|
||||||
|
LIGHT_GREEN = 1,
|
||||||
|
LIGHT_BLUE = 2,
|
||||||
|
LIGHT_INTENSITY = 3,
|
||||||
|
LIGHT_SECONDARY_INTENSITY = 4,
|
||||||
|
LIGHT_SCALE = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ELightType
|
||||||
|
{
|
||||||
|
PointLight,
|
||||||
|
PulseLight,
|
||||||
|
FlickerLight,
|
||||||
|
RandomFlickerLight,
|
||||||
|
SectorLight,
|
||||||
|
SpotLight,
|
||||||
|
ColorPulseLight,
|
||||||
|
ColorFlickerLight,
|
||||||
|
RandomColorFlickerLight
|
||||||
|
};
|
||||||
|
|
||||||
Default
|
Default
|
||||||
{
|
{
|
||||||
Height 0;
|
Height 0;
|
||||||
|
@ -136,29 +159,6 @@ class PointLightFlickerRandomSubtractive : PointLightFlickerRandom
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class VavoomLight : DynamicLight native
|
|
||||||
{
|
|
||||||
Default
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class VavoomLightWhite : VavoomLight native
|
|
||||||
{
|
|
||||||
Default
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class VavoomLightColor : VavoomLight native
|
|
||||||
{
|
|
||||||
Default
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class PointLightAttenuated : PointLight
|
class PointLightAttenuated : PointLight
|
||||||
{
|
{
|
||||||
Default
|
Default
|
||||||
|
@ -199,3 +199,45 @@ class PointLightFlickerRandomAttenuated :PointLightFlickerRandom
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class VavoomLight : DynamicLight
|
||||||
|
{
|
||||||
|
Default
|
||||||
|
{
|
||||||
|
DynamicLight.Type "Point";
|
||||||
|
}
|
||||||
|
|
||||||
|
override void BeginPlay ()
|
||||||
|
{
|
||||||
|
if (CurSector) AddZ(-CurSector.floorplane.ZatPoint(pos.XY), false); // z is absolute for Vavoom lights
|
||||||
|
Super.BeginPlay();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class VavoomLightWhite : VavoomLight
|
||||||
|
{
|
||||||
|
override void BeginPlay ()
|
||||||
|
{
|
||||||
|
args[LIGHT_INTENSITY] = args[0] * 4;
|
||||||
|
args[LIGHT_RED] = 128;
|
||||||
|
args[LIGHT_GREEN] = 128;
|
||||||
|
args[LIGHT_BLUE] = 128;
|
||||||
|
|
||||||
|
Super.BeginPlay();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class VavoomLightColor : VavoomLight
|
||||||
|
{
|
||||||
|
override void BeginPlay ()
|
||||||
|
{
|
||||||
|
int radius = args[0] * 4;
|
||||||
|
args[LIGHT_RED] = args[1] >> 1;
|
||||||
|
args[LIGHT_GREEN] = args[2] >> 1;
|
||||||
|
args[LIGHT_BLUE] = args[3] >> 1;
|
||||||
|
args[LIGHT_INTENSITY] = radius;
|
||||||
|
Super.BeginPlay();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -138,7 +138,7 @@ class PlayerPawn : Actor native
|
||||||
native void CheckWeaponSwitch(class<Inventory> item);
|
native void CheckWeaponSwitch(class<Inventory> item);
|
||||||
}
|
}
|
||||||
|
|
||||||
class PlayerChunk : PlayerPawn native
|
class PlayerChunk : PlayerPawn
|
||||||
{
|
{
|
||||||
Default
|
Default
|
||||||
{
|
{
|
||||||
|
|
|
@ -157,8 +157,8 @@ extend class PlayerPawn
|
||||||
{
|
{
|
||||||
if (AllActorClasses[i] is "Key")
|
if (AllActorClasses[i] is "Key")
|
||||||
{
|
{
|
||||||
readonly<Key> keyitem = GetDefaultByType ((class<Key>)(AllActorClasses[i]));
|
let keyitem = GetDefaultByType (AllActorClasses[i]);
|
||||||
if (keyitem.KeyNumber != 0)
|
if (keyitem.special1 != 0)
|
||||||
{
|
{
|
||||||
let item = Inventory(Spawn(AllActorClasses[i]));
|
let item = Inventory(Spawn(AllActorClasses[i]));
|
||||||
if (!item.CallTryPickup (self))
|
if (!item.CallTryPickup (self))
|
||||||
|
|
Loading…
Reference in a new issue