From 4ff07b68eeacf5ec9262b3663569725a02e64ee1 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 22 Jun 2008 09:13:19 +0000 Subject: [PATCH] - 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) --- docs/rh-log.txt | 10 ++ src/codepointers.h | 2 + src/g_doom/a_bossbrain.cpp | 144 ++++++++++++++++++++------- src/g_level.cpp | 91 +++++++++++++++-- src/g_level.h | 22 +++- src/g_shared/a_pickups.h | 1 + src/g_shared/a_randomspawner.cpp | 86 ++++++++++++++++ src/g_shared/a_weapons.cpp | 3 +- src/g_shared/sbarinfo_display.cpp | 2 +- src/g_shared/sbarinfo_parser.cpp | 1 + src/textures/textures.h | 4 +- src/thingdef/thingdef_codeptr.cpp | 49 ++++++++- src/thingdef/thingdef_properties.cpp | 9 +- src/version.h | 2 +- wadsrc/decorate/nativeclasses.txt | 6 +- zdoom.vcproj | 7 ++ 16 files changed, 382 insertions(+), 57 deletions(-) create mode 100644 src/g_shared/a_randomspawner.cpp diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 53e82bea6b..fa4544ecdd 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -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) - Fixed: The mugshot would not reset on re-spawn. - Fixed: Picking up a weapon would sometimes not activate the grin. diff --git a/src/codepointers.h b/src/codepointers.h index 25270f6131..63e18004d1 100644 --- a/src/codepointers.h +++ b/src/codepointers.h @@ -110,3 +110,5 @@ ACTOR(LookEx) ACTOR(JumpIfTargetInLOS) ACTOR(DamageMaster) ACTOR(DamageChildren) +ACTOR(CheckForReload) +ACTOR(ResetReloadCounter) diff --git a/src/g_doom/a_bossbrain.cpp b/src/g_doom/a_bossbrain.cpp index 832c872cd4..8f96cfb601 100644 --- a/src/g_doom/a_bossbrain.cpp +++ b/src/g_doom/a_bossbrain.cpp @@ -6,6 +6,7 @@ #include "s_sound.h" #include "a_doomglobal.h" #include "statnums.h" +#include "thingdef/thingdef.h" void A_Fire (AActor *); // from m_archvile.cpp @@ -242,12 +243,18 @@ void A_BrainSpit (AActor *self) 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 - spit = P_SpawnMissile (self, targ, RUNTIME_CLASS(ASpawnShot)); + spit = P_SpawnMissile (self, targ, spawntype); if (spit != NULL) { spit->target = targ; + spit->master = self; // [RH] Do this correctly for any trajectory. Doom would divide by 0 // if the target had the same y coordinate as the spitter. if ((spit->momx | spit->momy) == 0) @@ -265,7 +272,15 @@ void A_BrainSpit (AActor *self) spit->reactiontime /= spit->state->GetTics(); } - S_Sound (self, CHAN_WEAPON, "brain/spit", 1, ATTN_NONE); + 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); + } } } @@ -275,51 +290,109 @@ void A_SpawnFly (AActor *self) AActor *fog; AActor *targ; int r; - const char *type; if (--self->reactiontime) return; // still flying targ = self->target; - // First spawn teleport fire. - fog = Spawn (targ->x, targ->y, targ->z, ALLOW_REPLACE); - S_Sound (fog, CHAN_BODY, "brain/spawn", 1, ATTN_NORM); - // Randomly select monster to spawn. - r = pr_spawnfly (); - - // Probability distribution (kind of :), - // decreasing likelihood. - if (r < 50) type = "DoomImp"; - else if (r < 90) type = "Demon"; - else if (r < 120) type = "Spectre"; - else if (r < 130) type = "PainElemental"; - else if (r < 160) type = "Cacodemon"; - else if (r < 162) type = "Archvile"; - else if (r < 172) type = "Revenant"; - else if (r < 192) type = "Arachnotron"; - else if (r < 222) type = "Fatso"; - else if (r < 246) type = "HellKnight"; - else type = "BaronOfHell"; - - newmobj = Spawn (type, targ->x, targ->y, targ->z, ALLOW_REPLACE); - if (newmobj != NULL) + const PClass *spawntype = NULL; + int index = CheckIndex (1, NULL); + // First spawn teleport fire. + if (index >= 0) { - // Make the new monster hate what the boss eye hates - AActor *eye = self->target; - - if (eye != NULL) + spawntype = PClass::FindClass ((ENamedName)StateParameters[index]); + if (spawntype != NULL) { - newmobj->CopyFriendliness (eye, false); + fog = Spawn (spawntype, targ->x, targ->y, targ->z, ALLOW_REPLACE); + if (fog != NULL) S_Sound (fog, CHAN_BODY, fog->SeeSound, 1, ATTN_NORM); } - if (newmobj->SeeState != NULL && P_LookForPlayers (newmobj, true)) - newmobj->SetState (newmobj->SeeState); + } + else + { + fog = Spawn (targ->x, targ->y, targ->z, ALLOW_REPLACE); + if (fog != NULL) S_Sound (fog, CHAN_BODY, "brain/spawn", 1, ATTN_NORM); + } - if (!(newmobj->ObjectFlags & OF_EuthanizeMe)) + 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) { - // telefrag anything in this spot - P_TeleportMove (newmobj, newmobj->x, newmobj->y, newmobj->z, true); + 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. + r = pr_spawnfly (); + + // Probability distribution (kind of :), + // decreasing likelihood. + if (r < 50) type = "DoomImp"; + else if (r < 90) type = "Demon"; + else if (r < 120) type = "Spectre"; + else if (r < 130) type = "PainElemental"; + else if (r < 160) type = "Cacodemon"; + else if (r < 162) type = "Archvile"; + else if (r < 172) type = "Revenant"; + else if (r < 192) type = "Arachnotron"; + else if (r < 222) type = "Fatso"; + else if (r < 246) type = "HellKnight"; + else type = "BaronOfHell"; + + SpawnName = type; + } + spawntype = PClass::FindClass(SpawnName); + if (spawntype != NULL) + { + newmobj = Spawn (spawntype, targ->x, targ->y, targ->z, ALLOW_REPLACE); + if (newmobj != NULL) + { + // Make the new monster hate what the boss eye hates + AActor *eye = self->target; + + if (eye != NULL) + { + newmobj->CopyFriendliness (eye, false); + } + if (newmobj->SeeState != NULL && P_LookForPlayers (newmobj, true)) + newmobj->SetState (newmobj->SeeState); + + if (!(newmobj->ObjectFlags & OF_EuthanizeMe)) + { + // telefrag anything in this spot + P_TeleportMove (newmobj, newmobj->x, newmobj->y, newmobj->z, true); + } } } @@ -375,3 +448,4 @@ void DBrainState::Serialize (FArchive &arc) arc << SerialTarget; } } + diff --git a/src/g_level.cpp b/src/g_level.cpp index 89c37337f0..cb4ecf3c60 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -108,6 +108,48 @@ static void ClearClusterInfoStrings (cluster_info_t *cinfo); static void ParseSkill (FScanner &sc); static void G_VerifySkill(); +struct FOptionalMapinfoParser +{ + const char *keyword; + MIParseFunc parsefunc; +}; + + +static TArray optmapinf(TArray::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 EndSequences; @@ -314,9 +356,6 @@ static const char *MapInfoMapLevel[] = "noinfiniteflightpowerup", "allowrespawn", "teamdamage", - "fogdensity", - "outsidefogdensity", - "skyfog", "teamplayon", "teamplayoff", "checkswitchrange", @@ -466,9 +505,6 @@ MapHandlers[] = { MITYPE_CLRFLAG, LEVEL_INFINITE_FLIGHT, 0 }, { MITYPE_SETFLAG, LEVEL_ALLOWRESPAWN, 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_FORCETEAMPLAYOFF, ~LEVEL_FORCETEAMPLAYON }, { MITYPE_SETFLAG, LEVEL_CHECKSWITCHRANGE, 0 }, @@ -632,6 +668,19 @@ static FSpecialAction *CopySpecialActions(FSpecialAction *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) { if (string != NULL) @@ -663,6 +712,12 @@ static void ClearLevelInfoStrings(level_info_t *linfo) delete spac; spac = next; } + for (FOptionalMapinfoData *spac = linfo->opdata; spac != NULL; ) + { + FOptionalMapinfoData *next = spac->Next; + delete spac; + spac = next; + } } static void ClearClusterInfoStrings(cluster_info_t *cinfo) @@ -743,6 +798,7 @@ static void G_DoParseMapInfo (int lump) CopyString(levelinfo->soundinfo); CopyString(levelinfo->sndseq); levelinfo->specialactions = CopySpecialActions(levelinfo->specialactions); + levelinfo->opdata = CopyOptData(levelinfo->opdata); if (HexenHack) { levelinfo->WallHorizLight = levelinfo->WallVertLight = 0; @@ -867,7 +923,28 @@ static void ParseMapInfoLower (FScanner &sc, sc.UnGet (); 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; switch (handler->type) { diff --git a/src/g_level.h b/src/g_level.h index 7d6d206b6b..2f003c4d96 100644 --- a/src/g_level.h +++ b/src/g_level.h @@ -136,6 +136,20 @@ struct FSpecialAction class FCompressedMemFile; 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 { char mapname[9]; @@ -187,13 +201,11 @@ struct level_info_t char *sndseq; char bordertexture[9]; - int fogdensity; - int outsidefogdensity; - int skyfog; - FSpecialAction * specialactions; - float teamdamage; + FSpecialAction * specialactions; + FOptionalMapinfoData *opdata; + }; // [RH] These get zeroed every tic and are updated by thinkers. diff --git a/src/g_shared/a_pickups.h b/src/g_shared/a_pickups.h index a19b05a50b..f9ccbe2a66 100644 --- a/src/g_shared/a_pickups.h +++ b/src/g_shared/a_pickups.h @@ -218,6 +218,7 @@ public: const PClass *AltProjectileType; // Projectile used by alternate attack int SelectionOrder; // Lower-numbered weapons get picked first fixed_t MoveCombatDist; // Used by bots, but do they *really* need it? + int ReloadCounter; // For A_CheckForReload // In-inventory instance variables TObjPtr Ammo1, Ammo2; diff --git a/src/g_shared/a_randomspawner.cpp b/src/g_shared/a_randomspawner.cpp new file mode 100644 index 0000000000..f0e646c245 --- /dev/null +++ b/src/g_shared/a_randomspawner.cpp @@ -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 + diff --git a/src/g_shared/a_weapons.cpp b/src/g_shared/a_weapons.cpp index 27742cc9ea..1ca3d179e5 100644 --- a/src/g_shared/a_weapons.cpp +++ b/src/g_shared/a_weapons.cpp @@ -53,7 +53,8 @@ void AWeapon::Serialize (FArchive &arc) << SelectionOrder << MoveCombatDist << Ammo1 << Ammo2 << SisterWeapon << GivenAsMorphWeapon - << bAltFire; + << bAltFire + << ReloadCounter; } //=========================================================================== diff --git a/src/g_shared/sbarinfo_display.cpp b/src/g_shared/sbarinfo_display.cpp index 91ba7e0772..8027ca1a3d 100644 --- a/src/g_shared/sbarinfo_display.cpp +++ b/src/g_shared/sbarinfo_display.cpp @@ -479,7 +479,7 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset, int a } else if((cmd.flags & DRAWIMAGE_INVENTORYICON)) texture = TexMan[cmd.sprite_index]; - else if(cmd.image_index > 0) + else if(cmd.image_index >= 0) texture = Images[cmd.image_index]; DrawGraphic(texture, cmd.x, cmd.y, xOffset, yOffset, alpha, !!(cmd.flags & DRAWIMAGE_TRANSLATABLE), false, !!(cmd.flags & DRAWIMAGE_OFFSET_CENTER)); diff --git a/src/g_shared/sbarinfo_parser.cpp b/src/g_shared/sbarinfo_parser.cpp index 0be4682d39..77ad4b6a51 100644 --- a/src/g_shared/sbarinfo_parser.cpp +++ b/src/g_shared/sbarinfo_parser.cpp @@ -447,6 +447,7 @@ void SBarInfo::ParseSBarInfoBlock(FScanner &sc, SBarInfoBlock &block) } else { + //sc.CheckToken(TK_Identifier); cmd.flags |= DRAWIMAGE_INVENTORYICON; const PClass* item = PClass::FindClass(sc.String); if(item == NULL || !PClass::FindClass("Inventory")->IsAncestorOf(item)) //must be a kind of Inventory diff --git a/src/textures/textures.h b/src/textures/textures.h index 369a85edbb..073a11e5b5 100644 --- a/src/textures/textures.h +++ b/src/textures/textures.h @@ -21,14 +21,14 @@ class FTextureID friend void R_InitSpriteDefs (); public: - FTextureID() {} + FTextureID() throw() {} bool isNull() const { return texnum == 0; } bool isValid() const { return texnum > 0; } bool Exists() const { return texnum >= 0; } void SetInvalid() { texnum = -1; } 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! // The switch list needs these to sort the switches by texture index diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index b446a2d72d..d156abbb96 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -1416,7 +1416,7 @@ static void InitSpawnedItem(AActor *self, AActor *mo, int flags) (deathmatch && attacker->FriendPlayer!=0 && attacker->FriendPlayer!=mo->FriendPlayer)) { // 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 *** + +//=========================================================================== +// +// 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; +} diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp index cc4d637d79..d2a581eb3b 100644 --- a/src/thingdef/thingdef_properties.cpp +++ b/src/thingdef/thingdef_properties.cpp @@ -98,7 +98,8 @@ enum DEPF_LOWGRAVITY, DEPF_LONGMELEERANGE, DEPF_SHORTMISSILERANGE, - DEPF_PICKUPFLASH + DEPF_PICKUPFLASH, + DEPF_QUARTERGRAVITY, }; static flagdef ActorFlags[]= @@ -256,7 +257,9 @@ static flagdef ActorFlags[]= DEFINE_DEPRECATED_FLAG(LOWGRAVITY), DEFINE_DEPRECATED_FLAG(SHORTMISSILERANGE), DEFINE_DEPRECATED_FLAG(LONGMELEERANGE), + DEFINE_DEPRECATED_FLAG(QUARTERGRAVITY), DEFINE_DUMMY_FLAG(NONETID), + DEFINE_DUMMY_FLAG(ALLOWCLIENTSPAWN), }; static flagdef InventoryFlags[] = @@ -292,7 +295,6 @@ static flagdef WeaponFlags[] = DEFINE_FLAG(WIF, PRIMARY_USES_BOTH, AWeapon, WeaponFlags), DEFINE_FLAG(WIF, WIMPY_WEAPON, 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_BOT, EXPLOSIVE, 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: defaults->meleethreshold = set? 196*FRACUNIT : 0; break; + case DEPF_QUARTERGRAVITY: + defaults->gravity = set? FRACUNIT/4 : FRACUNIT; + break; case DEPF_PICKUPFLASH: if (set) { diff --git a/src/version.h b/src/version.h index f2093bbe91..200f8c8123 100644 --- a/src/version.h +++ b/src/version.h @@ -75,7 +75,7 @@ // SAVESIG should match SAVEVER. // MINSAVEVER is the minimum level snapshot version that can be loaded. -#define MINSAVEVER 1036 +#define MINSAVEVER 1044 #if SVN_REVISION_NUMBER < MINSAVEVER // Never write a savegame with a version lower than what we need diff --git a/wadsrc/decorate/nativeclasses.txt b/wadsrc/decorate/nativeclasses.txt index 43d3add23b..ad3a421f6a 100644 --- a/wadsrc/decorate/nativeclasses.txt +++ b/wadsrc/decorate/nativeclasses.txt @@ -50,9 +50,9 @@ class Actor extends Thinker action native A_BrainScream(); action native A_BrainDie(); action native A_BrainAwake(); - action native A_BrainSpit(); + action native A_BrainSpit(optional class spawntype); action native A_SpawnSound(); - action native A_SpawnFly(); + action native A_SpawnFly(optional class spawntype); action native A_BrainExplode(); action native A_Die(optional name damagetype); action native A_Detonate(); @@ -215,5 +215,7 @@ class Inventory extends Actor action native A_CheckReload(); action native A_GunFlash(); action native A_Saw(optional coerce sound fullsound, optional coerce sound hitsound, optional eval int damage, optional class pufftype); + action native A_CheckForReload(eval int counter, state label); + action native A_ResetReloadCounter(); } diff --git a/zdoom.vcproj b/zdoom.vcproj index 8028d5d7be..db9dc0031f 100644 --- a/zdoom.vcproj +++ b/zdoom.vcproj @@ -55,9 +55,11 @@ EnableIntrinsicFunctions="true" FavorSizeOrSpeed="1" 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" PreprocessorDefinitions="NDEBUG,WIN32,_WIN32,_WINDOWS,USEASM,HAVE_STRUPR,HAVE_FILELENGTH" StringPooling="true" + ExceptionHandling="1" RuntimeLibrary="0" EnableFunctionLevelLinking="true" ForceConformanceInForLoopScope="true" @@ -106,6 +108,7 @@ TerminalServerAware="2" OptimizeReferences="2" EnableCOMDATFolding="2" + LinkTimeCodeGeneration="0" SetChecksum="true" /> + +