Merge branch 'master' into openal

This commit is contained in:
Christoph Oelckers 2015-04-24 09:21:06 +02:00
commit 1f2a431d15
318 changed files with 7825 additions and 5901 deletions

View File

@ -2,8 +2,12 @@ cmake_minimum_required( VERSION 2.4 )
project(ZDoom)
if( COMMAND cmake_policy )
if( POLICY CMP0011 )
cmake_policy( SET CMP0011 NEW )
endif( POLICY CMP0011 )
if( POLICY CMP0054 )
cmake_policy( SET CMP0054 NEW )
endif( POLICY CMP0054 )
endif( COMMAND cmake_policy )
list( APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR} )

View File

@ -44,7 +44,9 @@ if(__create_launchers)
endif()
set(__create_launchers YES)
cmake_policy( SET CMP0026 OLD )
if( POLICY CMP0026 )
cmake_policy( SET CMP0026 OLD )
endif( POLICY CMP0026 )
include(CleanDirectoryList)

View File

@ -119,6 +119,7 @@ Note: All <bool> fields default to false unless mentioned otherwise.
blockhitscan = <bool>; // Line blocks hitscan attacks
locknumber = <int>; // Line special is locked
arg0str = <string>; // Alternate string-based version of arg0
moreids = <string>; // Additional line IDs, specified as a space separated list of numbers (e.g. "2 666 1003 4505")
transparent = <bool>; // true = line is a Strife transparent line (alpha 0.25)
@ -201,6 +202,7 @@ Note: All <bool> fields default to false unless mentioned otherwise.
// sound sequence thing in the sector will override this property.
hidden = <bool>; // if true this sector will not be drawn on the textured automap.
waterzone = <bool>; // Sector is under water and swimmable
moreids = <string>; // Additional sector IDs/tags, specified as a space separated list of numbers (e.g. "2 666 1003 4505")
* Note about dropactors
@ -370,6 +372,9 @@ Added transparent line property (to be folded back to core UDMF standard), and h
Added plane equations for sector slopes. (Please read carefully to ensure proper use!)
Changed language describing the DIALOGUE lump to mention USDF as an option.
1.25 19.04.2015
Added 'moreids' for linedefs and sectors.
===============================================================================
EOF
===============================================================================

View File

@ -783,6 +783,7 @@ set( NOT_COMPILED_SOURCE_FILES
g_hexen/a_fighterquietus.cpp
g_hexen/a_firedemon.cpp
g_hexen/a_flechette.cpp
g_hexen/a_flies.cpp
g_hexen/a_fog.cpp
g_hexen/a_healingradius.cpp
g_hexen/a_heresiarch.cpp
@ -875,6 +876,7 @@ add_executable( zdoom WIN32 MACOSX_BUNDLE
f_wipe.cpp
farchive.cpp
files.cpp
g_doomedmap.cpp
g_game.cpp
g_hub.cpp
g_level.cpp
@ -935,6 +937,7 @@ add_executable( zdoom WIN32 MACOSX_BUNDLE
p_spec.cpp
p_states.cpp
p_switch.cpp
p_tags.cpp
p_teleport.cpp
p_terrain.cpp
p_things.cpp

View File

@ -1035,7 +1035,7 @@ public:
virtual bool UpdateWaterLevel (fixed_t oldz, bool splash=true);
bool isFast();
bool isSlow();
void SetIdle();
void SetIdle(bool nofunction=false);
void ClearCounters();
FState *GetRaiseState();
void Revive();

View File

@ -43,158 +43,11 @@
#include "configfile.h"
#include "i_system.h"
#include "d_event.h"
#include "w_wad.h"
#include <math.h>
#include <stdlib.h>
/* Default keybindings for Doom (and all other games)
*/
static const FBinding DefBindings[] =
{
{ "`", "toggleconsole" },
{ "1", "slot 1" },
{ "2", "slot 2" },
{ "3", "slot 3" },
{ "4", "slot 4" },
{ "5", "slot 5" },
{ "6", "slot 6" },
{ "7", "slot 7" },
{ "8", "slot 8" },
{ "9", "slot 9" },
{ "0", "slot 0" },
{ "[", "invprev" },
{ "]", "invnext" },
{ "mwheelleft", "invprev" },
{ "mwheelright", "invnext" },
{ "enter", "invuse" },
{ "-", "sizedown" },
{ "=", "sizeup" },
{ "ctrl", "+attack" },
{ "alt", "+strafe" },
{ "shift", "+speed" },
{ "space", "+use" },
{ "rightarrow", "+right" },
{ "leftarrow", "+left" },
{ "uparrow", "+forward" },
{ "downarrow", "+back" },
{ ",", "+moveleft" },
{ ".", "+moveright" },
{ "mouse1", "+attack" },
{ "mouse2", "+strafe" },
{ "mouse3", "+forward" },
{ "mouse4", "+speed" },
{ "capslock", "toggle cl_run" },
{ "f1", "menu_help" },
{ "f2", "menu_save" },
{ "f3", "menu_load" },
{ "f4", "menu_options" },
{ "f5", "menu_display" },
{ "f6", "quicksave" },
{ "f7", "menu_endgame" },
{ "f8", "togglemessages" },
{ "f9", "quickload" },
{ "f11", "bumpgamma" },
{ "f10", "menu_quit" },
{ "tab", "togglemap" },
{ "pause", "pause" },
{ "sysrq", "screenshot" },
{ "t", "messagemode" },
{ "\\", "+showscores" },
{ "f12", "spynext" },
{ "mwheeldown", "weapnext" },
{ "mwheelup", "weapprev" },
// Generic joystick buttons
{ "joy1", "+attack" },
{ "joy2", "+strafe" },
{ "joy3", "+speed" },
{ "joy4", "+use" },
// Xbox 360 / PS2 controllers
{ "pad_a", "+use" },
{ "pad_y", "+jump" },
{ "rtrigger", "+attack" },
{ "ltrigger", "+altattack" },
{ "lshoulder", "weapprev" },
{ "rshoulder", "weapnext" },
{ "dpadleft", "invprev" },
{ "dpadright", "invnext" },
{ "dpaddown", "invuse" },
{ "dpadup", "togglemap" },
{ "pad_start", "pause" },
{ "pad_back", "menu_main" },
{ "lthumb", "crouch" },
{ NULL, NULL }
};
static const FBinding DefRavenBindings[] =
{
{ "pgup", "+moveup" },
{ "ins", "+movedown" },
{ "home", "land" },
{ "pgdn", "+lookup" },
{ "del", "+lookdown" },
{ "end", "centerview" },
{ NULL, NULL }
};
static const FBinding DefHereticBindings[] =
{
{ "backspace", "use ArtiTomeOfPower" },
{ NULL, NULL }
};
static const FBinding DefHexenBindings[] =
{
{ "/", "+jump" },
{ "backspace", "invuseall" },
{ "\\", "use ArtiHealth" },
{ "0", "useflechette" },
{ "9", "use ArtiBlastRadius" },
{ "8", "use ArtiTeleport" },
{ "7", "use ArtiTeleportOther" },
{ "6", "use ArtiPork" },
{ "5", "use ArtiInvulnerability2" },
{ "scroll", "+showscores" },
{ NULL, NULL }
};
static const FBinding DefStrifeBindings[] =
{
{ "a", "+jump" },
{ "w", "showpop 1" },
{ "backspace", "invdrop" },
{ "z", "showpop 3" },
{ "k", "showpop 2" },
{ "q", "invquery" },
{ NULL, NULL }
// not done
// h - use health
};
static const FBinding DefAutomapBindings[] =
{
{ "f", "am_togglefollow" },
{ "g", "am_togglegrid" },
{ "p", "am_toggletexture" },
{ "m", "am_setmark" },
{ "c", "am_clearmarks" },
{ "0", "am_gobig" },
{ "rightarrow", "+am_panright" },
{ "leftarrow", "+am_panleft" },
{ "uparrow", "+am_panup" },
{ "downarrow", "+am_pandown" },
{ "-", "+am_zoomout" },
{ "=", "+am_zoomin" },
{ "kp-", "+am_zoomout" },
{ "kp+", "+am_zoomin" },
{ "mwheelup", "am_zoom 1.2" },
{ "mwheeldown", "am_zoom -1.2" },
{ NULL, NULL }
};
const char *KeyNames[NUM_KEYS] =
{
// This array is dependant on the particular keyboard input
@ -452,21 +305,6 @@ void FKeyBindings::DoBind (const char *key, const char *bind)
//
//=============================================================================
void FKeyBindings::SetBinds(const FBinding *binds)
{
while (binds->Key)
{
DoBind (binds->Key, binds->Bind);
binds++;
}
}
//=============================================================================
//
//
//
//=============================================================================
void FKeyBindings::UnbindAll ()
{
for (int i = 0; i < NUM_KEYS; ++i)
@ -785,29 +623,37 @@ CCMD (rebind)
void C_BindDefaults ()
{
Bindings.SetBinds (DefBindings);
int lump, lastlump = 0;
if (gameinfo.gametype & (GAME_Raven|GAME_Strife))
while ((lump = Wads.FindLump("DEFBINDS", &lastlump)) != -1)
{
Bindings.SetBinds (DefRavenBindings);
}
FScanner sc(lump);
if (gameinfo.gametype == GAME_Heretic)
while (sc.GetString())
{
Bindings.SetBinds (DefHereticBindings);
}
FKeyBindings *dest = &Bindings;
int key;
if (gameinfo.gametype == GAME_Hexen)
// bind destination is optional and is the same as the console command
if (sc.Compare("bind"))
{
Bindings.SetBinds (DefHexenBindings);
sc.MustGetString();
}
if (gameinfo.gametype == GAME_Strife)
else if (sc.Compare("doublebind"))
{
Bindings.SetBinds (DefStrifeBindings);
dest = &DoubleBindings;
sc.MustGetString();
}
else if (sc.Compare("mapbind"))
{
dest = &AutomapBindings;
sc.MustGetString();
}
key = GetConfigKeyFromName(sc.String);
sc.MustGetString();
dest->SetBind(key, sc.String);
}
}
AutomapBindings.SetBinds(DefAutomapBindings);
}
CCMD(binddefaults)

View File

@ -42,19 +42,12 @@ class FCommandLine;
void C_NameKeys (char *str, int first, int second);
struct FBinding
{
const char *Key;
const char *Bind;
};
class FKeyBindings
{
FString Binds[NUM_KEYS];
public:
void PerformBind(FCommandLine &argv, const char *msg);
void SetBinds(const FBinding *binds);
bool DoKey(event_t *ev);
void ArchiveBindings(FConfigFile *F, const char *matchcmd = NULL);
int GetKeysForCommand (const char *cmd, int *first, int *second);

View File

@ -450,11 +450,10 @@ CCMD (exec)
for (int i = 1; i < argv.argc(); ++i)
{
switch (C_ExecFile (argv[i], gamestate == GS_STARTUP))
if (!C_ExecFile(argv[i]))
{
case 1: Printf ("Could not open \"%s\"\n", argv[1]); break;
case 2: Printf ("Error parsing \"%s\"\n", argv[1]); break;
default: break;
Printf ("Could not exec \"%s\"\n", argv[i]);
break;
}
}
}
@ -641,6 +640,23 @@ CCMD (error_fatal)
}
}
//==========================================================================
//
// CCMD crashout
//
// Debugging routine for testing the crash logger.
// Useless in a win32 debug build, because that doesn't enable the crash logger.
//
//==========================================================================
#if !defined(_WIN32) || !defined(_DEBUG)
CCMD (crashout)
{
*(volatile int *)0 = 0;
}
#endif
CCMD (dir)
{
FString dir, path;
@ -889,21 +905,42 @@ CCMD(info)
"the NOBLOCKMAP flag or have height/radius of 0.\n");
}
//-----------------------------------------------------------------------------
//
//
//
//-----------------------------------------------------------------------------
CCMD(monster)
{
AActor * mo;
typedef bool (*ActorTypeChecker) (AActor *);
if (CheckCheatmode ()) return;
static bool IsActorAMonster(AActor *mo)
{
return mo->flags3&MF3_ISMONSTER && !(mo->flags&MF_CORPSE) && !(mo->flags&MF_FRIENDLY);
}
static bool IsActorAnItem(AActor *mo)
{
return mo->IsKindOf(RUNTIME_CLASS(AInventory)) && mo->flags&MF_SPECIAL;
}
static bool IsActorACountItem(AActor *mo)
{
return mo->IsKindOf(RUNTIME_CLASS(AInventory)) && mo->flags&MF_SPECIAL && mo->flags&MF_COUNTITEM;
}
static void PrintFilteredActorList(const ActorTypeChecker IsActorType, const char *FilterName)
{
AActor *mo;
const PClass *FilterClass = NULL;
if (FilterName != NULL)
{
FilterClass = PClass::FindClass(FilterName);
if (FilterClass == NULL || FilterClass->ActorInfo == NULL)
{
Printf("%s is not an actor class.\n", FilterName);
return;
}
}
TThinkerIterator<AActor> it;
while ( (mo = it.Next()) )
{
if (mo->flags3&MF3_ISMONSTER && !(mo->flags&MF_CORPSE) && !(mo->flags&MF_FRIENDLY))
if ((FilterClass == NULL || mo->IsA(FilterClass)) && IsActorType(mo))
{
Printf ("%s at (%d,%d,%d)\n",
mo->GetClass()->TypeName.GetChars(),
@ -912,6 +949,18 @@ CCMD(monster)
}
}
//-----------------------------------------------------------------------------
//
//
//
//-----------------------------------------------------------------------------
CCMD(monster)
{
if (CheckCheatmode ()) return;
PrintFilteredActorList(IsActorAMonster, argv.argc() > 1 ? argv[1] : NULL);
}
//-----------------------------------------------------------------------------
//
//
@ -919,20 +968,21 @@ CCMD(monster)
//-----------------------------------------------------------------------------
CCMD(items)
{
AActor * mo;
if (CheckCheatmode ()) return;
TThinkerIterator<AActor> it;
while ( (mo = it.Next()) )
{
if (mo->IsKindOf(RUNTIME_CLASS(AInventory)) && mo->flags&MF_SPECIAL)
{
Printf ("%s at (%d,%d,%d)\n",
mo->GetClass()->TypeName.GetChars(),
mo->x >> FRACBITS, mo->y >> FRACBITS, mo->z >> FRACBITS);
}
}
PrintFilteredActorList(IsActorAnItem, argv.argc() > 1 ? argv[1] : NULL);
}
//-----------------------------------------------------------------------------
//
//
//
//-----------------------------------------------------------------------------
CCMD(countitems)
{
if (CheckCheatmode ()) return;
PrintFilteredActorList(IsActorACountItem, argv.argc() > 1 ? argv[1] : NULL);
}
//-----------------------------------------------------------------------------

View File

@ -185,9 +185,6 @@ static const char *KeyConfCommands[] =
"clearplayerclasses"
};
static TArray<FString> StoredStartupSets;
static bool RunningStoredStartups;
// CODE --------------------------------------------------------------------
IMPLEMENT_CLASS (DWaitingCommand)
@ -540,18 +537,6 @@ void ResetButtonStates ()
}
}
void C_ExecStoredSets()
{
assert(!RunningStoredStartups);
RunningStoredStartups = true;
for (unsigned i = 0; i < StoredStartupSets.Size(); ++i)
{
C_DoCommand(StoredStartupSets[i]);
}
StoredStartupSets.Clear();
RunningStoredStartups = false;
}
void C_DoCommand (const char *cmd, int keynum)
{
FConsoleCommand *com;
@ -627,22 +612,7 @@ void C_DoCommand (const char *cmd, int keynum)
if ( (com = FindNameInHashTable (Commands, beg, len)) )
{
if (gamestate == GS_STARTUP && !RunningStoredStartups &&
len == 3 && strnicmp(beg, "set", 3) == 0)
{
// Save setting of unknown cvars for later, in case a loaded wad has a
// CVARINFO that defines it.
FCommandLine args(beg);
if (args.argc() > 1 && FindCVar(args[1], NULL) == NULL)
{
StoredStartupSets.Push(beg);
}
else
{
com->Run(args, players[consoleplayer].mo, keynum);
}
}
else if (gamestate != GS_STARTUP || ParsingKeyConf ||
if (gamestate != GS_STARTUP || ParsingKeyConf ||
(len == 3 && strnicmp (beg, "set", 3) == 0) ||
(len == 7 && strnicmp (beg, "logfile", 7) == 0) ||
(len == 9 && strnicmp (beg, "unbindall", 9) == 0) ||
@ -687,17 +657,9 @@ void C_DoCommand (const char *cmd, int keynum)
}
else
{ // We don't know how to handle this command
if (gamestate == GS_STARTUP && !RunningStoredStartups)
{
// Save it for later, in case a CVARINFO defines it.
StoredStartupSets.Push(beg);
}
else
{
Printf ("Unknown command \"%.*s\"\n", (int)len, beg);
}
}
}
}
void AddCommandString (char *cmd, int keynum)
@ -1368,7 +1330,7 @@ CCMD (key)
// Execute any console commands specified on the command line.
// These all begin with '+' as opposed to '-'.
void C_ExecCmdLineParams ()
FExecList *C_ParseCmdLineParams(FExecList *exec)
{
for (int currArg = 1; currArg < Args->NumArgs(); )
{
@ -1389,10 +1351,15 @@ void C_ExecCmdLineParams ()
cmdString = BuildString (cmdlen, Args->GetArgList (argstart));
if (!cmdString.IsEmpty())
{
C_DoCommand (&cmdString[1]);
if (exec == NULL)
{
exec = new FExecList;
}
exec->AddCommand(&cmdString[1]);
}
}
}
return exec;
}
bool FConsoleCommand::IsAlias ()
@ -1469,28 +1436,60 @@ void FConsoleAlias::SafeDelete ()
}
}
static BYTE PullinBad = 2;
static const char *PullinFile;
extern TArray<FString> allwads;
void FExecList::AddCommand(const char *cmd, const char *file)
{
// Pullins are special and need to be separated from general commands.
// They also turned out to be a really bad idea, since they make things
// more complicated. :(
if (file != NULL && strnicmp(cmd, "pullin", 6) == 0 && isspace(cmd[6]))
{
FCommandLine line(cmd);
C_SearchForPullins(this, file, line);
}
// Recursive exec: Parse this file now.
else if (strnicmp(cmd, "exec", 4) == 0 && isspace(cmd[4]))
{
FCommandLine argv(cmd);
for (int i = 1; i < argv.argc(); ++i)
{
C_ParseExecFile(argv[i], this);
}
}
else
{
Commands.Push(cmd);
}
}
int C_ExecFile (const char *file, bool usePullin)
void FExecList::ExecCommands() const
{
for (unsigned i = 0; i < Commands.Size(); ++i)
{
AddCommandString(Commands[i].LockBuffer());
Commands[i].UnlockBuffer();
}
}
void FExecList::AddPullins(TArray<FString> &wads) const
{
for (unsigned i = 0; i < Pullins.Size(); ++i)
{
D_AddFile(wads, Pullins[i]);
}
}
FExecList *C_ParseExecFile(const char *file, FExecList *exec)
{
FILE *f;
char cmd[4096];
int retval = 0;
BYTE pullinSaved = PullinBad;
const char *fileSaved = PullinFile;
if ( (f = fopen (file, "r")) )
{
PullinBad = 1-usePullin;
PullinFile = file;
while (fgets (cmd, 4095, f))
while (fgets(cmd, countof(cmd)-1, f))
{
// Comments begin with //
char *stop = cmd + strlen (cmd) - 1;
char *stop = cmd + strlen(cmd) - 1;
char *comment = cmd;
int inQuote = 0;
@ -1517,88 +1516,78 @@ int C_ExecFile (const char *file, bool usePullin)
{ // Comment in middle of line
*comment = 0;
}
AddCommandString (cmd);
}
if (!feof (f))
if (exec == NULL)
{
retval = 2;
exec = new FExecList;
}
fclose (f);
exec->AddCommand(cmd, file);
}
if (!feof(f))
{
Printf("Error parsing \"%s\"\n", file);
}
fclose(f);
}
else
{
retval = 1;
Printf ("Could not open \"%s\"\n", file);
}
return exec;
}
bool C_ExecFile (const char *file)
{
FExecList *exec = C_ParseExecFile(file, NULL);
if (exec != NULL)
{
exec->ExecCommands();
if (exec->Pullins.Size() > 0)
{
Printf(TEXTCOLOR_BOLD "Notice: Pullin files were ignored.\n");
}
delete exec;
}
return exec != NULL;
}
void C_SearchForPullins(FExecList *exec, const char *file, FCommandLine &argv)
{
const char *lastSlash;
assert(exec != NULL);
assert(file != NULL);
#ifdef __unix__
lastSlash = strrchr(file, '/');
#else
const char *lastSlash1, *lastSlash2;
lastSlash1 = strrchr(file, '/');
lastSlash2 = strrchr(file, '\\');
lastSlash = MAX(lastSlash1, lastSlash2);
#endif
for (int i = 1; i < argv.argc(); ++i)
{
// Try looking for the wad in the same directory as the .cfg
// before looking for it in the current directory.
if (lastSlash != NULL)
{
FString path(file, (lastSlash - file) + 1);
path += argv[i];
if (FileExists(path))
{
exec->Pullins.Push(path);
continue;
}
}
exec->Pullins.Push(argv[i]);
}
PullinBad = pullinSaved;
PullinFile = fileSaved;
return retval;
}
CCMD (pullin)
{
if (PullinBad == 2)
{
Printf ("This command is only valid from .cfg\n"
// Actual handling for pullin is now completely special-cased above
Printf (TEXTCOLOR_BOLD "Pullin" TEXTCOLOR_NORMAL " is only valid from .cfg\n"
"files and only when used at startup.\n");
}
else if (argv.argc() > 1)
{
const char *lastSlash;
#ifdef __unix__
lastSlash = strrchr (PullinFile, '/');
#else
const char *lastSlash1, *lastSlash2;
lastSlash1 = strrchr (PullinFile, '/');
lastSlash2 = strrchr (PullinFile, '\\');
lastSlash = MAX (lastSlash1, lastSlash2);
#endif
if (PullinBad)
{
Printf ("Not loading:");
}
for (int i = 1; i < argv.argc(); ++i)
{
if (PullinBad)
{
Printf (" %s", argv[i]);
}
else
{
// Try looking for the wad in the same directory as the .cfg
// before looking for it in the current directory.
char *path = argv[i];
if (lastSlash != NULL)
{
size_t pathlen = lastSlash - PullinFile + strlen (argv[i]) + 2;
path = new char[pathlen];
strncpy (path, PullinFile, (lastSlash - PullinFile) + 1);
strcpy (path + (lastSlash - PullinFile) + 1, argv[i]);
if (!FileExists (path))
{
delete[] path;
path = argv[i];
}
else
{
FixPathSeperator (path);
}
}
D_AddFile (allwads, path);
if (path != argv[i])
{
delete[] path;
}
}
}
if (PullinBad)
{
Printf ("\n");
}
}
}

View File

@ -39,31 +39,6 @@
class FConfigFile;
class APlayerPawn;
extern bool CheckCheatmode (bool printmsg = true);
void C_ExecCmdLineParams ();
void C_ExecStoredSets();
// Add commands to the console as if they were typed in. Can handle wait
// and semicolon-separated commands. This function may modify the source
// string, but the string will be restored to its original state before
// returning. Therefore, commands passed must not be in read-only memory.
void AddCommandString (char *text, int keynum=0);
// Process a single console command. Does not handle wait.
void C_DoCommand (const char *cmd, int keynum=0);
int C_ExecFile (const char *cmd, bool usePullin);
// Write out alias commands to a file for all current aliases.
void C_ArchiveAliases (FConfigFile *f);
void C_SetAlias (const char *name, const char *cmd);
void C_ClearAliases ();
// build a single string out of multiple strings
FString BuildString (int argc, FString *argv);
// Class that can parse command lines
class FCommandLine
{
@ -83,6 +58,44 @@ private:
bool noescapes;
};
// Contains the contents of an exec'ed file
struct FExecList
{
TArray<FString> Commands;
TArray<FString> Pullins;
void AddCommand(const char *cmd, const char *file = NULL);
void ExecCommands() const;
void AddPullins(TArray<FString> &wads) const;
};
extern bool CheckCheatmode (bool printmsg = true);
FExecList *C_ParseCmdLineParams(FExecList *exec);
// Add commands to the console as if they were typed in. Can handle wait
// and semicolon-separated commands. This function may modify the source
// string, but the string will be restored to its original state before
// returning. Therefore, commands passed must not be in read-only memory.
void AddCommandString (char *text, int keynum=0);
// Process a single console command. Does not handle wait.
void C_DoCommand (const char *cmd, int keynum=0);
FExecList *C_ParseExecFile(const char *file, FExecList *source);
void C_SearchForPullins(FExecList *exec, const char *file, class FCommandLine &args);
bool C_ExecFile(const char *file);
// Write out alias commands to a file for all current aliases.
void C_ArchiveAliases (FConfigFile *f);
void C_SetAlias (const char *name, const char *cmd);
void C_ClearAliases ();
// build a single string out of multiple strings
FString BuildString (int argc, FString *argv);
typedef void (*CCmdRun) (FCommandLine &argv, APlayerPawn *instigator, int key);
class FConsoleCommand

View File

@ -957,7 +957,7 @@ void ScanDirectory(TArray<FFileList> &list, const char *dirpath)
}
}
#elif defined(__sun) || defined(linux)
#elif defined(__sun) || defined(__linux__)
//==========================================================================
//

View File

@ -49,6 +49,7 @@
#include "gi.h"
#include "g_level.h"
#include "p_lnspec.h"
#include "p_tags.h"
#include "r_state.h"
#include "w_wad.h"
@ -551,7 +552,8 @@ void SetCompatibilityParams()
{
if ((unsigned)CompatParams[i + 1] < (unsigned)numsectors)
{
sectors[CompatParams[i + 1]].tag = CompatParams[i + 2];
// this assumes that the sector does not have any tags yet!
tagManager.AddSectorTag(CompatParams[i + 1], CompatParams[i + 2]);
}
i += 3;
break;
@ -595,12 +597,13 @@ CCMD (mapchecksum)
else
{
map->GetChecksum(cksum);
const char *wadname = Wads.GetWadName(Wads.GetLumpFile(map->lumpnum));
delete map;
for (size_t j = 0; j < sizeof(cksum); ++j)
{
Printf("%02X", cksum[j]);
}
Printf(" // %s\n", argv[i]);
Printf(" // %s %s\n", wadname, argv[i]);
}
}
}

View File

