mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-24 04:51:19 +00:00
- Added 'EndTitle' nextmap option which goes to the regular title loop after
the game has finished. - Added NOBOSSRIP flag. Note: we are now at flags6! - Added SetSkyScrollSpeed(int skyplane, fixed speed) ACS function. - Added THRUACTORS flag that disables all actor<->actor collision detection. - Added DONTSEEKINVISIBLE flag for missiles that can't home in on invisible targets. - Added SFX_TRANSFERPITCH flag to A_SpawnItemEx. - Added Ultimate Freedoom IWAD detection. - Added GetAirSupply and SetAirSupply functions to ACS. - Fixed: The *surface sound was not played when drowning was switched off by setting the level's air supply to 0. SVN r1619 (trunk)
This commit is contained in:
parent
092512c44a
commit
9c4cbedc26
17 changed files with 144 additions and 87 deletions
|
@ -1,4 +1,18 @@
|
|||
May 27, 2009
|
||||
May 30, 2009 (Changes by Graf Zahl)
|
||||
- Added 'EndTitle' nextmap option which goes to the regular title loop after
|
||||
the game has finished.
|
||||
- Added NOBOSSRIP flag. Note: we are now at flags6!
|
||||
- Added SetSkyScrollSpeed(int skyplane, fixed speed) ACS function.
|
||||
- Added THRUACTORS flag that disables all actor<->actor collision detection.
|
||||
- Added DONTSEEKINVISIBLE flag for missiles that can't home in on invisible
|
||||
targets.
|
||||
- Added SFX_TRANSFERPITCH flag to A_SpawnItemEx.
|
||||
- Added Ultimate Freedoom IWAD detection.
|
||||
- Added GetAirSupply and SetAirSupply functions to ACS.
|
||||
- Fixed: The *surface sound was not played when drowning was switched off
|
||||
by setting the level's air supply to 0.
|
||||
|
||||
May 27, 2009
|
||||
- Fixed: The mouse wheel generated no events in GUI mode if you weren't
|
||||
fullscreen. (e.g. You could no longer scroll the console with the mouse
|
||||
buffer.)
|
||||
|
|
|
@ -155,7 +155,7 @@ enum
|
|||
|
||||
MF2_DONTREFLECT = 0x00000001, // this projectile cannot be reflected
|
||||
MF2_WINDTHRUST = 0x00000002, // gets pushed around by the wind specials
|
||||
//MF2_BOUNCE1 = 0x00000004,
|
||||
MF2_DONTSEEKINVISIBLE=0x00000004, // For seeker missiles: Don't home in on invisible/shadow targets
|
||||
MF2_BLASTED = 0x00000008, // actor will temporarily take damage from impact
|
||||
MF2_FLY = 0x00000010, // fly mode is active
|
||||
MF2_FLOORCLIP = 0x00000020, // if feet are allowed to be clipped
|
||||
|
@ -176,7 +176,7 @@ enum
|
|||
MF2_NODMGTHRUST = 0x00020000, // does not thrust target when damaging
|
||||
MF2_TELESTOMP = 0x00040000, // mobj can stomp another
|
||||
MF2_FLOATBOB = 0x00080000, // use float bobbing z movement
|
||||
//MF2_BOUNCE2 = 0x00100000,
|
||||
MF2_THRUACTORS = 0x00100000, // performs no actor<->actor collision checks
|
||||
MF2_IMPACT = 0x00200000, // an MF_MISSILE mobj can activate SPAC_IMPACT
|
||||
MF2_PUSHWALL = 0x00400000, // mobj can push walls
|
||||
MF2_MCROSS = 0x00800000, // can activate monster cross lines
|
||||
|
@ -304,6 +304,8 @@ enum
|
|||
MF5_PAINLESS = 0x40000000, // Actor always inflicts painless damage.
|
||||
MF5_MOVEWITHSECTOR = 0x80000000, // P_ChangeSector() will still process this actor if it has MF_NOBLOCKMAP
|
||||
|
||||
MF6_NOBOSSRIP = 0x00000001, // For rippermissiles: Don't rip through bosses.
|
||||
|
||||
|
||||
// --- mobj.renderflags ---
|
||||
|
||||
|
@ -646,6 +648,8 @@ public:
|
|||
// Calculate amount of missile damage
|
||||
virtual int GetMissileDamage(int mask, int add);
|
||||
|
||||
bool CanSeek(AActor *target) const;
|
||||
|
||||
// info for drawing
|
||||
// NOTE: The first member variable *must* be x.
|
||||
fixed_t x,y,z;
|
||||
|
@ -683,6 +687,7 @@ public:
|
|||
DWORD flags3; // [RH] Hexen/Heretic actor-dependant behavior made flaggable
|
||||
DWORD flags4; // [RH] Even more flags!
|
||||
DWORD flags5; // OMG! We need another one.
|
||||
DWORD flags6; // Shit! Where did all the flags go?
|
||||
int special1; // Special info
|
||||
int special2; // Special info
|
||||
int health;
|
||||
|
|
|
@ -71,7 +71,8 @@ const IWADInfo IWADInfos[NUM_IWAD_TYPES] =
|
|||
{ "Strife: Teaser (Old Version)", NULL, MAKERGB(224,173,153), MAKERGB(0,107,101), GAME_Strife, "mapinfo/strife.txt", GI_MAPxx | GI_SHAREWARE },
|
||||
{ "Strife: Teaser (New Version)", NULL, MAKERGB(224,173,153), MAKERGB(0,107,101), GAME_Strife, "mapinfo/strife.txt", GI_MAPxx | GI_SHAREWARE | GI_TEASER2 },
|
||||
{ "Freedoom", "Freedoom", MAKERGB(50,84,67), MAKERGB(198,220,209), GAME_Doom, "mapinfo/doom2.txt", GI_MAPxx },
|
||||
{ "Freedoom \"Demo\"", "Freedoom1",MAKERGB(50,84,67), MAKERGB(198,220,209), GAME_Doom, "mapinfo/doom1.txt" },
|
||||
{ "Ultimate Freedoom", "Freedoom1",MAKERGB(50,84,67), MAKERGB(198,220,209), GAME_Doom, "mapinfo/doom1.txt" },
|
||||
{ "Freedoom \"Demo\"", NULL, MAKERGB(50,84,67), MAKERGB(198,220,209), GAME_Doom, "mapinfo/doom1.txt" },
|
||||
{ "FreeDM", "FreeDM", MAKERGB(50,84,67), MAKERGB(198,220,209), GAME_Doom, "mapinfo/doom2.txt", GI_MAPxx },
|
||||
{ "Chex(R) Quest", "Chex1", MAKERGB(255,255,0), MAKERGB(0,192,0), GAME_Chex, "mapinfo/chex.txt" },
|
||||
{ "Chex(R) Quest 3", "Chex3", MAKERGB(255,255,0), MAKERGB(0,192,0), GAME_Chex, "mapinfo/chex3.txt" },
|
||||
|
@ -98,6 +99,7 @@ static const char *IWADNames[] =
|
|||
"strife0.wad",
|
||||
"freedoom.wad", // Freedoom.wad is distributed as Doom2.wad, but this allows to have both in the same directory.
|
||||
"freedoom1.wad",
|
||||
"freedoomu.wad",
|
||||
"freedm.wad",
|
||||
"chex.wad",
|
||||
"chex3.wad",
|
||||
|
@ -117,6 +119,7 @@ static const char *IWADNames[] =
|
|||
"STRIFE0.WAD",
|
||||
"FREEDOOM.WAD",
|
||||
"FREEDOOM1.WAD",
|
||||
"FREEDOOMU.WAD",
|
||||
"FREEDM.WAD",
|
||||
"CHEX.WAD",
|
||||
"CHEX3.WAD",
|
||||
|
@ -211,59 +214,7 @@ static EIWADType ScanIWAD (const char *iwad)
|
|||
}
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
else if (header.Magic == ZIP_ID)
|
||||
{ // Using a zip as an IWAD replacement requires that the key lumps be in the global scope.
|
||||
// This is because most of them will be "Custom IWADs" so all that we really should need
|
||||
// to find is GAMEINFO, but why limit ourselves?
|
||||
header.NumLumps = 0;
|
||||
FileReader *reader = new FileReader(f);
|
||||
DWORD centraldir = Zip_FindCentralDir(reader);
|
||||
delete reader;
|
||||
if (fseek(f, centraldir, SEEK_SET) == 0)
|
||||
{
|
||||
// First locate directory
|
||||
FZipEndOfCentralDirectory directory;
|
||||
if (0 != fread(&directory, sizeof(directory), 1, f) && LittleLong(directory.Magic) == 0x06054b50)
|
||||
{
|
||||
header.NumLumps += LittleLong(directory.NumEntries);
|
||||
if (fseek(f, LittleLong(directory.DirectoryOffset), SEEK_SET) == 0)
|
||||
{
|
||||
// Scan directory for lumps in the global scope with key names.
|
||||
do
|
||||
{
|
||||
FZipCentralDirectoryInfo entry;
|
||||
if (0 == fread(&entry, sizeof(entry), 1, f))
|
||||
break;
|
||||
if (LittleLong(entry.Magic) == 0x02014b50)
|
||||
{
|
||||
// Now determine the lump's short name
|
||||
char* fullname = new char[LittleLong(entry.NameLength)];
|
||||
if (0 == fread(fullname, LittleLong(entry.NameLength), 1, f))
|
||||
{
|
||||
delete[] fullname;
|
||||
break;
|
||||
}
|
||||
FString name = fullname;
|
||||
delete[] fullname;
|
||||
|
||||
if(name.LastIndexOf('/') != -1)
|
||||
continue;
|
||||
name.Truncate(name.LastIndexOf('.'));
|
||||
|
||||
for (size_t j = 0; j < NUM_CHECKLUMPS; j++)
|
||||
if (strnicmp (name, checklumps[j], 8) == 0)
|
||||
lumpsfound[j]++;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
while(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
fclose (f);
|
||||
}
|
||||
|
||||
|
@ -368,9 +319,16 @@ static EIWADType ScanIWAD (const char *iwad)
|
|||
else
|
||||
{
|
||||
if (lumpsfound[Check_FreeDoom])
|
||||
{
|
||||
if (!lumpsfound[Check_e2m1])
|
||||
{
|
||||
return IWAD_FreeDoom1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return IWAD_FreeDoomU;
|
||||
}
|
||||
}
|
||||
for (i = Check_e2m1; i < NUM_CHECKLUMPS; i++)
|
||||
{
|
||||
if (!lumpsfound[i])
|
||||
|
|
|
@ -74,6 +74,7 @@ enum EIWADType
|
|||
IWAD_StrifeTeaser,
|
||||
IWAD_StrifeTeaser2,
|
||||
IWAD_FreeDoom,
|
||||
IWAD_FreeDoomU,
|
||||
IWAD_FreeDoom1,
|
||||
IWAD_FreeDM,
|
||||
IWAD_ChexQuest,
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include "g_level.h"
|
||||
#include "d_event.h"
|
||||
#include "v_palette.h"
|
||||
#include "d_main.h"
|
||||
|
||||
static void FadePic ();
|
||||
static void GetFinaleText (const char *msgLumpName);
|
||||
|
@ -1277,6 +1278,9 @@ void F_Drawer (void)
|
|||
case END_Demon:
|
||||
F_DemonScroll ();
|
||||
break;
|
||||
case END_TitleScreen:
|
||||
D_StartTitle ();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -73,7 +73,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Tracer)
|
|||
// adjust direction
|
||||
dest = self->tracer;
|
||||
|
||||
if (!dest || dest->health <= 0 || self->Speed == 0 || (dest->flags5 & MF5_CANTSEEK))
|
||||
if (!dest || dest->health <= 0 || self->Speed == 0 || !self->CanSeek(dest))
|
||||
return;
|
||||
|
||||
// change angle
|
||||
|
|
|
@ -414,7 +414,8 @@ enum EndTypes
|
|||
END_Underwater,
|
||||
END_Chess,
|
||||
END_Strife,
|
||||
END_BuyStrife
|
||||
END_BuyStrife,
|
||||
END_TitleScreen
|
||||
};
|
||||
|
||||
struct EndSequence
|
||||
|
|
|
@ -892,6 +892,11 @@ void FMapInfoParser::ParseNextMap(char *mapname)
|
|||
newSeq.EndType = END_BuyStrife;
|
||||
useseq = true;
|
||||
}
|
||||
else if (sc.Compare("endtitle"))
|
||||
{
|
||||
newSeq.EndType = END_TitleScreen;
|
||||
useseq = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy (mapname, sc.String, 8);
|
||||
|
|
|
@ -91,7 +91,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Tracer2)
|
|||
|
||||
dest = self->tracer;
|
||||
|
||||
if (!dest || dest->health <= 0 || self->Speed == 0 || (dest->flags5 & MF5_CANTSEEK))
|
||||
if (!dest || dest->health <= 0 || self->Speed == 0 || !self->CanSeek(dest))
|
||||
return;
|
||||
|
||||
// change angle
|
||||
|
|
|
@ -2796,6 +2796,9 @@ enum EACSFunctions
|
|||
ACSF_SetActivatorToTarget,
|
||||
ACSF_GetActorViewHeight,
|
||||
ACSF_GetChar,
|
||||
ACSF_GetAirSupply,
|
||||
ACSF_SetAirSupply,
|
||||
ACSF_SetSkyScrollSpeed,
|
||||
};
|
||||
|
||||
int DLevelScript::SideFromID(int id, int side)
|
||||
|
@ -2907,6 +2910,37 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args)
|
|||
}
|
||||
}
|
||||
|
||||
case ACSF_GetAirSupply:
|
||||
{
|
||||
if (args[0] < 0 || args[0] >= MAXPLAYERS || !playeringame[args[0]])
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return players[args[0]].air_finished - level.time;
|
||||
}
|
||||
}
|
||||
|
||||
case ACSF_SetAirSupply:
|
||||
{
|
||||
if (args[0] < 0 || args[0] >= MAXPLAYERS || !playeringame[args[0]])
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
players[args[0]].air_finished = args[1] + level.time;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
case ACSF_SetSkyScrollSpeed:
|
||||
{
|
||||
if (args[0] == 1) level.skyspeed1 = FIXED2FLOAT(args[1]);
|
||||
else if (args[0] == 2) level.skyspeed2 = FIXED2FLOAT(args[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -752,6 +752,9 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm)
|
|||
if (thing == tm.thing)
|
||||
return true;
|
||||
|
||||
if ((thing->flags2 | tm.thing->flags2) & MF2_THRUACTORS)
|
||||
return true;
|
||||
|
||||
if (!(thing->flags & (MF_SOLID|MF_SPECIAL|MF_SHOOTABLE)) )
|
||||
return true; // can't hit thing
|
||||
|
||||
|
@ -966,6 +969,8 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm)
|
|||
return true;
|
||||
}
|
||||
if (tm.DoRipping && !(thing->flags5 & MF5_DONTRIP))
|
||||
{
|
||||
if (!(tm.thing->flags6 & MF6_NOBOSSRIP) || !(thing->flags2 & MF2_BOSS))
|
||||
{
|
||||
if (tm.LastRipped != thing)
|
||||
{
|
||||
|
@ -994,6 +999,7 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm)
|
|||
spechit.Clear ();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Do damage
|
||||
damage = tm.thing->GetMissileDamage ((tm.thing->flags4 & MF4_STRIFEDAMAGE) ? 3 : 7, 1);
|
||||
if (damage > 0)
|
||||
|
|
|
@ -233,6 +233,7 @@ void AActor::Serialize (FArchive &arc)
|
|||
<< flags3
|
||||
<< flags4
|
||||
<< flags5
|
||||
<< flags6
|
||||
<< special1
|
||||
<< special2
|
||||
<< health
|
||||
|
@ -1403,6 +1404,26 @@ int P_FaceMobj (AActor *source, AActor *target, angle_t *delta)
|
|||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// CanSeek
|
||||
//
|
||||
// Checks if a seeker missile can home in on its target
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
bool AActor::CanSeek(AActor *target) const
|
||||
{
|
||||
if (target->flags5 & MF5_CANTSEEK) return false;
|
||||
if ((flags2 & MF2_DONTSEEKINVISIBLE) &&
|
||||
((target->flags & MF_SHADOW) ||
|
||||
target->renderflags & RF_INVISIBLE ||
|
||||
target->RenderStyle.IsVisible(target->alpha)
|
||||
)
|
||||
) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNC P_SeekerMissile
|
||||
|
@ -1421,7 +1442,7 @@ bool P_SeekerMissile (AActor *actor, angle_t thresh, angle_t turnMax)
|
|||
AActor *target;
|
||||
|
||||
target = actor->tracer;
|
||||
if (target == NULL || actor->Speed == 0 || (target->flags5 & MF5_CANTSEEK))
|
||||
if (target == NULL || actor->Speed == 0 || !actor->CanSeek(target))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -965,7 +965,8 @@ bool APlayerPawn::ResetAirSupply (bool playgasp)
|
|||
{
|
||||
S_Sound (this, CHAN_VOICE, "*gasp", 1, ATTN_NORM);
|
||||
}
|
||||
player->air_finished = level.time + level.airsupply;
|
||||
if (level.airsupply> 0) player->air_finished = level.time + level.airsupply;
|
||||
else player->air_finished = INT_MAX;
|
||||
return wasdrowning;
|
||||
}
|
||||
|
||||
|
@ -2330,7 +2331,7 @@ void P_PlayerThink (player_t *player)
|
|||
}
|
||||
|
||||
// Handle air supply
|
||||
if (level.airsupply > 0)
|
||||
//if (level.airsupply > 0)
|
||||
{
|
||||
if (player->mo->waterlevel < 3 ||
|
||||
(player->mo->flags2 & MF2_INVULNERABLE) ||
|
||||
|
|
|
@ -1296,6 +1296,7 @@ enum SIX_Flags
|
|||
SIXF_TELEFRAG=64,
|
||||
// 128 is used by Skulltag!
|
||||
SIXF_TRANSFERAMBUSHFLAG=256,
|
||||
SIXF_TRANSFERPITCH=512,
|
||||
};
|
||||
|
||||
|
||||
|
@ -1311,6 +1312,7 @@ static bool InitSpawnedItem(AActor *self, AActor *mo, int flags)
|
|||
}
|
||||
|
||||
mo->angle=self->angle;
|
||||
if (flags & SIXF_TRANSFERPITCH) mo->pitch = self->pitch;
|
||||
while (originator && isMissile(originator)) originator = originator->target;
|
||||
|
||||
if (flags & SIXF_TELEFRAG)
|
||||
|
|
|
@ -94,6 +94,7 @@ static FFlagDef ActorFlags[]=
|
|||
DEFINE_FLAG(MF, ICECORPSE, AActor, flags),
|
||||
DEFINE_FLAG(MF2, DONTREFLECT, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, WINDTHRUST, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, DONTSEEKINVISIBLE, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, BLASTED, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, FLOORCLIP, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, SPAWNFLOAT, AActor, flags2),
|
||||
|
@ -109,6 +110,7 @@ static FFlagDef ActorFlags[]=
|
|||
DEFINE_FLAG(MF2, DONTTRANSLATE, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, TELESTOMP, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, FLOATBOB, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, THRUACTORS, AActor, flags2),
|
||||
DEFINE_FLAG2(MF2_IMPACT, ACTIVATEIMPACT, AActor, flags2),
|
||||
DEFINE_FLAG2(MF2_PUSHWALL, CANPUSHWALLS, AActor, flags2),
|
||||
DEFINE_FLAG2(MF2_MCROSS, ACTIVATEMCROSS, AActor, flags2),
|
||||
|
@ -207,6 +209,8 @@ static FFlagDef ActorFlags[]=
|
|||
DEFINE_FLAG(MF5, PAINLESS, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, MOVEWITHSECTOR, AActor, flags5),
|
||||
|
||||
DEFINE_FLAG(MF6, NOBOSSRIP, AActor, flags6),
|
||||
|
||||
// Effect flags
|
||||
DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects),
|
||||
DEFINE_FLAG2(FX_ROCKET, ROCKETTRAIL, AActor, effects),
|
||||
|
|
|
@ -75,7 +75,7 @@
|
|||
// SAVESIG should match SAVEVER.
|
||||
|
||||
// MINSAVEVER is the minimum level snapshot version that can be loaded.
|
||||
#define MINSAVEVER 1599
|
||||
#define MINSAVEVER 1619
|
||||
|
||||
#if SVN_REVISION_NUMBER < MINSAVEVER
|
||||
// Never write a savegame with a version lower than what we need
|
||||
|
|
|
@ -15,6 +15,7 @@ const int SXF_NOCHECKPOSITION = 32;
|
|||
const int SXF_TELEFRAG=64;
|
||||
const int SXF_CLIENTSPAWN=128; // only used by Skulltag
|
||||
const int SXF_TRANSFERAMBUSHFLAG=256;
|
||||
const int SXF_TRANSFERPITCH=512;
|
||||
|
||||
// Flags for A_Chase
|
||||
const int CHF_FASTCHASE = 1;
|
||||
|
|
Loading…
Reference in a new issue