mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-10 06:42:12 +00:00
Merge branch 'master' into openal
This commit is contained in:
commit
1f2a431d15
318 changed files with 7825 additions and 5901 deletions
|
@ -2,8 +2,12 @@ cmake_minimum_required( VERSION 2.4 )
|
|||
project(ZDoom)
|
||||
|
||||
if( COMMAND cmake_policy )
|
||||
cmake_policy( SET CMP0011 NEW )
|
||||
cmake_policy( SET CMP0054 NEW )
|
||||
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} )
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
===============================================================================
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
208
src/c_bind.cpp
208
src/c_bind.cpp
|
@ -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)
|
||||
{
|
||||
Bindings.SetBinds (DefHereticBindings);
|
||||
}
|
||||
while (sc.GetString())
|
||||
{
|
||||
FKeyBindings *dest = &Bindings;
|
||||
int key;
|
||||
|
||||
if (gameinfo.gametype == GAME_Hexen)
|
||||
{
|
||||
Bindings.SetBinds (DefHexenBindings);
|
||||
// bind destination is optional and is the same as the console command
|
||||
if (sc.Compare("bind"))
|
||||
{
|
||||
sc.MustGetString();
|
||||
}
|
||||
else if (sc.Compare("doublebind"))
|
||||
{
|
||||
dest = &DoubleBindings;
|
||||
sc.MustGetString();
|
||||
}
|
||||
else if (sc.Compare("mapbind"))
|
||||
{
|
||||
dest = &AutomapBindings;
|
||||
sc.MustGetString();
|
||||
}
|
||||
key = GetConfigKeyFromName(sc.String);
|
||||
sc.MustGetString();
|
||||
dest->SetBind(key, sc.String);
|
||||
}
|
||||
}
|
||||
|
||||
if (gameinfo.gametype == GAME_Strife)
|
||||
{
|
||||
Bindings.SetBinds (DefStrifeBindings);
|
||||
}
|
||||
|
||||
AutomapBindings.SetBinds(DefAutomapBindings);
|
||||
}
|
||||
|
||||
CCMD(binddefaults)
|
||||
|
|
|
@ -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);
|
||||
|
|
102
src/c_cmds.cpp
102
src/c_cmds.cpp
|
@ -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);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -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,15 +657,7 @@ 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);
|
||||
}
|
||||
Printf ("Unknown command \"%.*s\"\n", (int)len, beg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 (exec == NULL)
|
||||
{
|
||||
exec = new FExecList;
|
||||
}
|
||||
exec->AddCommand(cmd, file);
|
||||
}
|
||||
if (!feof (f))
|
||||
if (!feof(f))
|
||||
{
|
||||
retval = 2;
|
||||
Printf("Error parsing \"%s\"\n", file);
|
||||
}
|
||||
fclose (f);
|
||||
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"
|
||||
"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");
|
||||
}
|
||||
}
|
||||
// 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");
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -957,7 +957,7 @@ void ScanDirectory(TArray<FFileList> &list, const char *dirpath)
|
|||
}
|
||||
}
|
||||
|
||||
#elif defined(__sun) || defined(linux)
|
||||
#elif defined(__sun) || defined(__linux__)
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 = §ion->RootEntry;
|
||||
section->Next = NULL;
|
||||
memcpy (section->Name, name, namelen);
|
||||
section->Name[namelen] = 0;
|
||||
section->SectionName = name;
|
||||
*LastSectionPtr = section;
|
||||
LastSectionPtr = §ion->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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
115
src/d_main.cpp
115
src/d_main.cpp
|
@ -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)
|
||||
{
|
||||
file = group;
|
||||
file += ".Autoload";
|
||||
D_AddConfigWads(allwads, file);
|
||||
}
|
||||
|
||||
// Add IWAD-specific wads
|
||||
if (autoname != NULL)
|
||||
while ((len = LumpFilterIWAD.IndexOf('.', lastpos+1)) > 0)
|
||||
{
|
||||
file = autoname;
|
||||
file += ".Autoload";
|
||||
file = LumpFilterIWAD.Left(len) + ".Autoload";
|
||||
D_AddConfigWads(allwads, file);
|
||||
lastpos = len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2211,7 +2200,8 @@ void D_DoomMain (void)
|
|||
DArgs *execFiles;
|
||||
TArray<FString> pwads;
|
||||
FString *args;
|
||||
int argcount;
|
||||
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;
|
||||
|
|
17
src/d_main.h
17
src/d_main.h
|
@ -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;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -69,3 +69,4 @@ int SinglePlayerClass[MAXPLAYERS];
|
|||
bool ToggleFullscreen;
|
||||
int BorderTopRefresh;
|
||||
|
||||
FString LumpFilterIWAD;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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 = §ors[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 = §ors[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 = §ors[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(§ors[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=§ors[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));
|
||||
P_TranslateLineDef(&lines[i], &mld);
|
||||
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!
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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 = §ors[secnum];
|
||||
if(sec->floordata || sec->ceilingdata || sec->lightingdata)
|
||||
|
|
|
@ -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,42 +614,42 @@ 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;
|
||||
|
||||
AActor *spray = Spawn(spraytype, linetarget->x, linetarget->y,
|
||||
linetarget->z + (linetarget->height >> 2), ALLOW_REPLACE);
|
||||
|
||||
if (spray)
|
||||
if (linetarget != NULL)
|
||||
{
|
||||
if (spray->flags6 & MF6_MTHRUSPECIES && spray->GetSpecies() == linetarget->GetSpecies())
|
||||
AActor *spray = Spawn(spraytype, linetarget->x, linetarget->y,
|
||||
linetarget->z + (linetarget->height >> 2), ALLOW_REPLACE);
|
||||
|
||||
int dmgFlags = 0;
|
||||
FName dmgType = NAME_BFGSplash;
|
||||
|
||||
if (spray != NULL)
|
||||
{
|
||||
spray->Destroy(); // [MC] Remove it because technically, the spray isn't trying to "hit" them.
|
||||
continue;
|
||||
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->flags3 & MF3_FOILINVUL) dmgFlags |= DMG_FOILINVUL;
|
||||
if (spray->flags7 & MF7_FOILBUDDHA) dmgFlags |= DMG_FOILBUDDHA;
|
||||
dmgType = spray->DamageType;
|
||||
}
|
||||
if (spray->flags5 & MF5_PUFFGETSOWNER)
|
||||
spray->target = self->target;
|
||||
}
|
||||
|
||||
if (defdamage == 0)
|
||||
{
|
||||
damage = 0;
|
||||
for (j = 0; j < damagecnt; ++j)
|
||||
damage += (pr_bfgspray() & 7) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// if this is used, damagecnt will be ignored
|
||||
damage = defdamage;
|
||||
}
|
||||
if (defdamage == 0)
|
||||
{
|
||||
damage = 0;
|
||||
for (j = 0; j < damagecnt; ++j)
|
||||
damage += (pr_bfgspray() & 7) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// if this is used, damagecnt will be ignored
|
||||
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
277
src/g_doomedmap.cpp
Normal 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
|
||||
}
|
|
@ -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
106
src/g_hexen/a_flies.cpp
Normal 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);
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,41 +627,20 @@ void FGameConfigFile::AddAutoexec (DArgs *list, const char *game)
|
|||
|
||||
mysnprintf (section, countof(section), "%s.AutoExec", game);
|
||||
|
||||
if (bMigrating)
|
||||
// If <game>.AutoExec section does not exist, create it
|
||||
// with a default autoexec.cfg file present.
|
||||
CreateStandardAutoExec(section, false);
|
||||
// Run any files listed in the <game>.AutoExec section
|
||||
if (!SectionIsEmpty())
|
||||
{
|
||||
FBaseCVar *autoexec = FindCVar ("autoexec", NULL);
|
||||
|
||||
if (autoexec != NULL)
|
||||
while (NextInSection (key, value))
|
||||
{
|
||||
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);
|
||||
// Run any files listed in the <game>.AutoExec section
|
||||
if (!SectionIsEmpty())
|
||||
{
|
||||
while (NextInSection (key, value))
|
||||
if (stricmp (key, "Path") == 0 && *value != '\0')
|
||||
{
|
||||
if (stricmp (key, "Path") == 0 && *value != '\0')
|
||||
FString expanded_path = ExpandEnvVars(value);
|
||||
if (FileExists(expanded_path))
|
||||
{
|
||||
FString expanded_path = ExpandEnvVars(value);
|
||||
if (FileExists(expanded_path))
|
||||
{
|
||||
list->AppendArg (ExpandEnvVars(value));
|
||||
}
|
||||
list->AppendArg (ExpandEnvVars(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -673,13 +651,6 @@ 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;
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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")
|
||||
|
|
1
src/gi.h
1
src/gi.h
|
@ -153,7 +153,6 @@ struct gameinfo_t
|
|||
int definventorymaxamount;
|
||||
int defaultrespawntime;
|
||||
int defaultdropstyle;
|
||||
int player5start;
|
||||
DWORD pickupcolor;
|
||||
TArray<FString> quitmessages;
|
||||
FName mTitleColor;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
166
src/info.cpp
166
src/info.cpp
|
@ -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 ())
|
||||
|
|
66
src/info.h
66
src/info.h
|
@ -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];
|
||||
const PClass *Type;
|
||||
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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -326,6 +326,7 @@ xx(Arg4)
|
|||
xx(Arg0Str)
|
||||
xx(Arg1Str)
|
||||
xx(Id)
|
||||
xx(MoreIds)
|
||||
xx(V1)
|
||||
xx(V2)
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
else
|
||||
{
|
||||
fwrite("\2\0\0", 1, 4, File); // Dual OPL-2
|
||||
}
|
||||
NeedClockRate = false;
|
||||
chips[0] = new OPL_DOSBOXdump(file, numchips > 1);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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=§ors[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
|
||||
{
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
112
src/p_acs.cpp
112
src/p_acs.cpp
|
@ -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(§ors[secnum], args[2], seqname, 0);
|
||||
SN_StartSequence(§ors[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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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(§ors[secnum], type, line, tag, speed, speed2, height, crush, silent, change, hexencrush);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 = §ors[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 = §ors[secnum];
|
||||
if (sec->ceilingdata != NULL)
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,10 +3204,7 @@ 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);
|
||||
P_DamageMobj (self, NULL, NULL, self->health, damagetype, DMG_FORCED);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
114
src/p_floor.cpp
114
src/p_floor.cpp
|
@ -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 = §ors[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 = §ors[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;
|
||||
continue;
|
||||
}
|
||||
|
||||
// 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 = §ors[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 = §ors[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 = §ors[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 = §ors[sectorIndex];
|
||||
manual_waggle:
|
||||
if ((!ceiling && sector->PlaneMoving(sector_t::floor)) ||
|
||||
(ceiling && sector->PlaneMoving(sector_t::ceiling)))
|
||||
{ // Already busy with another thinker
|
||||
|
|
|
@ -338,7 +338,14 @@ static bool LoadGLSegs(FileReader * lump)
|
|||
|
||||
ml->side=LittleShort(ml->side);
|
||||
segs[i].sidedef = ldef->sidedef[ml->side];
|
||||
segs[i].frontsector = ldef->sidedef[ml->side]->sector;
|
||||
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];
|
||||
segs[i].frontsector = ldef->sidedef[ml->side]->sector;
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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,105 +1043,97 @@ 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.
|
||||
{
|
||||
// Take half damage in trainer mode
|
||||
damage = FixedMul(damage, G_SkillProperty(SKILLP_DamageFactor));
|
||||
}
|
||||
// Special damage types
|
||||
if (inflictor)
|
||||
{
|
||||
if (inflictor->flags4 & MF4_SPECTRAL)
|
||||
if (player && damage > 1)
|
||||
{
|
||||
if (player != NULL)
|
||||
// Take half damage in trainer mode
|
||||
damage = FixedMul(damage, G_SkillProperty(SKILLP_DamageFactor));
|
||||
}
|
||||
// Special damage types
|
||||
if (inflictor)
|
||||
{
|
||||
if (inflictor->flags4 & MF4_SPECTRAL)
|
||||
{
|
||||
if (!deathmatch && inflictor->FriendPlayer > 0)
|
||||
return -1;
|
||||
if (player != NULL)
|
||||
{
|
||||
if (!deathmatch && inflictor->FriendPlayer > 0)
|
||||
return -1;
|
||||
}
|
||||
else if (target->flags4 & MF4_SPECTRAL)
|
||||
{
|
||||
if (inflictor->FriendPlayer == 0 && !target->IsHostile(inflictor))
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (target->flags4 & MF4_SPECTRAL)
|
||||
|
||||
damage = inflictor->DoSpecialDamage(target, damage, mod);
|
||||
if (damage < 0)
|
||||
{
|
||||
if (inflictor->FriendPlayer == 0 && !target->IsHostile(inflictor))
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (damage > 0)
|
||||
damage = inflictor->DoSpecialDamage (target, damage, mod);
|
||||
|
||||
if ((damage == -1) && (target->player == NULL)) //This isn't meant for the player.
|
||||
{
|
||||
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);
|
||||
|
||||
// Handle active damage modifiers (e.g. PowerDamage)
|
||||
if (damage > 0 && source->Inventory != NULL)
|
||||
{
|
||||
source->Inventory->ModifyDamage(damage, 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 passive damage modifiers (e.g. PowerProtection), provided they are not afflicted with protection penetrating powers.
|
||||
if ((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;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(flags & DMG_NO_FACTOR))
|
||||
{
|
||||
damage = FixedMul(damage, target->DamageFactor);
|
||||
if (damage > 0)
|
||||
// Handle passive damage modifiers (e.g. PowerProtection), provided they are not afflicted with protection penetrating powers.
|
||||
if (damage > 0 && (target->Inventory != NULL) && !(flags & DMG_NO_PROTECT))
|
||||
{
|
||||
damage = DamageTypeDefinition::ApplyMobjDamageFactor(damage, mod, target->GetClass()->ActorInfo->DamageFactors);
|
||||
target->Inventory->ModifyDamage(damage, mod, damage, true);
|
||||
}
|
||||
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)
|
||||
{ // Still allow FORCEPAIN
|
||||
if (forcedPain)
|
||||
goto dopain;
|
||||
else if (fakedPain)
|
||||
goto fakepain;
|
||||
|
||||
return -1;
|
||||
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 (target->flags5 & MF5_NODAMAGE)
|
||||
{
|
||||
damage = 0;
|
||||
}
|
||||
}
|
||||
if (damage == -1 && target->player == NULL) //Make sure it's not a player, the pain has yet to be processed with cheats.
|
||||
if (damage < 0)
|
||||
{
|
||||
if (fakedPain)
|
||||
goto fakepain;
|
||||
|
||||
// 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,8 +1224,22 @@ 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 (§ors[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 = §ors[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 = §ors[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 = §ors[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 = §ors[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 = §ors[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();
|
||||
}
|
||||
|
|
|
@ -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 != §ors[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];
|
||||
|
||||
|
|
139
src/p_lnspec.cpp
139
src/p_lnspec.cpp
|
@ -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(§ors[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 = §ors[secnum];
|
||||
rtn = true;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
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 != 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);
|
||||
}
|
||||
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;
|
||||
|
|
208
src/p_mobj.cpp
208
src/p_mobj.cpp
|
@ -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)
|
||||
{
|
||||
FPlayerStart start(mthing);
|
||||
deathmatchstarts.Push(start);
|
||||
return NULL;
|
||||
}
|
||||
// find which type to spawn
|
||||
FDoomEdEntry *mentry = mthing->info;
|
||||
|
||||
// Convert Strife starts to Hexen-style starts
|
||||
if (gameinfo.gametype == GAME_Strife && mthing->type >= 118 && mthing->type <= 127)
|
||||
if (mentry == NULL)
|
||||
{
|
||||
mthing->args[0] = mthing->type - 117;
|
||||
mthing->type = 1;
|
||||
}
|
||||
|
||||
// [RH] Record polyobject-related things
|
||||
if (gameinfo.gametype == GAME_Hexen)
|
||||
{
|
||||
switch (mthing->type)
|
||||
// [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.
|
||||
{
|
||||
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;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (mthing->type == PO_ANCHOR_TYPE ||
|
||||
mthing->type == PO_SPAWN_TYPE ||
|
||||
mthing->type == PO_SPAWNCRUSH_TYPE ||
|
||||
mthing->type == PO_SPAWNHURT_TYPE)
|
||||
if (mentry->Type == NULL && mentry->Special <= 0)
|
||||
{
|
||||
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;
|
||||
polyspawns = polyspawn;
|
||||
if (mthing->type != PO_ANCHOR_TYPE)
|
||||
po_NumPolyobjs++;
|
||||
// has been explicitly set to not spawning anything.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// check for players specially
|
||||
int pnum = -1;
|
||||
|
||||
if (mthing->type <= 4 && mthing->type > 0)
|
||||
// copy args to mapthing so that we have them in one place for the rest of this function
|
||||
if (mentry->ArgsDefined)
|
||||
{
|
||||
pnum = mthing->type - 1;
|
||||
if (mentry->Type!= NULL) mthing->special = mentry->Special;
|
||||
memcpy(mthing->args, mentry->Args, sizeof(mthing->args));
|
||||
}
|
||||
else
|
||||
|
||||
int pnum = -1;
|
||||
if (mentry->Type == NULL)
|
||||
{
|
||||
if (mthing->type >= gameinfo.player5start && mthing->type < gameinfo.player5start + MAXPLAYERS - 4)
|
||||
|
||||
switch (mentry->Special)
|
||||
{
|
||||
pnum = mthing->type - gameinfo.player5start + 4;
|
||||
case SMT_DeathmatchStart:
|
||||
{
|
||||
// count deathmatch start positions
|
||||
FPlayerStart start(mthing, 0);
|
||||
deathmatchstarts.Push(start);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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 = mentry->Special;
|
||||
polyspawns = polyspawn;
|
||||
if (mentry->Special != SMT_PolyAnchor)
|
||||
po_NumPolyobjs++;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,51 +4762,25 @@ 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 = mentry->Type->GetReplacement();
|
||||
|
||||
const AActor *defaults = GetDefaultByType (i);
|
||||
if (defaults->SpawnState == NULL ||
|
||||
sprites[defaults->SpawnState->sprite].numframes == 0)
|
||||
{
|
||||
// Handle decorate replacements explicitly here
|
||||
// to check for missing frames in the replacement object.
|
||||
i = i->GetReplacement();
|
||||
// We don't load mods for shareware games so we'll just ignore
|
||||
// missing actors. Heretic needs this since the shareware includes
|
||||
// the retail weapons in Deathmatch.
|
||||
if (gameinfo.flags & GI_SHAREWARE)
|
||||
return NULL;
|
||||
|
||||
const AActor *defaults = GetDefaultByType (i);
|
||||
if (defaults->SpawnState == NULL ||
|
||||
sprites[defaults->SpawnState->sprite].numframes == 0)
|
||||
{
|
||||
// We don't load mods for shareware games so we'll just ignore
|
||||
// missing actors. Heretic needs this since the shareware includes
|
||||
// the retail weapons in Deathmatch.
|
||||
if (gameinfo.flags & GI_SHAREWARE)
|
||||
return NULL;
|
||||
|
||||
Printf ("%s at (%i, %i) has no frames\n",
|
||||
i->TypeName.GetChars(), mthing->x>>FRACBITS, mthing->y>>FRACBITS);
|
||||
i = PClass::FindClass("Unknown");
|
||||
}
|
||||
Printf ("%s at (%i, %i) has no frames\n",
|
||||
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++)
|
||||
|
|
|
@ -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 = §ors[secnum];
|
||||
|
||||
manual_pillar:
|
||||
if (sec->PlaneMoving(sector_t::floor) || sec->PlaneMoving(sector_t::ceiling))
|
||||
continue;
|
||||
|
||||
|
|
|
@ -233,42 +233,33 @@ bool EV_DoPlat (int tag, line_t *line, DPlat::EPlatType type, int height,
|
|||
fixed_t newheight = 0;
|
||||
vertex_t *spot;
|
||||
|
||||
if (tag != 0)
|
||||
{
|
||||
// Activate all <type> plats that are in_stasis
|
||||
switch (type)
|
||||
{
|
||||
case DPlat::platToggle:
|
||||
rtn = true;
|
||||
case DPlat::platPerpetualRaise:
|
||||
P_ActivateInStasis (tag);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// [RH] If tag is zero, use the sector on the back side
|
||||
// of the activating line (if any).
|
||||
if (!tag)
|
||||
{
|
||||
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)
|
||||
{
|
||||
case DPlat::platToggle:
|
||||
rtn = true;
|
||||
case DPlat::platPerpetualRaise:
|
||||
P_ActivateInStasis (tag);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
secnum = -1;
|
||||
while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0)
|
||||
FSectorTagIterator itr(tag, line);
|
||||
while ((secnum = itr.Next()) >= 0)
|
||||
{
|
||||
sec = §ors[secnum];
|
||||
|
||||
manual_plat:
|
||||
if (sec->PlaneMoving(sector_t::floor))
|
||||
{
|
||||
if (!manual)
|
||||
continue;
|
||||
else
|
||||
return false;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Find lowest & highest floors around sector
|
||||
|
@ -406,8 +397,6 @@ manual_plat:
|
|||
default:
|
||||
break;
|
||||
}
|
||||
if (manual)
|
||||
return rtn;
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
104
src/p_setup.cpp
104
src/p_setup.cpp
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,24 +281,27 @@ 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)
|
||||
{
|
||||
if (vertexes[i].x == mt->x && vertexes[i].y == mt->y)
|
||||
for (int i = 0; i < numvertexes; i++)
|
||||
{
|
||||
if (mt->type == THING_VertexFloorZ)
|
||||
if (vertexes[i].x == mt->x && vertexes[i].y == mt->y)
|
||||
{
|
||||
vt_heights[0][i] = mt->z;
|
||||
if (mt->info->Special == SMT_VertexFloorZ)
|
||||
{
|
||||
vt_heights[0][i] = mt->z;
|
||||
}
|
||||
else
|
||||
{
|
||||
vt_heights[1][i] = mt->z;
|
||||
}
|
||||
vt_found = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
vt_heights[1][i] = mt->z;
|
||||
}
|
||||
vt_found = true;
|
||||
}
|
||||
mt->EdNum = 0;
|
||||
}
|
||||
mt->type = 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);
|
||||
else
|
||||
{ // 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
201
src/p_spec.cpp
201
src/p_spec.cpp
|
@ -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
|
||||
|
@ -260,13 +228,13 @@ bool P_ActivateLine (line_t *line, AActor *mo, int side, int activationType)
|
|||
}
|
||||
// some old WADs use this method to create walls that change the texture when shot.
|
||||
else if (activationType == SPAC_Impact && // only for shootable triggers
|
||||
(level.flags2 & LEVEL2_DUMMYSWITCHES) && // this is only a compatibility setting for an old hack!
|
||||
(level.flags2 & LEVEL2_DUMMYSWITCHES) && // this is only a compatibility setting for an old hack!
|
||||
!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 = §ors[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(§ors[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(§ors[s], plane, reference, alpha);
|
||||
}
|
||||
|
@ -1374,38 +1351,41 @@ 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)
|
||||
{
|
||||
sec->MoreFlags |= SECF_FAKEFLOORONLY;
|
||||
sec = lines[i].frontsector;
|
||||
if (lines[i].args[1] & 2)
|
||||
{
|
||||
sec->MoreFlags |= SECF_FAKEFLOORONLY;
|
||||
}
|
||||
if (lines[i].args[1] & 4)
|
||||
{
|
||||
sec->MoreFlags |= SECF_CLIPFAKEPLANES;
|
||||
}
|
||||
if (lines[i].args[1] & 8)
|
||||
{
|
||||
sec->MoreFlags |= SECF_UNDERWATER;
|
||||
}
|
||||
else if (forcewater)
|
||||
{
|
||||
sec->MoreFlags |= SECF_FORCEDUNDERWATER;
|
||||
}
|
||||
if (lines[i].args[1] & 16)
|
||||
{
|
||||
sec->MoreFlags |= SECF_IGNOREHEIGHTSEC;
|
||||
}
|
||||
if (lines[i].args[1] & 32)
|
||||
{
|
||||
sec->MoreFlags |= SECF_NOFAKELIGHT;
|
||||
}
|
||||
FSectorTagIterator itr(lines[i].args[0]);
|
||||
while ((s = itr.Next()) >= 0)
|
||||
{
|
||||
sectors[s].heightsec = sec;
|
||||
sec->e->FakeFloor.Sectors.Push(§ors[s]);
|
||||
sectors[s].AdjustFloorClip();
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (lines[i].args[1] & 4)
|
||||
{
|
||||
sec->MoreFlags |= SECF_CLIPFAKEPLANES;
|
||||
}
|
||||
if (lines[i].args[1] & 8)
|
||||
{
|
||||
sec->MoreFlags |= SECF_UNDERWATER;
|
||||
}
|
||||
else if (forcewater)
|
||||
{
|
||||
sec->MoreFlags |= SECF_FORCEDUNDERWATER;
|
||||
}
|
||||
if (lines[i].args[1] & 16)
|
||||
{
|
||||
sec->MoreFlags |= SECF_IGNOREHEIGHTSEC;
|
||||
}
|
||||
if (lines[i].args[1] & 32)
|
||||
{
|
||||
sec->MoreFlags |= SECF_NOFAKELIGHT;
|
||||
}
|
||||
for (s = -1; (s = P_FindSectorFromTag(lines[i].args[0],s)) >= 0;)
|
||||
{
|
||||
sectors[s].heightsec = sec;
|
||||
sec->e->FakeFloor.Sectors.Push(§ors[s]);
|
||||
sectors[s].AdjustFloorClip();
|
||||
}
|
||||
break;
|
||||
|
||||
// killough 3/16/98: Add support for setting
|
||||
// floor lighting independently (e.g. lava)
|
||||
|
@ -1458,9 +1438,10 @@ 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;)
|
||||
sectors[s].gravity = grav;
|
||||
float grav = ((float)P_AproxDistance (lines[i].dx, lines[i].dy)) / (FRACUNIT * 100.0f);
|
||||
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,9 +1475,12 @@ 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;
|
||||
break;
|
||||
{
|
||||
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;)
|
||||
{
|
||||
FSectorTagIterator itr(l->args[0]);
|
||||
while ((s = itr.Next()) >= 0)
|
||||
{
|
||||
new DScroller (DScroller::sc_ceiling, -dx, dy, control, s, accel);
|
||||
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
|
||||
|
|
|
@ -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
353
src/p_tags.cpp
Normal 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
133
src/p_tags.h
Normal 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
|
|
@ -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 = §ors[secnum];
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
|
133
src/p_things.cpp
133
src/p_things.cpp
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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(§ors[i]));
|
||||
fwrite (&ms, sizeof(ms), 1, file);
|
||||
}
|
||||
return numsectors * sizeof(ms);
|
||||
|
|
|
@ -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;
|
||||
|
||||
// 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;
|
||||
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.
|
||||
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 ();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -128,6 +128,8 @@ enum
|
|||
kVK_UpArrow = 0x7E
|
||||
};
|
||||
|
||||
static const NSOpenGLPixelFormatAttribute NSOpenGLPFAAllowOfflineRenderers = NSOpenGLPixelFormatAttribute(96);
|
||||
|
||||
#endif // prior to 10.5
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
const CFIndex flavorCount = CFArrayGetCount(flavorTypeArray);
|
||||
|
||||
for (CFIndex flavorIndex = 0; flavorIndex < flavorCount; ++flavorIndex)
|
||||
else if (CFDataRef data = GetPasteboardData(itemID, kUTTypeUTF16PlainText))
|
||||
{
|
||||
const CFStringRef flavorType = static_cast<const CFStringRef>(
|
||||
CFArrayGetValueAtIndex(flavorTypeArray, flavorIndex));
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
static const CFStringEncoding ENCODING = kCFStringEncodingUTF16LE;
|
||||
#else // __BIG_ENDIAN__
|
||||
static const CFStringEncoding ENCODING = kCFStringEncodingUTF16BE;
|
||||
#endif // __LITTLE_ENDIAN__
|
||||
|
||||
if (UTTypeConformsTo(flavorType, CFSTR("public.utf8-plain-text")))
|
||||
if (const CFStringRef utf16 = CFStringCreateFromExternalRepresentation(kCFAllocatorDefault, data, ENCODING))
|
||||
{
|
||||
CFDataRef flavorData;
|
||||
const CFRange range = { 0, CFStringGetLength(utf16) };
|
||||
CFIndex bufferLength = 0;
|
||||
|
||||
if (0 == PasteboardCopyItemFlavorData(s_clipboard, itemID, flavorType, &flavorData))
|
||||
if (CFStringGetBytes(utf16, range, kCFStringEncodingUTF8, '?', false, NULL, 0, &bufferLength) > 0)
|
||||
{
|
||||
result += reinterpret_cast<const char*>(CFDataGetBytePtr(flavorData));
|
||||
UInt8* const buffer = reinterpret_cast<UInt8*>(result.LockNewBuffer(bufferLength));
|
||||
|
||||
CFStringGetBytes(utf16, range, kCFStringEncodingUTF8, '?', false, buffer, bufferLength, NULL);
|
||||
|
||||
result.UnlockBuffer();
|
||||
}
|
||||
|
||||
CFRelease(flavorData);
|
||||
CFRelease(utf16);
|
||||
}
|
||||
}
|
||||
|
||||
CFRelease(flavorTypeArray);
|
||||
|
||||
return result;
|
||||
#endif
|
||||
return "";
|
||||
|
|
|
@ -43,5 +43,7 @@
|
|||
</array>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>NSApplication</string>
|
||||
<key>NSSupportsAutomaticGraphicsSwitching</key>
|
||||
<string>YES</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
@ -37,7 +37,7 @@ static struct {
|
|||
pid_t pid;
|
||||
int has_siginfo;
|
||||
siginfo_t siginfo;
|
||||
char buf[1024];
|
||||
char buf[4096];
|
||||
} crash_info;
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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__
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
Loading…
Reference in a new issue