@ -66,15 +66,13 @@ FConfigFile::FConfigFile ()
//
//====================================================================
FConfigFile::FConfigFile (const char *pathname,
void (*nosechandler)(const char *pathname, FConfigFile *config, void *userdata),
void *userdata)
FConfigFile::FConfigFile (const char *pathname)
{
Sections = CurrentSection = NULL;
LastSectionPtr = &Sections;
CurrentEntry = NULL;
ChangePathName (pathname);
LoadConfigFile (nosechandler, userdata);
LoadConfigFile ();
OkayToWrite = true;
FileExisted = true;
}
@ -118,8 +116,7 @@ FConfigFile::~FConfigFile ()
delete[] (char *)entry;
entry = nextentry;
}
section->~FConfigSection();
delete[] (char *)section;
delete section;
section = nextsection;
}
}
@ -140,7 +137,7 @@ FConfigFile &FConfigFile::operator = (const FConfigFile &other)
while (fromsection != NULL)
{
fromentry = fromsection->RootEntry;
tosection = NewConfigSection (fromsection->Name);
tosection = NewConfigSection (fromsection->SectionName);
while (fromentry != NULL)
{
NewConfigEntry (tosection, fromentry->Key, fromentry->Value);
@ -311,7 +308,7 @@ const char *FConfigFile::GetCurrentSection () const
{
if (CurrentSection != NULL)
{
return CurrentSection->Name;
return CurrentSection->SectionName.GetChars();
}
return NULL;
}
@ -508,13 +505,29 @@ FConfigFile::FConfigSection *FConfigFile::FindSection (const char *name) const
{
FConfigSection *section = Sections;
while (section != NULL && stricmp (section->Name, name) != 0)
while (section != NULL && section->SectionName.CompareNoCase(name) != 0)
{
section = section->Next;
}
return section;
}
//====================================================================
//
// FConfigFile :: RenameSection
//
//====================================================================
void FConfigFile::RenameSection (const char *oldname, const char *newname) const
{
FConfigSection *section = FindSection(oldname);
if (section != NULL)
{
section->SectionName = newname;
}
}
//====================================================================
//
// FConfigFile :: FindEntry
@ -542,19 +555,15 @@ FConfigFile::FConfigEntry *FConfigFile::FindEntry (
FConfigFile::FConfigSection *FConfigFile::NewConfigSection (const char *name)
{
FConfigSection *section;
char *memblock;
section = FindSection (name);
if (section == NULL)
{
size_t namelen = strlen (name);
memblock = new char[sizeof(*section)+namelen];
section = ::new(memblock) FConfigSection;
section = new FConfigSection;
section->RootEntry = NULL;
section->LastEntryPtr = &section->RootEntry;
section->Next = NULL;
memcpy (section->Name, name, namelen);
section->Name[namelen] = 0;
section->SectionName = name;
*LastSectionPtr = section;
LastSectionPtr = &section->Next;
}
@ -591,7 +600,7 @@ FConfigFile::FConfigEntry *FConfigFile::NewConfigEntry (
//
//====================================================================
void FConfigFile::LoadConfigFile (void (*nosechandler)(const char *pathname, FConfigFile *config, void *userdata), void *userdata)
void FConfigFile::LoadConfigFile ()
{
FILE *file = fopen (PathName, "r");
bool succ;
@ -605,14 +614,6 @@ void FConfigFile::LoadConfigFile (void (*nosechandler)(const char *pathname, FCo
succ = ReadConfig (file);
fclose (file);
FileExisted = succ;
if (!succ)
{ // First valid line did not define a section
if (nosechandler != NULL)
{
nosechandler (PathName, this, userdata);
}
}
}
//====================================================================
@ -787,7 +788,7 @@ bool FConfigFile::WriteConfigFile () const
{
fputs (section->Note.GetChars(), file);
}
fprintf (file, "[%s]\n", section->Name);
fprintf (file, "[%s]\n", section->SectionName.GetChars());
while (entry != NULL)
{
if (strpbrk(entry->Value, "\r\n") == NULL)

View File

@ -41,8 +41,7 @@ class FConfigFile
{
public:
FConfigFile ();
FConfigFile (const char *pathname,
void (*nosechandler)(const char *pathname, FConfigFile *config, void *userdata)=0, void *userdata=NULL);
FConfigFile (const char *pathname);
FConfigFile (const FConfigFile &other);
virtual ~FConfigFile ();
@ -70,7 +69,7 @@ public:
const char *GetPathName () const { return PathName.GetChars(); }
void ChangePathName (const char *path);
void LoadConfigFile (void (*nosechandler)(const char *pathname, FConfigFile *config, void *userdata), void *userdata);
void LoadConfigFile ();
bool WriteConfigFile () const;
protected:
@ -79,6 +78,7 @@ protected:
virtual char *ReadLine (char *string, int n, void *file) const;
bool ReadConfig (void *file);
static const char *GenerateEndTag(const char *value);
void RenameSection(const char *oldname, const char *newname) const;
bool OkayToWrite;
bool FileExisted;
@ -94,11 +94,12 @@ private:
};
struct FConfigSection
{
FString SectionName;
FConfigEntry *RootEntry;
FConfigEntry **LastEntryPtr;
FConfigSection *Next;
FString Note;
char Name[1]; // + length of name
//char Name[1]; // + length of name
};
FConfigSection *Sections;

View File

@ -47,6 +47,7 @@
#include "v_video.h"
#include "gameconfigfile.h"
#include "resourcefiles/resourcefile.h"
#include "version.h"
CVAR (Bool, queryiwad, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG);
@ -137,12 +138,6 @@ void FIWadManager::ParseIWadInfo(const char *fn, const char *data, int datasize)
sc.MustGetString();
iwad->Autoname = sc.String;
}
else if (sc.Compare("Group"))
{
sc.MustGetStringName("=");
sc.MustGetString();
iwad->Group = sc.String;
}
else if (sc.Compare("Config"))
{
sc.MustGetStringName("=");
@ -224,6 +219,11 @@ void FIWadManager::ParseIWadInfo(const char *fn, const char *data, int datasize)
sc.ScriptError("Unknown keyword '%s'", sc.String);
}
}
if (iwad->MapInfo.IsEmpty())
{
// We must at least load the minimum defaults to allow the engine to run.
iwad->MapInfo = "mapinfo/mindefaults.txt";
}
}
else if (sc.Compare("NAMES"))
{
@ -252,7 +252,7 @@ void FIWadManager::ParseIWadInfo(const char *fn, const char *data, int datasize)
//==========================================================================
//
// Lool for IWAD definition lump
// Look for IWAD definition lump
//
//==========================================================================
@ -301,11 +301,11 @@ int FIWadManager::ScanIWAD (const char *iwad)
FResourceLump *lump = iwadfile->GetLump(ii);
CheckLumpName(lump->Name);
if (lump->FullName != NULL)
if (lump->FullName.IsNotEmpty())
{
if (strnicmp(lump->FullName, "maps/", 5) == 0)
{
FString mapname(lump->FullName+5, strcspn(lump->FullName+5, "."));
FString mapname(&lump->FullName[5], strcspn(&lump->FullName[5], "."));
CheckLumpName(mapname);
}
}
@ -392,7 +392,6 @@ int FIWadManager::IdentifyVersion (TArray<FString> &wadfiles, const char *iwad,
bool iwadparmfound = false;
FString custwad;
ParseIWadInfos(zdoom_wad);
wads.Resize(mIWadNames.Size());
foundwads.Resize(mIWads.Size());
memset(&foundwads[0], 0, foundwads.Size() * sizeof(foundwads[0]));
@ -504,19 +503,19 @@ int FIWadManager::IdentifyVersion (TArray<FString> &wadfiles, const char *iwad,
if (numwads == 0)
{
I_FatalError ("Cannot find a game IWAD (doom.wad, doom2.wad, heretic.wad, etc.).\n"
"Did you install ZDoom properly? You can do either of the following:\n"
"Did you install " GAMENAME " properly? You can do either of the following:\n"
"\n"
#if defined(_WIN32)
"1. Place one or more of these wads in the same directory as ZDoom.\n"
"2. Edit your zdoom-username.ini and add the directories of your iwads\n"
"1. Place one or more of these wads in the same directory as " GAMENAME ".\n"
"2. Edit your " GAMENAMELOWERCASE "-username.ini and add the directories of your iwads\n"
"to the list beneath [IWADSearch.Directories]");
#elif defined(__APPLE__)
"1. Place one or more of these wads in ~/Library/Application Support/zdoom/\n"
"2. Edit your ~/Library/Preferences/zdoom.ini and add the directories\n"
"1. Place one or more of these wads in ~/Library/Application Support/" GAMENAMELOWERCASE "/\n"
"2. Edit your ~/Library/Preferences/" GAMENAMELOWERCASE ".ini and add the directories\n"
"of your iwads to the list beneath [IWADSearch.Directories]");
#else
"1. Place one or more of these wads in ~/.config/zdoom/.\n"
"2. Edit your ~/.config/zdoom/zdoom.ini and add the directories of your\n"
"1. Place one or more of these wads in ~/.config/" GAMENAMELOWERCASE "/.\n"
"2. Edit your ~/.config/" GAMENAMELOWERCASE "/" GAMENAMELOWERCASE ".ini and add the directories of your\n"
"iwads to the list beneath [IWADSearch.Directories]");
#endif
}

View File

@ -214,6 +214,7 @@ bool autostart;
FString StoredWarp;
bool advancedemo;
FILE *debugfile;
FILE *hashfile;
event_t events[MAXEVENTS];
int eventhead;
int eventtail;
@ -1656,7 +1657,7 @@ static const char *BaseFileSearch (const char *file, const char *ext, bool lookf
return wad;
}
if (GameConfig->SetSection ("FileSearch.Directories"))
if (GameConfig != NULL && GameConfig->SetSection ("FileSearch.Directories"))
{
const char *key;
const char *value;
@ -1722,12 +1723,13 @@ bool ConsiderPatches (const char *arg)
//
//==========================================================================
void D_MultiExec (DArgs *list, bool usePullin)
FExecList *D_MultiExec (DArgs *list, FExecList *exec)
{
for (int i = 0; i < list->NumArgs(); ++i)
{
C_ExecFile (list->GetArg (i), usePullin);
exec = C_ParseExecFile(list->GetArg(i), exec);
}
return exec;
}
static void GetCmdLineFiles(TArray<FString> &wadfiles)
@ -1977,10 +1979,6 @@ static void D_DoomInit()
}
FRandom::StaticClearRandom ();
Printf ("M_LoadDefaults: Load system defaults.\n");
M_LoadDefaults (); // load before initing other systems
}
//==========================================================================
@ -1989,8 +1987,10 @@ static void D_DoomInit()
//
//==========================================================================
static void AddAutoloadFiles(const char *group, const char *autoname)
static void AddAutoloadFiles(const char *autoname)
{
LumpFilterIWAD.Format("%s.", autoname); // The '.' is appened to simplify parsing the string
if (!(gameinfo.flags & GI_SHAREWARE) && !Args->CheckParm("-noautoload"))
{
FString file;
@ -2021,25 +2021,14 @@ static void AddAutoloadFiles(const char *group, const char *autoname)
// Add common (global) wads
D_AddConfigWads (allwads, "Global.Autoload");
// Add game-specific wads
file = gameinfo.ConfigName;
file += ".Autoload";
D_AddConfigWads (allwads, file);
long len;
int lastpos = -1;
// Add group-specific wads
if (group != NULL)
while ((len = LumpFilterIWAD.IndexOf('.', lastpos+1)) > 0)
{
file = group;
file += ".Autoload";
D_AddConfigWads(allwads, file);
}
// Add IWAD-specific wads
if (autoname != NULL)
{
file = autoname;
file += ".Autoload";
file = LumpFilterIWAD.Left(len) + ".Autoload";
D_AddConfigWads(allwads, file);
lastpos = len;
}
}
}
@ -2212,6 +2201,7 @@ void D_DoomMain (void)
TArray<FString> pwads;
FString *args;
int argcount;
FIWadManager *iwad_man;
// +logfile gets checked too late to catch the full startup log in the logfile so do some extra check for it here.
FString logfile = Args->TakeValue("+logfile");
@ -2220,9 +2210,27 @@ void D_DoomMain (void)
execLogfile(logfile);
}
if (Args->CheckParm("-hashfiles"))
{
const char *filename = "fileinfo.txt";
Printf("Hashing loaded content to: %s\n", filename);
hashfile = fopen(filename, "w");
if (hashfile)
{
fprintf(hashfile, "%s version %s (%s)\n", GAMENAME, GetVersionString(), GetGitHash());
#ifdef __VERSION__
fprintf(hashfile, "Compiler version: %s\n", __VERSION__);
#endif
fprintf(hashfile, "Command line:");
for (int i = 0; i < Args->NumArgs(); ++i)
{
fprintf(hashfile, " %s", Args->GetArg(i));
}
fprintf(hashfile, "\n");
}
}
D_DoomInit();
PClass::StaticInit ();
atterm(FinalGC);
// [RH] Make sure zdoom.pk3 is always loaded,
// as it contains magic stuff we need.
@ -2234,6 +2242,14 @@ void D_DoomMain (void)
}
FString basewad = wad;
iwad_man = new FIWadManager;
iwad_man->ParseIWadInfos(basewad);
Printf ("M_LoadDefaults: Load system defaults.\n");
M_LoadDefaults (iwad_man); // load before initing other systems
PClass::StaticInit ();
atterm(FinalGC);
// reinit from here
@ -2255,7 +2271,11 @@ void D_DoomMain (void)
// restart is initiated without a defined IWAD assume for now that it's not going to change.
if (iwad.IsEmpty()) iwad = lastIWAD;
FIWadManager *iwad_man = new FIWadManager;
if (iwad_man == NULL)
{
iwad_man = new FIWadManager;
iwad_man->ParseIWadInfos(basewad);
}
const FIWADInfo *iwad_info = iwad_man->FindIWAD(allwads, iwad, basewad);
gameinfo.gametype = iwad_info->gametype;
gameinfo.flags = iwad_info->flags;
@ -2270,36 +2290,54 @@ void D_DoomMain (void)
FBaseCVar::DisableCallbacks();
GameConfig->DoGameSetup (gameinfo.ConfigName);
AddAutoloadFiles(iwad_info->Group, iwad_info->Autoname);
AddAutoloadFiles(iwad_info->Autoname);
// Run automatically executed files
// Process automatically executed files
FExecList *exec;
execFiles = new DArgs;
GameConfig->AddAutoexec (execFiles, gameinfo.ConfigName);
D_MultiExec (execFiles, true);
GameConfig->AddAutoexec(execFiles, gameinfo.ConfigName);
exec = D_MultiExec(execFiles, NULL);
// Run .cfg files at the start of the command line.
// Process .cfg files at the start of the command line.
execFiles = Args->GatherFiles ("-exec");
D_MultiExec (execFiles, true);
exec = D_MultiExec(execFiles, exec);
C_ExecCmdLineParams (); // [RH] do all +set commands on the command line
// [RH] process all + commands on the command line
exec = C_ParseCmdLineParams(exec);
CopyFiles(allwads, pwads);
if (exec != NULL)
{
exec->AddPullins(allwads);
}
// Since this function will never leave we must delete this array here manually.
pwads.Clear();
pwads.ShrinkToFit();
if (hashfile)
{
Printf("Notice: File hashing is incredibly verbose. Expect loading files to take much longer than usual.\n");
}
Printf ("W_Init: Init WADfiles.\n");
Wads.InitMultipleFiles (allwads);
allwads.Clear();
allwads.ShrinkToFit();
SetMapxxFlag();
GameConfig->DoKeySetup(gameinfo.ConfigName);
// Now that wads are loaded, define mod-specific cvars.
ParseCVarInfo();
// Try setting previously unknown cvars again, as a CVARINFO may have made them known.
C_ExecStoredSets();
// Actually exec command line commands and exec files.
if (exec != NULL)
{
exec->ExecCommands();
delete exec;
exec = NULL;
}
// [RH] Initialize localizable strings.
GStrings.LoadStrings (false);
@ -2414,6 +2452,8 @@ void D_DoomMain (void)
// Create replacements for dehacked pickups
FinishDehPatch();
InitActorNumsFromMapinfo();
InitSpawnablesFromMapinfo();
FActorInfo::StaticSetActorNums ();
//Added by MC:
@ -2465,6 +2505,7 @@ void D_DoomMain (void)
FBaseCVar::EnableNoSet ();
delete iwad_man; // now we won't need this anymore
iwad_man = NULL;
// [RH] Run any saved commands from the command line or autoexec.cfg now.
gamestate = GS_FULLCONSOLE;

View File

@ -75,7 +75,6 @@ struct FIWADInfo
{
FString Name; // Title banner text for this IWAD
FString Autoname; // Name of autoload ini section for this IWAD
FString Group; // Groupname for this IWAD
FString Configname; // Name of config section for this IWAD
FString Required; // Requires another IWAD
DWORD FgColor; // Foreground color for title banner
@ -116,15 +115,13 @@ extern FStartupInfo DoomStartupInfo;
//
//==========================================================================
struct FIWadManager
class FIWadManager
{
private:
TArray<FIWADInfo> mIWads;
TArray<FString> mIWadNames;
TArray<int> mLumpsFound;
void ParseIWadInfo(const char *fn, const char *data, int datasize);
void ParseIWadInfos(const char *fn);
void ClearChecks();
void CheckLumpName(const char *name);
int GetIWadInfo();
@ -132,7 +129,19 @@ private:
int CheckIWAD (const char *doomwaddir, WadStuff *wads);
int IdentifyVersion (TArray<FString> &wadfiles, const char *iwad, const char *zdoom_wad);
public:
void ParseIWadInfos(const char *fn);
const FIWADInfo *FindIWAD(TArray<FString> &wadfiles, const char *iwad, const char *basewad);
const FString *GetAutoname(unsigned int num) const
{
if (num < mIWads.Size()) return &mIWads[num].Autoname;
else return NULL;
}
int GetIWadFlags(unsigned int num) const
{
if (num < mIWads.Size()) return mIWads[num].flags;
else return false;
}
};

View File

@ -443,10 +443,15 @@ public:
FName LastDamageType; // [RH] For damage-specific pain and death sounds
//Added by MC:
TObjPtr<DBot> Bot;
TObjPtr<AActor> MUSINFOactor; // For MUSINFO purposes
SBYTE MUSINFOtics;
bool settings_controller; // Player can control game settings.
SBYTE crouching;
SBYTE crouchdir;
//Added by MC:
TObjPtr<DBot> Bot;
float BlendR; // [RH] Final blending values
float BlendG;
@ -458,8 +463,6 @@ public:
int MinPitch; // Viewpitch limits (negative is up, positive is down)
int MaxPitch;
SBYTE crouching;
SBYTE crouchdir;
fixed_t crouchfactor;
fixed_t crouchoffset;
fixed_t crouchviewdelta;

View File

@ -328,6 +328,7 @@ PClass *PClass::CreateDerivedClass (FName name, unsigned int size)
info->Class = type;
info->GameFilter = GAME_Any;
info->SpawnID = 0;
info->ConversationID = 0;
info->DoomEdNum = -1;
info->OwnedStates = NULL;
info->NumOwnedStates = 0;
@ -423,6 +424,7 @@ void PClass::InitializeActorInfo ()
info->Class = this;
info->GameFilter = GAME_Any;
info->SpawnID = 0;
info->ConversationID = 0;
info->DoomEdNum = -1;
info->OwnedStates = NULL;
info->NumOwnedStates = 0;

View File

@ -337,6 +337,7 @@ struct mapthinghexen_t
};
class FArchive;
struct FDoomEdEntry;
// Internal representation of a mapthing
struct FMapThing
@ -346,9 +347,10 @@ struct FMapThing
fixed_t y;
fixed_t z;
short angle;
short type;
WORD SkillFilter;
WORD ClassFilter;
short EdNum;
FDoomEdEntry *info;
DWORD flags;
int special;
int args[5];
@ -363,8 +365,6 @@ struct FMapThing
short pitch;
short roll;
DWORD RenderStyle;
void Serialize (FArchive &);
};
@ -429,10 +429,10 @@ struct FPlayerStart
short angle, type;
FPlayerStart() { }
FPlayerStart(const FMapThing *mthing)
FPlayerStart(const FMapThing *mthing, int pnum)
: x(mthing->x), y(mthing->y), z(mthing->z),
angle(mthing->angle),
type(mthing->type)
type(pnum)
{ }
};
// Player spawn spots for deathmatch.

View File

@ -69,3 +69,4 @@ int SinglePlayerClass[MAXPLAYERS];
bool ToggleFullscreen;
int BorderTopRefresh;
FString LumpFilterIWAD;

View File

@ -172,6 +172,7 @@ extern bool playeringame[/*MAXPLAYERS*/];
// File handling stuff.
extern FILE* debugfile;
extern FILE* hashfile;
// if true, load all graphics at level load
extern bool precache;
@ -249,4 +250,7 @@ EXTERN_CVAR (Int, compatflags);
EXTERN_CVAR (Int, compatflags2);
extern int i_compatflags, i_compatflags2, ii_compatflags, ii_compatflags2, ib_compatflags;
// Filters from AddAutoloadFiles(). Used to filter files from archives.
extern FString LumpFilterIWAD;
#endif

View File

@ -46,6 +46,9 @@
#include "zstring.h"
#include "vectors.h"
struct PClass;
typedef TMap<int, const PClass *> FClassMap;
// Since this file is included by everything, it seems an appropriate place
// to check the NOASM/USEASM macros.

View File

@ -169,6 +169,7 @@ void FS_EmulateCmd(char * string)
{
// No, this is not correct. But this is the way Legacy WADs expect it to be handled!
if (players[i].mo != NULL) players[i].mo->ViewHeight = playerviewheight;
players[i].viewheight = playerviewheight;
players[i].Uncrouch();
}
while (sc.GetString())

View File

@ -67,6 +67,7 @@
#include "v_font.h"
#include "r_data/colormaps.h"
#include "farchive.h"
#include "p_setup.h"
static FRandom pr_script("FScript");
@ -312,18 +313,24 @@ static int T_GetPlayerNum(const svalue_t &arg)
// sectors directly by passing a negative value
//
//==========================================================================
int T_FindSectorFromTag(int tagnum,int startsector)
class FSSectorTagIterator : public FSectorTagIterator
{
if (tagnum<=0)
public:
FSSectorTagIterator(int tag)
: FSectorTagIterator(tag)
{
if (startsector<0)
if (tag < 0)
{
if (tagnum==-32768) return 0;
if (-tagnum<numsectors) return -tagnum;
searchtag = INT_MIN;
start = tag == -32768? 0 : -tag < numsectors? -tag : -1;
}
return -1;
}
return P_FindSectorFromTag(tagnum,startsector);
};
inline int T_FindFirstSectorFromTag(int tagnum)
{
FSSectorTagIterator it(tagnum);
return it.Next();
}
@ -1158,7 +1165,7 @@ void FParser::SF_ObjSector(void)
}
t_return.type = svt_int;
t_return.value.i = mo ? mo->Sector->tag : 0; // nullptr check
t_return.value.i = mo ? tagManager.GetFirstSectorTag(mo->Sector) : 0; // nullptr check
}
//==========================================================================
@ -1420,7 +1427,7 @@ void FParser::SF_PointToDist(void)
double y = floatvalue(t_argv[3]) - floatvalue(t_argv[1]);
t_return.type = svt_fixed;
t_return.value.f = FLOAT2FIXED(sqrt(x*x+y*y)*65536.f);
t_return.value.f = FLOAT2FIXED(sqrt(x*x+y*y));
}
}
@ -1536,7 +1543,8 @@ void FParser::SF_StartSectorSound(void)
tagnum = intvalue(t_argv[0]);
int i=-1;
while ((i = T_FindSectorFromTag(tagnum, i)) >= 0)
FSSectorTagIterator itr(tagnum);
while ((i = itr.Next()) >= 0)
{
sector = &sectors[i];
S_Sound(sector, CHAN_BODY, T_FindSound(stringvalue(t_argv[1])), 1.0f, ATTN_NORM);
@ -1595,7 +1603,8 @@ void FParser::SF_FloorHeight(void)
// set all sectors with tag
while ((i = T_FindSectorFromTag(tagnum, i)) >= 0)
FSSectorTagIterator itr(tagnum);
while ((i = itr.Next()) >= 0)
{
if (sectors[i].floordata) continue; // don't move floors that are active!
@ -1612,7 +1621,7 @@ void FParser::SF_FloorHeight(void)
}
else
{
secnum = T_FindSectorFromTag(tagnum, -1);
secnum = T_FindFirstSectorFromTag(tagnum);
if(secnum < 0)
{
script_error("sector not found with tagnum %i\n", tagnum);
@ -1671,7 +1680,8 @@ void FParser::SF_MoveFloor(void)
// move all sectors with tag
while ((secnum = T_FindSectorFromTag(tagnum, secnum)) >= 0)
FSSectorTagIterator itr(tagnum);
while ((secnum = itr.Next()) >= 0)
{
sec = &sectors[secnum];
// Don't start a second thinker on the same floor
@ -1733,7 +1743,8 @@ void FParser::SF_CeilingHeight(void)
dest = fixedvalue(t_argv[1]);
// set all sectors with tag
while ((i = T_FindSectorFromTag(tagnum, i)) >= 0)
FSSectorTagIterator itr(tagnum);
while ((i = itr.Next()) >= 0)
{
if (sectors[i].ceilingdata) continue; // don't move ceilings that are active!
@ -1750,7 +1761,7 @@ void FParser::SF_CeilingHeight(void)
}
else
{
secnum = T_FindSectorFromTag(tagnum, -1);
secnum = T_FindFirstSectorFromTag(tagnum);
if(secnum < 0)
{
script_error("sector not found with tagnum %i\n", tagnum);
@ -1823,7 +1834,8 @@ void FParser::SF_MoveCeiling(void)
silent=t_argc>4 ? intvalue(t_argv[4]):1;
// move all sectors with tag
while ((secnum = T_FindSectorFromTag(tagnum, secnum)) >= 0)
FSSectorTagIterator itr(tagnum);
while ((secnum = itr.Next()) >= 0)
{
sec = &sectors[secnum];
@ -1851,7 +1863,7 @@ void FParser::SF_LightLevel(void)
tagnum = intvalue(t_argv[0]);
// argv is sector tag
secnum = T_FindSectorFromTag(tagnum, -1);
secnum = T_FindFirstSectorFromTag(tagnum);
if(secnum < 0)
{
@ -1865,7 +1877,8 @@ void FParser::SF_LightLevel(void)
int i = -1;
// set all sectors with tag
while ((i = T_FindSectorFromTag(tagnum, i)) >= 0)
FSSectorTagIterator itr(tagnum);
while ((i = itr.Next()) >= 0)
{
sectors[i].SetLightLevel(intvalue(t_argv[1]));
}
@ -1984,7 +1997,8 @@ void FParser::SF_FadeLight(void)
destlevel = intvalue(t_argv[1]);
speed = t_argc>2 ? intvalue(t_argv[2]) : 1;
for (i = -1; (i = P_FindSectorFromTag(sectag,i)) >= 0;)
FSectorTagIterator it(sectag);
while ((i = it.Next()) >= 0)
{
if (!sectors[i].lightingdata) new DLightLevel(&sectors[i],destlevel,speed);
}
@ -2006,7 +2020,7 @@ void FParser::SF_FloorTexture(void)
tagnum = intvalue(t_argv[0]);
// argv is sector tag
secnum = T_FindSectorFromTag(tagnum, -1);
secnum = T_FindFirstSectorFromTag(tagnum);
if(secnum < 0)
{ script_error("sector not found with tagnum %i\n", tagnum); return;}
@ -2019,7 +2033,8 @@ void FParser::SF_FloorTexture(void)
FTextureID picnum = TexMan.GetTexture(t_argv[1].string, FTexture::TEX_Flat, FTextureManager::TEXMAN_Overridable);
// set all sectors with tag
while ((i = T_FindSectorFromTag(tagnum, i)) >= 0)
FSSectorTagIterator itr(tagnum);
while ((i = itr.Next()) >= 0)
{
sectors[i].SetTexture(sector_t::floor, picnum);
}
@ -2057,7 +2072,7 @@ void FParser::SF_SectorColormap(void)
tagnum = intvalue(t_argv[0]);
// argv is sector tag
secnum = T_FindSectorFromTag(tagnum, -1);
secnum = T_FindFirstSectorFromTag(tagnum);
if(secnum < 0)
{ script_error("sector not found with tagnum %i\n", tagnum); return;}
@ -2068,7 +2083,8 @@ void FParser::SF_SectorColormap(void)
{
DWORD cm = R_ColormapNumForName(t_argv[1].value.s);
while ((i = T_FindSectorFromTag(tagnum, i)) >= 0)
FSSectorTagIterator itr(tagnum);
while ((i = itr.Next()) >= 0)
{
sectors[i].midmap=cm;
sectors[i].heightsec=&sectors[i];
@ -2094,7 +2110,7 @@ void FParser::SF_CeilingTexture(void)
tagnum = intvalue(t_argv[0]);
// argv is sector tag
secnum = T_FindSectorFromTag(tagnum, -1);
secnum = T_FindFirstSectorFromTag(tagnum);
if(secnum < 0)
{ script_error("sector not found with tagnum %i\n", tagnum); return;}
@ -2107,7 +2123,8 @@ void FParser::SF_CeilingTexture(void)
FTextureID picnum = TexMan.GetTexture(t_argv[1].string, FTexture::TEX_Flat, FTextureManager::TEXMAN_Overridable);
// set all sectors with tag
while ((i = T_FindSectorFromTag(tagnum, i)) >= 0)
FSSectorTagIterator itr(tagnum);
while ((i = itr.Next()) >= 0)
{
sectors[i].SetTexture(sector_t::ceiling, picnum);
}
@ -2210,9 +2227,6 @@ void FParser::SF_RunCommand(void)
//
//==========================================================================
// any linedef type
extern void P_TranslateLineDef (line_t *ld, maplinedef_t *mld);
void FParser::SF_LineTrigger()
{
if (CheckArgs(1))
@ -2281,9 +2295,11 @@ void FParser::SF_SetLineBlocking(void)
{
blocking=blocks[blocking];
int tag=intvalue(t_argv[0]);
for (int i = -1; (i = P_FindLineFromID(tag, i)) >= 0;)
FLineIdIterator itr(tag);
int i;
while ((i = itr.Next()) >= 0)
{
lines[i].flags = (lines[i].flags & ~(ML_BLOCKING|ML_BLOCKEVERYTHING)) | blocking;
lines[i].flags = (lines[i].flags & ~(ML_BLOCKING | ML_BLOCKEVERYTHING)) | blocking;
}
}
}
@ -2302,7 +2318,9 @@ void FParser::SF_SetLineMonsterBlocking(void)
int blocking = intvalue(t_argv[1]) ? ML_BLOCKMONSTERS : 0;
int tag=intvalue(t_argv[0]);
for (int i = -1; (i = P_FindLineFromID(tag, i)) >= 0;)
FLineIdIterator itr(tag);
int i;
while ((i = itr.Next()) >= 0)
{
lines[i].flags = (lines[i].flags & ~ML_BLOCKMONSTERS) | blocking;
}
@ -2357,12 +2375,13 @@ void FParser::SF_SetLineTexture(void)
texture = stringvalue(t_argv[3]);
texturenum = TexMan.GetTexture(texture, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable);
for (i = -1; (i = P_FindLineFromID(tag, i)) >= 0;)
FLineIdIterator itr(tag);
while ((i = itr.Next()) >= 0)
{
// bad sidedef, Hexen just SEGV'd here!
if(lines[i].sidedef[side] != NULL)
if (lines[i].sidedef[side] != NULL)
{
if (position >=0 && position <=2)
if (position >= 0 && position <= 2)
{
lines[i].sidedef[side]->SetTexture(position, texturenum);
}
@ -2376,7 +2395,8 @@ void FParser::SF_SetLineTexture(void)
int sections = intvalue(t_argv[3]);
// set all sectors with tag
for (i = -1; (i = P_FindLineFromID(tag, i)) >= 0;)
FLineIdIterator itr(tag);
while ((i = itr.Next()) >= 0)
{
side_t *sided = lines[i].sidedef[side];
if(sided != NULL)
@ -4201,7 +4221,7 @@ void FParser::SF_SetColor(void)
{
tagnum = intvalue(t_argv[0]);
secnum = T_FindSectorFromTag(tagnum, -1);
secnum = T_FindFirstSectorFromTag(tagnum);
if(secnum < 0)
{
@ -4222,7 +4242,8 @@ void FParser::SF_SetColor(void)
else return;
// set all sectors with tag
while ((i = T_FindSectorFromTag(tagnum, i)) >= 0)
FSSectorTagIterator itr(tagnum);
while ((i = itr.Next()) >= 0)
{
sectors[i].ColorMap = GetSpecialLights (color, sectors[i].ColorMap->Fade, 0);
}
@ -4291,7 +4312,7 @@ void FParser::SF_KillInSector()
while ((mo=it.Next()))
{
if (mo->flags3&MF3_ISMONSTER && mo->Sector->tag==tag) P_DamageMobj(mo, NULL, NULL, 1000000, NAME_Massacre);
if (mo->flags3&MF3_ISMONSTER && tagManager.SectorHasTag(mo->Sector, tag)) P_DamageMobj(mo, NULL, NULL, 1000000, NAME_Massacre);
}
}
}
@ -4314,7 +4335,7 @@ void FParser::SF_SectorType(void)
tagnum = intvalue(t_argv[0]);
// argv is sector tag
secnum = T_FindSectorFromTag(tagnum, -1);
secnum = T_FindFirstSectorFromTag(tagnum);
if(secnum < 0)
{ script_error("sector not found with tagnum %i\n", tagnum); return;}
@ -4327,7 +4348,8 @@ void FParser::SF_SectorType(void)
int spec = intvalue(t_argv[1]);
// set all sectors with tag
while ((i = T_FindSectorFromTag(tagnum, i)) >= 0)
FSSectorTagIterator itr(tagnum);
while ((i = itr.Next()) >= 0)
{
sectors[i].special = spec;
}
@ -4355,18 +4377,17 @@ void FParser::SF_SetLineTrigger()
id=intvalue(t_argv[0]);
spec=intvalue(t_argv[1]);
if (t_argc>2) tag=intvalue(t_argv[2]);
for (i = -1; (i = P_FindLineFromID (id, i)) >= 0; )
FLineIdIterator itr(id);
while ((i = itr.Next()) >= 0)
{
if (t_argc==2) tag=lines[i].id;
maplinedef_t mld;
mld.special=spec;
mld.tag=tag;
mld.flags=0;
mld.special = spec;
mld.tag = tag;
mld.flags = 0;
int f = lines[i].flags;
P_TranslateLineDef(&lines[i], &mld);
lines[i].id=tag;
lines[i].flags = (lines[i].flags & (ML_MONSTERSCANACTIVATE|ML_REPEAT_SPECIAL|ML_SPAC_MASK|ML_FIRSTSIDEONLY)) |
(f & ~(ML_MONSTERSCANACTIVATE|ML_REPEAT_SPECIAL|ML_SPAC_MASK|ML_FIRSTSIDEONLY));
lines[i].flags = (lines[i].flags & (ML_MONSTERSCANACTIVATE | ML_REPEAT_SPECIAL | ML_SPAC_MASK | ML_FIRSTSIDEONLY)) |
(f & ~(ML_MONSTERSCANACTIVATE | ML_REPEAT_SPECIAL | ML_SPAC_MASK | ML_FIRSTSIDEONLY));
}
}
@ -4375,33 +4396,13 @@ void FParser::SF_SetLineTrigger()
//==========================================================================
//
// new for GZDoom: Changes a sector's tag
// (I only need this because MAP02 in RTC-3057 has some issues with the GL
// renderer that I can't fix without the scripts. But loading a FS on top on
// ACS still works so I can hack around it with this.)
//
//
//==========================================================================
void FParser::SF_ChangeTag()
{
if (CheckArgs(2))
{
for (int secnum = -1; (secnum = P_FindSectorFromTag (t_argv[0].value.i, secnum)) >= 0; )
{
sectors[secnum].tag=t_argv[1].value.i;
}
// Recreate the hash tables
int i;
for (i=numsectors; --i>=0; ) sectors[i].firsttag = -1;
for (i=numsectors; --i>=0; )
{
int j = (unsigned) sectors[i].tag % (unsigned) numsectors;
sectors[i].nexttag = sectors[j].firsttag;
sectors[j].firsttag = i;
}
}
// Development garbage!
}

View File

@ -452,9 +452,9 @@ bool DFraggleThinker::wait_finished(DRunningScript *script)
case wt_tagwait:
{
int secnum = -1;
while ((secnum = P_FindSectorFromTag(script->wait_data, secnum)) >= 0)
int secnum;
FSectorTagIterator itr(script->wait_data);
while ((secnum = itr.Next()) >= 0)
{
sector_t *sec = &sectors[secnum];
if(sec->floordata || sec->ceilingdata || sec->lightingdata)

View File

@ -584,7 +584,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BFGSpray)
int j;
int damage;
angle_t an;
AActor *thingToHit;
AActor *linetarget;
ACTION_PARAM_START(7);
@ -615,21 +614,25 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BFGSpray)
// self->target is the originator (player) of the missile
P_AimLineAttack(self->target, an, distance, &linetarget, vrange);
if (!linetarget)
continue;
if (linetarget != NULL)
{
AActor *spray = Spawn(spraytype, linetarget->x, linetarget->y,
linetarget->z + (linetarget->height >> 2), ALLOW_REPLACE);
if (spray)
int dmgFlags = 0;
FName dmgType = NAME_BFGSplash;
if (spray != NULL)
{
if (spray->flags6 & MF6_MTHRUSPECIES && spray->GetSpecies() == linetarget->GetSpecies())
{
spray->Destroy(); // [MC] Remove it because technically, the spray isn't trying to "hit" them.
continue;
}
if (spray->flags5 & MF5_PUFFGETSOWNER)
spray->target = self->target;
if (spray->flags5 & MF5_PUFFGETSOWNER) spray->target = self->target;
if (spray->flags3 & MF3_FOILINVUL) dmgFlags |= DMG_FOILINVUL;
if (spray->flags7 & MF7_FOILBUDDHA) dmgFlags |= DMG_FOILBUDDHA;
dmgType = spray->DamageType;
}
if (defdamage == 0)
@ -644,13 +647,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BFGSpray)
damage = defdamage;
}
int dmgFlagPass = 0;
dmgFlagPass += (spray != NULL && (spray->flags3 & MF3_FOILINVUL)) ? DMG_FOILINVUL : 0; //[MC]Because the original foilinvul wasn't working.
dmgFlagPass += (spray != NULL && (spray->flags7 & MF7_FOILBUDDHA)) ? DMG_FOILBUDDHA : 0;
thingToHit = linetarget;
int newdam = P_DamageMobj (thingToHit, self->target, self->target, damage, spray != NULL? FName(spray->DamageType) : FName(NAME_BFGSplash),
dmgFlagPass);
P_TraceBleed (newdam > 0 ? newdam : damage, thingToHit, self->target);
int newdam = P_DamageMobj(linetarget, self->target, self->target, damage, dmgType, dmgFlags);
P_TraceBleed(newdam > 0 ? newdam : damage, linetarget, self->target);
}
}
}

277
src/g_doomedmap.cpp Normal file
View File

@ -0,0 +1,277 @@
/*
** g_doomedmap.cpp
**
**---------------------------------------------------------------------------
** Copyright 1998-2015 Randy Heit
** Copyright 2015 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.
**---------------------------------------------------------------------------
**
**
*/
#include "info.h"
#include "p_lnspec.h"
#include "m_fixed.h"
#include "c_dispatch.h"
#include "templates.h"
#include "cmdlib.h"
#include "g_level.h"
#include "v_text.h"
#include "i_system.h"
const char *SpecialMapthingNames[] = {
"$Player1Start",
"$Player2Start",
"$Player3Start",
"$Player4Start",
"$Player5Start",
"$Player6Start",
"$Player7Start",
"$Player8Start",
"$DeathmatchStart",
"$SSeqOverride",
"$PolyAnchor",
"$PolySpawn",
"$PolySpawnCrush",
"$PolySpawnHurt",
"$SlopeFloorPointLine",
"$SlopeCeilingPointLine",
"$SetFloorSlope",
"$SetCeilingSlope",
"$VavoomFloor",
"$VavoomCeiling",
"$CopyFloorPlane",
"$CopyCeilingPlane",
"$VertexFloorZ",
"$VertexCeilingZ",
};
//==========================================================================
//
// Stuff that's only valid during definition time
//
//==========================================================================
struct MapinfoEdMapItem
{
FName classname; // DECORATE is read after MAPINFO so we do not have the actual classes available here yet.
short special;
bool argsdefined;
int args[5];
// These are for error reporting. We must store the file information because it's no longer available when these items get resolved.
FString filename;
int linenum;
};
typedef TMap<int, MapinfoEdMapItem> IdMap;
static IdMap DoomEdFromMapinfo;
//==========================================================================
//
//
//==========================================================================
FDoomEdMap DoomEdMap;
static int STACK_ARGS sortnums (const void *a, const void *b)
{
return (*(const FDoomEdMap::Pair**)a)->Key - (*(const FDoomEdMap::Pair**)b)->Key;
}
CCMD (dumpmapthings)
{
TArray<FDoomEdMap::Pair*> infos(DoomEdMap.CountUsed());
FDoomEdMap::Iterator it(DoomEdMap);
FDoomEdMap::Pair *pair;
while (it.NextPair(pair))
{
infos.Push(pair);
}
if (infos.Size () == 0)
{
Printf ("No map things registered\n");
}
else
{
qsort (&infos[0], infos.Size (), sizeof(FDoomEdMap::Pair*), sortnums);
for (unsigned i = 0; i < infos.Size (); ++i)
{
if (infos[i]->Value.Type != NULL)
{
Printf("%6d %s\n", infos[i]->Key, infos[i]->Value.Type->TypeName.GetChars());
}
else if (infos[i]->Value.Special > 0)
{
Printf("%6d %s\n", infos[i]->Key, SpecialMapthingNames[infos[i]->Value.Special - 1]);
}
else
{
Printf("%6d none", infos[i]->Key);
}
}
}
}
void FMapInfoParser::ParseDoomEdNums()
{
TMap<int, bool> defined;
int error = 0;
MapinfoEdMapItem editem;
editem.filename = sc.ScriptName;
ParseOpenBrace();
while (true)
{
if (sc.CheckString("}")) return;
else if (sc.CheckNumber())
{
int ednum = sc.Number;
sc.MustGetStringName("=");
sc.MustGetString();
bool *def = defined.CheckKey(ednum);
if (def != NULL)
{
sc.ScriptMessage("Editor Number %d defined more than once", ednum);
error++;
}
defined[ednum] = true;
if (sc.String[0] == '$')
{
// todo: add special stuff like playerstarts and sound sequence overrides here, too.
editem.classname = NAME_None;
editem.special = sc.MustMatchString(SpecialMapthingNames) + 1; // todo: assign proper constants
}
else
{
editem.classname = sc.String;
editem.special = -1;
}
memset(editem.args, 0, sizeof(editem.args));
editem.argsdefined = false;
int minargs = 0;
int maxargs = 5;
FString specialname;
if (sc.CheckString(","))
{
editem.argsdefined = true; // mark args as used - if this is done we need to prevent assignment of map args in P_SpawnMapThing.
if (editem.special < 0) editem.special = 0;
if (!sc.CheckNumber())
{
sc.MustGetString();
specialname = sc.String; // save for later error reporting.
editem.special = P_FindLineSpecial(sc.String, &minargs, &maxargs);
if (editem.special == 0 || minargs == -1)
{
sc.ScriptMessage("Invalid special %s for Editor Number %d", sc.String, ednum);
error++;
minargs = 0;
maxargs = 5;
}
if (!sc.CheckString(","))
{
// special case: Special without arguments
if (minargs != 0)
{
sc.ScriptMessage("Incorrect number of args for special %s, min = %d, max = %d, found = 0", specialname.GetChars(), minargs, maxargs);
error++;
}
DoomEdFromMapinfo.Insert(ednum, editem);
continue;
}
sc.MustGetNumber();
}
int i = 0;
while (i < 5)
{
editem.args[i] = sc.Number;
i++;
if (!sc.CheckString(",")) break;
sc.MustGetNumber();
}
if (specialname.IsNotEmpty() && (i < minargs || i > maxargs))
{
sc.ScriptMessage("Incorrect number of args for special %s, min = %d, max = %d, found = %d", specialname.GetChars(), minargs, maxargs, i);
error++;
}
}
DoomEdFromMapinfo.Insert(ednum, editem);
}
else
{
sc.ScriptError("Number expected");
}
}
if (error > 0)
{
sc.ScriptError("%d errors encountered in DoomEdNum definition");
}
}
void InitActorNumsFromMapinfo()
{
DoomEdMap.Clear();
IdMap::Iterator it(DoomEdFromMapinfo);
IdMap::Pair *pair;
int error = 0;
while (it.NextPair(pair))
{
const PClass *cls = NULL;
if (pair->Value.classname != NAME_None)
{
cls = PClass::FindClass(pair->Value.classname);
if (cls == NULL)
{
Printf(TEXTCOLOR_RED "Script error, \"%s\" line %d:\nUnknown actor class %s\n",
pair->Value.filename.GetChars(), pair->Value.linenum, pair->Value.classname.GetChars());
error++;
}
}
FDoomEdEntry ent;
ent.Type = cls;
ent.Special = pair->Value.special;
ent.ArgsDefined = pair->Value.argsdefined;
memcpy(ent.Args, pair->Value.args, sizeof(ent.Args));
DoomEdMap.Insert(pair->Key, ent);
}
if (error > 0)
{
I_Error("%d unknown actor classes found", error);
}
DoomEdFromMapinfo.Clear(); // we do not need this any longer
}

View File

@ -2516,7 +2516,7 @@ bool G_ProcessIFFDemo (FString &mapname)
id = ReadLong (&demo_p);
if (id != ZDEM_ID)
{
Printf ("Not a ZDoom demo file!\n");
Printf ("Not a " GAMENAME " demo file!\n");
return true;
}
@ -2541,12 +2541,12 @@ bool G_ProcessIFFDemo (FString &mapname)
demover = ReadWord (&demo_p); // ZDoom version demo was created with
if (demover < MINDEMOVERSION)
{
Printf ("Demo requires an older version of ZDoom!\n");
Printf ("Demo requires an older version of " GAMENAME "!\n");
//return true;
}
if (ReadWord (&demo_p) > DEMOGAMEVERSION) // Minimum ZDoom version
{
Printf ("Demo requires a newer version of ZDoom!\n");
Printf ("Demo requires a newer version of " GAMENAME "!\n");
return true;
}
if (demover >= 0x21a)
@ -2673,7 +2673,7 @@ void G_DoPlayDemo (void)
if (ReadLong (&demo_p) != FORM_ID)
{
const char *eek = "Cannot play non-ZDoom demos.\n";
const char *eek = "Cannot play non-" GAMENAME " demos.\n";
C_ForgetCVars();
M_Free(demobuffer);

106
src/g_hexen/a_flies.cpp Normal file
View File

@ -0,0 +1,106 @@
static FRandom pr_fly("GetOffMeFly");
//===========================================================================
//
// FindCorpse
//
// Finds a corpse to buzz around. We can't use a blockmap check because
// corpses generally aren't linked into the blockmap.
//
//===========================================================================
static AActor *FindCorpse(AActor *fly, sector_t *sec, int recurselimit)
{
AActor *fallback = NULL;
sec->validcount = validcount;
// Search the current sector
for (AActor *check = sec->thinglist; check != NULL; check = check->snext)
{
if (check == fly)
continue;
if (!(check->flags & MF_CORPSE))
continue;
if (!P_CheckSight(fly, check))
continue;
fallback = check;
if (pr_fly(2)) // 50% chance to try to pick a different corpse
continue;
return check;
}
if (--recurselimit <= 0 || (fallback != NULL && pr_fly(2)))
{
return fallback;
}
// Try neighboring sectors
for (int i = 0; i < sec->linecount; ++i)
{
line_t *line = sec->lines[i];
sector_t *sec2 = (line->frontsector == sec) ? line->backsector : line->frontsector;
if (sec2 != NULL && sec2->validcount != validcount)
{
AActor *neighbor = FindCorpse(fly, sec2, recurselimit);
if (neighbor != NULL)
{
return neighbor;
}
}
}
return fallback;
}
DEFINE_ACTION_FUNCTION(AActor, A_FlySearch)
{
// The version from the retail beta is not so great for general use:
// 1. Pick one of the first fifty thinkers at random.
// 2. Starting from that thinker, find one that is an actor, not itself,
// and within sight. Give up after 100 sequential thinkers.
// It's effectively useless if there are more than 150 thinkers on a map.
//
// So search the sectors instead. We can't potentially find something all
// the way on the other side of the map and we can't find invisible corpses,
// but at least we aren't crippled on maps with lots of stuff going on.
validcount++;
AActor *other = FindCorpse(self, self->Sector, 5);
if (other != NULL)
{
self->target = other;
self->SetState(self->FindState("Buzz"));
}
}
DEFINE_ACTION_FUNCTION(AActor, A_FlyBuzz)
{
AActor *targ = self->target;
if (targ == NULL || !(targ->flags & MF_CORPSE) || pr_fly() < 5)
{
self->SetIdle();
return;
}
angle_t ang = R_PointToAngle2(self->x, self->y, targ->x, targ->y);
self->angle = ang;
self->args[0]++;
ang >>= ANGLETOFINESHIFT;
if (!P_TryMove(self, self->x + 6 * finecosine[ang], self->y + 6 * finesine[ang], true))
{
self->SetIdle(true);
return;
}
if (self->args[0] & 2)
{
self->velx += (pr_fly() - 128) << BOBTOFINESHIFT;
self->vely += (pr_fly() - 128) << BOBTOFINESHIFT;
}
int zrand = pr_fly();
if (targ->z + 5*FRACUNIT < self->z && zrand > 150)
{
zrand = -zrand;
}
self->velz = zrand << BOBTOFINESHIFT;
if (pr_fly() < 40)
{
S_Sound(self, CHAN_VOICE, self->ActiveSound, 0.5f, ATTN_STATIC);
}
}

View File

@ -38,6 +38,7 @@
#include "a_fighterquietus.cpp"
#include "a_firedemon.cpp"
#include "a_flechette.cpp"
#include "a_flies.cpp"
#include "a_fog.cpp"
#include "a_healingradius.cpp"
#include "a_heresiarch.cpp"

View File

@ -1229,6 +1229,7 @@ void G_FinishTravel ()
pawn->lastenemy = NULL;
pawn->player->mo = pawn;
pawn->player->camera = pawn;
pawn->player->viewheight = pawn->ViewHeight;
pawn->flags2 &= ~MF2_BLASTED;
DObject::StaticPointerSubstitution (oldpawn, pawn);
oldpawn->Destroy();
@ -1457,7 +1458,9 @@ void G_SerializeLevel (FArchive &arc, bool hubLoad)
if (SaveVersion >= 3313)
{
arc << level.nextmusic;
// This is a player property now
int nextmusic;
arc << nextmusic;
}
// Hub transitions must keep the current total time

View File

@ -104,6 +104,9 @@ struct FMapInfoParser
void ParseIntermissionAction(FIntermissionDescriptor *Desc);
void ParseIntermission();
void ParseDoomEdNums();
void ParseSpawnNums();
void ParseConversationIDs();
void ParseAMColors(bool);
FName CheckEndSequence();
FName ParseEndGame();
@ -336,6 +339,7 @@ struct level_info_t
TArray<FSpecialAction> specialactions;
TArray<FSoundID> PrecacheSounds;
TArray<FTextureID> PrecacheTextures;
level_info_t()
{
@ -412,7 +416,6 @@ struct FLevelLocals
int musicorder;
int cdtrack;
unsigned int cdid;
int nextmusic; // For MUSINFO purposes
FTextureID skytexture1;
FTextureID skytexture2;

View File

@ -1065,6 +1065,25 @@ DEFINE_MAP_OPTION(PrecacheSounds, true)
} while (parse.sc.CheckString(","));
}
DEFINE_MAP_OPTION(PrecacheTextures, true)
{
parse.ParseAssign();
do
{
parse.sc.MustGetString();
FTextureID tex = TexMan.CheckForTexture(parse.sc.String, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable|FTextureManager::TEXMAN_TryAny|FTextureManager::TEXMAN_ReturnFirst);
if (!tex.isValid())
{
parse.sc.ScriptMessage("Unknown texture \"%s\"", parse.sc.String);
}
else
{
info->PrecacheTextures.Push(tex);
}
} while (parse.sc.CheckString(","));
}
DEFINE_MAP_OPTION(redirect, true)
{
parse.ParseAssign();
@ -1857,6 +1876,42 @@ void FMapInfoParser::ParseMapInfo (int lump, level_info_t &gamedefaults, level_i
sc.ScriptError("intermission definitions not supported with old MAPINFO syntax");
}
}
else if (sc.Compare("doomednums"))
{
if (format_type != FMT_Old)
{
format_type = FMT_New;
ParseDoomEdNums();
}
else
{
sc.ScriptError("doomednums definitions not supported with old MAPINFO syntax");
}
}
else if (sc.Compare("spawnnums"))
{
if (format_type != FMT_Old)
{
format_type = FMT_New;
ParseSpawnNums();
}
else
{
sc.ScriptError("spawnnums definitions not supported with old MAPINFO syntax");
}
}
else if (sc.Compare("conversationids"))
{
if (format_type != FMT_Old)
{
format_type = FMT_New;
ParseConversationIDs();
}
else
{
sc.ScriptError("conversationids definitions not supported with old MAPINFO syntax");
}
}
else if (sc.Compare("automap") || sc.Compare("automap_overlay"))
{
if (format_type != FMT_Old)

View File

@ -1757,6 +1757,7 @@ IMPLEMENT_CLASS(APowerRegeneration)
void APowerRegeneration::DoEffect()
{
Super::DoEffect();
if (Owner != NULL && Owner->health > 0 && (level.time & 31) == 0)
{
if (P_GiveBody(Owner, Strength/FRACUNIT))

View File

@ -593,7 +593,7 @@ bool AInventory::HandlePickup (AInventory *item)
{
if (item->GetClass() == GetClass())
{
if (Amount < MaxAmount || sv_unlimited_pickup)
if (Amount < MaxAmount || (sv_unlimited_pickup && !item->ShouldStay()))
{
if (Amount > 0 && Amount + item->Amount < 0)
{

View File

@ -119,7 +119,9 @@ void ASkyCamCompat::BeginPlay ()
// Finally, skyboxify all tagged sectors
// This involves changing their texture to the sky flat, because while
// EE works with any texture for its skybox portals, ZDoom doesn't.
for (int secnum =-1; (secnum = P_FindSectorFromTag (skybox_id, secnum)) != -1; )
FSectorTagIterator it(skybox_id);
int secnum;
while ((secnum = it.Next()) >= 0)
{
// plane: 0=floor, 1=ceiling, 2=both
if (refline->args[2] == 1 || refline->args[2] == 2)

View File

@ -1502,7 +1502,7 @@ void DBaseStatusBar::DrawTopStuff (EHudState state)
{
screen->DrawText (SmallFont, CR_TAN, 0, ST_Y - 40 * CleanYfac,
"Demo was recorded with a different version\n"
"of ZDoom. Expect it to go out of sync.",
"of " GAMENAME ". Expect it to go out of sync.",
DTA_CleanNoMove, true, TAG_DONE);
}

View File

@ -636,7 +636,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CheckTerrain)
}
else if ((sec->special & 0xFF) == Scroll_StrifeCurrent)
{
int anglespeed = sec->tag - 100;
int anglespeed = tagManager.GetFirstSectorTag(sec) - 100;
fixed_t speed = (anglespeed % 10) << (FRACBITS - 4);
angle_t finean = (anglespeed / 10) << (32-3);
finean >>= ANGLETOFINESHIFT;

View File

@ -61,6 +61,7 @@ extern HWND Window;
#include "doomstat.h"
#include "i_system.h"
#include "gi.h"
#include "d_main.h"
EXTERN_CVAR (Bool, con_centernotify)
EXTERN_CVAR (Int, msg0color)
@ -75,7 +76,7 @@ EXTERN_CVAR (Color, am_cdwallcolor)
EXTERN_CVAR (Float, spc_amp)
EXTERN_CVAR (Bool, wi_percents)
FGameConfigFile::FGameConfigFile ()
FGameConfigFile::FGameConfigFile (FIWadManager *iwad_man)
{
#ifdef __APPLE__
FString user_docs, user_app_support, local_app_support;
@ -83,16 +84,10 @@ FGameConfigFile::FGameConfigFile ()
FString pathname;
OkayToWrite = false; // Do not allow saving of the config before DoGameSetup()
bMigrating = false;
bModSetup = false;
pathname = GetConfigPath (true);
ChangePathName (pathname);
LoadConfigFile (MigrateStub, NULL);
if (!HaveSections ())
{ // Config file not found; try the old one
MigrateOldConfig ();
}
LoadConfigFile ();
// If zdoom.ini was read from the program directory, switch
// to the user directory now. If it was read from the user
@ -169,28 +164,49 @@ FGameConfigFile::FGameConfigFile ()
// Create auto-load sections, so users know what's available.
// Note that this totem pole is the reverse of the order that
// they will appear in the file.
CreateSectionAtStart("Harmony.Autoload");
CreateSectionAtStart("UrbanBrawl.Autoload");
CreateSectionAtStart("Chex3.Autoload");
CreateSectionAtStart("Chex1.Autoload");
CreateSectionAtStart("Chex.Autoload");
CreateSectionAtStart("Strife.Autoload");
CreateSectionAtStart("HexenDK.Autoload");
CreateSectionAtStart("Hexen.Autoload");
CreateSectionAtStart("HereticSR.Autoload");
CreateSectionAtStart("Heretic.Autoload");
CreateSectionAtStart("FreeDM.Autoload");
CreateSectionAtStart("Freedoom2.Autoload");
CreateSectionAtStart("Freedoom1.Autoload");
CreateSectionAtStart("Freedoom.Autoload");
CreateSectionAtStart("Plutonia.Autoload");
CreateSectionAtStart("TNT.Autoload");
CreateSectionAtStart("Doom2BFG.Autoload");
CreateSectionAtStart("Doom2.Autoload");
CreateSectionAtStart("DoomBFG.Autoload");
CreateSectionAtStart("DoomU.Autoload");
CreateSectionAtStart("Doom1.Autoload");
CreateSectionAtStart("Doom.Autoload");
double last = 0;
if (SetSection ("LastRun"))
{
const char *lastver = GetValueForKey ("Version");
if (lastver != NULL) last = atof(lastver);
}
if (last < 211)
{
RenameSection("Chex3.Autoload", "chex.chex3.Autoload");
RenameSection("Chex1.Autoload", "chex.chex1.Autoload");
RenameSection("HexenDK.Autoload", "hexen.deathkings.Autoload");
RenameSection("HereticSR.Autoload", "heretic.shadow.Autoload");
RenameSection("FreeDM.Autoload", "doom.freedoom.freedm.Autoload");
RenameSection("Freedoom2.Autoload", "doom.freedoom.phase2.Autoload");
RenameSection("Freedoom1.Autoload", "doom.freedoom.phase1.Autoload");
RenameSection("Freedoom.Autoload", "doom.freedoom.Autoload");
RenameSection("DoomBFG.Autoload", "doom.doom1.bfg.Autoload");
RenameSection("DoomU.Autoload", "doom.doom1.ultimate.Autoload");
RenameSection("Doom1.Autoload", "doom.doom1.registered.Autoload");
RenameSection("TNT.Autoload", "doom.doom2.tnt.Autoload");
RenameSection("Plutonia.Autoload", "doom.doom2.plutonia.Autoload");
RenameSection("Doom2BFG.Autoload", "doom.doom2.bfg.Autoload");
RenameSection("Doom2.Autoload", "doom.doom2.commercial.Autoload");
}
const FString *pAuto;
for (int num = 0; (pAuto = iwad_man->GetAutoname(num)) != NULL; num++)
{
if (!(iwad_man->GetIWadFlags(num) & GI_SHAREWARE)) // we do not want autoload sections for shareware IWADs (which may have an autoname for resource filtering)
{
FString workname = *pAuto;
while (workname.IsNotEmpty())
{
FString section = workname + ".Autoload";
CreateSectionAtStart(section.GetChars());
long dotpos = workname.LastIndexOf('.');
if (dotpos < 0) break;
workname.Truncate(dotpos);
}
}
}
CreateSectionAtStart("Global.Autoload");
// The same goes for auto-exec files.
@ -223,9 +239,10 @@ FGameConfigFile::FGameConfigFile ()
"# Wad files to automatically load depending on the game and IWAD you are\n"
"# playing. You may have have files that are loaded for all similar IWADs\n"
"# (the game) and files that are only loaded for particular IWADs. For example,\n"
"# any files listed under Doom.Autoload will be loaded for any version of Doom,\n"
"# but files listed under Doom2.Autoload will only load when you are\n"
"# playing Doom 2.\n\n");
"# any files listed under 'doom.Autoload' will be loaded for any version of Doom,\n"
"# but files listed under 'doom.doom2.Autoload' will only load when you are\n"
"# playing a Doom 2 based game (doom2.wad, tnt.wad or plutonia.wad), and files listed under\n"
"# 'doom.doom2.commercial.Autoload' only when playing doom2.wad.\n\n");
}
FGameConfigFile::~FGameConfigFile ()
@ -237,18 +254,6 @@ void FGameConfigFile::WriteCommentHeader (FILE *file) const
fprintf (file, "# This file was generated by " GAMENAME " %s on %s\n", GetVersionString(), myasctime());
}
void FGameConfigFile::MigrateStub (const char *pathname, FConfigFile *config, void *userdata)
{
static_cast<FGameConfigFile *>(config)->bMigrating = true;
}
void FGameConfigFile::MigrateOldConfig ()
{
// Set default key bindings. These will be overridden
// by the bindings in the config file if it exists.
C_SetDefaultBindings ();
}
void FGameConfigFile::DoGlobalSetup ()
{
if (SetSection ("GlobalSettings.Unknown"))
@ -361,10 +366,6 @@ void FGameConfigFile::DoGameSetup (const char *gamename)
const char *key;
const char *value;
if (bMigrating)
{
MigrateOldConfig ();
}
sublen = countof(section) - 1 - mysnprintf (section, countof(section), "%s.", gamename);
subsection = section + countof(section) - sublen - 1;
section[countof(section) - 1] = '\0';
@ -400,41 +401,6 @@ void FGameConfigFile::DoGameSetup (const char *gamename)
ReadCVars (0);
}
if (!bMigrating)
{
C_SetDefaultBindings ();
}
strncpy (subsection, "Bindings", sublen);
if (SetSection (section))
{
Bindings.UnbindAll();
while (NextInSection (key, value))
{
Bindings.DoBind (key, value);
}
}
strncpy (subsection, "DoubleBindings", sublen);
if (SetSection (section))
{
DoubleBindings.UnbindAll();
while (NextInSection (key, value))
{
DoubleBindings.DoBind (key, value);
}
}
strncpy (subsection, "AutomapBindings", sublen);
if (SetSection (section))
{
AutomapBindings.UnbindAll();
while (NextInSection (key, value))
{
AutomapBindings.DoBind (key, value);
}
}
strncpy (subsection, "ConsoleAliases", sublen);
if (SetSection (section))
{
@ -455,6 +421,39 @@ void FGameConfigFile::DoGameSetup (const char *gamename)
OkayToWrite = true;
}
// Moved from DoGameSetup so that it can happen after wads are loaded
void FGameConfigFile::DoKeySetup(const char *gamename)
{
static const struct { const char *label; FKeyBindings *bindings; } binders[] =
{
{ "Bindings", &Bindings },
{ "DoubleBindings", &DoubleBindings },
{ "AutomapBindings", &AutomapBindings },
{ NULL, NULL }
};
const char *key, *value;
sublen = countof(section) - 1 - mysnprintf(section, countof(section), "%s.", gamename);
subsection = section + countof(section) - sublen - 1;
section[countof(section) - 1] = '\0';
C_SetDefaultBindings ();
for (int i = 0; binders[i].label != NULL; ++i)
{
strncpy(subsection, binders[i].label, sublen);
if (SetSection(section))
{
FKeyBindings *bindings = binders[i].bindings;
bindings->UnbindAll();
while (NextInSection(key, value))
{
bindings->DoBind(key, value);
}
}
}
}
// Like DoGameSetup(), but for mod-specific cvars.
// Called after CVARINFO has been parsed.
void FGameConfigFile::DoModSetup(const char *gamename)
@ -628,26 +627,6 @@ void FGameConfigFile::AddAutoexec (DArgs *list, const char *game)
mysnprintf (section, countof(section), "%s.AutoExec", game);
if (bMigrating)
{
FBaseCVar *autoexec = FindCVar ("autoexec", NULL);
if (autoexec != NULL)
{
UCVarValue val;
char *path;
val = autoexec->GetGenericRep (CVAR_String);
path = copystring (val.String);
delete autoexec;
SetSection (section, true);
SetValueForKey ("Path", path);
list->AppendArg (path);
delete[] path;
}
}
else
{
// If <game>.AutoExec section does not exist, create it
// with a default autoexec.cfg file present.
CreateStandardAutoExec(section, false);
@ -666,20 +645,12 @@ void FGameConfigFile::AddAutoexec (DArgs *list, const char *game)
}
}
}
}
}
void FGameConfigFile::SetRavenDefaults (bool isHexen)
{
UCVarValue val;
if (bMigrating)
{
con_centernotify.ResetToDefault ();
msg0color.ResetToDefault ();
color.ResetToDefault ();
}
val.Bool = false;
wi_percents.SetGenericRepDefault (val, CVAR_Bool);
val.Bool = true;

View File

@ -38,15 +38,17 @@
#include "configfile.h"
class DArgs;
class FIWadManager;
class FGameConfigFile : public FConfigFile
{
public:
FGameConfigFile ();
FGameConfigFile (FIWadManager *iwad_man);
~FGameConfigFile ();
void DoGlobalSetup ();
void DoGameSetup (const char *gamename);
void DoKeySetup (const char *gamename);
void DoModSetup (const char *gamename);
void ArchiveGlobalData ();
void ArchiveGameData (const char *gamename);
@ -59,13 +61,9 @@ protected:
void CreateStandardAutoExec (const char *section, bool start);
private:
static void MigrateStub (const char *pathname, FConfigFile *config, void *userdata);
void MigrateOldConfig ();
void SetRavenDefaults (bool isHexen);
void ReadCVars (DWORD flags);
bool bMigrating;
bool bModSetup;
char section[64];

View File

@ -335,7 +335,6 @@ void FMapInfoParser::ParseGameInfo()
GAMEINFOKEY_INT(defaultrespawntime, "defaultrespawntime")
GAMEINFOKEY_INT(defaultdropstyle, "defaultdropstyle")
GAMEINFOKEY_STRING(Endoom, "endoom")
GAMEINFOKEY_INT(player5start, "player5start")
GAMEINFOKEY_STRINGARRAY(quitmessages, "addquitmessages", 0, false)
GAMEINFOKEY_STRINGARRAY(quitmessages, "quitmessages", 0, true)
GAMEINFOKEY_STRING(mTitleColor, "menufontcolor_title")

View File

@ -153,7 +153,6 @@ struct gameinfo_t
int definventorymaxamount;
int defaultrespawntime;
int defaultdropstyle;
int player5start;
DWORD pickupcolor;
TArray<FString> quitmessages;
FName mTitleColor;

View File

@ -319,7 +319,11 @@ void PacketGet (void)
}
else if (c > 0)
{ //The packet is not from any in-game node, so we might as well discard it.
Printf("Dropped packet: Unknown host (%s:%d)\n", inet_ntoa(fromaddress.sin_addr), fromaddress.sin_port);
// Don't show the message for disconnect notifications.
if (c != 2 || TransmitBuffer[0] != PRE_FAKE || TransmitBuffer[1] != PRE_DISCONNECT)
{
DPrintf("Dropped packet: Unknown host (%s:%d)\n", inet_ntoa(fromaddress.sin_addr), fromaddress.sin_port);
}
doomcom.remotenode = -1;
return;
}

View File

@ -141,9 +141,6 @@ void FActorInfo::StaticInit ()
void FActorInfo::StaticSetActorNums ()
{
SpawnableThings.Clear();
DoomEdMap.Empty ();
for (unsigned int i = 0; i < PClass::m_RuntimeActors.Size(); ++i)
{
PClass::m_RuntimeActors[i]->ActorInfo->RegisterIDs ();
@ -159,6 +156,15 @@ void FActorInfo::RegisterIDs ()
{
const PClass *cls = PClass::FindClass(Class->TypeName);
// Conversation IDs have never been filtered by game so we cannot start doing that.
if (ConversationID > 0)
{
StrifeTypes[ConversationID] = cls;
if (cls != Class)
{
Printf(TEXTCOLOR_RED"Conversation ID %d refers to hidden class type '%s'\n", SpawnID, cls->TypeName.GetChars());
}
}
if (GameFilter == GAME_Any || (GameFilter & gameinfo.gametype))
{
if (SpawnID > 0)
@ -171,23 +177,22 @@ void FActorInfo::RegisterIDs ()
}
if (DoomEdNum != -1)
{
DoomEdMap.AddType (DoomEdNum, cls);
FDoomEdEntry *oldent = DoomEdMap.CheckKey(DoomEdNum);
if (oldent != NULL && oldent->Special == -2)
{
Printf(TEXTCOLOR_RED"Editor number %d defined twice for classes '%s' and '%s'\n", DoomEdNum, cls->TypeName.GetChars(), oldent->Type->TypeName.GetChars());
}
FDoomEdEntry ent;
memset(&ent, 0, sizeof(ent));
ent.Type = cls;
ent.Special = -2; // use -2 instead of -1 so that we can recognize DECORATE defined entries and print a warning message if duplicates occur.
DoomEdMap.Insert(DoomEdNum, ent);
if (cls != Class)
{
Printf(TEXTCOLOR_RED"Editor number %d refers to hidden class type '%s'\n", DoomEdNum, cls->TypeName.GetChars());
}
}
}
// Fill out the list for Chex Quest with Doom's actors
if (gameinfo.gametype == GAME_Chex && DoomEdMap.FindType(DoomEdNum) == NULL &&
(GameFilter & GAME_Doom))
{
DoomEdMap.AddType (DoomEdNum, Class, true);
if (cls != Class)
{
Printf(TEXTCOLOR_RED"Editor number %d refers to hidden class type '%s'\n", DoomEdNum, cls->TypeName.GetChars());
}
}
}
//==========================================================================
@ -389,139 +394,6 @@ fixed_t *DmgFactors::CheckFactor(FName type)
return pdf;
}
//==========================================================================
//
//
//==========================================================================
FDoomEdMap DoomEdMap;
FDoomEdMap::FDoomEdEntry *FDoomEdMap::DoomEdHash[DOOMED_HASHSIZE];
FDoomEdMap::~FDoomEdMap()
{
Empty();
}
void FDoomEdMap::AddType (int doomednum, const PClass *type, bool temporary)
{
unsigned int hash = (unsigned int)doomednum % DOOMED_HASHSIZE;
FDoomEdEntry *entry = DoomEdHash[hash];
while (entry && entry->DoomEdNum != doomednum)
{
entry = entry->HashNext;
}
if (entry == NULL)
{
entry = new FDoomEdEntry;
entry->HashNext = DoomEdHash[hash];
entry->DoomEdNum = doomednum;
DoomEdHash[hash] = entry;
}
else if (!entry->temp)
{
Printf (PRINT_BOLD, "Warning: %s and %s both have doomednum %d.\n",
type->TypeName.GetChars(), entry->Type->TypeName.GetChars(), doomednum);
}
entry->temp = temporary;
entry->Type = type;
}
void FDoomEdMap::DelType (int doomednum)
{
unsigned int hash = (unsigned int)doomednum % DOOMED_HASHSIZE;
FDoomEdEntry **prev = &DoomEdHash[hash];
FDoomEdEntry *entry = *prev;
while (entry && entry->DoomEdNum != doomednum)
{
prev = &entry->HashNext;
entry = entry->HashNext;
}
if (entry != NULL)
{
*prev = entry->HashNext;
delete entry;
}
}
void FDoomEdMap::Empty ()
{
int bucket;
for (bucket = 0; bucket < DOOMED_HASHSIZE; ++bucket)
{
FDoomEdEntry *probe = DoomEdHash[bucket];
while (probe != NULL)
{
FDoomEdEntry *next = probe->HashNext;
delete probe;
probe = next;
}
DoomEdHash[bucket] = NULL;
}
}
const PClass *FDoomEdMap::FindType (int doomednum) const
{
unsigned int hash = (unsigned int)doomednum % DOOMED_HASHSIZE;
FDoomEdEntry *entry = DoomEdHash[hash];
while (entry && entry->DoomEdNum != doomednum)
entry = entry->HashNext;
return entry ? entry->Type : NULL;
}
struct EdSorting
{
const PClass *Type;
int DoomEdNum;
};
static int STACK_ARGS sortnums (const void *a, const void *b)
{
return ((const EdSorting *)a)->DoomEdNum -
((const EdSorting *)b)->DoomEdNum;
}
void FDoomEdMap::DumpMapThings ()
{
TArray<EdSorting> infos (PClass::m_Types.Size());
int i;
for (i = 0; i < DOOMED_HASHSIZE; ++i)
{
FDoomEdEntry *probe = DoomEdHash[i];
while (probe != NULL)
{
EdSorting sorting = { probe->Type, probe->DoomEdNum };
infos.Push (sorting);
probe = probe->HashNext;
}
}
if (infos.Size () == 0)
{
Printf ("No map things registered\n");
}
else
{
qsort (&infos[0], infos.Size (), sizeof(EdSorting), sortnums);
for (i = 0; i < (int)infos.Size (); ++i)
{
Printf ("%6d %s\n",
infos[i].DoomEdNum, infos[i].Type->TypeName.GetChars());
}
}
}
CCMD (dumpmapthings)
{
FDoomEdMap::DumpMapThings ();
}
static void SummonActor (int command, int command2, FCommandLine argv)
{
if (CheckCheatmode ())

View File

@ -266,7 +266,8 @@ struct FActorInfo
FActorInfo *Replacee;
int NumOwnedStates;
BYTE GameFilter;
BYTE SpawnID;
WORD SpawnID;
WORD ConversationID;
SWORD DoomEdNum;
FStateLabels *StateList;
DmgFactors *DamageFactors;
@ -278,34 +279,51 @@ struct FActorInfo
TArray<const PClass *> ForbiddenToPlayerClass;
};
class FDoomEdMap
struct FDoomEdEntry
{
public:
~FDoomEdMap();
const PClass *FindType (int doomednum) const;
void AddType (int doomednum, const PClass *type, bool temporary = false);
void DelType (int doomednum);
void Empty ();
static void DumpMapThings ();
private:
enum { DOOMED_HASHSIZE = 256 };
struct FDoomEdEntry
{
FDoomEdEntry *HashNext;
const PClass *Type;
int DoomEdNum;
bool temp;
};
static FDoomEdEntry *DoomEdHash[DOOMED_HASHSIZE];
short Special;
bool ArgsDefined;
int Args[5];
};
enum ESpecialMapthings
{
SMT_Player1Start = 1,
SMT_Player2Start,
SMT_Player3Start,
SMT_Player4Start,
SMT_Player5Start,
SMT_Player6Start,
SMT_Player7Start,
SMT_Player8Start,
SMT_DeathmatchStart,
SMT_SSeqOverride,
SMT_PolyAnchor,
SMT_PolySpawn,
SMT_PolySpawnCrush,
SMT_PolySpawnHurt,
SMT_SlopeFloorPointLine,
SMT_SlopeCeilingPointLine,
SMT_SetFloorSlope,
SMT_SetCeilingSlope,
SMT_VavoomFloor,
SMT_VavoomCeiling,
SMT_CopyFloorPlane,
SMT_CopyCeilingPlane,
SMT_VertexFloorZ,
SMT_VertexCeilingZ,
};
typedef TMap<int, FDoomEdEntry> FDoomEdMap;
extern FDoomEdMap DoomEdMap;
void InitActorNumsFromMapinfo();
int GetSpriteIndex(const char * spritename, bool add = true);
TArray<FName> &MakeStateNameList(const char * fname);
void AddStateLight(FState *state, const char *lname);

View File

@ -410,9 +410,9 @@ CCMD (writeini)
// M_LoadDefaults
//
void M_LoadDefaults ()
void M_LoadDefaults (FIWadManager *iwad_man)
{
GameConfig = new FGameConfigFile;
GameConfig = new FGameConfigFile(iwad_man);
GameConfig->DoGlobalSetup ();
atterm (M_SaveDefaultsFinal);
}

View File

@ -28,6 +28,7 @@
class FConfigFile;
class FGameConfigFile;
class FIWadManager;
extern FGameConfigFile *GameConfig;
@ -40,7 +41,7 @@ void M_FindResponseFile (void);
// Pass a NULL to get the original behavior.
void M_ScreenShot (const char *filename);
void M_LoadDefaults ();
void M_LoadDefaults (FIWadManager *iwad_man);
bool M_SaveDefaults (const char *filename);
void M_SaveCustomKeys (FConfigFile *config, char *section, char *subsection, size_t sublen);

View File

@ -204,7 +204,7 @@ FString M_GetConfigPath(bool for_reading)
{
path += "/" GAME_DIR;
CreatePath(path);
path += "/zdoom.ini";
path += "/" GAMENAMELOWERCASE ".ini";
}
else
{ // construct "$PROGDIR/zdoom-$USER.ini"
@ -224,11 +224,11 @@ FString M_GetConfigPath(bool for_reading)
*probe = '_';
++probe;
}
path << "zdoom-" << uname << ".ini";
path << GAMENAMELOWERCASE "-" << uname << ".ini";
}
else
{ // Couldn't get user name, so just use zdoom.ini
path += "zdoom.ini";
path += GAMENAMELOWERCASE ".ini";
}
}
@ -239,7 +239,7 @@ FString M_GetConfigPath(bool for_reading)
if (!FileExists(path))
{
path = progdir;
path << "zdoom.ini";
path << GAMENAMELOWERCASE ".ini";
}
}
@ -411,11 +411,11 @@ FString M_GetConfigPath(bool for_reading)
noErr == FSRefMakePath(&folder, (UInt8*)cpath, PATH_MAX))
{
FString path;
path << cpath << "/zdoom.ini";
path << cpath << "/" GAMENAMELOWERCASE ".ini";
return path;
}
// Ungh.
return "zdoom.ini";
return GAMENAMELOWERCASE ".ini";
}
//===========================================================================
@ -497,12 +497,12 @@ FString GetUserFile (const char *file)
// This can be removed after a release or two
// Transfer the old zdoom directory to the new location
bool moved = false;
FString oldpath = NicePath("~/.zdoom/");
FString oldpath = NicePath("~/." GAMENAMELOWERCASE "/");
if (stat (oldpath, &extrainfo) != -1)
{
if (rename(oldpath, path) == -1)
{
I_Error ("Failed to move old zdoom directory (%s) to new location (%s).",
I_Error ("Failed to move old " GAMENAMELOWERCASE " directory (%s) to new location (%s).",
oldpath.GetChars(), path.GetChars());
}
else
@ -598,7 +598,7 @@ FString M_GetCajunPath(const char *botfilename)
FString M_GetConfigPath(bool for_reading)
{
return GetUserFile("zdoom.ini");
return GetUserFile(GAMENAMELOWERCASE ".ini");
}
//===========================================================================

View File

@ -489,7 +489,13 @@ bool FOptionMenuItem::MouseEvent(int type, int x, int y)
int FOptionMenuItem::GetIndent()
{
return mCentered? 0 : SmallFont->StringWidth(mLabel);
if (mCentered)
{
return 0;
}
const char *label = mLabel;
if (*label == '$') label = GStrings(label+1);
return SmallFont->StringWidth(label);
}
void FOptionMenuItem::drawLabel(int indent, int y, EColorRange color, bool grayed)

View File

@ -326,6 +326,7 @@ xx(Arg4)
xx(Arg0Str)
xx(Arg1Str)
xx(Id)
xx(MoreIds)
xx(V1)
xx(V2)

View File

@ -45,6 +45,35 @@
// TYPES -------------------------------------------------------------------
class OPLDump : public OPLEmul
{
public:
OPLDump(FILE *file) : File(file), TimePerTick(0), CurTime(0),
CurIntTime(0), TickMul(1), CurChip(0) {}
// If we're doing things right, these should never be reset.
virtual void Reset() { assert(0); }
// Update() is only used for getting waveform data, which dumps don't do.
virtual void Update(float *buffer, int length) { assert(0); }
// OPL dumps don't pan beyond what OPL3 is capable of (which is
// already written using registers from the original data).
virtual void SetPanning(int c, float left, float right) {}
// Only for the OPL dumpers, not the emulators
virtual void SetClockRate(double samples_per_tick) {}
virtual void WriteDelay(int ticks) = 0;
protected:
FILE *File;
double TimePerTick; // in milliseconds
double CurTime;
int CurIntTime;
int TickMul;
BYTE CurChip;
};
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
@ -59,6 +88,173 @@
// CODE --------------------------------------------------------------------
class OPL_RDOSdump : public OPLDump
{
public:
OPL_RDOSdump(FILE *file) : OPLDump(file)
{
assert(File != NULL);
fwrite("RAWADATA\0", 1, 10, File);
NeedClockRate = true;
}
virtual ~OPL_RDOSdump()
{
if (File != NULL)
{
WORD endmark = 0xFFFF;
fwrite(&endmark, 2, 1, File);
fclose(File);
}
}
virtual void WriteReg(int reg, int v)
{
assert(File != NULL);
BYTE chipnum = reg >> 8;
if (chipnum != CurChip)
{
BYTE switcher[2] = { chipnum + 1, 2 };
fwrite(switcher, 1, 2, File);
}
reg &= 255;
if (reg != 0 && reg != 2 && (reg != 255 || v != 255))
{
BYTE cmd[2] = { BYTE(v), BYTE(reg) };
fwrite(cmd, 1, 2, File);
}
}
virtual void SetClockRate(double samples_per_tick)
{
TimePerTick = samples_per_tick / OPL_SAMPLE_RATE * 1000.0;
double clock_rate;
int clock_mul;
WORD clock_word;
clock_rate = samples_per_tick * ADLIB_CLOCK_MUL;
clock_mul = 1;
// The RDos raw format's clock rate is stored in a word. Therefore,
// the longest tick that can be stored is only ~55 ms.
while (clock_rate / clock_mul + 0.5 > 65535.0)
{
clock_mul++;
}
clock_word = WORD(clock_rate / clock_mul + 0.5);
if (NeedClockRate)
{ // Set the initial clock rate.
clock_word = LittleShort(clock_word);
fseek(File, 8, SEEK_SET);
fwrite(&clock_word, 2, 1, File);
fseek(File, 0, SEEK_END);
NeedClockRate = false;
}
else
{ // Change the clock rate in the middle of the song.
BYTE clock_change[4] = { 0, 2, BYTE(clock_word & 255), BYTE(clock_word >> 8) };
fwrite(clock_change, 1, 4, File);
}
}
virtual void WriteDelay(int ticks)
{
if (ticks > 0)
{ // RDos raw has very precise delays but isn't very efficient at
// storing long delays.
BYTE delay[2];
ticks *= TickMul;
delay[1] = 0;
while (ticks > 255)
{
ticks -= 255;
delay[0] = 255;
fwrite(delay, 1, 2, File);
}
delay[0] = BYTE(ticks);
fwrite(delay, 1, 2, File);
}
}
protected:
bool NeedClockRate;
};
class OPL_DOSBOXdump : public OPLDump
{
public:
OPL_DOSBOXdump(FILE *file, bool dual) : OPLDump(file), Dual(dual)
{
assert(File != NULL);
fwrite("DBRAWOPL"
"\0\0" // Minor version number
"\1\0" // Major version number
"\0\0\0\0" // Total milliseconds
"\0\0\0", // Total data
1, 20, File);
char type[4] = { Dual * 2, 0, 0, 0 }; // Single or dual OPL-2
fwrite(type, 1, 4, File);
}
virtual ~OPL_DOSBOXdump()
{
if (File != NULL)
{
long where_am_i = ftell(File);
DWORD len[2];
fseek(File, 12, SEEK_SET);
len[0] = LittleLong(CurIntTime);
len[1] = LittleLong(DWORD(where_am_i - 24));
fwrite(len, 4, 2, File);
fclose(File);
}
}
virtual void WriteReg(int reg, int v)
{
assert(File != NULL);
BYTE chipnum = reg >> 8;
if (chipnum != CurChip)
{
CurChip = chipnum;
fputc(chipnum + 2, File);
}
reg &= 255;
BYTE cmd[3] = { 4, BYTE(reg), BYTE(v) };
fwrite (cmd + (reg > 4), 1, 3 - (reg > 4), File);
}
virtual void WriteDelay(int ticks)
{
if (ticks > 0)
{ // DosBox only has millisecond-precise delays.
int delay;
CurTime += TimePerTick * ticks;
delay = int(CurTime + 0.5) - CurIntTime;
CurIntTime += delay;
while (delay > 65536)
{
BYTE cmd[3] = { 1, 255, 255 };
fwrite(cmd, 1, 2, File);
delay -= 65536;
}
delay--;
if (delay <= 255)
{
BYTE cmd[2] = { 0, BYTE(delay) };
fwrite(cmd, 1, 2, File);
}
else
{
assert(delay <= 65535);
BYTE cmd[3] = { 1, BYTE(delay & 255), BYTE(delay >> 8) };
fwrite(cmd, 1, 3, File);
}
}
}
protected:
bool Dual;
};
//==========================================================================
//
// OPLDumperMIDIDevice Constructor
@ -139,139 +335,34 @@ DiskWriterIO::~DiskWriterIO()
//
//==========================================================================
int DiskWriterIO::OPLinit(uint numchips, bool, bool)
int DiskWriterIO::OPLinit(uint numchips, bool, bool initopl3)
{
// If the file extension is unknown or not present, the default format
// is RAW. Otherwise, you can use DRO.
if (Filename.Len() < 5 || stricmp(&Filename[Filename.Len() - 4], ".dro") != 0)
{
Format = FMT_RDOS;
}
else
{
Format = FMT_DOSBOX;
}
File = fopen(Filename, "wb");
if (File == NULL)
FILE *file = fopen(Filename, "wb");
if (file == NULL)
{
Printf("Could not open %s for writing.\n", Filename.GetChars());
return 0;
}
if (Format == FMT_RDOS)
numchips = clamp(numchips, 1u, 2u);
memset(chips, 0, sizeof(chips));
// If the file extension is unknown or not present, the default format
// is RAW. Otherwise, you can use DRO.
if (Filename.Len() < 5 || stricmp(&Filename[Filename.Len() - 4], ".dro") != 0)
{
fwrite("RAWADATA\0", 1, 10, File);
NeedClockRate = true;
chips[0] = new OPL_RDOSdump(file);
}
else
{
fwrite("DBRAWOPL"
"\0\0" // Minor version number
"\1\0" // Major version number
"\0\0\0\0" // Total milliseconds
"\0\0\0", // Total data
1, 20, File);
if (numchips == 1)
{
fwrite("\0\0\0", 1, 4, File); // Single OPL-2
chips[0] = new OPL_DOSBOXdump(file, numchips > 1);
}
else
{
fwrite("\2\0\0", 1, 4, File); // Dual OPL-2
}
NeedClockRate = false;
}
TimePerTick = 0;
TickMul = 1;
CurTime = 0;
CurIntTime = 0;
CurChip = 0;
OPLchannels = OPL2CHANNELS * numchips;
OPLwriteInitState(false);
NumChips = numchips;
IsOPL3 = numchips > 1;
OPLwriteInitState(initopl3);
return numchips;
}
//==========================================================================
//
// DiskWriterIO :: OPLdeinit
//
//==========================================================================
void DiskWriterIO::OPLdeinit()
{
if (File != NULL)
{
if (Format == FMT_RDOS)
{
WORD endmark = 65535;
fwrite(&endmark, 2, 1, File);
}
else
{
long where_am_i = ftell(File);
DWORD len[2];
fseek(File, 12, SEEK_SET);
len[0] = LittleLong(CurIntTime);
len[1] = LittleLong(DWORD(where_am_i - 24));
fwrite(len, 4, 2, File);
}
fclose(File);
File = NULL;
}
}
//==========================================================================
//
// DiskWriterIO :: OPLwriteReg
//
//==========================================================================
void DiskWriterIO::OPLwriteReg(int which, uint reg, uchar data)
{
SetChip(which);
if (Format == FMT_RDOS)
{
if (reg != 0 && reg != 2 && (reg != 255 || data != 255))
{
BYTE cmd[2] = { data, BYTE(reg) };
fwrite(cmd, 1, 2, File);
}
}
else
{
BYTE cmd[3] = { 4, BYTE(reg), data };
fwrite (cmd + (reg > 4), 1, 3 - (reg > 4), File);
}
}
//==========================================================================
//
// DiskWriterIO :: SetChip
//
//==========================================================================
void DiskWriterIO :: SetChip(int chipnum)
{
assert(chipnum == 0 || chipnum == 1);
if (chipnum != CurChip)
{
CurChip = chipnum;
if (Format == FMT_RDOS)
{
BYTE switcher[2] = { BYTE(chipnum + 1), 2 };
fwrite(switcher, 1, 2, File);
}
else
{
BYTE switcher = chipnum + 2;
fwrite(&switcher, 1, 1, File);
}
}
}
//==========================================================================
//
// DiskWriterIO :: SetClockRate
@ -280,39 +371,7 @@ void DiskWriterIO :: SetChip(int chipnum)
void DiskWriterIO::SetClockRate(double samples_per_tick)
{
TimePerTick = samples_per_tick / OPL_SAMPLE_RATE * 1000.0;
if (Format == FMT_RDOS)
{
double clock_rate;
int clock_mul;
WORD clock_word;
clock_rate = samples_per_tick * ADLIB_CLOCK_MUL;
clock_mul = 1;
// The RDos raw format's clock rate is stored in a word. Therefore,
// the longest tick that can be stored is only ~55 ms.
while (clock_rate / clock_mul + 0.5 > 65535.0)
{
clock_mul++;
}
clock_word = WORD(clock_rate / clock_mul + 0.5);
if (NeedClockRate)
{ // Set the initial clock rate.
clock_word = LittleShort(clock_word);
fseek(File, 8, SEEK_SET);
fwrite(&clock_word, 2, 1, File);
fseek(File, 0, SEEK_END);
NeedClockRate = false;
}
else
{ // Change the clock rate in the middle of the song.
BYTE clock_change[4] = { 0, 2, BYTE(clock_word & 255), BYTE(clock_word >> 8) };
fwrite(clock_change, 1, 4, File);
}
}
static_cast<OPLDump *>(chips[0])->SetClockRate(samples_per_tick);
}
//==========================================================================
@ -323,50 +382,5 @@ void DiskWriterIO::SetClockRate(double samples_per_tick)
void DiskWriterIO :: WriteDelay(int ticks)
{
if (ticks <= 0)
{
return;
}
if (Format == FMT_RDOS)
{ // RDos raw has very precise delays but isn't very efficient at
// storing long delays.
BYTE delay[2];
ticks *= TickMul;
delay[1] = 0;
while (ticks > 255)
{
ticks -= 255;
delay[0] = 255;
fwrite(delay, 1, 2, File);
}
delay[0] = BYTE(ticks);
fwrite(delay, 1, 2, File);
}
else
{ // DosBox only has millisecond-precise delays.
int delay;
CurTime += TimePerTick * ticks;
delay = int(CurTime + 0.5) - CurIntTime;
CurIntTime += delay;
while (delay > 65536)
{
BYTE cmd[3] = { 1, 255, 255 };
fwrite(cmd, 1, 2, File);
delay -= 65536;
}
delay--;
if (delay <= 255)
{
BYTE cmd[2] = { 0, BYTE(delay) };
fwrite(cmd, 1, 2, File);
}
else
{
assert(delay <= 65535);
BYTE cmd[3] = { 1, BYTE(delay & 255), BYTE(delay >> 8) };
fwrite(cmd, 1, 3, File);
}
}
static_cast<OPLDump *>(chips[0])->WriteDelay(ticks);
}

View File

@ -195,25 +195,11 @@ struct DiskWriterIO : public OPLio
DiskWriterIO(const char *filename);
~DiskWriterIO();
int OPLinit(uint numchips, bool notused=false, bool notused2=false);
void OPLdeinit();
void OPLwriteReg(int which, uint reg, uchar data);
int OPLinit(uint numchips, bool notused, bool initopl3);
void SetClockRate(double samples_per_tick);
void WriteDelay(int ticks);
void SetChip(int chipnum);
FILE *File;
FString Filename;
int Format;
bool NeedClockRate;
double TimePerTick; // In milliseconds
double CurTime;
int CurIntTime;
int TickMul;
int CurChip;
enum { FMT_RDOS, FMT_DOSBOX };
};
struct musicBlock {

View File

@ -220,7 +220,8 @@ static int P_Set3DFloor(line_t * line, int param, int param2, int alpha)
int tag=line->args[0];
sector_t * sec = line->frontsector, * ss;
for (s=-1; (s = P_FindSectorFromTag(tag,s)) >= 0;)
FSectorTagIterator it(tag);
while ((s = it.Next()) >= 0)
{
ss=&sectors[s];
@ -488,7 +489,7 @@ void P_Recalculate3DFloors(sector_t * sector)
// by the clipping code below.
ffloors.Push(pick);
}
else if ((pick->flags&(FF_SWIMMABLE|FF_TRANSLUCENT) || (!(pick->flags&(FF_ALLSIDES|FF_BOTHPLANES)))) && pick->flags&FF_EXISTS)
else if ((pick->flags&(FF_SWIMMABLE|FF_TRANSLUCENT) || (!(pick->flags&FF_RENDERALL))) && pick->flags&FF_EXISTS)
{
// We must check if this nonsolid segment gets clipped from the top by another 3D floor
if (solid != NULL && solid_bottom < height)
@ -843,7 +844,7 @@ void P_Spawn3DFloors (void)
{
if (line->args[1]&8)
{
line->id = line->args[4];
tagManager.AddLineID(i, line->args[4]);
}
else
{

View File

@ -143,7 +143,9 @@ void P_Attach3dMidtexLinesToSector(sector_t *sector, int lineid, int tag, bool c
if (tag == 0)
{
for(int line = -1; (line = P_FindLineFromID(lineid,line)) >= 0; )
FLineIdIterator itr(lineid);
int line;
while ((line = itr.Next()) >= 0)
{
line_t *ln = &lines[line];
@ -157,13 +159,15 @@ void P_Attach3dMidtexLinesToSector(sector_t *sector, int lineid, int tag, bool c
}
else
{
for(int sec = -1; (sec = P_FindSectorFromTag(tag, sec)) >= 0; )
FSectorTagIterator it(tag);
int sec;
while ((sec = it.Next()) >= 0)
{
for (int line = 0; line < sectors[sec].linecount; line ++)
{
line_t *ln = sectors[sec].lines[line];
if (lineid != 0 && ln->id != lineid) continue;
if (lineid != 0 && !tagManager.LineHasID(ln, lineid)) continue;
if (ln->frontsector == NULL || ln->backsector == NULL || !(ln->flags & ML_3DMIDTEX))
{

View File

@ -1341,7 +1341,7 @@ DPlaneWatcher::DPlaneWatcher (AActor *it, line_t *line, int lineSide, bool ceili
{
int secnum;
secnum = P_FindSectorFromTag (tag, -1);
secnum = P_FindFirstSectorFromTag (tag);
if (secnum >= 0)
{
secplane_t plane;
@ -1409,12 +1409,6 @@ void DPlaneWatcher::Tick ()
// own behavior is loaded (if it has one).
void FBehavior::StaticLoadDefaultModules ()
{
// When playing Strife, STRFHELP is always loaded.
if (gameinfo.gametype == GAME_Strife)
{
StaticLoadModule (Wads.CheckNumForName ("STRFHELP", ns_acslibrary));
}
// Scan each LOADACS lump and load the specified modules in order
int lump, lastlump = 0;
@ -3217,7 +3211,7 @@ do_count:
if (actor->health > 0 &&
(kind == NULL || actor->IsA (kind)))
{
if (actor->Sector->tag == tag || tag == -1)
if (tag == -1 || tagManager.SectorHasTag(actor->Sector, tag))
{
// Don't count items in somebody's inventory
if (!actor->IsKindOf (RUNTIME_CLASS(AInventory)) ||
@ -3237,7 +3231,7 @@ do_count:
if (actor->health > 0 &&
(kind == NULL || actor->IsA (kind)))
{
if (actor->Sector->tag == tag || tag == -1)
if (tag == -1 || tagManager.SectorHasTag(actor->Sector, tag))
{
// Don't count items in somebody's inventory
if (!actor->IsKindOf (RUNTIME_CLASS(AInventory)) ||
@ -3274,7 +3268,8 @@ void DLevelScript::ChangeFlat (int tag, int name, bool floorOrCeiling)
flat = TexMan.GetTexture (flatname, FTexture::TEX_Flat, FTextureManager::TEXMAN_Overridable);
while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0)
FSectorTagIterator it(tag);
while ((secnum = it.Next()) >= 0)
{
int pos = floorOrCeiling? sector_t::ceiling : sector_t::floor;
sectors[secnum].SetTexture(pos, flat);
@ -3305,7 +3300,8 @@ void DLevelScript::SetLineTexture (int lineid, int side, int position, int name)
texture = TexMan.GetTexture (texname, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable);
while ((linenum = P_FindLineFromID (lineid, linenum)) >= 0)
FLineIdIterator itr(lineid);
while ((linenum = itr.Next()) >= 0)
{
side_t *sidedef;
@ -3903,7 +3899,13 @@ void DLevelScript::DoSetActorProperty (AActor *actor, int property, int value)
case APROP_ViewHeight:
if (actor->IsKindOf (RUNTIME_CLASS (APlayerPawn)))
{
static_cast<APlayerPawn *>(actor)->ViewHeight = value;
if (actor->player != NULL)
{
actor->player->viewheight = value;
}
}
break;
case APROP_AttackZOffset:
@ -4463,7 +4465,7 @@ int DLevelScript::SideFromID(int id, int side)
}
else
{
int line = P_FindLineFromID(id, -1);
int line = P_FindFirstLineFromID(id);
if (line == -1) return -1;
if (lines[line].sidedef[side] == NULL) return -1;
return lines[line].sidedef[side]->Index;
@ -4479,7 +4481,7 @@ int DLevelScript::LineFromID(int id)
}
else
{
return P_FindLineFromID(id, -1);
return P_FindFirstLineFromID(id);
}
}
@ -4767,25 +4769,19 @@ static void SetActorRoll(AActor *activator, int tid, int angle, bool interpolate
}
}
static void SetActorTeleFog(AActor *activator, int tid, FName telefogsrc, FName telefogdest)
static void SetActorTeleFog(AActor *activator, int tid, FString telefogsrc, FString telefogdest)
{
//Simply put, if it doesn't exist, it won't change. One can use "" in this scenario.
const PClass *check;
// Set the actor's telefog to the specified actor. Handle "" as "don't
// change" since "None" should work just fine for disabling the fog (given
// that it will resolve to NAME_None which is not a valid actor name).
if (tid == 0)
{
if (activator != NULL)
{
check = PClass::FindClass(telefogsrc);
if (check == NULL || !stricmp(telefogsrc, "none") || !stricmp(telefogsrc, "null"))
activator->TeleFogSourceType = NULL;
else
activator->TeleFogSourceType = check;
check = PClass::FindClass(telefogdest);
if (check == NULL || !stricmp(telefogdest, "none") || !stricmp(telefogdest, "null"))
activator->TeleFogDestType = NULL;
else
activator->TeleFogDestType = check;
if (telefogsrc.IsNotEmpty())
activator->TeleFogSourceType = PClass::FindClass(telefogsrc);
if (telefogdest.IsNotEmpty())
activator->TeleFogDestType = PClass::FindClass(telefogdest);
}
}
else
@ -4793,19 +4789,14 @@ static void SetActorTeleFog(AActor *activator, int tid, FName telefogsrc, FName
FActorIterator iterator(tid);
AActor *actor;
const PClass * const src = telefogsrc.IsNotEmpty() ? PClass::FindClass(telefogsrc) : NULL;
const PClass * const dest = telefogdest.IsNotEmpty() ? PClass::FindClass(telefogdest) : NULL;
while ((actor = iterator.Next()))
{
check = PClass::FindClass(telefogsrc);
if (check == NULL || !stricmp(telefogsrc, "none") || !stricmp(telefogsrc, "null"))
actor->TeleFogSourceType = NULL;
else
actor->TeleFogSourceType = check;
check = PClass::FindClass(telefogdest);
if (check == NULL || !stricmp(telefogdest, "none") || !stricmp(telefogdest, "null"))
actor->TeleFogDestType = NULL;
else
actor->TeleFogDestType = check;
if (telefogsrc.IsNotEmpty())
actor->TeleFogSourceType = src;
if (telefogdest.IsNotEmpty())
actor->TeleFogDestType = dest;
}
}
}
@ -4856,10 +4847,10 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args, const
return 0; // Not implemented yet
case ACSF_GetSectorUDMFInt:
return GetUDMFInt(UDMF_Sector, P_FindSectorFromTag(args[0], -1), FBehavior::StaticLookupString(args[1]));
return GetUDMFInt(UDMF_Sector, P_FindFirstSectorFromTag(args[0]), FBehavior::StaticLookupString(args[1]));
case ACSF_GetSectorUDMFFixed:
return GetUDMFFixed(UDMF_Sector, P_FindSectorFromTag(args[0], -1), FBehavior::StaticLookupString(args[1]));
return GetUDMFFixed(UDMF_Sector, P_FindFirstSectorFromTag(args[0]), FBehavior::StaticLookupString(args[1]));
case ACSF_GetSideUDMFInt:
return GetUDMFInt(UDMF_Side, SideFromID(args[0], args[1]), FBehavior::StaticLookupString(args[2]));
@ -5186,11 +5177,11 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args, const
int space = args[2] < CHAN_FLOOR || args[2] > CHAN_INTERIOR ? CHAN_FULLHEIGHT : args[2];
if (seqname != NULL)
{
int secnum = -1;
while ((secnum = P_FindSectorFromTag(args[0], secnum)) >= 0)
FSectorTagIterator it(args[0]);
int s;
while ((s = it.Next()) >= 0)
{
SN_StartSequence(&sectors[secnum], args[2], seqname, 0);
SN_StartSequence(&sectors[s], args[2], seqname, 0);
}
}
}
@ -5709,9 +5700,9 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound)
case ACSF_SetLineActivation:
if (argCount >= 2)
{
int line = -1;
while ((line = P_FindLineFromID(args[0], line)) >= 0)
int line;
FLineIdIterator itr(args[0]);
while ((line = itr.Next()) >= 0)
{
lines[line].activation = args[1];
}
@ -5721,7 +5712,7 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound)
case ACSF_GetLineActivation:
if (argCount > 0)
{
int line = P_FindLineFromID(args[0], -1);
int line = P_FindFirstLineFromID(args[0]);
return line >= 0 ? lines[line].activation : 0;
}
break;
@ -5969,11 +5960,13 @@ int DLevelScript::RunScript ()
// Wait for tagged sector(s) to go inactive, then enter
// state running
{
int secnum = -1;
while ((secnum = P_FindSectorFromTag (statedata, secnum)) >= 0)
int secnum;
FSectorTagIterator it(statedata);
while ((secnum = it.Next()) >= 0)
{
if (sectors[secnum].floordata || sectors[secnum].ceilingdata)
return resultValue;
}
// If we got here, none of the tagged sectors were busy
state = SCRIPT_Running;
@ -8013,9 +8006,10 @@ scriptwait:
case PCD_SETLINEBLOCKING:
{
int line = -1;
int line;
while ((line = P_FindLineFromID (STACK(2), line)) >= 0)
FLineIdIterator itr(STACK(2));
while ((line = itr.Next()) >= 0)
{
switch (STACK(1))
{
@ -8048,9 +8042,10 @@ scriptwait:
case PCD_SETLINEMONSTERBLOCKING:
{
int line = -1;
int line;
while ((line = P_FindLineFromID (STACK(2), line)) >= 0)
FLineIdIterator itr(STACK(2));
while ((line = itr.Next()) >= 0)
{
if (STACK(1))
lines[line].flags |= ML_BLOCKMONSTERS;
@ -8075,7 +8070,8 @@ scriptwait:
arg0 = -FName(FBehavior::StaticLookupString(arg0));
}
while ((linenum = P_FindLineFromID (STACK(7), linenum)) >= 0)
FLineIdIterator itr(STACK(7));
while ((linenum = itr.Next()) >= 0)
{
line_t *line = &lines[linenum];
line->special = specnum;
@ -8535,7 +8531,7 @@ scriptwait:
fixed_t z = 0;
if (tag != 0)
secnum = P_FindSectorFromTag (tag, -1);
secnum = P_FindFirstSectorFromTag (tag);
else
secnum = int(P_PointInSector (x, y) - sectors);
@ -8557,7 +8553,7 @@ scriptwait:
case PCD_GETSECTORLIGHTLEVEL:
{
int secnum = P_FindSectorFromTag (STACK(1), -1);
int secnum = P_FindFirstSectorFromTag (STACK(1));
int z = -1;
if (secnum >= 0)

View File

@ -716,30 +716,31 @@ static int LoadSprites (spritetype *sprites, Xsprite *xsprites, int numsprites,
mapthings[count].args[1] = xsprites[i].Data4;
mapthings[count].args[2] = xsprites[i].Data1;
mapthings[count].args[3] = xsprites[i].Data2;
mapthings[count].type = 14065;
mapthings[count].EdNum = 14065;
}
else if (xsprites != NULL && sprites[i].lotag == 1)
{ // Blood player start
if (xsprites[i].Data1 < 4)
mapthings[count].type = 1 + xsprites[i].Data1;
mapthings[count].EdNum= 1 + xsprites[i].Data1;
else
mapthings[count].type = gameinfo.player5start + xsprites[i].Data1 - 4;
mapthings[count].EdNum = 4001 + xsprites[i].Data1 - 4;
}
else if (xsprites != NULL && sprites[i].lotag == 2)
{ // Bloodbath start
mapthings[count].type = 11;
mapthings[count].EdNum = 11;
}
else
{
if (sprites[i].cstat & 32768) continue;
if (sprites[i].xrepeat == 0 || sprites[i].yrepeat == 0) continue;
mapthings[count].type = 9988;
mapthings[count].EdNum = 9988;
mapthings[count].args[0] = sprites[i].picnum;
mapthings[count].args[2] = sprites[i].xrepeat;
mapthings[count].args[3] = sprites[i].yrepeat;
mapthings[count].args[4] = sprites[i].cstat;
}
mapthings[count].info = DoomEdMap.CheckKey(mapthings[count].EdNum);
count++;
}
return count;
@ -780,14 +781,14 @@ vertex_t *FindVertex (fixed_t x, fixed_t y)
static void CreateStartSpot (fixed_t *pos, FMapThing *start)
{
short angle = LittleShort(*(WORD *)(&pos[3]));
FMapThing mt =
{
0, (LittleLong(pos[0])<<12), ((-LittleLong(pos[1]))<<12), 0,// tid, x, y, z
short(Scale ((2048-angle)&2047, 360, 2048)), 1, // angle, type
0, 0, // Skillfilter, Classfilter
7|MTF_SINGLE|224, // flags
0, {0}, 0 // special is 0, args and Conversation are 0
};
FMapThing mt = { 0, };
mt.x = LittleLong(pos[0])<<12;
mt.y = (-LittleLong(pos[1]))<<12;
mt.angle = short(Scale((2048-angle)&2047, 360, 2048));
mt.info = DoomEdMap.CheckKey(1);
mt.EdNum = 1;
mt.flags = 7|MTF_SINGLE|224;
*start = mt;
}

View File

@ -510,9 +510,9 @@ bool EV_DoCeiling (DCeiling::ECeiling type, line_t *line,
P_ActivateInStasisCeiling (tag);
}
secnum = -1;
// affects all sectors with the same tag as the linedef
while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0)
FSectorTagIterator it(tag);
while ((secnum = it.Next()) >= 0)
{
rtn |= !!DCeiling::Create(&sectors[secnum], type, line, tag, speed, speed2, height, crush, silent, change, hexencrush);
}

View File

@ -60,6 +60,7 @@
#include "farchive.h"
#include "p_lnspec.h"
#include "r_utility.h"
#include "p_local.h"
#include "menu/menu.h"
// The conversations as they exist inside a SCRIPTxx lump.
@ -105,11 +106,10 @@ void GiveSpawner (player_t *player, const PClass *type);
TArray<FStrifeDialogueNode *> StrifeDialogues;
typedef TMap<int, const PClass *> FStrifeTypeMap; // maps conversation IDs to actor classes
typedef TMap<int, int> FDialogueIDMap; // maps dialogue IDs to dialogue array index (for ACS)
typedef TMap<FName, int> FDialogueMap; // maps actor class names to dialogue array index
static FStrifeTypeMap StrifeTypes;
FClassMap StrifeTypes;
static FDialogueIDMap DialogueRoots;
static FDialogueMap ClassRoots;
static int ConversationMenuY;

View File

@ -484,8 +484,8 @@ bool EV_DoDoor (DDoor::EVlDoor type, line_t *line, AActor *thing,
else
{ // [RH] Remote door
secnum = -1;
while ((secnum = P_FindSectorFromTag (tag,secnum)) >= 0)
FSectorTagIterator it(tag);
while ((secnum = it.Next()) >= 0)
{
sec = &sectors[secnum];
// if the ceiling is already moving, don't start the door action
@ -812,7 +812,8 @@ bool EV_SlidingDoor (line_t *line, AActor *actor, int tag, int speed, int delay)
return false;
}
while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0)
FSectorTagIterator it(tag);
while ((secnum = it.Next()) >= 0)
{
sec = &sectors[secnum];
if (sec->ceilingdata != NULL)

View File

@ -586,7 +586,7 @@ void P_DrawSplash2 (int count, fixed_t x, fixed_t y, fixed_t z, angle_t angle, i
}
}
void P_DrawRailTrail (AActor *source, const FVector3 &start, const FVector3 &end, int color1, int color2, float maxdiff, int flags, const PClass *spawnclass, angle_t angle, int duration, float sparsity, float drift)
void P_DrawRailTrail (AActor *source, const FVector3 &start, const FVector3 &end, int color1, int color2, float maxdiff, int flags, const PClass *spawnclass, angle_t angle, int duration, float sparsity, float drift, int SpiralOffset)
{
double length, lengthsquared;
int steps, i;
@ -678,7 +678,7 @@ void P_DrawRailTrail (AActor *source, const FVector3 &start, const FVector3 &end
color1 = color1 == 0 ? -1 : ParticleColor(color1);
pos = start;
deg = FAngle(270);
deg = FAngle(SpiralOffset);
for (i = spiral_steps; i; i--)
{
particle_t *p = NewParticle ();

View File

@ -88,7 +88,7 @@ void P_RunEffects (void);
void P_RunEffect (AActor *actor, int effects);
void P_DrawRailTrail (AActor *source, const FVector3 &start, const FVector3 &end, int color1, int color2, float maxdiff = 0, int flags = 0, const PClass *spawnclass = NULL, angle_t angle = 0, int duration = 35, float sparsity = 1.0, float drift = 1.0);
void P_DrawRailTrail (AActor *source, const FVector3 &start, const FVector3 &end, int color1, int color2, float maxdiff = 0, int flags = 0, const PClass *spawnclass = NULL, angle_t angle = 0, int duration = 35, float sparsity = 1.0, float drift = 1.0, int SpiralOffset = 270);
void P_DrawSplash (int count, fixed_t x, fixed_t y, fixed_t z, angle_t angle, int kind);
void P_DrawSplash2 (int count, fixed_t x, fixed_t y, fixed_t z, angle_t angle, int updown, int kind);
void P_DisconnectEffect (AActor *actor);

View File

@ -44,6 +44,7 @@
#include "thingdef/thingdef.h"
#include "d_dehacked.h"
#include "g_level.h"
#include "r_data/r_translate.h"
#include "teaminfo.h"
#include "gi.h"
@ -2615,7 +2616,7 @@ static bool P_CheckForResurrection(AActor *self, bool usevilestates)
S_Sound(corpsehit, CHAN_BODY, "vile/raise", 1, ATTN_IDLE);
info = corpsehit->GetDefault();
if (corpsehit->state == corpsehit->FindState(NAME_GenericCrush))
if (GetTranslationType(corpsehit->Translation) == TRANSLATION_Blood)
{
corpsehit->Translation = info->Translation; // Clean up bloodcolor translation from crushed corpses
}
@ -3203,9 +3204,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Die)
ACTION_PARAM_START(1);
ACTION_PARAM_NAME(damagetype, 0);
if (self->flags & MF_MISSILE)
P_ExplodeMissile(self, NULL, NULL);
else
P_DamageMobj (self, NULL, NULL, self->health, damagetype, DMG_FORCED);
}

View File

@ -290,28 +290,13 @@ bool EV_DoFloor (DFloor::EFloor floortype, line_t *line, int tag,
rtn = false;
// check if a manual trigger; if so do just the sector on the backside
if (tag == 0)
{
if (!line || !(sec = line->backsector))
return rtn;
secnum = (int)(sec-sectors);
goto manual_floor;
}
secnum = -1;
while (tag && (secnum = P_FindSectorFromTag (tag, secnum)) >= 0)
FSectorTagIterator it(tag, line);
while ((secnum = it.Next()) >= 0)
{
sec = &sectors[secnum];
manual_floor:
// ALREADY MOVING? IF SO, KEEP GOING...
if (sec->PlaneMoving(sector_t::floor))
{
// There was a test for 0/non-0 here, supposed to prevent 0-tags from executing "continue" and searching for unrelated sectors
// Unfortunately, the condition had been reversed, so that searches for tag-0 would continue,
// while numbered tags would abort (return false, even if some floors have been successfully triggered)
// All occurences of the condition (faulty or not) have been replaced by a looping condition: Looping only occurs if we're looking for a non-0 tag.
continue;
}
@ -545,9 +530,9 @@ manual_floor:
bool EV_FloorCrushStop (int tag)
{
int secnum = -1;
while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0)
int secnum;
FSectorTagIterator it(tag);
while ((secnum = it.Next()) >= 0)
{
sector_t *sec = sectors + secnum;
@ -562,21 +547,6 @@ bool EV_FloorCrushStop (int tag)
return true;
}
//==========================================================================
//
// Linear tag search to emulate stair building from Doom.exe
//
//==========================================================================
static int P_FindSectorFromTagLinear (int tag, int start)
{
for (int i=start+1;i<numsectors;i++)
{
if (sectors[i].tag == tag) return i;
}
return -1;
}
//==========================================================================
//
// BUILD A STAIRCASE!
@ -591,7 +561,7 @@ bool EV_BuildStairs (int tag, DFloor::EStair type, line_t *line,
fixed_t stairsize, fixed_t speed, int delay, int reset, int igntxt,
int usespecials)
{
int secnum;
int secnum = -1;
int osecnum; //jff 3/4/98 save old loop index
int height;
fixed_t stairstep;
@ -607,44 +577,27 @@ bool EV_BuildStairs (int tag, DFloor::EStair type, line_t *line,
sector_t* prev = NULL;
DFloor* floor;
bool manual = false;
if (speed == 0)
return false;
persteptime = FixedDiv (stairsize, speed) >> FRACBITS;
int (* FindSector) (int tag, int start) =
(i_compatflags & COMPATF_STAIRINDEX)? P_FindSectorFromTagLinear : P_FindSectorFromTag;
// check if a manual trigger, if so do just the sector on the backside
if (tag == 0)
{
if (!line || !(sec = line->backsector))
return rtn;
secnum = (int)(sec-sectors);
manual = true;
goto manual_stair;
}
FSectorTagIterator itr(tag, line);
// The compatibility mode doesn't work with a hashing algorithm.
// It needs the original linear search method. This was broken in Boom.
secnum = -1;
while ((secnum = FindSector (tag, secnum)) >= 0)
bool compatible = tag != 0 && (i_compatflags & COMPATF_STAIRINDEX);
while ((secnum = itr.NextCompat(compatible, secnum)) >= 0)
{
sec = &sectors[secnum];
manual_stair:
// ALREADY MOVING? IF SO, KEEP GOING...
//jff 2/26/98 add special lockout condition to wait for entire
//staircase to build before retriggering
if (sec->PlaneMoving(sector_t::floor) || sec->stairlock)
{
if (!manual)
continue;
else
return rtn;
}
// new floor thinker
@ -781,14 +734,6 @@ manual_stair:
// [RH] make sure the first sector doesn't point to a previous one, otherwise
// it can infinite loop when the first sector stops moving.
sectors[osecnum].prevsec = -1;
if (manual)
{
return rtn;
}
if (!(i_compatflags & COMPATF_STAIRINDEX))
{
secnum = osecnum; //jff 3/4/98 restore loop index
}
}
return rtn;
}
@ -811,21 +756,13 @@ bool EV_DoDonut (int tag, line_t *line, fixed_t pillarspeed, fixed_t slimespeed)
vertex_t* spot;
fixed_t height;
secnum = -1;
rtn = false;
if (tag == 0)
{
if (!line || !(s1 = line->backsector))
return rtn;
goto manual_donut;
}
while (tag && (secnum = P_FindSectorFromTag(tag,secnum)) >= 0)
FSectorTagIterator itr(tag, line);
while ((secnum = itr.Next()) >= 0)
{
s1 = &sectors[secnum]; // s1 is pillar's sector
manual_donut:
// ALREADY MOVING? IF SO, KEEP GOING...
if (s1->PlaneMoving(sector_t::floor))
continue; // safe now, because we check that tag is non-0 in the looping condition [fdari]
@ -1042,19 +979,12 @@ bool EV_DoElevator (line_t *line, DElevator::EElevator elevtype,
secnum = -1;
rtn = false;
if (tag == 0)
{
if (!line || !(sec = line->backsector))
return rtn;
goto manual_elevator;
}
FSectorTagIterator itr(tag, line);
// act on all sectors with the same tag as the triggering linedef
while (tag && (secnum = P_FindSectorFromTag (tag, secnum)) >= 0) // never loop for a non-0 tag (condition moved to beginning of loop) [FDARI]
while ((secnum = itr.Next()) >= 0)
{
sec = &sectors[secnum];
manual_elevator:
// If either floor or ceiling is already activated, skip it
if (sec->PlaneMoving(sector_t::floor) || sec->ceilingdata) //jff 2/22/98
continue; // the loop used to break at the end if tag were 0, but would miss that step if "continue" occured [FDARI]
@ -1142,10 +1072,10 @@ bool EV_DoChange (line_t *line, EChange changetype, int tag)
sector_t *sec;
sector_t *secm;
secnum = -1;
rtn = false;
// change all sectors with the same tag as the linedef
while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0)
FSectorTagIterator it(tag);
while ((secnum = it.Next()) >= 0)
{
sec = &sectors[secnum];
@ -1374,20 +1304,12 @@ bool EV_StartWaggle (int tag, line_t *line, int height, int speed, int offset,
bool retCode;
retCode = false;
sectorIndex = -1;
if (tag == 0)
{
if (!line || !(sector = line->backsector))
return retCode;
goto manual_waggle;
}
FSectorTagIterator itr(tag, line);
while (tag && (sectorIndex = P_FindSectorFromTag(tag, sectorIndex)) >= 0)
while ((sectorIndex = itr.Next()) >= 0)
{
sector = &sectors[sectorIndex];
manual_waggle:
if ((!ceiling && sector->PlaneMoving(sector_t::floor)) ||
(ceiling && sector->PlaneMoving(sector_t::ceiling)))
{ // Already busy with another thinker

View File

@ -338,7 +338,14 @@ static bool LoadGLSegs(FileReader * lump)
ml->side=LittleShort(ml->side);
segs[i].sidedef = ldef->sidedef[ml->side];
if (ldef->sidedef[ml->side] != NULL)
{
segs[i].frontsector = ldef->sidedef[ml->side]->sector;
}
else
{
segs[i].frontsector = NULL;
}
if (ldef->flags & ML_TWOSIDED && ldef->sidedef[ml->side^1] != NULL)
{
segs[i].backsector = ldef->sidedef[ml->side^1]->sector;
@ -346,7 +353,7 @@ static bool LoadGLSegs(FileReader * lump)
else
{
ldef->flags &= ~ML_TWOSIDED;
segs[i].backsector = 0;
segs[i].backsector = NULL;
}
}
@ -385,7 +392,14 @@ static bool LoadGLSegs(FileReader * lump)
ml->side=LittleShort(ml->side);
segs[i].sidedef = ldef->sidedef[ml->side];
if (ldef->sidedef[ml->side] != NULL)
{
segs[i].frontsector = ldef->sidedef[ml->side]->sector;
}
else
{
segs[i].frontsector = NULL;
}
if (ldef->flags & ML_TWOSIDED && ldef->sidedef[ml->side^1] != NULL)
{
segs[i].backsector = ldef->sidedef[ml->side^1]->sector;
@ -393,7 +407,7 @@ static bool LoadGLSegs(FileReader * lump)
else
{
ldef->flags &= ~ML_TWOSIDED;
segs[i].backsector = 0;
segs[i].backsector = NULL;
}
}

View File

@ -925,9 +925,9 @@ static inline bool MustForcePain(AActor *target, AActor *inflictor)
(inflictor->flags6 & MF6_FORCEPAIN) && !(inflictor->flags5 & MF5_PAINLESS));
}
static inline bool isFakePain(AActor *target, AActor *inflictor)
static inline bool isFakePain(AActor *target, AActor *inflictor, int damage)
{
return ((target->flags7 & MF7_ALLOWPAIN) || ((inflictor != NULL) && (inflictor->flags7 & MF7_CAUSEPAIN)));
return ((target->flags7 & MF7_ALLOWPAIN && damage > 0) || ((inflictor != NULL) && (inflictor->flags7 & MF7_CAUSEPAIN)));
}
@ -950,13 +950,15 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
int fakeDamage = 0;
int holdDamage = 0;
if (damage < 0) damage = 0;
if (target == NULL || !((target->flags & MF_SHOOTABLE) || (target->flags6 & MF6_VULNERABLE)))
{ // Shouldn't happen
return -1;
}
//Rather than unnecessarily call the function over and over again, let's be a little more efficient.
fakedPain = (isFakePain(target, inflictor));
fakedPain = (isFakePain(target, inflictor, damage));
forcedPain = (MustForcePain(target, inflictor));
// Spectral targets only take damage from spectral projectiles.
@ -989,9 +991,11 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
{
if (fakedPain)
{
invulpain = true; //This returns -1 later.
fakeDamage = damage;
goto fakepain; //The label is above the massive pile of checks.
// big mess here: What do we use for the pain threshold?
// We cannot run the various damage filters below so for consistency it needs to be 0.
damage = 0;
invulpain = true;
goto fakepain;
}
else
return -1;
@ -1010,12 +1014,6 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
}
}
if ((fakedPain) && (damage < TELEFRAG_DAMAGE))
{
//Intentionally do not jump to fakepain because the damage hasn't been dished out yet.
//Once it's dished out, THEN we can disregard damage factors affecting pain chances.
fakeDamage = damage;
}
if (inflictor != NULL)
{
@ -1035,7 +1033,9 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
{
target->velx = target->vely = target->velz = 0;
}
if (!(flags & DMG_FORCED)) // DMG_FORCED skips all special damage checks
player = target->player;
if (!(flags & DMG_FORCED)) // DMG_FORCED skips all special damage checks, TELEFRAG_DAMAGE may not be reduced at all
{
if (target->flags2 & MF2_DORMANT)
{
@ -1043,8 +1043,9 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
return -1;
}
player = target->player;
if (player && damage > 1 && damage < TELEFRAG_DAMAGE)
if (damage < TELEFRAG_DAMAGE) // TELEFRAG_DAMAGE may not be reduced at all or it may not guarantee its effect.
{
if (player && damage > 1)
{
// Take half damage in trainer mode
damage = FixedMul(damage, G_SkillProperty(SKILLP_DamageFactor));
@ -1065,83 +1066,74 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
return -1;
}
}
if (damage > 0)
damage = inflictor->DoSpecialDamage (target, damage, mod);
if ((damage == -1) && (target->player == NULL)) //This isn't meant for the player.
damage = inflictor->DoSpecialDamage(target, damage, mod);
if (damage < 0)
{
if (fakedPain) //Hold off ending the function before we can deal the pain chances.
goto fakepain;
return -1;
}
}
// Handle active damage modifiers (e.g. PowerDamage)
if (source != NULL)
{
int olddam = damage;
if (source->Inventory != NULL)
if (damage > 0 && source != NULL)
{
source->Inventory->ModifyDamage(olddam, mod, damage, false);
}
damage = FixedMul(damage, source->DamageMultiply);
if (((source->flags7 & MF7_CAUSEPAIN) && (fakeDamage <= 0)) || (olddam != damage && damage <= 0))
{ // Still allow FORCEPAIN
if (forcedPain)
goto dopain;
else if (fakedPain)
goto fakepain;
return -1;
// Handle active damage modifiers (e.g. PowerDamage)
if (damage > 0 && source->Inventory != NULL)
{
source->Inventory->ModifyDamage(damage, mod, damage, false);
}
}
// Handle passive damage modifiers (e.g. PowerProtection), provided they are not afflicted with protection penetrating powers.
if ((target->Inventory != NULL) && !(flags & DMG_NO_PROTECT))
if (damage > 0 && (target->Inventory != NULL) && !(flags & DMG_NO_PROTECT))
{
int olddam = damage;
target->Inventory->ModifyDamage(olddam, mod, damage, true);
if ((olddam != damage && damage <= 0) && target->player == NULL)
{ // Still allow FORCEPAIN and make sure we're still passing along fake damage to hit enemies for their pain states.
if (forcedPain)
goto dopain;
else if (fakedPain)
goto fakepain;
return -1;
target->Inventory->ModifyDamage(damage, mod, damage, true);
}
}
if (!(flags & DMG_NO_FACTOR))
if (damage > 0 && !(flags & DMG_NO_FACTOR))
{
damage = FixedMul(damage, target->DamageFactor);
if (damage > 0)
{
damage = DamageTypeDefinition::ApplyMobjDamageFactor(damage, mod, target->GetClass()->ActorInfo->DamageFactors);
}
if (damage <= 0 && target->player == NULL)
}
if (damage >= 0)
{
damage = target->TakeSpecialDamage(inflictor, source, damage, mod);
}
// '<0' is handled below. This only handles the case where damage gets reduced to 0.
if (damage == 0 && olddam > 0)
{
{ // Still allow FORCEPAIN
if (forcedPain)
{
goto dopain;
}
else if (fakedPain)
{
goto fakepain;
}
return -1;
}
}
if (damage > 0)
damage = target->TakeSpecialDamage (inflictor, source, damage, mod);
}
if (damage == -1 && target->player == NULL) //Make sure it's not a player, the pain has yet to be processed with cheats.
if (target->flags5 & MF5_NODAMAGE)
{
if (fakedPain)
goto fakepain;
damage = 0;
}
}
if (damage < 0)
{
// any negative value means that something in the above chain has cancelled out all damage and all damage effects, including pain.
return -1;
}
// Push the target unless the source's weapon's kickback is 0.
// (i.e. Gauntlets/Chainsaw)
if (!(plrDontThrust) && inflictor && inflictor != target // [RH] Not if hurting own self
if (!plrDontThrust && inflictor && inflictor != target // [RH] Not if hurting own self
&& !(target->flags & MF_NOCLIP)
&& !(inflictor->flags2 & MF2_NODMGTHRUST)
&& !(flags & DMG_THRUSTLESS)
@ -1182,10 +1174,11 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
{
fltthrust = clamp((damage * 0.125 * kickback) / target->Mass, 0., fltthrust);
}
thrust = FLOAT2FIXED(fltthrust);
// Don't apply ultra-small damage thrust.
if (thrust < FRACUNIT / 100)
thrust = 0;
// Don't apply ultra-small damage thrust
if (thrust < FRACUNIT/100) thrust = 0;
// make fall forwards sometimes
if ((damage < 40) && (damage > target->health)
@ -1194,7 +1187,8 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
// [RH] But only if not too fast and not flying
&& thrust < 10*FRACUNIT
&& !(target->flags & MF_NOGRAVITY)
&& (inflictor == NULL || !(inflictor->flags5 & MF5_NOFORWARDFALL)))
&& (inflictor == NULL || !(inflictor->flags5 & MF5_NOFORWARDFALL))
)
{
ang += ANG180;
thrust *= 4;
@ -1230,9 +1224,23 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
if (damage < TELEFRAG_DAMAGE)
{ // Still allow telefragging :-(
damage = (int)((float)damage * level.teamdamage);
if (damage <= 0)
if (damage < 0)
{
return damage;
}
else if (damage == 0)
{
if (forcedPain)
{
goto dopain;
}
else if (fakedPain)
{
goto fakepain;
}
return -1;
}
}
}
//
@ -1268,7 +1276,6 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
else if ((((player->mo->flags7 & MF7_ALLOWPAIN) || (player->mo->flags5 & MF5_NODAMAGE)) || ((inflictor != NULL) && (inflictor->flags7 & MF7_CAUSEPAIN))))
{
invulpain = true;
fakeDamage = damage;
goto fakepain;
}
else
@ -1325,7 +1332,7 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
// but telefragging should still do enough damage to kill the player)
// Ignore players that are already dead.
// [MC]Buddha2 absorbs telefrag damage, and anything else thrown their way.
if (((player->cheats & CF_BUDDHA2) || (((player->cheats & CF_BUDDHA) || (player->mo->flags7 & MF7_BUDDHA)) && (damage < TELEFRAG_DAMAGE))) && (player->playerstate != PST_DEAD))
if (!(flags & DMG_FORCED) && (((player->cheats & CF_BUDDHA2) || (((player->cheats & CF_BUDDHA) || (player->mo->flags7 & MF7_BUDDHA)) && (damage < TELEFRAG_DAMAGE))) && (player->playerstate != PST_DEAD)))
{
// If this is a voodoo doll we need to handle the real player as well.
player->mo->health = target->health = player->health = 1;
@ -1390,7 +1397,7 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
if (target->health <= 0)
{
//[MC]Buddha flag for monsters.
if ((target->flags7 & MF7_BUDDHA) && (damage < TELEFRAG_DAMAGE) && ((inflictor == NULL || !(inflictor->flags3 & MF7_FOILBUDDHA)) && !(flags & DMG_FOILBUDDHA)))
if (!(flags & DMG_FORCED) && ((target->flags7 & MF7_BUDDHA) && (damage < TELEFRAG_DAMAGE) && ((inflictor == NULL || !(inflictor->flags7 & MF7_FOILBUDDHA)) && !(flags & DMG_FOILBUDDHA))))
{ //FOILBUDDHA or Telefrag damage must kill it.
target->health = 1;
}
@ -1451,15 +1458,6 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
fakepain: //Needed so we can skip the rest of the above, but still obey the original rules.
//CAUSEPAIN can always attempt to trigger the chances of pain.
//ALLOWPAIN can do the same, only if the (unfiltered aka fake) damage is greater than 0.
if ((((target->flags7 & MF7_ALLOWPAIN) && (fakeDamage > 0))
|| ((inflictor != NULL) && (inflictor->flags7 & MF7_CAUSEPAIN))))
{
holdDamage = damage; //Store the modified damage away after factors are taken into account.
damage = fakeDamage; //Retrieve the original damage.
}
if (!(target->flags5 & MF5_NOPAIN) && (inflictor == NULL || !(inflictor->flags5 & MF5_PAINLESS)) &&
(target->player != NULL || !G_SkillProperty(SKILLP_NoPain)) && !(target->flags & MF_SKULLFLY))
{
@ -1474,7 +1472,7 @@ fakepain: //Needed so we can skip the rest of the above, but still obey the orig
}
}
if ((((damage >= target->PainThreshold)) && (pr_damagemobj() < painchance))
if (((damage >= target->PainThreshold) && (pr_damagemobj() < painchance))
|| (inflictor != NULL && (inflictor->flags6 & MF6_FORCEPAIN)))
{
dopain:
@ -1555,10 +1553,6 @@ dopain:
{
return -1; //NOW we return -1!
}
else if (fakedPain)
{
return holdDamage; //This is the calculated damage after all is said and done.
}
return damage;
}

View File

@ -189,9 +189,8 @@ DFlicker::DFlicker (sector_t *sector, int upper, int lower)
void EV_StartLightFlickering (int tag, int upper, int lower)
{
int secnum;
secnum = -1;
while ((secnum = P_FindSectorFromTag (tag,secnum)) >= 0)
FSectorTagIterator it(tag);
while ((secnum = it.Next()) >= 0)
{
new DFlicker (&sectors[secnum], upper, lower);
}
@ -359,9 +358,8 @@ DStrobe::DStrobe (sector_t *sector, int utics, int ltics, bool inSync)
void EV_StartLightStrobing (int tag, int upper, int lower, int utics, int ltics)
{
int secnum;
secnum = -1;
while ((secnum = P_FindSectorFromTag (tag,secnum)) >= 0)
FSectorTagIterator it(tag);
while ((secnum = it.Next()) >= 0)
{
sector_t *sec = &sectors[secnum];
if (sec->lightingdata)
@ -374,9 +372,8 @@ void EV_StartLightStrobing (int tag, int upper, int lower, int utics, int ltics)
void EV_StartLightStrobing (int tag, int utics, int ltics)
{
int secnum;
secnum = -1;
while ((secnum = P_FindSectorFromTag (tag,secnum)) >= 0)
FSectorTagIterator it(tag);
while ((secnum = it.Next()) >= 0)
{
sector_t *sec = &sectors[secnum];
if (sec->lightingdata)
@ -396,16 +393,14 @@ void EV_StartLightStrobing (int tag, int utics, int ltics)
void EV_TurnTagLightsOff (int tag)
{
int i;
int secnum;
// [RH] Don't do a linear search
for (secnum = -1; (secnum = P_FindSectorFromTag (tag, secnum)) >= 0; )
FSectorTagIterator it(tag);
while ((secnum = it.Next()) >= 0)
{
sector_t *sector = sectors + secnum;
int min = sector->lightlevel;
for (i = 0; i < sector->linecount; i++)
for (int i = 0; i < sector->linecount; i++)
{
sector_t *tsec = getNextSector (sector->lines[i],sector);
if (!tsec)
@ -427,10 +422,9 @@ void EV_TurnTagLightsOff (int tag)
void EV_LightTurnOn (int tag, int bright)
{
int secnum = -1;
// [RH] Don't do a linear search
while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0)
int secnum;
FSectorTagIterator it(tag);
while ((secnum = it.Next()) >= 0)
{
sector_t *sector = sectors + secnum;
int tbright = bright; //jff 5/17/98 search for maximum PER sector
@ -480,15 +474,14 @@ void EV_LightTurnOn (int tag, int bright)
void EV_LightTurnOnPartway (int tag, fixed_t frac)
{
int i;
frac = clamp<fixed_t> (frac, 0, FRACUNIT);
// Search all sectors for ones with same tag as activating line
i = -1;
while ((i = P_FindSectorFromTag (tag, i)) >= 0)
int secnum;
FSectorTagIterator it(tag);
while ((secnum = it.Next()) >= 0)
{
sector_t *temp, *sector = sectors + i;
sector_t *temp, *sector = &sectors[secnum];
int j, bright = 0, min = sector->lightlevel;
for (j = 0; j < sector->linecount; ++j)
@ -520,9 +513,9 @@ void EV_LightTurnOnPartway (int tag, fixed_t frac)
void EV_LightChange (int tag, int value)
{
int secnum = -1;
while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0)
int secnum;
FSectorTagIterator it(tag);
while ((secnum = it.Next()) >= 0)
{
sectors[secnum].SetLightLevel(sectors[secnum].lightlevel + value);
}
@ -681,8 +674,8 @@ void EV_StartLightGlowing (int tag, int upper, int lower, int tics)
lower = temp;
}
secnum = -1;
while ((secnum = P_FindSectorFromTag (tag,secnum)) >= 0)
FSectorTagIterator it(tag);
while ((secnum = it.Next()) >= 0)
{
sector_t *sec = &sectors[secnum];
if (sec->lightingdata)
@ -701,9 +694,8 @@ void EV_StartLightGlowing (int tag, int upper, int lower, int tics)
void EV_StartLightFading (int tag, int value, int tics)
{
int secnum;
secnum = -1;
while ((secnum = P_FindSectorFromTag (tag,secnum)) >= 0)
FSectorTagIterator it(tag);
while ((secnum = it.Next()) >= 0)
{
sector_t *sec = &sectors[secnum];
if (sec->lightingdata)
@ -846,7 +838,7 @@ void EV_StopLightEffect (int tag)
while ((effect = iterator.Next()) != NULL)
{
if (effect->GetSector()->tag == tag)
if (tagManager.SectorHasTag(effect->GetSector(), tag))
{
effect->Destroy();
}

View File

@ -278,7 +278,7 @@ static void RemoveTaggedSectors(extsector_t::linked::plane &scrollplane, int tag
{
for(int i = scrollplane.Sectors.Size()-1; i>=0; i--)
{
if (scrollplane.Sectors[i].Sector->tag == tag)
if (tagManager.SectorHasTag(scrollplane.Sectors[i].Sector, tag))
{
scrollplane.Sectors.Delete(i);
}
@ -316,7 +316,9 @@ bool P_AddSectorLinks(sector_t *control, int tag, INTBOOL ceiling, int movetype)
if (movetype > 0)
{
for(int sec = -1; (sec = P_FindSectorFromTag(tag, sec)) >= 0; )
int sec;
FSectorTagIterator itr(tag);
while ((sec = itr.Next()) >= 0)
{
// Don't attach to self!
if (control != &sectors[sec])
@ -346,7 +348,9 @@ void P_AddSectorLinksByID(sector_t *control, int id, INTBOOL ceiling)
{
extsector_t::linked::plane &scrollplane = ceiling? control->e->Linked.Ceiling : control->e->Linked.Floor;
for(int line = -1; (line = P_FindLineFromID(id, line)) >= 0; )
FLineIdIterator itr(id);
int line;
while ((line = itr.Next()) >= 0)
{
line_t *ld = &lines[line];

View File

@ -1266,7 +1266,7 @@ FUNC(LS_Thing_Destroy)
while (actor)
{
AActor *temp = iterator.Next ();
if (actor->flags & MF_SHOOTABLE && actor->Sector->tag == arg2)
if (actor->flags & MF_SHOOTABLE && tagManager.SectorHasTag(actor->Sector, arg2))
P_DamageMobj (actor, NULL, it, arg1 ? TELEFRAG_DAMAGE : actor->health, NAME_None);
actor = temp;
}
@ -1279,7 +1279,7 @@ FUNC(LS_Thing_Destroy)
while (actor)
{
AActor *temp = iterator.Next ();
if (actor->flags & MF_SHOOTABLE && (arg2 == 0 || actor->Sector->tag == arg2))
if (actor->flags & MF_SHOOTABLE && (arg2 == 0 || tagManager.SectorHasTag(actor->Sector, arg2)))
P_DamageMobj (actor, NULL, it, arg1 ? TELEFRAG_DAMAGE : actor->health, NAME_None);
actor = temp;
}
@ -1914,9 +1914,9 @@ FUNC(LS_Sector_ChangeSound)
if (!arg0)
return false;
secNum = -1;
rtn = false;
while ((secNum = P_FindSectorFromTag (arg0, secNum)) >= 0)
FSectorTagIterator itr(arg0);
while ((secNum = itr.Next()) >= 0)
{
sectors[secNum].seqType = arg1;
rtn = true;
@ -1933,9 +1933,9 @@ FUNC(LS_Sector_ChangeFlags)
if (!arg0)
return false;
secNum = -1;
rtn = false;
while ((secNum = P_FindSectorFromTag (arg0, secNum)) >= 0)
FSectorTagIterator itr(arg0);
while ((secNum = itr.Next()) >= 0)
{
sectors[secNum].Flags = (sectors[secNum].Flags | arg1) & ~arg2;
rtn = true;
@ -1969,10 +1969,11 @@ void AdjustPusher (int tag, int magnitude, int angle, DPusher::EPusher type)
}
size_t numcollected = Collection.Size ();
int secnum = -1;
int secnum;
// Now create pushers for any sectors that don't already have them.
while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0)
FSectorTagIterator itr(tag);
while ((secnum = itr.Next()) >= 0)
{
unsigned int i;
for (i = 0; i < numcollected; i++)
@ -2020,9 +2021,9 @@ FUNC(LS_Sector_SetTranslucent)
{
if (arg0 != 0)
{
int secnum = -1;
while ((secnum = P_FindSectorFromTag (arg0, secnum)) >= 0)
int secnum;
FSectorTagIterator itr(arg0);
while ((secnum = itr.Next()) >= 0)
{
sectors[secnum].SetAlpha(arg1, Scale(arg2, OPAQUE, 255));
sectors[secnum].ChangeFlags(arg1, ~PLANEF_ADDITIVE, arg3? PLANEF_ADDITIVE:0);
@ -2037,7 +2038,7 @@ FUNC(LS_Sector_SetLink)
{
if (arg0 != 0) // control tag == 0 is for static initialization and must not be handled here
{
int control = P_FindSectorFromTag(arg0, -1);
int control = P_FindFirstSectorFromTag(arg0);
if (control >= 0)
{
return P_AddSectorLinks(&sectors[control], arg1, arg2, arg3);
@ -2062,7 +2063,7 @@ static void SetWallScroller (int id, int sidechoice, fixed_t dx, fixed_t dy, int
{
int wallnum = scroller->GetWallNum ();
if (wallnum >= 0 && sides[wallnum].linedef->id == id &&
if (wallnum >= 0 && tagManager.LineHasID(sides[wallnum].linedef, id) &&
int(sides[wallnum].linedef->sidedef[sidechoice] - sides) == wallnum &&
Where == scroller->GetScrollParts())
{
@ -2081,7 +2082,7 @@ static void SetWallScroller (int id, int sidechoice, fixed_t dx, fixed_t dy, int
while ( (collect.Obj = iterator.Next ()) )
{
if ((collect.RefNum = ((DScroller *)collect.Obj)->GetWallNum ()) != -1 &&
sides[collect.RefNum].linedef->id == id &&
tagManager.LineHasID(sides[collect.RefNum].linedef, id) &&
int(sides[collect.RefNum].linedef->sidedef[sidechoice] - sides) == collect.RefNum &&
Where == ((DScroller *)collect.Obj)->GetScrollParts())
{
@ -2092,10 +2093,11 @@ static void SetWallScroller (int id, int sidechoice, fixed_t dx, fixed_t dy, int
}
size_t numcollected = Collection.Size ();
int linenum = -1;
int linenum;
// Now create scrollers for any walls that don't already have them.
while ((linenum = P_FindLineFromID (id, linenum)) >= 0)
FLineIdIterator itr(id);
while ((linenum = itr.Next()) >= 0)
{
if (lines[linenum].sidedef[sidechoice] != NULL)
{
@ -2167,7 +2169,7 @@ static void SetScroller (int tag, DScroller::EScrollType type, fixed_t dx, fixed
{
if (scroller->IsType (type))
{
if (sectors[scroller->GetAffectee ()].tag == tag)
if (tagManager.SectorHasTag(scroller->GetAffectee (), tag))
{
i++;
scroller->SetRate (dx, dy);
@ -2181,7 +2183,8 @@ static void SetScroller (int tag, DScroller::EScrollType type, fixed_t dx, fixed
}
// Need to create scrollers for the sector(s)
for (i = -1; (i = P_FindSectorFromTag (tag, i)) >= 0; )
FSectorTagIterator itr(tag);
while ((i = itr.Next()) >= 0)
{
new DScroller (type, dx, dy, -1, i, 0);
}
@ -2240,8 +2243,10 @@ FUNC(LS_Sector_SetDamage)
// problems by adding an unwanted constructor.
// Since it doesn't really matter whether the type is translated
// here or in P_PlayerInSpecialSector I think it's the best solution.
int secnum = -1;
while ((secnum = P_FindSectorFromTag (arg0, secnum)) >= 0) {
FSectorTagIterator itr(arg0);
int secnum;
while ((secnum = itr.Next()) >= 0)
{
sectors[secnum].damage = arg1;
sectors[secnum].mod = arg2;
}
@ -2251,14 +2256,15 @@ FUNC(LS_Sector_SetDamage)
FUNC(LS_Sector_SetGravity)
// Sector_SetGravity (tag, intpart, fracpart)
{
int secnum = -1;
float gravity;
if (arg2 > 99)
arg2 = 99;
gravity = (float)arg1 + (float)arg2 * 0.01f;
while ((secnum = P_FindSectorFromTag (arg0, secnum)) >= 0)
FSectorTagIterator itr(arg0);
int secnum;
while ((secnum = itr.Next()) >= 0)
sectors[secnum].gravity = gravity;
return true;
@ -2267,9 +2273,9 @@ FUNC(LS_Sector_SetGravity)
FUNC(LS_Sector_SetColor)
// Sector_SetColor (tag, r, g, b, desaturate)
{
int secnum = -1;
while ((secnum = P_FindSectorFromTag (arg0, secnum)) >= 0)
FSectorTagIterator itr(arg0);
int secnum;
while ((secnum = itr.Next()) >= 0)
{
sectors[secnum].SetColor(arg1, arg2, arg3, arg4);
}
@ -2280,9 +2286,9 @@ FUNC(LS_Sector_SetColor)
FUNC(LS_Sector_SetFade)
// Sector_SetFade (tag, r, g, b)
{
int secnum = -1;
while ((secnum = P_FindSectorFromTag (arg0, secnum)) >= 0)
FSectorTagIterator itr(arg0);
int secnum;
while ((secnum = itr.Next()) >= 0)
{
sectors[secnum].SetFade(arg1, arg2, arg3);
}
@ -2292,11 +2298,12 @@ FUNC(LS_Sector_SetFade)
FUNC(LS_Sector_SetCeilingPanning)
// Sector_SetCeilingPanning (tag, x-int, x-frac, y-int, y-frac)
{
int secnum = -1;
fixed_t xofs = arg1 * FRACUNIT + arg2 * (FRACUNIT/100);
fixed_t yofs = arg3 * FRACUNIT + arg4 * (FRACUNIT/100);
while ((secnum = P_FindSectorFromTag (arg0, secnum)) >= 0)
FSectorTagIterator itr(arg0);
int secnum;
while ((secnum = itr.Next()) >= 0)
{
sectors[secnum].SetXOffset(sector_t::ceiling, xofs);
sectors[secnum].SetYOffset(sector_t::ceiling, yofs);
@ -2307,11 +2314,12 @@ FUNC(LS_Sector_SetCeilingPanning)
FUNC(LS_Sector_SetFloorPanning)
// Sector_SetFloorPanning (tag, x-int, x-frac, y-int, y-frac)
{
int secnum = -1;
fixed_t xofs = arg1 * FRACUNIT + arg2 * (FRACUNIT/100);
fixed_t yofs = arg3 * FRACUNIT + arg4 * (FRACUNIT/100);
while ((secnum = P_FindSectorFromTag (arg0, secnum)) >= 0)
FSectorTagIterator itr(arg0);
int secnum;
while ((secnum = itr.Next()) >= 0)
{
sectors[secnum].SetXOffset(sector_t::floor, xofs);
sectors[secnum].SetYOffset(sector_t::floor, yofs);
@ -2322,7 +2330,6 @@ FUNC(LS_Sector_SetFloorPanning)
FUNC(LS_Sector_SetFloorScale)
// Sector_SetFloorScale (tag, x-int, x-frac, y-int, y-frac)
{
int secnum = -1;
fixed_t xscale = arg1 * FRACUNIT + arg2 * (FRACUNIT/100);
fixed_t yscale = arg3 * FRACUNIT + arg4 * (FRACUNIT/100);
@ -2331,7 +2338,9 @@ FUNC(LS_Sector_SetFloorScale)
if (yscale)
yscale = FixedDiv (FRACUNIT, yscale);
while ((secnum = P_FindSectorFromTag (arg0, secnum)) >= 0)
FSectorTagIterator itr(arg0);
int secnum;
while ((secnum = itr.Next()) >= 0)
{
if (xscale)
sectors[secnum].SetXScale(sector_t::floor, xscale);
@ -2344,7 +2353,6 @@ FUNC(LS_Sector_SetFloorScale)
FUNC(LS_Sector_SetCeilingScale)
// Sector_SetCeilingScale (tag, x-int, x-frac, y-int, y-frac)
{
int secnum = -1;
fixed_t xscale = arg1 * FRACUNIT + arg2 * (FRACUNIT/100);
fixed_t yscale = arg3 * FRACUNIT + arg4 * (FRACUNIT/100);
@ -2353,7 +2361,9 @@ FUNC(LS_Sector_SetCeilingScale)
if (yscale)
yscale = FixedDiv (FRACUNIT, yscale);
while ((secnum = P_FindSectorFromTag (arg0, secnum)) >= 0)
FSectorTagIterator itr(arg0);
int secnum;
while ((secnum = itr.Next()) >= 0)
{
if (xscale)
sectors[secnum].SetXScale(sector_t::ceiling, xscale);
@ -2366,14 +2376,14 @@ FUNC(LS_Sector_SetCeilingScale)
FUNC(LS_Sector_SetFloorScale2)
// Sector_SetFloorScale2 (tag, x-factor, y-factor)
{
int secnum = -1;
if (arg1)
arg1 = FixedDiv (FRACUNIT, arg1);
if (arg2)
arg2 = FixedDiv (FRACUNIT, arg2);
while ((secnum = P_FindSectorFromTag (arg0, secnum)) >= 0)
FSectorTagIterator itr(arg0);
int secnum;
while ((secnum = itr.Next()) >= 0)
{
if (arg1)
sectors[secnum].SetXScale(sector_t::floor, arg1);
@ -2386,14 +2396,14 @@ FUNC(LS_Sector_SetFloorScale2)
FUNC(LS_Sector_SetCeilingScale2)
// Sector_SetFloorScale2 (tag, x-factor, y-factor)
{
int secnum = -1;
if (arg1)
arg1 = FixedDiv (FRACUNIT, arg1);
if (arg2)
arg2 = FixedDiv (FRACUNIT, arg2);
while ((secnum = P_FindSectorFromTag (arg0, secnum)) >= 0)
FSectorTagIterator itr(arg0);
int secnum;
while ((secnum = itr.Next()) >= 0)
{
if (arg1)
sectors[secnum].SetXScale(sector_t::ceiling, arg1);
@ -2406,11 +2416,12 @@ FUNC(LS_Sector_SetCeilingScale2)
FUNC(LS_Sector_SetRotation)
// Sector_SetRotation (tag, floor-angle, ceiling-angle)
{
int secnum = -1;
angle_t ceiling = arg2 * ANGLE_1;
angle_t floor = arg1 * ANGLE_1;
while ((secnum = P_FindSectorFromTag (arg0, secnum)) >= 0)
FSectorTagIterator itr(arg0);
int secnum;
while ((secnum = itr.Next()) >= 0)
{
sectors[secnum].SetAngle(sector_t::floor, floor);
sectors[secnum].SetAngle(sector_t::ceiling, ceiling);
@ -2421,30 +2432,28 @@ FUNC(LS_Sector_SetRotation)
FUNC(LS_Line_AlignCeiling)
// Line_AlignCeiling (lineid, side)
{
int line = P_FindLineFromID (arg0, -1);
bool ret = 0;
if (line < 0)
I_Error ("Sector_AlignCeiling: Lineid %d is undefined", arg0);
do
FLineIdIterator itr(arg0);
int line;
while ((line = itr.Next()) >= 0)
{
ret |= P_AlignFlat (line, !!arg1, 1);
} while ( (line = P_FindLineFromID (arg0, line)) >= 0);
}
return ret;
}
FUNC(LS_Line_AlignFloor)
// Line_AlignFloor (lineid, side)
{
int line = P_FindLineFromID (arg0, -1);
bool ret = 0;
if (line < 0)
I_Error ("Sector_AlignFloor: Lineid %d is undefined", arg0);
do
FLineIdIterator itr(arg0);
int line;
while ((line = itr.Next()) >= 0)
{
ret |= P_AlignFlat (line, !!arg1, 0);
} while ( (line = P_FindLineFromID (arg0, line)) >= 0);
}
return ret;
}
@ -2456,7 +2465,9 @@ FUNC(LS_Line_SetTextureOffset)
if (arg0 == 0 || arg3 < 0 || arg3 > 1)
return false;
for(int line = -1; (line = P_FindLineFromID (arg0, line)) >= 0; )
FLineIdIterator itr(arg0);
int line;
while ((line = itr.Next()) >= 0)
{
side_t *side = lines[line].sidedef[arg3];
if (side != NULL)
@ -2507,7 +2518,9 @@ FUNC(LS_Line_SetTextureScale)
if (arg0 == 0 || arg3 < 0 || arg3 > 1)
return false;
for(int line = -1; (line = P_FindLineFromID (arg0, line)) >= 0; )
FLineIdIterator itr(arg0);
int line;
while ((line = itr.Next()) >= 0)
{
side_t *side = lines[line].sidedef[arg3];
if (side != NULL)
@ -2578,7 +2591,9 @@ FUNC(LS_Line_SetBlocking)
if (arg2 & 1) clearflags |= flagtrans[i];
}
for(int line = -1; (line = P_FindLineFromID (arg0, line)) >= 0; )
FLineIdIterator itr(arg0);
int line;
while ((line = itr.Next()) >= 0)
{
lines[line].flags = (lines[line].flags & ~clearflags) | setflags;
}
@ -2871,8 +2886,9 @@ FUNC(LS_SetPlayerProperty)
FUNC(LS_TranslucentLine)
// TranslucentLine (id, amount, type)
{
int linenum = -1;
while ((linenum = P_FindLineFromID (arg0, linenum)) >= 0)
FLineIdIterator itr(arg0);
int linenum;
while ((linenum = itr.Next()) >= 0)
{
lines[linenum].Alpha = Scale(clamp(arg1, 0, 255), FRACUNIT, 255);
if (arg2 == 0)
@ -2997,10 +3013,11 @@ FUNC(LS_ForceField)
FUNC(LS_ClearForceField)
// ClearForceField (tag)
{
int secnum = -1;
bool rtn = false;
while ((secnum = P_FindSectorFromTag (arg0, secnum)) >= 0)
FSectorTagIterator itr(arg0);
int secnum;
while ((secnum = itr.Next()) >= 0)
{
sector_t *sec = &sectors[secnum];
rtn = true;

View File

@ -160,7 +160,8 @@ void P_CheckFakeFloorTriggers (AActor *mo, fixed_t oldz, bool oldz_has_viewheigh
//
// [RH] P_THINGS
//
extern TMap<int, const PClass *> SpawnableThings;
extern FClassMap SpawnableThings;
extern FClassMap StrifeTypes;
bool P_Thing_Spawn (int tid, AActor *source, int type, angle_t angle, bool fog, int newtid);
bool P_Thing_Projectile (int tid, AActor *source, int type, const char * type_name, angle_t angle,
@ -174,6 +175,7 @@ void P_RemoveThing(AActor * actor);
bool P_Thing_Raise(AActor *thing, AActor *raiser);
bool P_Thing_CanRaise(AActor *thing);
const PClass *P_GetSpawnableType(int spawnnum);
void InitSpawnablesFromMapinfo();
//
// P_MAPUTL
@ -472,7 +474,7 @@ void P_TraceBleed (int damage, AActor *target); // random direction version
bool P_HitFloor (AActor *thing);
bool P_HitWater (AActor *thing, sector_t *sec, fixed_t splashx = FIXED_MIN, fixed_t splashy = FIXED_MIN, fixed_t splashz=FIXED_MIN, bool checkabove = false, bool alert = true);
void P_CheckSplash(AActor *self, fixed_t distance);
void P_RailAttack (AActor *source, int damage, int offset_xy, fixed_t offset_z = 0, int color1 = 0, int color2 = 0, float maxdiff = 0, int flags = 0, const PClass *puff = NULL, angle_t angleoffset = 0, angle_t pitchoffset = 0, fixed_t distance = 8192*FRACUNIT, int duration = 0, float sparsity = 1.0, float drift = 1.0, const PClass *spawnclass = NULL); // [RH] Shoot a railgun
void P_RailAttack (AActor *source, int damage, int offset_xy, fixed_t offset_z = 0, int color1 = 0, int color2 = 0, float maxdiff = 0, int flags = 0, const PClass *puff = NULL, angle_t angleoffset = 0, angle_t pitchoffset = 0, fixed_t distance = 8192*FRACUNIT, int duration = 0, float sparsity = 1.0, float drift = 1.0, const PClass *spawnclass = NULL, int SpiralOffset = 270); // [RH] Shoot a railgun
enum // P_RailAttack / A_RailAttack / A_CustomRailgun / P_DrawRailTrail flags
{
@ -591,19 +593,6 @@ struct polyspawns_t
short type;
};
enum
{
PO_HEX_ANCHOR_TYPE = 3000,
PO_HEX_SPAWN_TYPE,
PO_HEX_SPAWNCRUSH_TYPE,
// [RH] Thing numbers that don't conflict with Doom things
PO_ANCHOR_TYPE = 9300,
PO_SPAWN_TYPE,
PO_SPAWNCRUSH_TYPE,
PO_SPAWNHURT_TYPE
};
extern int po_NumPolyobjs;
extern polyspawns_t *polyspawns; // [RH] list of polyobject things to spawn

View File

@ -1034,7 +1034,7 @@ bool PIT_CheckThing(AActor *thing, FCheckPosition &tm)
// Both things overlap in x or y direction
bool unblocking = false;
if (tm.FromPMove)
if (tm.FromPMove || tm.thing->player != NULL)
{
// Both actors already overlap. To prevent them from remaining stuck allow the move if it
// takes them further apart or the move does not change the position (when called from P_ChangeSector.)
@ -1288,7 +1288,7 @@ bool PIT_CheckThing(AActor *thing, FCheckPosition &tm)
// Do damage
damage = tm.thing->GetMissileDamage((tm.thing->flags4 & MF4_STRIFEDAMAGE) ? 3 : 7, 1);
if ((damage > 0) || (tm.thing->flags6 & MF6_FORCEPAIN))
if ((damage > 0) || (tm.thing->flags6 & MF6_FORCEPAIN) || (tm.thing->flags7 & MF7_CAUSEPAIN))
{
int newdam = P_DamageMobj(thing, tm.thing, tm.thing->target, damage, tm.thing->DamageType);
if (damage > 0)
@ -4140,7 +4140,7 @@ static ETraceStatus ProcessRailHit(FTraceResults &res, void *userdata)
//
//
//==========================================================================
void P_RailAttack(AActor *source, int damage, int offset_xy, fixed_t offset_z, int color1, int color2, float maxdiff, int railflags, const PClass *puffclass, angle_t angleoffset, angle_t pitchoffset, fixed_t distance, int duration, float sparsity, float drift, const PClass *spawnclass)
void P_RailAttack(AActor *source, int damage, int offset_xy, fixed_t offset_z, int color1, int color2, float maxdiff, int railflags, const PClass *puffclass, angle_t angleoffset, angle_t pitchoffset, fixed_t distance, int duration, float sparsity, float drift, const PClass *spawnclass, int SpiralOffset)
{
fixed_t vx, vy, vz;
angle_t angle, pitch;
@ -4243,13 +4243,16 @@ void P_RailAttack(AActor *source, int damage, int offset_xy, fixed_t offset_z, i
P_SpawnPuff(source, puffclass, x, y, z, (source->angle + angleoffset) - ANG90, 1, puffflags, hitactor);
}
if (puffDefaults && puffDefaults->PoisonDamage > 0 && puffDefaults->PoisonDuration != INT_MIN)
int dmgFlagPass = DMG_INFLICTOR_IS_PUFF;
if (puffDefaults != NULL) // is this even possible?
{
if (puffDefaults->PoisonDamage > 0 && puffDefaults->PoisonDuration != INT_MIN)
{
P_PoisonMobj(hitactor, thepuff ? thepuff : source, source, puffDefaults->PoisonDamage, puffDefaults->PoisonDuration, puffDefaults->PoisonPeriod, puffDefaults->PoisonDamageType);
}
int dmgFlagPass = DMG_INFLICTOR_IS_PUFF;
dmgFlagPass += (puffDefaults->flags3 & MF3_FOILINVUL) ? DMG_FOILINVUL : 0; //[MC]Because the original foilinvul check wasn't working.
dmgFlagPass += (puffDefaults->flags7 & MF7_FOILBUDDHA) ? DMG_FOILBUDDHA : 0;
if (puffDefaults->flags3 & MF3_FOILINVUL) dmgFlagPass |= DMG_FOILINVUL;
if (puffDefaults->flags7 & MF7_FOILBUDDHA) dmgFlagPass |= DMG_FOILBUDDHA;
}
int newdam = P_DamageMobj(hitactor, thepuff ? thepuff : source, source, damage, damagetype, dmgFlagPass);
if (bleed)
@ -4289,7 +4292,7 @@ void P_RailAttack(AActor *source, int damage, int offset_xy, fixed_t offset_z, i
end.X = FIXED2FLOAT(trace.X);
end.Y = FIXED2FLOAT(trace.Y);
end.Z = FIXED2FLOAT(trace.Z);
P_DrawRailTrail(source, start, end, color1, color2, maxdiff, railflags, spawnclass, source->angle + angleoffset, duration, sparsity, drift);
P_DrawRailTrail(source, start, end, color1, color2, maxdiff, railflags, spawnclass, source->angle + angleoffset, duration, sparsity, drift, SpiralOffset);
}
//==========================================================================
@ -4787,7 +4790,7 @@ void P_RadiusAttack(AActor *bombspot, AActor *bombsource, int bombdamage, int bo
points *= thing->GetClass()->Meta.GetMetaFixed(AMETA_RDFactor, FRACUNIT) / (double)FRACUNIT;
// points and bombdamage should be the same sign
if (((bombspot->flags7 & MF7_CAUSEPAIN) || (points * bombdamage) > 0) && P_CheckSight(thing, bombspot, SF_IGNOREVISIBILITY | SF_IGNOREWATERBOUNDARY))
if (((points * bombdamage) > 0) && P_CheckSight(thing, bombspot, SF_IGNOREVISIBILITY | SF_IGNOREWATERBOUNDARY))
{ // OK to damage; target is in direct path
double velz;
double thrust;

View File

@ -384,11 +384,6 @@ void AActor::Serialize (FArchive &arc)
}
}
void FMapThing::Serialize (FArchive &arc)
{
arc << thingid << x << y << z << angle << type << flags << special
<< args[0] << args[1] << args[2] << args[3] << args[4];
}
AActor::AActor () throw()
{
@ -3442,7 +3437,7 @@ void AActor::Tick ()
}
else if (scrolltype == Scroll_StrifeCurrent)
{ // Strife scroll special
int anglespeed = sec->tag - 100;
int anglespeed = tagManager.GetFirstSectorTag(sec) - 100;
fixed_t carryspeed = DivScale32 (anglespeed % 10, 16*CARRYFACTOR);
angle_t fineangle = (anglespeed / 10) << (32-3);
fineangle >>= ANGLETOFINESHIFT;
@ -4480,7 +4475,8 @@ APlayerPawn *P_SpawnPlayer (FPlayerStart *mthing, int playernum, int flags)
p->mo->ResetAirSupply(false);
p->Uncrouch();
p->MinPitch = p->MaxPitch = 0; // will be filled in by PostBeginPlay()/netcode
p->MUSINFOactor = NULL;
p->MUSINFOtics = -1;
p->velx = p->vely = 0; // killough 10/98: initialize bobbing to 0.
@ -4596,70 +4592,83 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position)
AActor *mobj;
fixed_t x, y, z;
if (mthing->type == 0 || mthing->type == -1)
if (mthing->EdNum == 0 || mthing->EdNum == -1)
return NULL;
// count deathmatch start positions
if (mthing->type == 11)
// find which type to spawn
FDoomEdEntry *mentry = mthing->info;
if (mentry == NULL)
{
FPlayerStart start(mthing);
// [RH] Don't die if the map tries to spawn an unknown thing
Printf ("Unknown type %i at (%i, %i)\n",
mthing->EdNum,
mthing->x>>FRACBITS, mthing->y>>FRACBITS);
mentry = DoomEdMap.CheckKey(0);
if (mentry == NULL) // we need a valid entry for the rest of this function so if we can't find a default, let's exit right away.
{
return NULL;
}
}
if (mentry->Type == NULL && mentry->Special <= 0)
{
// has been explicitly set to not spawning anything.
return NULL;
}
// copy args to mapthing so that we have them in one place for the rest of this function
if (mentry->ArgsDefined)
{
if (mentry->Type!= NULL) mthing->special = mentry->Special;
memcpy(mthing->args, mentry->Args, sizeof(mthing->args));
}
int pnum = -1;
if (mentry->Type == NULL)
{
switch (mentry->Special)
{
case SMT_DeathmatchStart:
{
// count deathmatch start positions
FPlayerStart start(mthing, 0);
deathmatchstarts.Push(start);
return NULL;
}
// Convert Strife starts to Hexen-style starts
if (gameinfo.gametype == GAME_Strife && mthing->type >= 118 && mthing->type <= 127)
{
mthing->args[0] = mthing->type - 117;
mthing->type = 1;
}
// [RH] Record polyobject-related things
if (gameinfo.gametype == GAME_Hexen)
{
switch (mthing->type)
{
case PO_HEX_ANCHOR_TYPE:
mthing->type = PO_ANCHOR_TYPE;
break;
case PO_HEX_SPAWN_TYPE:
mthing->type = PO_SPAWN_TYPE;
break;
case PO_HEX_SPAWNCRUSH_TYPE:
mthing->type = PO_SPAWNCRUSH_TYPE;
break;
}
}
if (mthing->type == PO_ANCHOR_TYPE ||
mthing->type == PO_SPAWN_TYPE ||
mthing->type == PO_SPAWNCRUSH_TYPE ||
mthing->type == PO_SPAWNHURT_TYPE)
case SMT_PolyAnchor:
case SMT_PolySpawn:
case SMT_PolySpawnCrush:
case SMT_PolySpawnHurt:
{
polyspawns_t *polyspawn = new polyspawns_t;
polyspawn->next = polyspawns;
polyspawn->x = mthing->x;
polyspawn->y = mthing->y;
polyspawn->angle = mthing->angle;
polyspawn->type = mthing->type;
polyspawn->type = mentry->Special;
polyspawns = polyspawn;
if (mthing->type != PO_ANCHOR_TYPE)
if (mentry->Special != SMT_PolyAnchor)
po_NumPolyobjs++;
return NULL;
}
// check for players specially
int pnum = -1;
case SMT_Player1Start:
case SMT_Player2Start:
case SMT_Player3Start:
case SMT_Player4Start:
case SMT_Player5Start:
case SMT_Player6Start:
case SMT_Player7Start:
case SMT_Player8Start:
pnum = mentry->Special - SMT_Player1Start;
break;
// Sound sequence override will be handled later
default:
break;
if (mthing->type <= 4 && mthing->type > 0)
{
pnum = mthing->type - 1;
}
else
{
if (mthing->type >= gameinfo.player5start && mthing->type < gameinfo.player5start + MAXPLAYERS - 4)
{
pnum = mthing->type - gameinfo.player5start + 4;
}
}
@ -4727,7 +4736,7 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position)
return NULL;
// save spots for respawning in network games
FPlayerStart start(mthing);
FPlayerStart start(mthing, pnum+1);
playerstarts[pnum] = start;
AllPlayerStarts.Push(start);
if (!deathmatch && !(level.flags2 & LEVEL2_RANDOMPLAYERSTARTS))
@ -4738,20 +4747,10 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position)
}
// [RH] sound sequence overriders
if (mthing->type >= 1400 && mthing->type < 1410)
if (mentry->Type == NULL && mentry->Special == SMT_SSeqOverride)
{
P_PointInSector (mthing->x, mthing->y)->seqType = mthing->type - 1400;
return NULL;
}
else if (mthing->type == 1411)
{
int type;
if (mthing->args[0] == 255)
type = -1;
else
type = mthing->args[0];
int type = mentry->Args[0];
if (type == 255) type = -1;
if (type > 63)
{
Printf ("Sound sequence %d out of range\n", type);
@ -4763,36 +4762,11 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position)
return NULL;
}
// [RH] Determine if it is an old ambient thing, and if so,
// map it to MT_AMBIENT with the proper parameter.
if (mthing->type >= 14001 && mthing->type <= 14064)
{
mthing->args[0] = mthing->type - 14000;
mthing->type = 14065;
}
else if (mthing->type >= 14101 && mthing->type <= 14164)
{
mthing->args[0] = mthing->type - 14100;
mthing->type = 14165;
}
// find which type to spawn
i = DoomEdMap.FindType (mthing->type);
if (i == NULL)
{
// [RH] Don't die if the map tries to spawn an unknown thing
Printf ("Unknown type %i at (%i, %i)\n",
mthing->type,
mthing->x>>FRACBITS, mthing->y>>FRACBITS);
i = PClass::FindClass("Unknown");
}
// [RH] If the thing's corresponding sprite has no frames, also map
// it to the unknown thing.
else
{
// Handle decorate replacements explicitly here
// to check for missing frames in the replacement object.
i = i->GetReplacement();
i = mentry->Type->GetReplacement();
const AActor *defaults = GetDefaultByType (i);
if (defaults->SpawnState == NULL ||
@ -4808,7 +4782,6 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position)
i->TypeName.GetChars(), mthing->x>>FRACBITS, mthing->y>>FRACBITS);
i = PClass::FindClass("Unknown");
}
}
const AActor *info = GetDefaultByType (i);
@ -4897,6 +4870,7 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position)
P_FindFloorCeiling(mobj, FFCF_SAMESECTOR | FFCF_ONLY3DFLOORS | FFCF_3DRESTRICT);
}
// if the actor got args defined either in DECORATE or MAPINFO we must ignore the map's properties.
if (!(mobj->flags2 & MF2_ARGSDEFINED))
{
// [RH] Set the thing's special
@ -6158,11 +6132,6 @@ int AActor::TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, FN
{
FState *death;
if (flags5 & MF5_NODAMAGE)
{
return 0;
}
// If the actor does not have a corresponding death state, then it does not take damage.
// Note that DeathState matches every kind of damagetype, so an actor has that, it can
// be hurt with any type of damage. Exception: Massacre damage always succeeds, because
@ -6240,11 +6209,11 @@ void AActor::Crash()
}
}
void AActor::SetIdle()
void AActor::SetIdle(bool nofunction)
{
FState *idle = FindState (NAME_Idle);
if (idle == NULL) idle = SpawnState;
SetState(idle);
SetState(idle, nofunction);
}
int AActor::SpawnHealth()
@ -6442,7 +6411,8 @@ void PrintMiscActorInfo(AActor *query)
}
}
static const char * renderstyles[]= {"None", "Normal", "Fuzzy", "SoulTrans",
"OptFuzzy", "Stencil", "Translucent", "Add", "Shaded", "TranslucentStencil"};
"OptFuzzy", "Stencil", "Translucent", "Add", "Shaded", "TranslucentStencil",
"Shadow", "Subtract", "AddStencil", "AddShaded"};
Printf("%s @ %p has the following flags:\n flags: %x", query->GetTag(), query, query->flags);
for (flagi = 0; flagi <= 31; flagi++)

View File

@ -220,20 +220,11 @@ bool EV_DoPillar (DPillar::EPillar type, line_t *line, int tag,
bool rtn = false;
// check if a manual trigger; if so do just the sector on the backside
if (tag == 0)
{
if (!line || !(sec = line->backsector))
return rtn;
secnum = (int)(sec-sectors);
goto manual_pillar;
}
secnum = -1;
while (tag && (secnum = P_FindSectorFromTag (tag, secnum)) >= 0)
FSectorTagIterator itr(tag, line);
while ((secnum = itr.Next()) >= 0)
{
sec = &sectors[secnum];
manual_pillar:
if (sec->PlaneMoving(sector_t::floor) || sec->PlaneMoving(sector_t::ceiling))
continue;

View File

@ -233,17 +233,8 @@ bool EV_DoPlat (int tag, line_t *line, DPlat::EPlatType type, int height,
fixed_t newheight = 0;
vertex_t *spot;
// [RH] If tag is zero, use the sector on the back side
// of the activating line (if any).
if (!tag)
if (tag != 0)
{
if (!line || !(sec = line->backsector))
return false;
secnum = (int)(sec - sectors);
manual = true;
goto manual_plat;
}
// Activate all <type> plats that are in_stasis
switch (type)
{
@ -256,19 +247,19 @@ bool EV_DoPlat (int tag, line_t *line, DPlat::EPlatType type, int height,
default:
break;
}
}
secnum = -1;
while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0)
// [RH] If tag is zero, use the sector on the back side
// of the activating line (if any).
FSectorTagIterator itr(tag, line);
while ((secnum = itr.Next()) >= 0)
{
sec = &sectors[secnum];
manual_plat:
if (sec->PlaneMoving(sector_t::floor))
{
if (!manual)
continue;
else
return false;
}
// Find lowest & highest floors around sector
@ -406,8 +397,6 @@ manual_plat:
default:
break;
}
if (manual)
return rtn;
}
return rtn;
}

View File

@ -348,9 +348,13 @@ void P_SerializeWorld (FArchive &arc)
{
arc << sec->lightlevel;
}
arc << sec->special
<< sec->tag
<< sec->soundtraversed
arc << sec->special;
if (SaveVersion < 4523)
{
short tag;
arc << tag;
}
arc << sec->soundtraversed
<< sec->seqType
<< sec->friction
<< sec->movefactor
@ -405,8 +409,13 @@ void P_SerializeWorld (FArchive &arc)
arc << li->flags
<< li->activation
<< li->special
<< li->Alpha
<< li->id;
<< li->Alpha;
if (SaveVersion < 4523)
{
int id;
arc << id;
}
if (P_IsACSSpecial(li->special))
{
P_SerializeACSScriptNumber(arc, li->args[0], false);

View File

@ -96,7 +96,6 @@ CVAR (Bool, gennodes, false, CVAR_SERVERINFO|CVAR_GLOBALCONFIG);
CVAR (Bool, genglnodes, false, CVAR_SERVERINFO);
CVAR (Bool, showloadtimes, false, 0);
static void P_InitTagLists ();
static void P_Shutdown ();
bool P_IsBuildMap(MapData *map);
@ -1514,7 +1513,7 @@ void P_LoadSectors (MapData *map, FMissingTextureTracker &missingtex)
else // [RH] Translate to new sector special
ss->special = P_TranslateSectorSpecial (LittleShort(ms->special));
ss->secretsector = !!(ss->special&SECRET_MASK);
ss->tag = LittleShort(ms->tag);
tagManager.AddSectorTag(i, LittleShort(ms->tag));
ss->thinglist = NULL;
ss->touching_thinglist = NULL; // phares 3/14/98
ss->seqType = defSeqType;
@ -1665,7 +1664,7 @@ AActor *SpawnMapThing(int index, FMapThing *mt, int position)
if (dumpspawnedthings)
{
Printf("%5d: (%5d, %5d, %5d), doomednum = %5d, flags = %04x, type = %s\n",
index, mt->x>>FRACBITS, mt->y>>FRACBITS, mt->z>>FRACBITS, mt->type, mt->flags,
index, mt->x>>FRACBITS, mt->y>>FRACBITS, mt->z>>FRACBITS, mt->EdNum, mt->flags,
spawned? spawned->GetClass()->TypeName.GetChars() : "(none)");
}
T_AddSpawnedThing(spawned);
@ -1785,7 +1784,8 @@ void P_LoadThings (MapData * map)
mti[i].x = LittleShort(mt->x) << FRACBITS;
mti[i].y = LittleShort(mt->y) << FRACBITS;
mti[i].angle = LittleShort(mt->angle);
mti[i].type = LittleShort(mt->type);
mti[i].EdNum = LittleShort(mt->type);
mti[i].info = DoomEdMap.CheckKey(mti[i].EdNum);
}
delete [] mtp;
}
@ -1825,7 +1825,8 @@ void P_LoadThings2 (MapData * map)
mti[i].y = LittleShort(mth[i].y)<<FRACBITS;
mti[i].z = LittleShort(mth[i].z)<<FRACBITS;
mti[i].angle = LittleShort(mth[i].angle);
mti[i].type = LittleShort(mth[i].type);
mti[i].EdNum = LittleShort(mth[i].type);
mti[i].info = DoomEdMap.CheckKey(mti[i].EdNum);
mti[i].flags = LittleShort(mth[i].flags);
mti[i].special = mth[i].special;
for(int j=0;j<5;j++) mti[i].args[j] = mth[i].args[j];
@ -1906,54 +1907,59 @@ void P_AdjustLine (line_t *ld)
}
}
void P_SetLineID (line_t *ld)
void P_SetLineID (int i, line_t *ld)
{
// [RH] Set line id (as appropriate) here
// for Doom format maps this must be done in P_TranslateLineDef because
// the tag doesn't always go into the first arg.
if (level.maptype == MAPTYPE_HEXEN)
{
int setid = -1;
switch (ld->special)
{
case Line_SetIdentification:
if (!(level.flags2 & LEVEL2_HEXENHACK))
{
ld->id = ld->args[0] + 256 * ld->args[4];
setid = ld->args[0] + 256 * ld->args[4];
ld->flags |= ld->args[1]<<16;
}
else
{
ld->id = ld->args[0];
setid = ld->args[0];
}
ld->special = 0;
break;
case TranslucentLine:
ld->id = ld->args[0];
setid = ld->args[0];
ld->flags |= ld->args[3]<<16;
break;
case Teleport_Line:
case Scroll_Texture_Model:
ld->id = ld->args[0];
setid = ld->args[0];
break;
case Polyobj_StartLine:
ld->id = ld->args[3];
setid = ld->args[3];
break;
case Polyobj_ExplicitLine:
ld->id = ld->args[4];
setid = ld->args[4];
break;
case Plane_Align:
ld->id = ld->args[2];
setid = ld->args[2];
break;
case Static_Init:
if (ld->args[1] == Init_SectorLink) ld->id = ld->args[0];
if (ld->args[1] == Init_SectorLink) setid = ld->args[0];
break;
}
if (setid != -1)
{
tagManager.AddLineID(i, setid);
}
}
}
@ -2036,7 +2042,7 @@ void P_FinishLoadingLineDef(line_t *ld, int alpha)
{
for (j = 0; j < numlines; j++)
{
if (lines[j].id == ld->args[0])
if (tagManager.LineHasID(j, ld->args[0]))
{
lines[j].Alpha = alpha;
if (additive)
@ -2138,17 +2144,16 @@ void P_LoadLineDefs (MapData * map)
mld = (maplinedef_t *)mldf;
ld = lines;
for (i = numlines; i > 0; i--, mld++, ld++)
for (i = 0; i < numlines; i++, mld++, ld++)
{
ld->Alpha = FRACUNIT; // [RH] Opaque by default
// [RH] Translate old linedef special and flags to be
// compatible with the new format.
P_TranslateLineDef (ld, mld);
P_TranslateLineDef (ld, mld, i);
ld->v1 = &vertexes[LittleShort(mld->v1)];
ld->v2 = &vertexes[LittleShort(mld->v2)];
//ld->id = -1; ID has been assigned in P_TranslateLineDef
P_SetSideNum (&ld->sidedef[0], LittleShort(mld->sidenum[0]));
P_SetSideNum (&ld->sidedef[1], LittleShort(mld->sidenum[1]));
@ -2218,7 +2223,7 @@ void P_LoadLineDefs2 (MapData * map)
mld = (maplinedef2_t *)mldf;
ld = lines;
for (i = numlines; i > 0; i--, mld++, ld++)
for (i = 0; i < numlines; i++, mld++, ld++)
{
int j;
@ -2231,13 +2236,12 @@ void P_LoadLineDefs2 (MapData * map)
ld->v1 = &vertexes[LittleShort(mld->v1)];
ld->v2 = &vertexes[LittleShort(mld->v2)];
ld->Alpha = FRACUNIT; // [RH] Opaque by default
ld->id = -1;
P_SetSideNum (&ld->sidedef[0], LittleShort(mld->sidenum[0]));
P_SetSideNum (&ld->sidedef[1], LittleShort(mld->sidenum[1]));
P_AdjustLine (ld);
P_SetLineID(ld);
P_SetLineID(i, ld);
P_SaveLineSpecial (ld);
if (level.flags2 & LEVEL2_CLIPMIDTEX) ld->flags |= ML_CLIP_MIDTEX;
if (level.flags2 & LEVEL2_WRAPMIDTEX) ld->flags |= ML_WRAP_MIDTEX;
@ -2493,7 +2497,7 @@ void P_ProcessSideTextures(bool checktranmap, side_t *sd, sector_t *sec, intmaps
for (s = 0; s < numsectors; s++)
{
if (sectors[s].tag == tag)
if (tagManager.SectorHasTag(s, tag))
{
if (!colorgood) color = sectors[s].ColorMap->Color;
if (!foggood) fog = sectors[s].ColorMap->Fade;
@ -3129,9 +3133,9 @@ static void P_GroupLines (bool buildmap)
{
if (sector->linecount == 0)
{
Printf ("Sector %i (tag %i) has no lines\n", i, sector->tag);
Printf ("Sector %i (tag %i) has no lines\n", i, tagManager.GetFirstSectorTag(sector));
// 0 the sector's tag so that no specials can use it
sector->tag = 0;
tagManager.RemoveSectorTags(i);
}
else
{
@ -3207,7 +3211,8 @@ static void P_GroupLines (bool buildmap)
// [RH] Moved this here
times[4].Clock();
P_InitTagLists(); // killough 1/30/98: Create xref tables for tags
// killough 1/30/98: Create xref tables for tags
tagManager.HashTags();
times[4].Unclock();
times[5].Clock();
@ -3304,62 +3309,20 @@ void P_LoadBehavior (MapData * map)
}
}
// Hash the sector tags across the sectors and linedefs.
static void P_InitTagLists ()
{
int i;
for (i=numsectors; --i>=0; ) // Initially make all slots empty.
sectors[i].firsttag = -1;
for (i=numsectors; --i>=0; ) // Proceed from last to first sector
{ // so that lower sectors appear first
int j = (unsigned) sectors[i].tag % (unsigned) numsectors; // Hash func
sectors[i].nexttag = sectors[j].firsttag; // Prepend sector to chain
sectors[j].firsttag = i;
}
// killough 4/17/98: same thing, only for linedefs
for (i=numlines; --i>=0; ) // Initially make all slots empty.
lines[i].firstid = -1;
for (i=numlines; --i>=0; ) // Proceed from last to first linedef
{ // so that lower linedefs appear first
int j = (unsigned) lines[i].id % (unsigned) numlines; // Hash func
lines[i].nextid = lines[j].firstid; // Prepend linedef to chain
lines[j].firstid = i;
}
}
void P_GetPolySpots (MapData * map, TArray<FNodeBuilder::FPolyStart> &spots, TArray<FNodeBuilder::FPolyStart> &anchors)
{
if (map->HasBehavior)
{
int spot1, spot2, spot3, anchor;
if (gameinfo.gametype == GAME_Hexen)
{
spot1 = PO_HEX_SPAWN_TYPE;
spot2 = PO_HEX_SPAWNCRUSH_TYPE;
anchor = PO_HEX_ANCHOR_TYPE;
}
else
{
spot1 = PO_SPAWN_TYPE;
spot2 = PO_SPAWNCRUSH_TYPE;
anchor = PO_ANCHOR_TYPE;
}
spot3 = PO_SPAWNHURT_TYPE;
for (unsigned int i = 0; i < MapThingsConverted.Size(); ++i)
{
if (MapThingsConverted[i].type == spot1 || MapThingsConverted[i].type == spot2 ||
MapThingsConverted[i].type == spot3 || MapThingsConverted[i].type == anchor)
FDoomEdEntry *mentry = MapThingsConverted[i].info;
if (mentry != NULL && mentry->Type == NULL && mentry->Special >= SMT_PolyAnchor && mentry->Special <= SMT_PolySpawnHurt)
{
FNodeBuilder::FPolyStart newvert;
newvert.x = MapThingsConverted[i].x;
newvert.y = MapThingsConverted[i].y;
newvert.polynum = MapThingsConverted[i].angle;
if (MapThingsConverted[i].type == anchor)
if (mentry->Special == SMT_PolyAnchor)
{
anchors.Push (newvert);
}
@ -3380,6 +3343,7 @@ void P_FreeLevelData ()
FPolyObj::ClearAllSubsectorLinks(); // can't be done as part of the polyobj deletion process.
SN_StopAllSequences ();
DThinker::DestroyAllThinkers ();
tagManager.Clear();
level.total_monsters = level.total_items = level.total_secrets =
level.killed_monsters = level.found_items = level.found_secrets =
wminfo.maxfrags = 0;

View File

@ -115,7 +115,7 @@ struct line_t;
struct maplinedef_t;
void P_LoadTranslator(const char *lumpname);
void P_TranslateLineDef (line_t *ld, maplinedef_t *mld);
void P_TranslateLineDef (line_t *ld, maplinedef_t *mld, int lineindexforid = -1);
int P_TranslateSectorSpecial (int);
int GetUDMFInt(int type, int index, const char *key);

View File

@ -45,9 +45,10 @@
static void P_SlopeLineToPoint (int lineid, fixed_t x, fixed_t y, fixed_t z, bool slopeCeil)
{
int linenum = -1;
int linenum;
while ((linenum = P_FindLineFromID (lineid, linenum)) != -1)
FLineIdIterator itr(lineid);
while ((linenum = itr.Next()) >= 0)
{
const line_t *line = &lines[linenum];
sector_t *sec;
@ -123,7 +124,7 @@ static void P_CopyPlane (int tag, sector_t *dest, bool copyCeil)
int secnum;
size_t planeofs;
secnum = P_FindSectorFromTag (tag, -1);
secnum = P_FindFirstSectorFromTag (tag);
if (secnum == -1)
{
return;
@ -266,20 +267,6 @@ void P_VavoomSlope(sector_t * sec, int id, fixed_t x, fixed_t y, fixed_t z, int
}
}
enum
{
THING_SlopeFloorPointLine = 9500,
THING_SlopeCeilingPointLine = 9501,
THING_SetFloorSlope = 9502,
THING_SetCeilingSlope = 9503,
THING_CopyFloorPlane = 9510,
THING_CopyCeilingPlane = 9511,
THING_VavoomFloor=1500,
THING_VavoomCeiling=1501,
THING_VertexFloorZ=1504,
THING_VertexCeilingZ=1505,
};
//==========================================================================
//
// P_SetSlopesFromVertexHeights
@ -294,13 +281,15 @@ static void P_SetSlopesFromVertexHeights(FMapThing *firstmt, FMapThing *lastmt,
for (mt = firstmt; mt < lastmt; ++mt)
{
if (mt->type == THING_VertexFloorZ || mt->type == THING_VertexCeilingZ)
if (mt->info != NULL && mt->info->Type == NULL)
{
for(int i=0; i<numvertexes; i++)
if (mt->info->Special == SMT_VertexFloorZ || mt->info->Special == SMT_VertexCeilingZ)
{
for (int i = 0; i < numvertexes; i++)
{
if (vertexes[i].x == mt->x && vertexes[i].y == mt->y)
{
if (mt->type == THING_VertexFloorZ)
if (mt->info->Special == SMT_VertexFloorZ)
{
vt_heights[0][i] = mt->z;
}
@ -311,7 +300,8 @@ static void P_SetSlopesFromVertexHeights(FMapThing *firstmt, FMapThing *lastmt,
vt_found = true;
}
}
mt->type = 0;
mt->EdNum = 0;
}
}
}
@ -427,49 +417,51 @@ void P_SpawnSlopeMakers (FMapThing *firstmt, FMapThing *lastmt, const int *oldve
for (mt = firstmt; mt < lastmt; ++mt)
{
if ((mt->type >= THING_SlopeFloorPointLine &&
mt->type <= THING_SetCeilingSlope) ||
mt->type == THING_VavoomFloor || mt->type == THING_VavoomCeiling)
if (mt->info != NULL && mt->info->Type == NULL &&
(mt->info->Special >= SMT_SlopeFloorPointLine && mt->info->Special <= SMT_VavoomCeiling))
{
fixed_t x, y, z;
secplane_t *refplane;
sector_t *sec;
bool ceiling;
x = mt->x;
y = mt->y;
sec = P_PointInSector (x, y);
if (mt->type & 1)
if (mt->info->Special == SMT_SlopeCeilingPointLine || mt->info->Special == SMT_VavoomCeiling || mt->info->Special == SMT_SetCeilingSlope)
{
refplane = &sec->ceilingplane;
ceiling = true;
}
else
{
refplane = &sec->floorplane;
ceiling = false;
}
z = refplane->ZatPoint (x, y) + (mt->z);
if (mt->type == THING_VavoomFloor || mt->type == THING_VavoomCeiling)
{
P_VavoomSlope(sec, mt->thingid, x, y, mt->z, mt->type & 1);
if (mt->info->Special <= SMT_SlopeCeilingPointLine)
{ // SlopeFloorPointLine and SlopCeilingPointLine
P_SlopeLineToPoint (mt->args[0], x, y, z, ceiling);
}
else if (mt->type <= THING_SlopeCeilingPointLine)
{ // THING_SlopeFloorPointLine and THING_SlopCeilingPointLine
P_SlopeLineToPoint (mt->args[0], x, y, z, mt->type & 1);
else if (mt->info->Special <= SMT_SetCeilingSlope)
{ // SetFloorSlope and SetCeilingSlope
P_SetSlope (refplane, ceiling, mt->angle, mt->args[0], x, y, z);
}
else
{ // THING_SetFloorSlope and THING_SetCeilingSlope
P_SetSlope (refplane, mt->type & 1, mt->angle, mt->args[0], x, y, z);
{ // VavoomFloor and VavoomCeiling
P_VavoomSlope(sec, mt->thingid, x, y, mt->z, ceiling);
}
mt->type = 0;
mt->EdNum = 0;
}
}
for (mt = firstmt; mt < lastmt; ++mt)
{
if (mt->type == THING_CopyFloorPlane ||
mt->type == THING_CopyCeilingPlane)
if (mt->info != NULL && mt->info->Type == NULL &&
(mt->info->Special == SMT_CopyFloorPlane || mt->info->Special == SMT_CopyCeilingPlane))
{
P_CopyPlane (mt->args[0], mt->x, mt->y, mt->type & 1);
mt->type = 0;
P_CopyPlane (mt->args[0], mt->x, mt->y, mt->info->Special == SMT_CopyCeilingPlane);
mt->EdNum = 0;
}
}

View File

@ -186,38 +186,6 @@ bool CheckIfExitIsGood (AActor *self, level_info_t *info)
// UTILITIES
//
//
// RETURN NEXT SECTOR # THAT LINE TAG REFERS TO
//
// Find the next sector with a specified tag.
// Rewritten by Lee Killough to use chained hashing to improve speed
int P_FindSectorFromTag (int tag, int start)
{
start = start >= 0 ? sectors[start].nexttag :
sectors[(unsigned) tag % (unsigned) numsectors].firsttag;
while (start >= 0 && sectors[start].tag != tag)
start = sectors[start].nexttag;
return start;
}
// killough 4/16/98: Same thing, only for linedefs
int P_FindLineFromID (int id, int start)
{
start = start >= 0 ? lines[start].nextid :
lines[(unsigned) id % (unsigned) numlines].firstid;
while (start >= 0 && lines[start].id != id)
start = lines[start].nextid;
return start;
}
//============================================================================
//
// P_ActivateLine
@ -264,9 +232,9 @@ bool P_ActivateLine (line_t *line, AActor *mo, int side, int activationType)
!repeat && // only non-repeatable triggers
(special<Generic_Floor || special>Generic_Crusher) && // not for Boom's generalized linedefs
special && // not for lines without a special
line->args[0] == line->id && // Safety check: exclude edited UDMF linedefs or ones that don't map the tag to args[0]
tagManager.LineHasID(line, line->args[0]) && // Safety check: exclude edited UDMF linedefs or ones that don't map the tag to args[0]
line->args[0] && // only if there's a tag (which is stored in the first arg)
P_FindSectorFromTag (line->args[0], -1) == -1) // only if no sector is tagged to this linedef
P_FindFirstSectorFromTag (line->args[0]) == -1) // only if no sector is tagged to this linedef
{
P_ChangeSwitchTexture (line->sidedef[0], repeat, special);
line->special = 0;
@ -657,9 +625,9 @@ static void DoSectorDamage(AActor *actor, sector_t *sec, int amount, FName type,
void P_SectorDamage(int tag, int amount, FName type, const PClass *protectClass, int flags)
{
int secnum = -1;
while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0)
FSectorTagIterator itr(tag);
int secnum;
while ((secnum = itr.Next()) >= 0)
{
AActor *actor, *next;
sector_t *sec = &sectors[secnum];
@ -884,12 +852,14 @@ DLightTransfer::DLightTransfer (sector_t *srcSec, int target, bool copyFloor)
if (copyFloor)
{
for (secnum = -1; (secnum = P_FindSectorFromTag (target, secnum)) >= 0; )
FSectorTagIterator itr(target);
while ((secnum = itr.Next()) >= 0)
sectors[secnum].ChangeFlags(sector_t::floor, 0, PLANEF_ABSLIGHTING);
}
else
{
for (secnum = -1; (secnum = P_FindSectorFromTag (target, secnum)) >= 0; )
FSectorTagIterator itr(target);
while ((secnum = itr.Next()) >= 0)
sectors[secnum].ChangeFlags(sector_t::ceiling, 0, PLANEF_ABSLIGHTING);
}
ChangeStatNum (STAT_LIGHTTRANSFER);
@ -912,12 +882,14 @@ void DLightTransfer::DoTransfer (int level, int target, bool floor)
if (floor)
{
for (secnum = -1; (secnum = P_FindSectorFromTag (target, secnum)) >= 0; )
FSectorTagIterator itr(target);
while ((secnum = itr.Next()) >= 0)
sectors[secnum].SetPlaneLight(sector_t::floor, level);
}
else
{
for (secnum = -1; (secnum = P_FindSectorFromTag (target, secnum)) >= 0; )
FSectorTagIterator itr(target);
while ((secnum = itr.Next()) >= 0)
sectors[secnum].SetPlaneLight(sector_t::ceiling, level);
}
}
@ -985,7 +957,8 @@ DWallLightTransfer::DWallLightTransfer (sector_t *srcSec, int target, BYTE flags
wallflags = WALLF_ABSLIGHTING | WALLF_NOFAKECONTRAST;
}
for (linenum = -1; (linenum = P_FindLineFromID (target, linenum)) >= 0; )
FLineIdIterator itr(target);
while ((linenum = itr.Next()) >= 0)
{
if (flags & WLF_SIDE1 && lines[linenum].sidedef[0] != NULL)
{
@ -1015,7 +988,8 @@ void DWallLightTransfer::DoTransfer (short lightlevel, int target, BYTE flags)
{
int linenum;
for (linenum = -1; (linenum = P_FindLineFromID (target, linenum)) >= 0; )
FLineIdIterator itr(target);
while ((linenum = itr.Next()) >= 0)
{
line_t *line = &lines[linenum];
@ -1173,7 +1147,9 @@ void P_SpawnPortal(line_t *line, int sectortag, int plane, int alpha)
reference->flags |= MF_JUSTATTACKED;
anchor->flags |= MF_JUSTATTACKED;
for (int s=-1; (s = P_FindSectorFromTag(sectortag,s)) >= 0;)
int s;
FSectorTagIterator itr(sectortag);
while ((s = itr.Next()) >= 0)
{
SetPortal(&sectors[s], plane, reference, alpha);
}
@ -1193,7 +1169,8 @@ void P_SpawnPortal(line_t *line, int sectortag, int plane, int alpha)
}
else
{
for (int s=-1; (s = P_FindSectorFromTag(lines[j].args[0],s)) >= 0;)
FSectorTagIterator itr(lines[j].args[0]);
while ((s = itr.Next()) >= 0)
{
SetPortal(&sectors[s], plane, reference, alpha);
}
@ -1374,6 +1351,7 @@ void P_SpawnSpecials (void)
// killough 3/7/98:
// support for drawn heights coming from different sector
case Transfer_Heights:
{
sec = lines[i].frontsector;
if (lines[i].args[1] & 2)
{
@ -1399,13 +1377,15 @@ void P_SpawnSpecials (void)
{
sec->MoreFlags |= SECF_NOFAKELIGHT;
}
for (s = -1; (s = P_FindSectorFromTag(lines[i].args[0],s)) >= 0;)
FSectorTagIterator itr(lines[i].args[0]);
while ((s = itr.Next()) >= 0)
{
sectors[s].heightsec = sec;
sec->e->FakeFloor.Sectors.Push(&sectors[s]);
sectors[s].AdjustFloorClip();
}
break;
}
// killough 3/16/98: Add support for setting
// floor lighting independently (e.g. lava)
@ -1459,7 +1439,8 @@ void P_SpawnSpecials (void)
case Init_Gravity:
{
float grav = ((float)P_AproxDistance (lines[i].dx, lines[i].dy)) / (FRACUNIT * 100.0f);
for (s = -1; (s = P_FindSectorFromTag(lines[i].args[0],s)) >= 0;)
FSectorTagIterator itr(lines[i].args[0]);
while ((s = itr.Next()) >= 0)
sectors[s].gravity = grav;
}
break;
@ -1470,7 +1451,8 @@ void P_SpawnSpecials (void)
case Init_Damage:
{
int damage = P_AproxDistance (lines[i].dx, lines[i].dy) >> FRACBITS;
for (s = -1; (s = P_FindSectorFromTag(lines[i].args[0],s)) >= 0;)
FSectorTagIterator itr(lines[i].args[0]);
while ((s = itr.Next()) >= 0)
{
sectors[s].damage = damage;
sectors[s].mod = 0;//MOD_UNKNOWN;
@ -1493,10 +1475,13 @@ void P_SpawnSpecials (void)
// or ceiling texture, to distinguish floor and ceiling sky.
case Init_TransferSky:
for (s = -1; (s = P_FindSectorFromTag(lines[i].args[0],s)) >= 0;)
sectors[s].sky = (i+1) | PL_SKYFLAT;
{
FSectorTagIterator itr(lines[i].args[0]);
while ((s = itr.Next()) >= 0)
sectors[s].sky = (i + 1) | PL_SKYFLAT;
break;
}
}
break;
}
}
@ -1756,7 +1741,7 @@ static void P_SpawnScrollers(void)
if (lines[i].special == Sector_CopyScroller)
{
// don't allow copying the scroller if the sector has the same tag as it would just duplicate it.
if (lines[i].args[0] != lines[i].frontsector->tag)
if (tagManager.SectorHasTag(lines[i].frontsector, lines[i].args[0]))
{
copyscrollers.Push(i);
}
@ -1832,25 +1817,29 @@ static void P_SpawnScrollers(void)
register int s;
case Scroll_Ceiling:
for (s=-1; (s = P_FindSectorFromTag (l->args[0],s)) >= 0;)
{
new DScroller (DScroller::sc_ceiling, -dx, dy, control, s, accel);
FSectorTagIterator itr(l->args[0]);
while ((s = itr.Next()) >= 0)
{
new DScroller(DScroller::sc_ceiling, -dx, dy, control, s, accel);
}
for(unsigned j = 0;j < copyscrollers.Size(); j++)
for (unsigned j = 0; j < copyscrollers.Size(); j++)
{
line_t *line = &lines[copyscrollers[j]];
if (line->args[0] == l->args[0] && (line->args[1] & 1))
{
new DScroller (DScroller::sc_ceiling, -dx, dy, control, int(line->frontsector-sectors), accel);
new DScroller(DScroller::sc_ceiling, -dx, dy, control, int(line->frontsector - sectors), accel);
}
}
break;
}
case Scroll_Floor:
if (l->args[2] != 1)
{ // scroll the floor texture
for (s=-1; (s = P_FindSectorFromTag (l->args[0],s)) >= 0;)
FSectorTagIterator itr(l->args[0]);
while ((s = itr.Next()) >= 0)
{
new DScroller (DScroller::sc_floor, -dx, dy, control, s, accel);
}
@ -1867,7 +1856,8 @@ static void P_SpawnScrollers(void)
if (l->args[2] > 0)
{ // carry objects on the floor
for (s=-1; (s = P_FindSectorFromTag (l->args[0],s)) >= 0;)
FSectorTagIterator itr(l->args[0]);
while ((s = itr.Next()) >= 0)
{
new DScroller (DScroller::sc_carry, dx, dy, control, s, accel);
}
@ -1886,10 +1876,15 @@ static void P_SpawnScrollers(void)
// killough 3/1/98: scroll wall according to linedef
// (same direction and speed as scrolling floors)
case Scroll_Texture_Model:
for (s=-1; (s = P_FindLineFromID (l->args[0],s)) >= 0;)
{
FLineIdIterator itr(l->args[0]);
while ((s = itr.Next()) >= 0)
{
if (s != i)
new DScroller (dx, dy, lines+s, control, accel);
new DScroller(dx, dy, lines + s, control, accel);
}
break;
}
case Scroll_Texture_Offsets:
// killough 3/2/98: scroll according to sidedef offsets
@ -2041,7 +2036,8 @@ void P_SetSectorFriction (int tag, int amount, bool alterFlag)
// higher friction value actually means 'less friction'.
movefactor = FrictionToMoveFactor(friction);
for (s = -1; (s = P_FindSectorFromTag (tag,s)) >= 0; )
FSectorTagIterator itr(tag);
while ((s = itr.Next()) >= 0)
{
// killough 8/28/98:
//
@ -2153,7 +2149,7 @@ DPusher::DPusher (DPusher::EPusher type, line_t *l, int magnitude, int angle,
int DPusher::CheckForSectorMatch (EPusher type, int tag)
{
if (m_Type == type && sectors[m_Affectee].tag == tag)
if (m_Type == type && tagManager.SectorHasTag(m_Affectee, tag))
return m_Affectee;
else
return -1;
@ -2356,20 +2352,27 @@ static void P_SpawnPushers ()
switch (l->special)
{
case Sector_SetWind: // wind
for (s = -1; (s = P_FindSectorFromTag (l->args[0],s)) >= 0 ; )
new DPusher (DPusher::p_wind, l->args[3] ? l : NULL, l->args[1], l->args[2], NULL, s);
{
FSectorTagIterator itr(l->args[0]);
while ((s = itr.Next()) >= 0)
new DPusher(DPusher::p_wind, l->args[3] ? l : NULL, l->args[1], l->args[2], NULL, s);
l->special = 0;
break;
}
case Sector_SetCurrent: // current
for (s = -1; (s = P_FindSectorFromTag (l->args[0],s)) >= 0 ; )
new DPusher (DPusher::p_current, l->args[3] ? l : NULL, l->args[1], l->args[2], NULL, s);
{
FSectorTagIterator itr(l->args[0]);
while ((s = itr.Next()) >= 0)
new DPusher(DPusher::p_current, l->args[3] ? l : NULL, l->args[1], l->args[2], NULL, s);
l->special = 0;
break;
}
case PointPush_SetForce: // push/pull
if (l->args[0]) { // [RH] Find thing by sector
for (s = -1; (s = P_FindSectorFromTag (l->args[0], s)) >= 0 ; )
FSectorTagIterator itr(l->args[0]);
while ((s = itr.Next()) >= 0)
{
AActor *thing = P_GetPushThing (s);
if (thing) { // No MT_P* means no effect

View File

@ -243,9 +243,7 @@ inline sector_t *getNextSector (line_t *line, const sector_t *sec)
}
int P_FindSectorFromTag (int tag, int start);
int P_FindLineFromID (int id, int start);
#include "p_tags.h"
//
// P_LIGHTS

353
src/p_tags.cpp Normal file
View File

@ -0,0 +1,353 @@
/*
** p_tags.cpp
** everything to do with tags and their management
**
**---------------------------------------------------------------------------
** Copyright 2015 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.
**---------------------------------------------------------------------------
**
**
*/
#include "p_tags.h"
#include "c_dispatch.h"
FTagManager tagManager;
//-----------------------------------------------------------------------------
//
//
//
//-----------------------------------------------------------------------------
static inline int sectindex(const sector_t *sector)
{
return (int)(intptr_t)(sector - sectors);
}
static inline int lineindex(const line_t *line)
{
return (int)(intptr_t)(line - lines);
}
//-----------------------------------------------------------------------------
//
//
//
//-----------------------------------------------------------------------------
void FTagManager::AddSectorTag(int sector, int tag)
{
if (tag == 0) return;
// This function assumes that all tags for a single sector get added sequentially.
// Should there ever be some need for compatibility.txt to add tags to sectors which already have a tag this function needs to be changed to adjust the startForSector indices.
while (startForSector.Size() <= (unsigned int)sector)
{
startForSector.Push(-1);
}
if (startForSector[sector] == -1)
{
startForSector[sector] = allTags.Size();
}
else
{
// check if the key was already defined
for (unsigned i = startForSector[sector]; i < allTags.Size(); i++)
{
if (allTags[i].tag == tag)
{
return;
}
}
}
FTagItem it = { sector, tag, -1 };
allTags.Push(it);
}
//-----------------------------------------------------------------------------
//
//
//
//-----------------------------------------------------------------------------
void FTagManager::RemoveSectorTags(int sect)
{
int start = startForSector[sect];
if (start >= 0)
{
while (allTags[start].target == sect)
{
allTags[start].tag = allTags[start].target = -1;
start++;
}
}
}
//-----------------------------------------------------------------------------
//
//
//
//-----------------------------------------------------------------------------
void FTagManager::AddLineID(int line, int tag)
{
if (tag == -1) return; // For line IDs -1 means 'not set', unlike sectors.
// This function assumes that all ids for a single line get added sequentially.
while (startForLine.Size() <= (unsigned int)line)
{
startForLine.Push(-1);
}
if (startForLine[line] == -1)
{
startForLine[line] = allIDs.Size();
}
else
{
// check if the key was already defined
for (unsigned i = startForLine[line]; i < allIDs.Size(); i++)
{
if (allIDs[i].tag == tag)
{
return;
}
}
}
FTagItem it = { line, tag, -1 };
allIDs.Push(it);
}
//-----------------------------------------------------------------------------
//
//
//
//-----------------------------------------------------------------------------
void FTagManager::HashTags()
{
// add an end marker so we do not need to check for the array's size in the other functions.
static FTagItem it = { -1, -1, -1 };
allTags.Push(it);
allIDs.Push(it);
// Initially make all slots empty.
memset(TagHashFirst, -1, sizeof(TagHashFirst));
memset(IDHashFirst, -1, sizeof(IDHashFirst));
// Proceed from last to first so that lower targets appear first
for (int i = allTags.Size() - 1; i >= 0; i--)
{
if (allTags[i].target >= 0) // only link valid entries
{
int hash = ((unsigned int)allTags[i].tag) % FTagManager::TAG_HASH_SIZE;
allTags[i].nexttag = TagHashFirst[hash];
TagHashFirst[hash] = i;
}
}
for (int i = allIDs.Size() - 1; i >= 0; i--)
{
if (allIDs[i].target >= 0) // only link valid entries
{
int hash = ((unsigned int)allIDs[i].tag) % FTagManager::TAG_HASH_SIZE;
allIDs[i].nexttag = IDHashFirst[hash];
IDHashFirst[hash] = i;
}
}
}
//-----------------------------------------------------------------------------
//
//
//
//-----------------------------------------------------------------------------
bool FTagManager::SectorHasTags(const sector_t *sector) const
{
int i = sectindex(sector);
return SectorHasTags(i);
}
//-----------------------------------------------------------------------------
//
//
//
//-----------------------------------------------------------------------------
int FTagManager::GetFirstSectorTag(const sector_t *sect) const
{
int i = sectindex(sect);
return SectorHasTags(i) ? allTags[startForSector[i]].tag : 0;
}
//-----------------------------------------------------------------------------
//
//
//
//-----------------------------------------------------------------------------
bool FTagManager::SectorHasTag(int i, int tag) const
{
if (SectorHasTags(i))
{
int ndx = startForSector[i];
while (allTags[ndx].target == i)
{
if (allTags[ndx].tag == tag) return true;
ndx++;
}
}
return false;
}
//-----------------------------------------------------------------------------
//
//
//
//-----------------------------------------------------------------------------
bool FTagManager::SectorHasTag(const sector_t *sector, int tag) const
{
return SectorHasTag(sectindex(sector), tag);
}
//-----------------------------------------------------------------------------
//
//
//
//-----------------------------------------------------------------------------
bool FTagManager::LineHasID(int i, int tag) const
{
if (LineHasIDs(i))
{
int ndx = startForLine[i];
while (allIDs[ndx].target == i)
{
if (allIDs[ndx].tag == tag) return true;
ndx++;
}
}
return false;
}
//-----------------------------------------------------------------------------
//
//
//
//-----------------------------------------------------------------------------
bool FTagManager::LineHasID(const line_t *line, int tag) const
{
return LineHasID(lineindex(line), tag);
}
//-----------------------------------------------------------------------------
//
//
//
//-----------------------------------------------------------------------------
void FTagManager::DumpTags()
{
for (unsigned i = 0; i < allTags.Size(); i++)
{
Printf("Sector %d, tag %d\n", allTags[i].target, allTags[i].tag);
}
for (unsigned i = 0; i < allIDs.Size(); i++)
{
Printf("Line %d, ID %d\n", allIDs[i].target, allIDs[i].tag);
}
}
CCMD(dumptags)
{
tagManager.DumpTags();
}
//-----------------------------------------------------------------------------
//
// RETURN NEXT SECTOR # THAT LINE TAG REFERS TO
//
// Find the next sector with a specified tag.
// Rewritten by Lee Killough to use chained hashing to improve speed
//
//-----------------------------------------------------------------------------
int FSectorTagIterator::Next()
{
int ret;
if (searchtag == INT_MIN)
{
ret = start;
start = -1;
}
else
{
while (start >= 0 && tagManager.allTags[start].tag != searchtag) start = tagManager.allTags[start].nexttag;
if (start == -1) return -1;
ret = tagManager.allTags[start].target;
start = start = tagManager.allTags[start].nexttag;
}
return ret;
}
//-----------------------------------------------------------------------------
//
// linear search for compatible stair building
//
//-----------------------------------------------------------------------------
int FSectorTagIterator::NextCompat(bool compat, int start)
{
if (!compat) return Next();
for (int i = start + 1; i < numsectors; i++)
{
if (tagManager.SectorHasTag(i, searchtag)) return i;
}
return -1;
}
//-----------------------------------------------------------------------------
//
// killough 4/16/98: Same thing, only for linedefs
//
//-----------------------------------------------------------------------------
int FLineIdIterator::Next()
{
while (start >= 0 && tagManager.allIDs[start].tag != searchtag) start = tagManager.allIDs[start].nexttag;
if (start == -1) return -1;
int ret = tagManager.allIDs[start].target;
start = start = tagManager.allIDs[start].nexttag;
return ret;
}

133
src/p_tags.h Normal file
View File

@ -0,0 +1,133 @@
#ifndef P_TAGS_H
#define P_TAGS_H 1
#include "r_defs.h"
#include "r_state.h"
struct FTagItem
{
int target; // either sector or line
int tag;
int nexttag; // for hashing
};
class FSectorTagIterator;
class FLineIdIterator;
class FTagManager
{
enum
{
TAG_HASH_SIZE = 256
};
friend class FSectorTagIterator;
friend class FLineIdIterator;
TArray<FTagItem> allTags;
TArray<FTagItem> allIDs;
TArray<int> startForSector;
TArray<int> startForLine;
int TagHashFirst[TAG_HASH_SIZE];
int IDHashFirst[TAG_HASH_SIZE];
bool SectorHasTags(int sect) const
{
return sect >= 0 && sect < (int)startForSector.Size() && startForSector[sect] >= 0;
}
bool LineHasIDs(int sect) const
{
return sect >= 0 && sect < (int)startForLine.Size() && startForLine[sect] >= 0;
}
public:
void Clear()
{
allTags.Clear();
allIDs.Clear();
startForSector.Clear();
startForLine.Clear();
memset(TagHashFirst, -1, sizeof(TagHashFirst));
}
bool SectorHasTags(const sector_t *sector) const;
int GetFirstSectorTag(const sector_t *sect) const;
bool SectorHasTag(int sector, int tag) const;
bool SectorHasTag(const sector_t *sector, int tag) const;
bool LineHasID(int line, int id) const;
bool LineHasID(const line_t *line, int id) const;
void HashTags();
void AddSectorTag(int sector, int tag);
void AddLineID(int line, int tag);
void RemoveSectorTags(int sect);
void DumpTags();
};
extern FTagManager tagManager;
class FSectorTagIterator
{
protected:
int searchtag;
int start;
public:
FSectorTagIterator(int tag)
{
searchtag = tag;
start = tagManager.TagHashFirst[((unsigned int)tag) % FTagManager::TAG_HASH_SIZE];
}
// Special constructor for actions that treat tag 0 as 'back of activation line'
FSectorTagIterator(int tag, line_t *line)
{
if (tag == 0)
{
searchtag = INT_MIN;
start = (line == NULL || line->backsector == NULL)? -1 : (int)(line->backsector - sectors);
}
else
{
searchtag = tag;
start = tagManager.TagHashFirst[((unsigned int)tag) % FTagManager::TAG_HASH_SIZE];
}
}
int Next();
int NextCompat(bool compat, int secnum);
};
class FLineIdIterator
{
protected:
int searchtag;
int start;
public:
FLineIdIterator(int id)
{
searchtag = id;
start = tagManager.IDHashFirst[((unsigned int)id) % FTagManager::TAG_HASH_SIZE];
}
int Next();
};
inline int P_FindFirstSectorFromTag(int tag)
{
FSectorTagIterator it(tag);
return it.Next();
}
inline int P_FindFirstLineFromID(int tag)
{
FLineIdIterator it(tag);
return it.Next();
}
#endif

View File

@ -250,7 +250,7 @@ static AActor *SelectTeleDest (int tid, int tag, bool norandom)
int count = 0;
while ( (searcher = iterator.Next ()) )
{
if (tag == 0 || searcher->Sector->tag == tag)
if (tag == 0 || tagManager.SectorHasTag(searcher->Sector, tag))
{
count++;
}
@ -289,7 +289,7 @@ static AActor *SelectTeleDest (int tid, int tag, bool norandom)
while (count > 0)
{
searcher = iterator.Next ();
if (tag == 0 || searcher->Sector->tag == tag)
if (tag == 0 || tagManager.SectorHasTag(searcher->Sector, tag))
{
count--;
}
@ -300,9 +300,10 @@ static AActor *SelectTeleDest (int tid, int tag, bool norandom)
if (tag != 0)
{
int secnum = -1;
int secnum;
while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0)
FSectorTagIterator itr(tag);
while ((secnum = itr.Next()) >= 0)
{
// Scanning the snext links of things in the sector will not work, because
// TeleportDests have MF_NOSECTOR set. So you have to search *everything*.
@ -423,7 +424,8 @@ bool EV_SilentLineTeleport (line_t *line, int side, AActor *thing, int id, INTBO
if (side || thing->flags2 & MF2_NOTELEPORT || !line || line->sidedef[1] == NULL)
return false;
for (i = -1; (i = P_FindLineFromID (id, i)) >= 0; )
FLineIdIterator itr(id);
while ((i = itr.Next()) >= 0)
{
if (line-lines == i)
continue;
@ -726,7 +728,8 @@ bool EV_TeleportSector (int tag, int source_tid, int dest_tid, bool fog, int gro
int secnum;
secnum = -1;
while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0)
FSectorTagIterator itr(tag);
while ((secnum = itr.Next()) >= 0)
{
msecnode_t *node;
const sector_t * const sec = &sectors[secnum];

View File

@ -69,6 +69,12 @@ public:
}
void Set(int index, int value)
{
if ((unsigned)index >= Types.Size())
{
int oldsize = Types.Size();
Resize(index + 1);
memset(&Types[oldsize], 0xff, (index + 1 - oldsize)*sizeof(WORD));
}
Types[index] = value;
}
};

View File

@ -45,9 +45,11 @@
#include "gi.h"
#include "templates.h"
#include "g_level.h"
#include "v_text.h"
#include "i_system.h"
// Set of spawnable things for the Thing_Spawn and Thing_Projectile specials.
TMap<int, const PClass *> SpawnableThings;
FClassMap SpawnableThings;
static FRandom pr_leadtarget ("LeadTarget");
@ -530,22 +532,32 @@ const PClass *P_GetSpawnableType(int spawnnum)
return NULL;
}
typedef TMap<int, const PClass *>::Pair SpawnablePair;
struct MapinfoSpawnItem
{
FName classname; // DECORATE is read after MAPINFO so we do not have the actual classes available here yet.
// These are for error reporting. We must store the file information because it's no longer available when these items get resolved.
FString filename;
int linenum;
};
typedef TMap<int, MapinfoSpawnItem> SpawnMap;
static SpawnMap SpawnablesFromMapinfo;
static SpawnMap ConversationIDsFromMapinfo;
static int STACK_ARGS SpawnableSort(const void *a, const void *b)
{
return (*((SpawnablePair **)a))->Key - (*((SpawnablePair **)b))->Key;
return (*((FClassMap::Pair **)a))->Key - (*((FClassMap::Pair **)b))->Key;
}
CCMD (dumpspawnables)
static void DumpClassMap(FClassMap &themap)
{
TMapIterator<int, const PClass *> it(SpawnableThings);
SpawnablePair *pair, **allpairs;
FClassMap::Iterator it(themap);
FClassMap::Pair *pair, **allpairs;
int i = 0;
// Sort into numerical order, since their arrangement in the map can
// be in an unspecified order.
allpairs = new TMap<int, const PClass *>::Pair *[SpawnableThings.CountUsed()];
allpairs = new FClassMap::Pair *[themap.CountUsed()];
while (it.NextPair(pair))
{
allpairs[i++] = pair;
@ -559,3 +571,110 @@ CCMD (dumpspawnables)
delete[] allpairs;
}
CCMD(dumpspawnables)
{
DumpClassMap(SpawnableThings);
}
CCMD (dumpconversationids)
{
DumpClassMap(StrifeTypes);
}
static void ParseSpawnMap(FScanner &sc, SpawnMap & themap, const char *descript)
{
TMap<int, bool> defined;
int error = 0;
MapinfoSpawnItem editem;
editem.filename = sc.ScriptName;
while (true)
{
if (sc.CheckString("}")) return;
else if (sc.CheckNumber())
{
int ednum = sc.Number;
sc.MustGetStringName("=");
sc.MustGetString();
bool *def = defined.CheckKey(ednum);
if (def != NULL)
{
sc.ScriptMessage("%s %d defined more than once", descript, ednum);
error++;
}
else if (ednum < 0)
{
sc.ScriptMessage("%s must be positive, got %d", descript, ednum);
error++;
}
defined[ednum] = true;
editem.classname = sc.String;
themap.Insert(ednum, editem);
}
else
{
sc.ScriptError("Number expected");
}
}
if (error > 0)
{
sc.ScriptError("%d errors encountered in %s definition", error, descript);
}
}
void FMapInfoParser::ParseSpawnNums()
{
ParseOpenBrace();
ParseSpawnMap(sc, SpawnablesFromMapinfo, "Spawn number");
}
void FMapInfoParser::ParseConversationIDs()
{
ParseOpenBrace();
ParseSpawnMap(sc, ConversationIDsFromMapinfo, "Conversation ID");
}
void InitClassMap(FClassMap &themap, SpawnMap &thedata)
{
themap.Clear();
SpawnMap::Iterator it(thedata);
SpawnMap::Pair *pair;
int error = 0;
while (it.NextPair(pair))
{
const PClass *cls = NULL;
if (pair->Value.classname != NAME_None)
{
cls = PClass::FindClass(pair->Value.classname);
if (cls == NULL)
{
Printf(TEXTCOLOR_RED "Script error, \"%s\" line %d:\nUnknown actor class %s\n",
pair->Value.filename.GetChars(), pair->Value.linenum, pair->Value.classname.GetChars());
error++;
}
themap.Insert(pair->Key, cls);
}
else
{
themap.Remove(pair->Key);
}
}
if (error > 0)
{
I_Error("%d unknown actor classes found", error);
}
thedata.Clear(); // we do not need this any longer
}
void InitSpawnablesFromMapinfo()
{
InitClassMap(SpawnableThings, SpawnablesFromMapinfo);
InitClassMap(StrifeTypes, ConversationIDsFromMapinfo);
}

View File

@ -46,6 +46,7 @@
#include "r_state.h"
#include "r_data/colormaps.h"
#include "w_wad.h"
#include "p_tags.h"
//===========================================================================
//
@ -500,7 +501,8 @@ public:
break;
case NAME_Type:
th->type = (short)CheckInt(key);
th->EdNum = (short)CheckInt(key);
th->info = DoomEdMap.CheckKey(th->EdNum);
break;
case NAME_Conversation:
@ -721,6 +723,7 @@ public:
break;
default:
CHECK_N(Zd | Zdt)
if (0 == strnicmp("user_", key.GetChars(), 5))
{ // Custom user key - Sets an actor's user variable directly
FMapThingUserData ud;
@ -776,10 +779,11 @@ public:
bool strifetrans = false;
bool strifetrans2 = false;
FString arg0str, arg1str;
int lineid; // forZDoomTranslated namespace
FString tagstring;
memset(ld, 0, sizeof(*ld));
ld->Alpha = FRACUNIT;
ld->id = -1;
ld->sidedef[0] = ld->sidedef[1] = NULL;
if (level.flags2 & LEVEL2_CLIPMIDTEX) ld->flags |= ML_CLIP_MIDTEX;
if (level.flags2 & LEVEL2_WRAPMIDTEX) ld->flags |= ML_WRAP_MIDTEX;
@ -812,7 +816,8 @@ public:
continue;
case NAME_Id:
ld->id = CheckInt(key);
lineid = CheckInt(key);
tagManager.AddLineID(index, lineid);
continue;
case NAME_Sidefront:
@ -1035,16 +1040,35 @@ public:
Flag(ld->flags, ML_3DMIDTEX_IMPASS, key);
continue;
case NAME_MoreIds:
// delay parsing of the tag string until parsing of the sector is complete
// This ensures that the ID is always the first tag in the list.
tagstring = CheckString(key);
break;
default:
break;
}
if (!strnicmp("user_", key.GetChars(), 5))
if ((namespace_bits & (Zd | Zdt)) && !strnicmp("user_", key.GetChars(), 5))
{
AddUserKey(key, UDMF_Line, index);
}
}
if (tagstring.IsNotEmpty())
{
FScanner sc;
sc.OpenString("tagstring", tagstring);
// scan the string as long as valid numbers can be found
while (sc.CheckNumber())
{
if (sc.Number != 0) tagManager.AddLineID(index, sc.Number);
}
}
if (isTranslated)
{
int saved = ld->flags;
@ -1052,7 +1076,7 @@ public:
maplinedef_t mld;
memset(&mld, 0, sizeof(mld));
mld.special = ld->special;
mld.tag = ld->id;
mld.tag = lineid;
P_TranslateLineDef(ld, &mld);
ld->flags = saved | (ld->flags&(ML_MONSTERSCANACTIVATE|ML_REPEAT_SPECIAL|ML_FIRSTSIDEONLY));
}
@ -1225,7 +1249,7 @@ public:
break;
}
if (!strnicmp("user_", key.GetChars(), 5))
if ((namespace_bits & (Zd | Zdt)) && !strnicmp("user_", key.GetChars(), 5))
{
AddUserKey(key, UDMF_Side, index);
}
@ -1252,6 +1276,7 @@ public:
int desaturation = -1;
int fplaneflags = 0, cplaneflags = 0;
double fp[4] = { 0 }, cp[4] = { 0 };
FString tagstring;
memset(sec, 0, sizeof(*sec));
sec->lightlevel = 160;
@ -1315,7 +1340,7 @@ public:
continue;
case NAME_Id:
sec->tag = (short)CheckInt(key);
tagManager.AddSectorTag(index, CheckInt(key));
continue;
default:
@ -1493,16 +1518,32 @@ public:
cp[3] = CheckFloat(key);
break;
case NAME_MoreIds:
// delay parsing of the tag string until parsing of the sector is complete
// This ensures that the ID is always the first tag in the list.
tagstring = CheckString(key);
break;
default:
break;
}
if (!strnicmp("user_", key.GetChars(), 5))
if ((namespace_bits & (Zd | Zdt)) && !strnicmp("user_", key.GetChars(), 5))
{
AddUserKey(key, UDMF_Sector, index);
}
}
if (tagstring.IsNotEmpty())
{
FScanner sc;
sc.OpenString("tagstring", tagstring);
// scan the string as long as valid numbers can be found
while (sc.CheckNumber())
{
if (sc.Number != 0) tagManager.AddSectorTag(index, sc.Number);
}
}
sec->secretsector = !!(sec->special&SECRET_MASK);
// Reset the planes to their defaults if not all of the plane equation's parameters were found.

View File

@ -295,14 +295,16 @@ player_t::player_t()
respawn_time(0),
camera(0),
air_finished(0),
MUSINFOactor(0),
MUSINFOtics(-1),
crouching(0),
crouchdir(0),
Bot(0),
BlendR(0),
BlendG(0),
BlendB(0),
BlendA(0),
LogText(),
crouching(0),
crouchdir(0),
crouchfactor(0),
crouchoffset(0),
crouchviewdelta(0),
@ -400,6 +402,8 @@ player_t &player_t::operator=(const player_t &p)
ConversationPC = p.ConversationPC;
ConversationNPCAngle = p.ConversationNPCAngle;
ConversationFaceTalker = p.ConversationFaceTalker;
MUSINFOactor = p.MUSINFOactor;
MUSINFOtics = p.MUSINFOtics;
return *this;
}
@ -430,6 +434,7 @@ size_t player_t::FixPointers (const DObject *old, DObject *rep)
if (*&PremorphWeapon == old) PremorphWeapon = static_cast<AWeapon *>(rep), changed++;
if (*&ConversationNPC == old) ConversationNPC = replacement, changed++;
if (*&ConversationPC == old) ConversationPC = replacement, changed++;
if (*&MUSINFOactor == old) MUSINFOactor = replacement, changed++;
return changed;
}
@ -443,6 +448,7 @@ size_t player_t::PropagateMark()
GC::Mark(ReadyWeapon);
GC::Mark(ConversationNPC);
GC::Mark(ConversationPC);
GC::Mark(MUSINFOactor);
GC::Mark(PremorphWeapon);
if (PendingWeapon != WP_NOCHANGE)
{
@ -2331,6 +2337,30 @@ void P_PlayerThink (player_t *player)
player->crouchoffset = -FixedMul(player->mo->ViewHeight, (FRACUNIT - player->crouchfactor));
// MUSINFO stuff
if (player->MUSINFOtics >= 0 && player->MUSINFOactor != NULL)
{
if (--player->MUSINFOtics < 0)
{
if (player - players == consoleplayer)
{
if (player->MUSINFOactor->args[0] != 0)
{
FName *music = level.info->MusicMap.CheckKey(player->MUSINFOactor->args[0]);
if (music != NULL)
{
S_ChangeMusic(music->GetChars(), player->MUSINFOactor->args[1]);
}
}
else
{
S_ChangeMusic("*");
}
}
DPrintf("MUSINFO change for player %d to %d\n", (int)(player - players), player->MUSINFOactor->args[0]);
}
}
if (player->playerstate == PST_DEAD)
{
@ -3105,6 +3135,10 @@ void player_t::Serialize (FArchive &arc)
{
userinfo.SkinChanged(skinname, CurrentPlayerClass);
}
if (SaveVersion >= 4522)
{
arc << MUSINFOactor << MUSINFOtics;
}
}

View File

@ -262,7 +262,7 @@ static int WriteSECTORS (FILE *file)
uppercopy (ms.ceilingpic, GetTextureName (sectors[i].GetTexture(sector_t::ceiling)));
ms.lightlevel = LittleShort((short)sectors[i].lightlevel);
ms.special = LittleShort(sectors[i].special);
ms.tag = LittleShort(sectors[i].tag);
ms.tag = LittleShort(tagManager.GetFirstSectorTag(&sectors[i]));
fwrite (&ms, sizeof(ms), 1, file);
}
return numsectors * sizeof(ms);

View File

@ -60,7 +60,7 @@ typedef enum
PushMany,
} triggertype_e;
void P_TranslateLineDef (line_t *ld, maplinedef_t *mld)
void P_TranslateLineDef (line_t *ld, maplinedef_t *mld, int lineindexforid)
{
unsigned short special = (unsigned short) LittleShort(mld->special);
short tag = LittleShort(mld->tag);
@ -100,11 +100,14 @@ void P_TranslateLineDef (line_t *ld, maplinedef_t *mld)
}
flags = newflags;
if (lineindexforid >= 0)
{
// For purposes of maintaining BOOM compatibility, each
// line also needs to have its ID set to the same as its tag.
// An external conversion program would need to do this more
// intelligently.
ld->id = tag;
tagManager.AddLineID(lineindexforid, tag);
}
// 0 specials are never translated.
if (special == 0)
@ -304,7 +307,7 @@ void P_TranslateTeleportThings ()
while ( (dest = iterator.Next()) )
{
if (dest->Sector->tag == 0)
if (!tagManager.SectorHasTags(dest->Sector))
{
dest->tid = 1;
dest->AddToHash ();

View File

@ -1561,8 +1561,8 @@ static void SpawnPolyobj (int index, int tag, int type)
sd->linedef->args[0] = 0;
IterFindPolySides(&polyobjs[index], sd);
po->MirrorNum = sd->linedef->args[1];
po->crush = (type != PO_SPAWN_TYPE) ? 3 : 0;
po->bHurtOnTouch = (type == PO_SPAWNHURT_TYPE);
po->crush = (type != SMT_PolySpawn) ? 3 : 0;
po->bHurtOnTouch = (type == SMT_PolySpawnHurt);
po->tag = tag;
po->seqType = sd->linedef->args[2];
if (po->seqType < 0 || po->seqType > 63)
@ -1632,8 +1632,8 @@ static void SpawnPolyobj (int index, int tag, int type)
}
if (po->Sidedefs.Size() > 0)
{
po->crush = (type != PO_SPAWN_TYPE) ? 3 : 0;
po->bHurtOnTouch = (type == PO_SPAWNHURT_TYPE);
po->crush = (type != SMT_PolySpawn) ? 3 : 0;
po->bHurtOnTouch = (type == SMT_PolySpawnHurt);
po->tag = tag;
po->seqType = po->Sidedefs[0]->linedef->args[3];
po->MirrorNum = po->Sidedefs[0]->linedef->args[2];
@ -1756,9 +1756,7 @@ void PO_Init (void)
for (polyspawn = polyspawns, prev = &polyspawns; polyspawn;)
{
// 9301 (3001) = no crush, 9302 (3002) = crushing, 9303 = hurting touch
if (polyspawn->type == PO_SPAWN_TYPE ||
polyspawn->type == PO_SPAWNCRUSH_TYPE ||
polyspawn->type == PO_SPAWNHURT_TYPE)
if (polyspawn->type >= SMT_PolySpawn && polyspawn->type <= SMT_PolySpawnHurt)
{
// Polyobj StartSpot Pt.
polyobjs[polyIndex].StartSpot.x = polyspawn->x;
@ -1778,7 +1776,7 @@ void PO_Init (void)
for (polyspawn = polyspawns; polyspawn;)
{
polyspawns_t *next = polyspawn->next;
if (polyspawn->type == PO_ANCHOR_TYPE)
if (polyspawn->type == SMT_PolyAnchor)
{
// Polyobj Anchor Pt.
TranslateToStartSpot (polyspawn->angle, polyspawn->x, polyspawn->y);

View File

@ -128,6 +128,8 @@ enum
kVK_UpArrow = 0x7E
};
static const NSOpenGLPixelFormatAttribute NSOpenGLPFAAllowOfflineRenderers = NSOpenGLPixelFormatAttribute(96);
#endif // prior to 10.5

View File

@ -72,6 +72,11 @@ CUSTOM_CVAR(Bool, fullscreen, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
setmodeneeded = true;
}
CUSTOM_CVAR(Bool, vid_autoswitch, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
{
Printf("You must restart " GAMENAME " to apply graphics switching mode\n");
}
RenderBufferOptions rbOpts;
@ -399,6 +404,11 @@ CocoaVideo::CocoaVideo(const int multisample)
attributes[i++] = NSOpenGLPFAStencilSize;
attributes[i++] = NSOpenGLPixelFormatAttribute(8);
if (!vid_autoswitch)
{
attributes[i++] = NSOpenGLPFAAllowOfflineRenderers;
}
if (multisample)
{
attributes[i++] = NSOpenGLPFAMultisample;

View File

@ -331,7 +331,7 @@ int I_PickIWad_Gtk (WadStuff *wads, int numwads, bool showwin, int defaultiwad)
gtk_container_add (GTK_CONTAINER(window), vbox);
// Create the top label.
widget = gtk_label_new ("ZDoom found more than one IWAD\nSelect from the list below to determine which one to use:");
widget = gtk_label_new (GAMENAME " found more than one IWAD\nSelect from the list below to determine which one to use:");
gtk_box_pack_start (GTK_BOX(vbox), widget, false, false, 0);
gtk_misc_set_alignment (GTK_MISC(widget), 0, 0);
@ -450,7 +450,7 @@ int I_PickIWad (WadStuff *wads, int numwads, bool showwin, int defaultiwad)
{
FString cmd("kdialog --title \"" GAMESIG " ");
cmd << GetVersionString() << ": Select an IWAD to use\""
" --menu \"ZDoom found more than one IWAD\n"
" --menu \"" GAMENAME " found more than one IWAD\n"
"Select from the list below to determine which one to use:\"";
for(i = 0; i < numwads; ++i)
@ -603,6 +603,15 @@ int I_FindAttr (findstate_t *fileinfo)
#ifdef __APPLE__
static PasteboardRef s_clipboard;
static CFDataRef GetPasteboardData(const PasteboardItemID itemID, const CFStringRef flavorType)
{
CFDataRef data = NULL;
const OSStatus result = PasteboardCopyItemFlavorData(s_clipboard, itemID, flavorType, &data);
return noErr == result ? data : NULL;
}
#endif // __APPLE__
// Clipboard support requires GTK+
@ -688,35 +697,41 @@ FString I_GetFromClipboard (bool use_primary_selection)
return FString();
}
CFArrayRef flavorTypeArray;
if (0 != PasteboardCopyItemFlavors(s_clipboard, itemID, &flavorTypeArray))
if (CFDataRef data = GetPasteboardData(itemID, kUTTypeUTF8PlainText))
{
return FString();
const CFIndex bufferLength = CFDataGetLength(data);
char* const buffer = result.LockNewBuffer(bufferLength);
memcpy(buffer, CFDataGetBytePtr(data), bufferLength);
result.UnlockBuffer();
}
else if (CFDataRef data = GetPasteboardData(itemID, kUTTypeUTF16PlainText))
{
#ifdef __LITTLE_ENDIAN__
static const CFStringEncoding ENCODING = kCFStringEncodingUTF16LE;
#else // __BIG_ENDIAN__
static const CFStringEncoding ENCODING = kCFStringEncodingUTF16BE;
#endif // __LITTLE_ENDIAN__
if (const CFStringRef utf16 = CFStringCreateFromExternalRepresentation(kCFAllocatorDefault, data, ENCODING))
{
const CFRange range = { 0, CFStringGetLength(utf16) };
CFIndex bufferLength = 0;
if (CFStringGetBytes(utf16, range, kCFStringEncodingUTF8, '?', false, NULL, 0, &bufferLength) > 0)
{
UInt8* const buffer = reinterpret_cast<UInt8*>(result.LockNewBuffer(bufferLength));
CFStringGetBytes(utf16, range, kCFStringEncodingUTF8, '?', false, buffer, bufferLength, NULL);
result.UnlockBuffer();
}
const CFIndex flavorCount = CFArrayGetCount(flavorTypeArray);
for (CFIndex flavorIndex = 0; flavorIndex < flavorCount; ++flavorIndex)
{
const CFStringRef flavorType = static_cast<const CFStringRef>(
CFArrayGetValueAtIndex(flavorTypeArray, flavorIndex));
if (UTTypeConformsTo(flavorType, CFSTR("public.utf8-plain-text")))
{
CFDataRef flavorData;
if (0 == PasteboardCopyItemFlavorData(s_clipboard, itemID, flavorType, &flavorData))
{
result += reinterpret_cast<const char*>(CFDataGetBytePtr(flavorData));
}
CFRelease(flavorData);
CFRelease(utf16);
}
}
CFRelease(flavorTypeArray);
return result;
#endif
return "";

View File

@ -43,5 +43,7 @@
</array>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>NSSupportsAutomaticGraphicsSwitching</key>
<string>YES</string>
</dict>
</plist>

View File

@ -37,7 +37,7 @@ static struct {
pid_t pid;
int has_siginfo;
siginfo_t siginfo;
char buf[1024];
char buf[4096];
} crash_info;

View File

@ -18,8 +18,6 @@
#include "templates.h"
#include "s_sound.h"
void ScaleWithAspect (int &w, int &h, int Width, int Height);
static void I_CheckGUICapture ();
static void I_CheckNativeMouse ();
@ -320,35 +318,11 @@ void MessagePump (const SDL_Event &sev)
int x, y;
SDL_GetMouseState (&x, &y);
// Detect if we're doing scaling in the Window and adjust the mouse
// coordinates accordingly. This could be more efficent, but I
// don't think performance is an issue in the menus.
SDL_Window *focus;
if (screen->IsFullscreen() && (focus = SDL_GetMouseFocus ()))
{
int w, h;
SDL_GetWindowSize (focus, &w, &h);
int realw = w, realh = h;
ScaleWithAspect (realw, realh, SCREENWIDTH, SCREENHEIGHT);
if (realw != SCREENWIDTH || realh != SCREENHEIGHT)
{
double xratio = (double)SCREENWIDTH/realw;
double yratio = (double)SCREENHEIGHT/realh;
if (realw < w)
{
x = (x - (w - realw)/2)*xratio;
y *= yratio;
}
else
{
y = (y - (h - realh)/2)*yratio;
x *= xratio;
}
}
}
event.data1 = x;
event.data2 = y;
screen->ScaleCoordsFromWindow(event.data1, event.data2);
event.type = EV_GUI_Event;
if(sev.type == SDL_MOUSEMOTION)
event.subtype = EV_GUI_MouseMove;

View File

@ -240,7 +240,7 @@ int main (int argc, char **argv)
#if !defined (__APPLE__)
{
int s[4] = { SIGSEGV, SIGILL, SIGFPE, SIGBUS };
cc_install_handlers(argc, argv, 4, s, "zdoom-crash.log", DoomSpecificInfo);
cc_install_handlers(argc, argv, 4, s, GAMENAMELOWERCASE "-crash.log", DoomSpecificInfo);
}
#endif // !__APPLE__

View File

@ -50,6 +50,7 @@ public:
friend class SDLVideo;
virtual void SetVSync (bool vsync);
virtual void ScaleCoordsFromWindow(SWORD &x, SWORD &y);
private:
PalEntry SourcePalette[256];
@ -723,6 +724,35 @@ void SDLFB::SetVSync (bool vsync)
#endif // __APPLE__
}
void SDLFB::ScaleCoordsFromWindow(SWORD &x, SWORD &y)
{
// Detect if we're doing scaling in the Window and adjust the mouse
// coordinates accordingly. This could be more efficent, but I
// don't think performance is an issue in the menus.
if(IsFullscreen())
{
int w, h;
SDL_GetWindowSize (Screen, &w, &h);
int realw = w, realh = h;
ScaleWithAspect (realw, realh, SCREENWIDTH, SCREENHEIGHT);
if (realw != SCREENWIDTH || realh != SCREENHEIGHT)
{
double xratio = (double)SCREENWIDTH/realw;
double yratio = (double)SCREENHEIGHT/realh;
if (realw < w)
{
x = (x - (w - realw)/2)*xratio;
y *= yratio;
}
else
{
y = (y - (h - realh)/2)*yratio;
x *= xratio;
}
}
}
}
ADD_STAT (blit)
{
FString out;

View File

@ -633,6 +633,7 @@ struct sector_t
return pos == floor? floorplane:ceilingplane;
}
bool PlaneMoving(int pos);
@ -650,12 +651,9 @@ struct sector_t
TObjPtr<AActor> SoundTarget;
short special;
short tag;
short lightlevel;
short seqType; // this sector's sound sequence
int nexttag,firsttag; // killough 1/30/98: improves searches for tags.
int sky;
FNameNoInit SeqName; // Sound sequence name. Setting seqType non-negative will override this.
@ -890,11 +888,8 @@ struct line_t
DWORD activation; // activation type
int special;
fixed_t Alpha; // <--- translucency (0=invisibile, FRACUNIT=opaque)
int id; // <--- same as tag or set with Line_SetIdentification
int args[5]; // <--- hexen-style arguments (expanded to ZDoom's full width)
int firstid, nextid;
side_t *sidedef[2];
//DWORD sidenum[2]; // sidenum[1] will be NO_SIDE if one sided
fixed_t bbox[4]; // bounding box, for the extent of the LineDef.
sector_t *frontsector, *backsector;
int validcount; // if == validcount, already checked

View File

@ -84,7 +84,7 @@ void FSoftwareRenderer::PrecacheTexture(FTexture *tex, int cache)
{
if (tex != NULL)
{
if (cache & 1)
if (cache & FTextureManager::HIT_Columnmode)
{
const FTexture::Span *spanp;
tex->GetColumn(0, &spanp);

Some files were not shown because too many files have changed in this diff Show More