mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-30 16:00:55 +00:00
- Added support for ST's QUARTERGRAVITY flag.
- Added a generalized version of Skulltag's A_CheckRailReload function. - Fixed: DrawImage didn't take 0 as a valid image index. - Added Gez's RandomSpawner submission with significant changes. - Added optional blocks for MAPINFO map definitions. ZDoom doesn't use this feature itself but it allows other ports based on ZDoom to implement their own sets of options without making such a MAPINFO unreadable by ZDoom. SVN r1044 (trunk)
This commit is contained in:
parent
b899fbeabe
commit
4ff07b68ee
16 changed files with 382 additions and 57 deletions
|
@ -1,3 +1,13 @@
|
||||||
|
June 22, 2008 (Changes by Graf Zahl)
|
||||||
|
- Added support for ST's QUARTERGRAVITY flag.
|
||||||
|
- Added a generalized version of Skulltag's A_CheckRailReload function.
|
||||||
|
- Fixed: DrawImage didn't take 0 as a valid image index.
|
||||||
|
- Added Gez's RandomSpawner submission with significant changes.
|
||||||
|
- Added optional blocks for MAPINFO map definitions. ZDoom doesn't use
|
||||||
|
this feature itself but it allows other ports based on ZDoom
|
||||||
|
to implement their own sets of options without making such a MAPINFO
|
||||||
|
unreadable by ZDoom.
|
||||||
|
|
||||||
June 16, 2008 (Changes by Graf Zahl)
|
June 16, 2008 (Changes by Graf Zahl)
|
||||||
- Fixed: The mugshot would not reset on re-spawn.
|
- Fixed: The mugshot would not reset on re-spawn.
|
||||||
- Fixed: Picking up a weapon would sometimes not activate the grin.
|
- Fixed: Picking up a weapon would sometimes not activate the grin.
|
||||||
|
|
|
@ -110,3 +110,5 @@ ACTOR(LookEx)
|
||||||
ACTOR(JumpIfTargetInLOS)
|
ACTOR(JumpIfTargetInLOS)
|
||||||
ACTOR(DamageMaster)
|
ACTOR(DamageMaster)
|
||||||
ACTOR(DamageChildren)
|
ACTOR(DamageChildren)
|
||||||
|
ACTOR(CheckForReload)
|
||||||
|
ACTOR(ResetReloadCounter)
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "s_sound.h"
|
#include "s_sound.h"
|
||||||
#include "a_doomglobal.h"
|
#include "a_doomglobal.h"
|
||||||
#include "statnums.h"
|
#include "statnums.h"
|
||||||
|
#include "thingdef/thingdef.h"
|
||||||
|
|
||||||
void A_Fire (AActor *); // from m_archvile.cpp
|
void A_Fire (AActor *); // from m_archvile.cpp
|
||||||
|
|
||||||
|
@ -242,12 +243,18 @@ void A_BrainSpit (AActor *self)
|
||||||
|
|
||||||
if (targ != NULL)
|
if (targ != NULL)
|
||||||
{
|
{
|
||||||
|
const PClass *spawntype = NULL;
|
||||||
|
int index = CheckIndex (1, NULL);
|
||||||
|
if (index >= 0) spawntype = PClass::FindClass ((ENamedName)StateParameters[index]);
|
||||||
|
if (spawntype == NULL) spawntype = RUNTIME_CLASS(ASpawnShot);
|
||||||
|
|
||||||
// spawn brain missile
|
// spawn brain missile
|
||||||
spit = P_SpawnMissile (self, targ, RUNTIME_CLASS(ASpawnShot));
|
spit = P_SpawnMissile (self, targ, spawntype);
|
||||||
|
|
||||||
if (spit != NULL)
|
if (spit != NULL)
|
||||||
{
|
{
|
||||||
spit->target = targ;
|
spit->target = targ;
|
||||||
|
spit->master = self;
|
||||||
// [RH] Do this correctly for any trajectory. Doom would divide by 0
|
// [RH] Do this correctly for any trajectory. Doom would divide by 0
|
||||||
// if the target had the same y coordinate as the spitter.
|
// if the target had the same y coordinate as the spitter.
|
||||||
if ((spit->momx | spit->momy) == 0)
|
if ((spit->momx | spit->momy) == 0)
|
||||||
|
@ -265,9 +272,17 @@ void A_BrainSpit (AActor *self)
|
||||||
spit->reactiontime /= spit->state->GetTics();
|
spit->reactiontime /= spit->state->GetTics();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (index >= 0)
|
||||||
|
{
|
||||||
|
S_Sound(self, CHAN_WEAPON, self->AttackSound, 1, ATTN_NONE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// compatibility fallback
|
||||||
S_Sound (self, CHAN_WEAPON, "brain/spit", 1, ATTN_NONE);
|
S_Sound (self, CHAN_WEAPON, "brain/spit", 1, ATTN_NONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void A_SpawnFly (AActor *self)
|
void A_SpawnFly (AActor *self)
|
||||||
{
|
{
|
||||||
|
@ -275,17 +290,69 @@ void A_SpawnFly (AActor *self)
|
||||||
AActor *fog;
|
AActor *fog;
|
||||||
AActor *targ;
|
AActor *targ;
|
||||||
int r;
|
int r;
|
||||||
const char *type;
|
|
||||||
|
|
||||||
if (--self->reactiontime)
|
if (--self->reactiontime)
|
||||||
return; // still flying
|
return; // still flying
|
||||||
|
|
||||||
targ = self->target;
|
targ = self->target;
|
||||||
|
|
||||||
// First spawn teleport fire.
|
|
||||||
fog = Spawn<ASpawnFire> (targ->x, targ->y, targ->z, ALLOW_REPLACE);
|
|
||||||
S_Sound (fog, CHAN_BODY, "brain/spawn", 1, ATTN_NORM);
|
|
||||||
|
|
||||||
|
const PClass *spawntype = NULL;
|
||||||
|
int index = CheckIndex (1, NULL);
|
||||||
|
// First spawn teleport fire.
|
||||||
|
if (index >= 0)
|
||||||
|
{
|
||||||
|
spawntype = PClass::FindClass ((ENamedName)StateParameters[index]);
|
||||||
|
if (spawntype != NULL)
|
||||||
|
{
|
||||||
|
fog = Spawn (spawntype, targ->x, targ->y, targ->z, ALLOW_REPLACE);
|
||||||
|
if (fog != NULL) S_Sound (fog, CHAN_BODY, fog->SeeSound, 1, ATTN_NORM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fog = Spawn<ASpawnFire> (targ->x, targ->y, targ->z, ALLOW_REPLACE);
|
||||||
|
if (fog != NULL) S_Sound (fog, CHAN_BODY, "brain/spawn", 1, ATTN_NORM);
|
||||||
|
}
|
||||||
|
|
||||||
|
FName SpawnName;
|
||||||
|
|
||||||
|
if (self->master != NULL)
|
||||||
|
{
|
||||||
|
FDropItem *di; // di will be our drop item list iterator
|
||||||
|
FDropItem *drop; // while drop stays as the reference point.
|
||||||
|
int n=0;
|
||||||
|
|
||||||
|
drop = di = GetDropItems(self->master->GetClass());
|
||||||
|
if (di != NULL)
|
||||||
|
{
|
||||||
|
while (di != NULL)
|
||||||
|
{
|
||||||
|
if (di->Name != NAME_None)
|
||||||
|
{
|
||||||
|
if (di->amount < 0) di->amount = 1; // default value is -1, we need a positive value.
|
||||||
|
n += di->amount; // this is how we can weight the list.
|
||||||
|
di = di->Next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
di = drop;
|
||||||
|
n = pr_spawnfly(n);
|
||||||
|
while (n > 0)
|
||||||
|
{
|
||||||
|
if (di->Name != NAME_None)
|
||||||
|
{
|
||||||
|
n -= di->amount; // logically, none of the -1 values have survived by now.
|
||||||
|
if (n > -1) di = di->Next; // If we get into the negatives, a spawnfog could be spawned...
|
||||||
|
// It would mean we've reached the end of the list of monsters.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SpawnName = di->Name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (SpawnName == NAME_None)
|
||||||
|
{
|
||||||
|
const char *type;
|
||||||
// Randomly select monster to spawn.
|
// Randomly select monster to spawn.
|
||||||
r = pr_spawnfly ();
|
r = pr_spawnfly ();
|
||||||
|
|
||||||
|
@ -303,7 +370,12 @@ void A_SpawnFly (AActor *self)
|
||||||
else if (r < 246) type = "HellKnight";
|
else if (r < 246) type = "HellKnight";
|
||||||
else type = "BaronOfHell";
|
else type = "BaronOfHell";
|
||||||
|
|
||||||
newmobj = Spawn (type, targ->x, targ->y, targ->z, ALLOW_REPLACE);
|
SpawnName = type;
|
||||||
|
}
|
||||||
|
spawntype = PClass::FindClass(SpawnName);
|
||||||
|
if (spawntype != NULL)
|
||||||
|
{
|
||||||
|
newmobj = Spawn (spawntype, targ->x, targ->y, targ->z, ALLOW_REPLACE);
|
||||||
if (newmobj != NULL)
|
if (newmobj != NULL)
|
||||||
{
|
{
|
||||||
// Make the new monster hate what the boss eye hates
|
// Make the new monster hate what the boss eye hates
|
||||||
|
@ -322,6 +394,7 @@ void A_SpawnFly (AActor *self)
|
||||||
P_TeleportMove (newmobj, newmobj->x, newmobj->y, newmobj->z, true);
|
P_TeleportMove (newmobj, newmobj->x, newmobj->y, newmobj->z, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// remove self (i.e., cube).
|
// remove self (i.e., cube).
|
||||||
self->Destroy ();
|
self->Destroy ();
|
||||||
|
@ -375,3 +448,4 @@ void DBrainState::Serialize (FArchive &arc)
|
||||||
arc << SerialTarget;
|
arc << SerialTarget;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -108,6 +108,48 @@ static void ClearClusterInfoStrings (cluster_info_t *cinfo);
|
||||||
static void ParseSkill (FScanner &sc);
|
static void ParseSkill (FScanner &sc);
|
||||||
static void G_VerifySkill();
|
static void G_VerifySkill();
|
||||||
|
|
||||||
|
struct FOptionalMapinfoParser
|
||||||
|
{
|
||||||
|
const char *keyword;
|
||||||
|
MIParseFunc parsefunc;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static TArray<FOptionalMapinfoParser> optmapinf(TArray<FOptionalMapinfoParser>::NoInit);
|
||||||
|
|
||||||
|
void AddOptionalMapinfoParser(const char *keyword, MIParseFunc parsefunc)
|
||||||
|
{
|
||||||
|
FOptionalMapinfoParser mi;
|
||||||
|
|
||||||
|
mi.keyword = keyword;
|
||||||
|
mi.parsefunc = parsefunc;
|
||||||
|
optmapinf.Push(mi);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ParseOptionalBlock(const char *keyword, FScanner &sc, level_info_t *info)
|
||||||
|
{
|
||||||
|
for(unsigned i=0;i<optmapinf.Size();i++)
|
||||||
|
{
|
||||||
|
if (!stricmp(keyword, optmapinf[i].keyword))
|
||||||
|
{
|
||||||
|
optmapinf[i].parsefunc(sc, info);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int bracecount = 0;
|
||||||
|
|
||||||
|
while (sc.GetString())
|
||||||
|
{
|
||||||
|
if (sc.Compare("{")) bracecount++;
|
||||||
|
else if (sc.Compare("}"))
|
||||||
|
{
|
||||||
|
if (--bracecount < 0) return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static FRandom pr_classchoice ("RandomPlayerClassChoice");
|
static FRandom pr_classchoice ("RandomPlayerClassChoice");
|
||||||
|
|
||||||
TArray<EndSequence> EndSequences;
|
TArray<EndSequence> EndSequences;
|
||||||
|
@ -314,9 +356,6 @@ static const char *MapInfoMapLevel[] =
|
||||||
"noinfiniteflightpowerup",
|
"noinfiniteflightpowerup",
|
||||||
"allowrespawn",
|
"allowrespawn",
|
||||||
"teamdamage",
|
"teamdamage",
|
||||||
"fogdensity",
|
|
||||||
"outsidefogdensity",
|
|
||||||
"skyfog",
|
|
||||||
"teamplayon",
|
"teamplayon",
|
||||||
"teamplayoff",
|
"teamplayoff",
|
||||||
"checkswitchrange",
|
"checkswitchrange",
|
||||||
|
@ -466,9 +505,6 @@ MapHandlers[] =
|
||||||
{ MITYPE_CLRFLAG, LEVEL_INFINITE_FLIGHT, 0 },
|
{ MITYPE_CLRFLAG, LEVEL_INFINITE_FLIGHT, 0 },
|
||||||
{ MITYPE_SETFLAG, LEVEL_ALLOWRESPAWN, 0 },
|
{ MITYPE_SETFLAG, LEVEL_ALLOWRESPAWN, 0 },
|
||||||
{ MITYPE_FLOAT, lioffset(teamdamage), 0 },
|
{ MITYPE_FLOAT, lioffset(teamdamage), 0 },
|
||||||
{ MITYPE_INT, lioffset(fogdensity), 0 },
|
|
||||||
{ MITYPE_INT, lioffset(outsidefogdensity), 0 },
|
|
||||||
{ MITYPE_INT, lioffset(skyfog), 0 },
|
|
||||||
{ MITYPE_SCFLAGS, LEVEL_FORCETEAMPLAYON, ~LEVEL_FORCETEAMPLAYOFF },
|
{ MITYPE_SCFLAGS, LEVEL_FORCETEAMPLAYON, ~LEVEL_FORCETEAMPLAYOFF },
|
||||||
{ MITYPE_SCFLAGS, LEVEL_FORCETEAMPLAYOFF, ~LEVEL_FORCETEAMPLAYON },
|
{ MITYPE_SCFLAGS, LEVEL_FORCETEAMPLAYOFF, ~LEVEL_FORCETEAMPLAYON },
|
||||||
{ MITYPE_SETFLAG, LEVEL_CHECKSWITCHRANGE, 0 },
|
{ MITYPE_SETFLAG, LEVEL_CHECKSWITCHRANGE, 0 },
|
||||||
|
@ -632,6 +668,19 @@ static FSpecialAction *CopySpecialActions(FSpecialAction *spec)
|
||||||
return spec;
|
return spec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static FOptionalMapinfoData *CopyOptData(FOptionalMapinfoData *opdata)
|
||||||
|
{
|
||||||
|
FOptionalMapinfoData **opt = &opdata;
|
||||||
|
|
||||||
|
while (*opt)
|
||||||
|
{
|
||||||
|
FOptionalMapinfoData *newop = (*opt)->Clone();
|
||||||
|
*opt = newop;
|
||||||
|
opt = &newop->Next;
|
||||||
|
}
|
||||||
|
return opdata;
|
||||||
|
}
|
||||||
|
|
||||||
static void CopyString (char *& string)
|
static void CopyString (char *& string)
|
||||||
{
|
{
|
||||||
if (string != NULL)
|
if (string != NULL)
|
||||||
|
@ -663,6 +712,12 @@ static void ClearLevelInfoStrings(level_info_t *linfo)
|
||||||
delete spac;
|
delete spac;
|
||||||
spac = next;
|
spac = next;
|
||||||
}
|
}
|
||||||
|
for (FOptionalMapinfoData *spac = linfo->opdata; spac != NULL; )
|
||||||
|
{
|
||||||
|
FOptionalMapinfoData *next = spac->Next;
|
||||||
|
delete spac;
|
||||||
|
spac = next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ClearClusterInfoStrings(cluster_info_t *cinfo)
|
static void ClearClusterInfoStrings(cluster_info_t *cinfo)
|
||||||
|
@ -743,6 +798,7 @@ static void G_DoParseMapInfo (int lump)
|
||||||
CopyString(levelinfo->soundinfo);
|
CopyString(levelinfo->soundinfo);
|
||||||
CopyString(levelinfo->sndseq);
|
CopyString(levelinfo->sndseq);
|
||||||
levelinfo->specialactions = CopySpecialActions(levelinfo->specialactions);
|
levelinfo->specialactions = CopySpecialActions(levelinfo->specialactions);
|
||||||
|
levelinfo->opdata = CopyOptData(levelinfo->opdata);
|
||||||
if (HexenHack)
|
if (HexenHack)
|
||||||
{
|
{
|
||||||
levelinfo->WallHorizLight = levelinfo->WallVertLight = 0;
|
levelinfo->WallHorizLight = levelinfo->WallVertLight = 0;
|
||||||
|
@ -867,7 +923,28 @@ static void ParseMapInfoLower (FScanner &sc,
|
||||||
sc.UnGet ();
|
sc.UnGet ();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
entry = sc.MustMatchString (strings);
|
entry = sc.MatchString (strings);
|
||||||
|
|
||||||
|
if (entry == -1)
|
||||||
|
{
|
||||||
|
FString keyword = sc.String;
|
||||||
|
sc.MustGetString();
|
||||||
|
if (levelinfo != NULL)
|
||||||
|
{
|
||||||
|
if (sc.Compare("{"))
|
||||||
|
{
|
||||||
|
ParseOptionalBlock(keyword, sc, levelinfo);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (!stricmp(keyword, "nobotnodes")) // Ignore this Skulltag option if it appears
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sc.ScriptError("Unknown keyword '%s'", keyword.GetChars());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
handler = handlers + entry;
|
handler = handlers + entry;
|
||||||
switch (handler->type)
|
switch (handler->type)
|
||||||
{
|
{
|
||||||
|
|
|
@ -136,6 +136,20 @@ struct FSpecialAction
|
||||||
class FCompressedMemFile;
|
class FCompressedMemFile;
|
||||||
class DScroller;
|
class DScroller;
|
||||||
|
|
||||||
|
class FScanner;
|
||||||
|
struct level_info_t;
|
||||||
|
typedef void (*MIParseFunc)(FScanner &sc, level_info_t *info);
|
||||||
|
|
||||||
|
void AddOptionalMapinfoParser(const char *keyword, MIParseFunc parsefunc);
|
||||||
|
|
||||||
|
struct FOptionalMapinfoData
|
||||||
|
{
|
||||||
|
FOptionalMapinfoData *Next;
|
||||||
|
FName identifier;
|
||||||
|
FOptionalMapinfoData() { Next = NULL; identifier = NAME_None; }
|
||||||
|
virtual FOptionalMapinfoData *Clone() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
struct level_info_t
|
struct level_info_t
|
||||||
{
|
{
|
||||||
char mapname[9];
|
char mapname[9];
|
||||||
|
@ -187,13 +201,11 @@ struct level_info_t
|
||||||
char *sndseq;
|
char *sndseq;
|
||||||
char bordertexture[9];
|
char bordertexture[9];
|
||||||
|
|
||||||
int fogdensity;
|
|
||||||
int outsidefogdensity;
|
|
||||||
int skyfog;
|
|
||||||
FSpecialAction * specialactions;
|
|
||||||
|
|
||||||
float teamdamage;
|
float teamdamage;
|
||||||
|
|
||||||
|
FSpecialAction * specialactions;
|
||||||
|
FOptionalMapinfoData *opdata;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// [RH] These get zeroed every tic and are updated by thinkers.
|
// [RH] These get zeroed every tic and are updated by thinkers.
|
||||||
|
|
|
@ -218,6 +218,7 @@ public:
|
||||||
const PClass *AltProjectileType; // Projectile used by alternate attack
|
const PClass *AltProjectileType; // Projectile used by alternate attack
|
||||||
int SelectionOrder; // Lower-numbered weapons get picked first
|
int SelectionOrder; // Lower-numbered weapons get picked first
|
||||||
fixed_t MoveCombatDist; // Used by bots, but do they *really* need it?
|
fixed_t MoveCombatDist; // Used by bots, but do they *really* need it?
|
||||||
|
int ReloadCounter; // For A_CheckForReload
|
||||||
|
|
||||||
// In-inventory instance variables
|
// In-inventory instance variables
|
||||||
TObjPtr<AAmmo> Ammo1, Ammo2;
|
TObjPtr<AAmmo> Ammo1, Ammo2;
|
||||||
|
|
86
src/g_shared/a_randomspawner.cpp
Normal file
86
src/g_shared/a_randomspawner.cpp
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
#include "actor.h"
|
||||||
|
#include "info.h"
|
||||||
|
#include "m_random.h"
|
||||||
|
#include "p_local.h"
|
||||||
|
#include "p_enemy.h"
|
||||||
|
#include "s_sound.h"
|
||||||
|
#include "a_doomglobal.h"
|
||||||
|
#include "statnums.h"
|
||||||
|
#include "gstrings.h"
|
||||||
|
#include "a_action.h"
|
||||||
|
#include "thingdef/thingdef.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
- in the decorate definition define multiple drop items
|
||||||
|
- use the function GetDropItems to get the first drop item, then iterate over them and count how many dropitems are defined.
|
||||||
|
- with M_Random( ) % NUMBEROFDROPITEMS you get a random drop item number (let's call it n)
|
||||||
|
- use GetDropItems again to get the first drop item, then iterate to the n-th drop item
|
||||||
|
*/
|
||||||
|
static FRandom pr_randomspawn("RandomSpawn");
|
||||||
|
|
||||||
|
class ARandomSpawner : public AActor
|
||||||
|
{
|
||||||
|
DECLARE_STATELESS_ACTOR (ARandomSpawner, AActor)
|
||||||
|
|
||||||
|
void PostBeginPlay()
|
||||||
|
{
|
||||||
|
AActor *newmobj;
|
||||||
|
FDropItem *di; // di will be our drop item list iterator
|
||||||
|
FDropItem *drop; // while drop stays as the reference point.
|
||||||
|
int n=0;
|
||||||
|
|
||||||
|
Super::PostBeginPlay();
|
||||||
|
|
||||||
|
drop = di = GetDropItems(RUNTIME_TYPE(this));
|
||||||
|
// Always make sure it actually exists.
|
||||||
|
if (di != NULL)
|
||||||
|
{
|
||||||
|
// First, we get the size of the array...
|
||||||
|
while (di != NULL)
|
||||||
|
{
|
||||||
|
if (di->Name != NAME_None)
|
||||||
|
{
|
||||||
|
if (di->amount < 0) di->amount = 1; // default value is -1, we need a positive value.
|
||||||
|
n += di->amount; // this is how we can weight the list.
|
||||||
|
di = di->Next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Then we reset the iterator to the start position...
|
||||||
|
di = drop;
|
||||||
|
// Take a random number...
|
||||||
|
n = pr_randomspawn(n);
|
||||||
|
// And iterate in the array up to the random number chosen.
|
||||||
|
while (n > 0)
|
||||||
|
{
|
||||||
|
if (di->Name != NAME_None)
|
||||||
|
{
|
||||||
|
n -= di->amount;
|
||||||
|
di = di->Next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// So now we can spawn the dropped item.
|
||||||
|
if (pr_randomspawn() <= di->probability) // prob 255 = always spawn, prob 0 = never spawn.
|
||||||
|
{
|
||||||
|
newmobj = Spawn(di->Name, x, y, z, ALLOW_REPLACE);
|
||||||
|
// copy everything relevant
|
||||||
|
newmobj->SpawnAngle = newmobj->angle = angle;
|
||||||
|
newmobj->special = special;
|
||||||
|
newmobj->args[0] = args[0];
|
||||||
|
newmobj->args[1] = args[1];
|
||||||
|
newmobj->args[2] = args[2];
|
||||||
|
newmobj->args[3] = args[3];
|
||||||
|
newmobj->args[4] = args[4];
|
||||||
|
newmobj->SpawnFlags = SpawnFlags;
|
||||||
|
newmobj->HandleSpawnFlags();
|
||||||
|
newmobj->momx = momx;
|
||||||
|
newmobj->momy = momy;
|
||||||
|
newmobj->momz = momz;
|
||||||
|
newmobj->CopyFriendliness(this, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
IMPLEMENT_STATELESS_ACTOR (ARandomSpawner, Any, -1, 0)
|
||||||
|
END_DEFAULTS
|
||||||
|
|
|
@ -53,7 +53,8 @@ void AWeapon::Serialize (FArchive &arc)
|
||||||
<< SelectionOrder
|
<< SelectionOrder
|
||||||
<< MoveCombatDist
|
<< MoveCombatDist
|
||||||
<< Ammo1 << Ammo2 << SisterWeapon << GivenAsMorphWeapon
|
<< Ammo1 << Ammo2 << SisterWeapon << GivenAsMorphWeapon
|
||||||
<< bAltFire;
|
<< bAltFire
|
||||||
|
<< ReloadCounter;
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
|
@ -479,7 +479,7 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset, int a
|
||||||
}
|
}
|
||||||
else if((cmd.flags & DRAWIMAGE_INVENTORYICON))
|
else if((cmd.flags & DRAWIMAGE_INVENTORYICON))
|
||||||
texture = TexMan[cmd.sprite_index];
|
texture = TexMan[cmd.sprite_index];
|
||||||
else if(cmd.image_index > 0)
|
else if(cmd.image_index >= 0)
|
||||||
texture = Images[cmd.image_index];
|
texture = Images[cmd.image_index];
|
||||||
|
|
||||||
DrawGraphic(texture, cmd.x, cmd.y, xOffset, yOffset, alpha, !!(cmd.flags & DRAWIMAGE_TRANSLATABLE), false, !!(cmd.flags & DRAWIMAGE_OFFSET_CENTER));
|
DrawGraphic(texture, cmd.x, cmd.y, xOffset, yOffset, alpha, !!(cmd.flags & DRAWIMAGE_TRANSLATABLE), false, !!(cmd.flags & DRAWIMAGE_OFFSET_CENTER));
|
||||||
|
|
|
@ -447,6 +447,7 @@ void SBarInfo::ParseSBarInfoBlock(FScanner &sc, SBarInfoBlock &block)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
//sc.CheckToken(TK_Identifier);
|
||||||
cmd.flags |= DRAWIMAGE_INVENTORYICON;
|
cmd.flags |= DRAWIMAGE_INVENTORYICON;
|
||||||
const PClass* item = PClass::FindClass(sc.String);
|
const PClass* item = PClass::FindClass(sc.String);
|
||||||
if(item == NULL || !PClass::FindClass("Inventory")->IsAncestorOf(item)) //must be a kind of Inventory
|
if(item == NULL || !PClass::FindClass("Inventory")->IsAncestorOf(item)) //must be a kind of Inventory
|
||||||
|
|
|
@ -21,14 +21,14 @@ class FTextureID
|
||||||
friend void R_InitSpriteDefs ();
|
friend void R_InitSpriteDefs ();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FTextureID() {}
|
FTextureID() throw() {}
|
||||||
bool isNull() const { return texnum == 0; }
|
bool isNull() const { return texnum == 0; }
|
||||||
bool isValid() const { return texnum > 0; }
|
bool isValid() const { return texnum > 0; }
|
||||||
bool Exists() const { return texnum >= 0; }
|
bool Exists() const { return texnum >= 0; }
|
||||||
void SetInvalid() { texnum = -1; }
|
void SetInvalid() { texnum = -1; }
|
||||||
bool operator ==(const FTextureID &other) const { return texnum == other.texnum; }
|
bool operator ==(const FTextureID &other) const { return texnum == other.texnum; }
|
||||||
bool operator !=(const FTextureID &other) const { return texnum != other.texnum; }
|
bool operator !=(const FTextureID &other) const { return texnum != other.texnum; }
|
||||||
FTextureID operator +(int offset);
|
FTextureID operator +(int offset) throw();
|
||||||
int GetIndex() const { return texnum; } // Use this only if you absolutely need the index!
|
int GetIndex() const { return texnum; } // Use this only if you absolutely need the index!
|
||||||
|
|
||||||
// The switch list needs these to sort the switches by texture index
|
// The switch list needs these to sort the switches by texture index
|
||||||
|
|
|
@ -1416,7 +1416,7 @@ static void InitSpawnedItem(AActor *self, AActor *mo, int flags)
|
||||||
(deathmatch && attacker->FriendPlayer!=0 && attacker->FriendPlayer!=mo->FriendPlayer))
|
(deathmatch && attacker->FriendPlayer!=0 && attacker->FriendPlayer!=mo->FriendPlayer))
|
||||||
{
|
{
|
||||||
// Target the monster which last attacked the player
|
// Target the monster which last attacked the player
|
||||||
mo->target = attacker;
|
mo->LastHeard = mo->target = attacker;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2261,3 +2261,50 @@ void A_DamageChildren(AActor * self)
|
||||||
}
|
}
|
||||||
|
|
||||||
// [KS] *** End of my modifications ***
|
// [KS] *** End of my modifications ***
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// Modified code pointer from Skulltag
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
void A_CheckForReload( AActor *self )
|
||||||
|
{
|
||||||
|
if ( self->player == NULL || self->player->ReadyWeapon == NULL )
|
||||||
|
return;
|
||||||
|
|
||||||
|
int index = CheckIndex(2);
|
||||||
|
if (index<0) return;
|
||||||
|
|
||||||
|
AWeapon *weapon = self->player->ReadyWeapon;
|
||||||
|
int count = EvalExpressionI (StateParameters[index], self);
|
||||||
|
|
||||||
|
weapon->ReloadCounter = (weapon->ReloadCounter+1) % count;
|
||||||
|
|
||||||
|
// If we have not made our last shot...
|
||||||
|
if (weapon->ReloadCounter != 0)
|
||||||
|
{
|
||||||
|
// Go back to the refire frames, instead of continuing on to the reload frames.
|
||||||
|
DoJump(self, CallingState, StateParameters[index + 1]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We need to reload. However, don't reload if we're out of ammo.
|
||||||
|
weapon->CheckAmmo( false, false );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// Resets the counter for the above function
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
void A_ResetReloadCounter(AActor *self)
|
||||||
|
{
|
||||||
|
if ( self->player == NULL || self->player->ReadyWeapon == NULL )
|
||||||
|
return;
|
||||||
|
|
||||||
|
AWeapon *weapon = self->player->ReadyWeapon;
|
||||||
|
weapon->ReloadCounter = 0;
|
||||||
|
}
|
||||||
|
|
|
@ -98,7 +98,8 @@ enum
|
||||||
DEPF_LOWGRAVITY,
|
DEPF_LOWGRAVITY,
|
||||||
DEPF_LONGMELEERANGE,
|
DEPF_LONGMELEERANGE,
|
||||||
DEPF_SHORTMISSILERANGE,
|
DEPF_SHORTMISSILERANGE,
|
||||||
DEPF_PICKUPFLASH
|
DEPF_PICKUPFLASH,
|
||||||
|
DEPF_QUARTERGRAVITY,
|
||||||
};
|
};
|
||||||
|
|
||||||
static flagdef ActorFlags[]=
|
static flagdef ActorFlags[]=
|
||||||
|
@ -256,7 +257,9 @@ static flagdef ActorFlags[]=
|
||||||
DEFINE_DEPRECATED_FLAG(LOWGRAVITY),
|
DEFINE_DEPRECATED_FLAG(LOWGRAVITY),
|
||||||
DEFINE_DEPRECATED_FLAG(SHORTMISSILERANGE),
|
DEFINE_DEPRECATED_FLAG(SHORTMISSILERANGE),
|
||||||
DEFINE_DEPRECATED_FLAG(LONGMELEERANGE),
|
DEFINE_DEPRECATED_FLAG(LONGMELEERANGE),
|
||||||
|
DEFINE_DEPRECATED_FLAG(QUARTERGRAVITY),
|
||||||
DEFINE_DUMMY_FLAG(NONETID),
|
DEFINE_DUMMY_FLAG(NONETID),
|
||||||
|
DEFINE_DUMMY_FLAG(ALLOWCLIENTSPAWN),
|
||||||
};
|
};
|
||||||
|
|
||||||
static flagdef InventoryFlags[] =
|
static flagdef InventoryFlags[] =
|
||||||
|
@ -292,7 +295,6 @@ static flagdef WeaponFlags[] =
|
||||||
DEFINE_FLAG(WIF, PRIMARY_USES_BOTH, AWeapon, WeaponFlags),
|
DEFINE_FLAG(WIF, PRIMARY_USES_BOTH, AWeapon, WeaponFlags),
|
||||||
DEFINE_FLAG(WIF, WIMPY_WEAPON, AWeapon, WeaponFlags),
|
DEFINE_FLAG(WIF, WIMPY_WEAPON, AWeapon, WeaponFlags),
|
||||||
DEFINE_FLAG(WIF, POWERED_UP, AWeapon, WeaponFlags),
|
DEFINE_FLAG(WIF, POWERED_UP, AWeapon, WeaponFlags),
|
||||||
//DEFINE_FLAG(WIF, EXTREME_DEATH, AWeapon, WeaponFlags), // this should be removed now!
|
|
||||||
DEFINE_FLAG(WIF, STAFF2_KICKBACK, AWeapon, WeaponFlags),
|
DEFINE_FLAG(WIF, STAFF2_KICKBACK, AWeapon, WeaponFlags),
|
||||||
DEFINE_FLAG(WIF_BOT, EXPLOSIVE, AWeapon, WeaponFlags),
|
DEFINE_FLAG(WIF_BOT, EXPLOSIVE, AWeapon, WeaponFlags),
|
||||||
DEFINE_FLAG2(WIF_BOT_MELEE, MELEEWEAPON, AWeapon, WeaponFlags),
|
DEFINE_FLAG2(WIF_BOT_MELEE, MELEEWEAPON, AWeapon, WeaponFlags),
|
||||||
|
@ -424,6 +426,9 @@ static void HandleDeprecatedFlags(AActor *defaults, bool set, int index)
|
||||||
case DEPF_LONGMELEERANGE:
|
case DEPF_LONGMELEERANGE:
|
||||||
defaults->meleethreshold = set? 196*FRACUNIT : 0;
|
defaults->meleethreshold = set? 196*FRACUNIT : 0;
|
||||||
break;
|
break;
|
||||||
|
case DEPF_QUARTERGRAVITY:
|
||||||
|
defaults->gravity = set? FRACUNIT/4 : FRACUNIT;
|
||||||
|
break;
|
||||||
case DEPF_PICKUPFLASH:
|
case DEPF_PICKUPFLASH:
|
||||||
if (set)
|
if (set)
|
||||||
{
|
{
|
||||||
|
|
|
@ -75,7 +75,7 @@
|
||||||
// SAVESIG should match SAVEVER.
|
// SAVESIG should match SAVEVER.
|
||||||
|
|
||||||
// MINSAVEVER is the minimum level snapshot version that can be loaded.
|
// MINSAVEVER is the minimum level snapshot version that can be loaded.
|
||||||
#define MINSAVEVER 1036
|
#define MINSAVEVER 1044
|
||||||
|
|
||||||
#if SVN_REVISION_NUMBER < MINSAVEVER
|
#if SVN_REVISION_NUMBER < MINSAVEVER
|
||||||
// Never write a savegame with a version lower than what we need
|
// Never write a savegame with a version lower than what we need
|
||||||
|
|
|
@ -50,9 +50,9 @@ class Actor extends Thinker
|
||||||
action native A_BrainScream();
|
action native A_BrainScream();
|
||||||
action native A_BrainDie();
|
action native A_BrainDie();
|
||||||
action native A_BrainAwake();
|
action native A_BrainAwake();
|
||||||
action native A_BrainSpit();
|
action native A_BrainSpit(optional class<Actor> spawntype);
|
||||||
action native A_SpawnSound();
|
action native A_SpawnSound();
|
||||||
action native A_SpawnFly();
|
action native A_SpawnFly(optional class<Actor> spawntype);
|
||||||
action native A_BrainExplode();
|
action native A_BrainExplode();
|
||||||
action native A_Die(optional name damagetype);
|
action native A_Die(optional name damagetype);
|
||||||
action native A_Detonate();
|
action native A_Detonate();
|
||||||
|
@ -215,5 +215,7 @@ class Inventory extends Actor
|
||||||
action native A_CheckReload();
|
action native A_CheckReload();
|
||||||
action native A_GunFlash();
|
action native A_GunFlash();
|
||||||
action native A_Saw(optional coerce sound fullsound, optional coerce sound hitsound, optional eval int damage, optional class<Actor> pufftype);
|
action native A_Saw(optional coerce sound fullsound, optional coerce sound hitsound, optional eval int damage, optional class<Actor> pufftype);
|
||||||
|
action native A_CheckForReload(eval int counter, state label);
|
||||||
|
action native A_ResetReloadCounter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,9 +55,11 @@
|
||||||
EnableIntrinsicFunctions="true"
|
EnableIntrinsicFunctions="true"
|
||||||
FavorSizeOrSpeed="1"
|
FavorSizeOrSpeed="1"
|
||||||
OmitFramePointers="true"
|
OmitFramePointers="true"
|
||||||
|
WholeProgramOptimization="false"
|
||||||
AdditionalIncludeDirectories="src\win32;src\sound;src;zlib;src\g_shared;src\g_doom;src\g_raven;src\g_heretic;src\g_hexen;src\g_strife;jpeg-6b;snes_spc\snes_spc"
|
AdditionalIncludeDirectories="src\win32;src\sound;src;zlib;src\g_shared;src\g_doom;src\g_raven;src\g_heretic;src\g_hexen;src\g_strife;jpeg-6b;snes_spc\snes_spc"
|
||||||
PreprocessorDefinitions="NDEBUG,WIN32,_WIN32,_WINDOWS,USEASM,HAVE_STRUPR,HAVE_FILELENGTH"
|
PreprocessorDefinitions="NDEBUG,WIN32,_WIN32,_WINDOWS,USEASM,HAVE_STRUPR,HAVE_FILELENGTH"
|
||||||
StringPooling="true"
|
StringPooling="true"
|
||||||
|
ExceptionHandling="1"
|
||||||
RuntimeLibrary="0"
|
RuntimeLibrary="0"
|
||||||
EnableFunctionLevelLinking="true"
|
EnableFunctionLevelLinking="true"
|
||||||
ForceConformanceInForLoopScope="true"
|
ForceConformanceInForLoopScope="true"
|
||||||
|
@ -106,6 +108,7 @@
|
||||||
TerminalServerAware="2"
|
TerminalServerAware="2"
|
||||||
OptimizeReferences="2"
|
OptimizeReferences="2"
|
||||||
EnableCOMDATFolding="2"
|
EnableCOMDATFolding="2"
|
||||||
|
LinkTimeCodeGeneration="0"
|
||||||
SetChecksum="true"
|
SetChecksum="true"
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
|
@ -2037,6 +2040,10 @@
|
||||||
RelativePath=".\src\g_shared\a_quake.cpp"
|
RelativePath=".\src\g_shared\a_quake.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\g_shared\a_randomspawner.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\src\g_shared\a_secrettrigger.cpp"
|
RelativePath=".\src\g_shared\a_secrettrigger.cpp"
|
||||||
>
|
>
|
||||||
|
|
Loading…
Reference in a new issue