- 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:
Christoph Oelckers 2009-05-30 08:56:40 +00:00
parent 092512c44a
commit 9c4cbedc26
17 changed files with 144 additions and 87 deletions

View file

@ -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.)

View file

@ -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;

View file

@ -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])

View file

@ -74,6 +74,7 @@ enum EIWADType
IWAD_StrifeTeaser,
IWAD_StrifeTeaser2,
IWAD_FreeDoom,
IWAD_FreeDoomU,
IWAD_FreeDoom1,
IWAD_FreeDM,
IWAD_ChexQuest,

View file

@ -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;

View file

@ -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

View file

@ -414,7 +414,8 @@ enum EndTypes
END_Underwater,
END_Chess,
END_Strife,
END_BuyStrife
END_BuyStrife,
END_TitleScreen
};
struct EndSequence

View file

@ -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);

View file

@ -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

View file

@ -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;

View file

@ -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)

View file

@ -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;
}

View file

@ -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) ||

View file

@ -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)

View file

@ -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),

View file

@ -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

View file

@ -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;