mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-01-18 15:42:34 +00:00
- Sync scriptbranch with trunk.
SVN r2269 (scripting)
This commit is contained in:
commit
42ac75e894
127 changed files with 2567 additions and 994 deletions
|
@ -1,5 +1,7 @@
|
|||
cmake_minimum_required( VERSION 2.4 )
|
||||
|
||||
include( CheckFunctionExists )
|
||||
|
||||
# DUMB is much slower in a Debug build than a Release build, so we force a Release
|
||||
# build here, since we're not maintaining DUMB, only using it.
|
||||
# Comment out the below line to allow Debug builds.
|
||||
|
@ -13,6 +15,11 @@ if( CMAKE_COMPILER_IS_GNUC )
|
|||
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wno-pointer-sign -Wno-uninitialized" )
|
||||
endif( CMAKE_COMPILER_IS_GNUC )
|
||||
|
||||
CHECK_FUNCTION_EXISTS( itoa ITOA_EXISTS )
|
||||
if( NOT ITOA_EXISTS )
|
||||
add_definitions( -DNEED_ITOA=1 )
|
||||
endif( NOT ITOA_EXISTS )
|
||||
|
||||
include_directories( include )
|
||||
|
||||
add_library( dumb
|
||||
|
|
|
@ -58,7 +58,7 @@ int32 dumb_resample(DUMB_RESAMPLER *resampler, sample_t *dst, int32 dst_size, VO
|
|||
|
||||
done = 0;
|
||||
dt = (int)(delta * 65536.0 + 0.5);
|
||||
if (dt == 0) return 0;
|
||||
if (dt == 0 || dt == 0x80000000) return 0;
|
||||
SET_VOLUME_VARIABLES;
|
||||
|
||||
if (VOLUMES_ARE_ZERO) dst = NULL;
|
||||
|
|
|
@ -24,9 +24,6 @@
|
|||
#include "internal/it.h"
|
||||
#include "internal/riff.h"
|
||||
|
||||
DUH *dumb_read_riff_amff( struct riff * stream );
|
||||
DUH *dumb_read_riff_am( struct riff * stream );
|
||||
|
||||
static int it_riff_am_process_sample( IT_SAMPLE * sample, const unsigned char * data, int len, int ver )
|
||||
{
|
||||
int header_length;
|
||||
|
|
|
@ -291,7 +291,7 @@ static int it_old_psm_read_patterns(IT_PATTERN * pattern, DUMBFILE * f, int num,
|
|||
if (channel >= chans)
|
||||
{
|
||||
//channel = 0;
|
||||
goto error_fb;
|
||||
//goto error_fb;
|
||||
}
|
||||
if (flags & 0x80) {
|
||||
if ((*ptr < 60) && (channel < pchans)) {
|
||||
|
|
|
@ -1271,7 +1271,11 @@ DUH *DUMBEXPORT dumb_read_psm_quick(DUMBFILE *f, int subsong)
|
|||
if ( ver )
|
||||
{
|
||||
tag[2][0] = "FORMATVERSION";
|
||||
#if NEED_ITOA
|
||||
sprintf(version, "%d", ver);
|
||||
#else
|
||||
itoa(ver, version, 10);
|
||||
#endif
|
||||
tag[2][1] = (const char *) &version;
|
||||
++n_tags;
|
||||
}
|
||||
|
|
1
specs/fmod_version.txt
Normal file
1
specs/fmod_version.txt
Normal file
|
@ -0,0 +1 @@
|
|||
This version of ZDoom must be compiled with any version between 4.22 and 4.28 inclusive.
|
|
@ -12,7 +12,7 @@ DEFINE_SPECIAL(Door_Close, 10, 2, 3, 3)
|
|||
DEFINE_SPECIAL(Door_Open, 11, 2, 3, 3)
|
||||
DEFINE_SPECIAL(Door_Raise, 12, 3, 4, 4)
|
||||
DEFINE_SPECIAL(Door_LockedRaise, 13, 4, 5, 5)
|
||||
DEFINE_SPECIAL(Door_Animated, 14, 3, 3, 3)
|
||||
DEFINE_SPECIAL(Door_Animated, 14, 4, 4, 4)
|
||||
DEFINE_SPECIAL(Autosave, 15, 0, 0, 0) // [RH] Save the game *now*
|
||||
DEFINE_SPECIAL(Transfer_WallLight, 16, -1, -1, 2)
|
||||
DEFINE_SPECIAL(Thing_Raise, 17, 1, 1, 1)
|
||||
|
|
29
src/actor.h
29
src/actor.h
|
@ -552,9 +552,6 @@ public:
|
|||
|
||||
virtual void Tick ();
|
||||
|
||||
// Smallest yaw interval for a mapthing to be spawned with
|
||||
virtual angle_t AngleIncrements ();
|
||||
|
||||
// Called when actor dies
|
||||
virtual void Die (AActor *source, AActor *inflictor);
|
||||
|
||||
|
@ -691,6 +688,31 @@ public:
|
|||
return ( abs(x - other->x) < blockdist && abs(y - other->y) < blockdist);
|
||||
}
|
||||
|
||||
PalEntry GetBloodColor() const
|
||||
{
|
||||
return GetClass()->BloodColor;
|
||||
}
|
||||
|
||||
PClassActor *GetBloodType(int type = 0) const
|
||||
{
|
||||
if (type == 0)
|
||||
{
|
||||
return PClass::FindActor(GetClass()->BloodType);
|
||||
}
|
||||
else if (type == 1)
|
||||
{
|
||||
return PClass::FindActor(GetClass()->BloodType2);
|
||||
}
|
||||
else if (type == 2)
|
||||
{
|
||||
return PClass::FindActor(GetClass()->BloodType3);
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate amount of missile damage
|
||||
virtual int GetMissileDamage(int mask, int add);
|
||||
|
||||
|
@ -821,6 +843,7 @@ public:
|
|||
FSoundIDNoInit UseSound; // [RH] Sound to play when an actor is used.
|
||||
FSoundIDNoInit BounceSound;
|
||||
FSoundIDNoInit WallBounceSound;
|
||||
FSoundIDNoInit CrushPainSound;
|
||||
|
||||
fixed_t Speed;
|
||||
fixed_t FloatSpeed;
|
||||
|
|
|
@ -1850,7 +1850,7 @@ void AM_drawPlayers ()
|
|||
{
|
||||
float h, s, v, r, g, b;
|
||||
|
||||
D_GetPlayerColor (i, &h, &s, &v);
|
||||
D_GetPlayerColor (i, &h, &s, &v, NULL);
|
||||
HSVtoRGB (&r, &g, &b, h, s, v);
|
||||
|
||||
color.FromRGB(clamp (int(r*255.f),0,255), clamp (int(g*255.f),0,255), clamp (int(b*255.f),0,255));
|
||||
|
|
|
@ -118,7 +118,7 @@ bool FCajunMaster::Reachable (AActor *looker, AActor *rtarget)
|
|||
//in doom is 90 degrees infront.
|
||||
bool FCajunMaster::Check_LOS (AActor *from, AActor *to, angle_t vangle)
|
||||
{
|
||||
if (!P_CheckSight (from, to, 2))
|
||||
if (!P_CheckSight (from, to, SF_SEEPASTBLOCKEVERYTHING))
|
||||
return false; // out of sight
|
||||
if (vangle == ANGLE_MAX)
|
||||
return true;
|
||||
|
@ -339,7 +339,7 @@ AActor *FCajunMaster::Choose_Mate (AActor *bot)
|
|||
&& !p_leader[count]) //taken?
|
||||
{
|
||||
|
||||
if (P_CheckSight (bot, client->mo, 1))
|
||||
if (P_CheckSight (bot, client->mo, SF_IGNOREVISIBILITY))
|
||||
{
|
||||
test = P_AproxDistance (client->mo->x - bot->x,
|
||||
client->mo->y - bot->y);
|
||||
|
@ -525,7 +525,7 @@ angle_t FCajunMaster::FireRox (AActor *bot, AActor *enemy, ticcmd_t *cmd)
|
|||
enemy->y + FixedMul(enemy->vely, (m+2*FRACUNIT)), ONFLOORZ, 1);
|
||||
dist = P_AproxDistance(actor->x-bglobal.body1->x, actor->y-bglobal.body1->y);
|
||||
//try the predicted location
|
||||
if (P_CheckSight (actor, bglobal.body1, 1)) //See the predicted location, so give a test missile
|
||||
if (P_CheckSight (actor, bglobal.body1, SF_IGNOREVISIBILITY)) //See the predicted location, so give a test missile
|
||||
{
|
||||
FCheckPosition tm;
|
||||
if (SafeCheckPosition (bot, actor->x, actor->y, tm))
|
||||
|
|
|
@ -788,8 +788,8 @@ CCMD(info)
|
|||
AActor *linetarget;
|
||||
|
||||
if (CheckCheatmode () || players[consoleplayer].mo == NULL) return;
|
||||
P_AimLineAttack(players[consoleplayer].mo,players[consoleplayer].mo->angle,MISSILERANGE, &linetarget, 0,
|
||||
false, false, true);
|
||||
P_AimLineAttack(players[consoleplayer].mo,players[consoleplayer].mo->angle,MISSILERANGE,
|
||||
&linetarget, 0, ALF_CHECKNONSHOOTABLE|ALF_FORCENOSMART);
|
||||
if (linetarget)
|
||||
{
|
||||
Printf("Target=%s, Health=%d, Spawnhealth=%d\n",
|
||||
|
@ -924,6 +924,19 @@ CCMD(nextsecret)
|
|||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
CCMD(currentpos)
|
||||
{
|
||||
AActor *mo = players[consoleplayer].mo;
|
||||
Printf("Current player position: (%1.3f,%1.3f,%1.3f), angle: %1.3f, floorheight: %1.3f, sector:%d, lightlevel: %d\n",
|
||||
FIXED2FLOAT(mo->x), FIXED2FLOAT(mo->y), FIXED2FLOAT(mo->z), mo->angle/float(ANGLE_1), FIXED2FLOAT(mo->floorz), mo->Sector->sectornum, mo->Sector->lightlevel);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
|
|
|
@ -1035,6 +1035,32 @@ FString BuildString (int argc, char **argv)
|
|||
}
|
||||
}
|
||||
|
||||
FString BuildString (int argc, FString *argv)
|
||||
{
|
||||
if (argc == 1)
|
||||
{
|
||||
return *argv;
|
||||
}
|
||||
else
|
||||
{
|
||||
FString buf;
|
||||
int arg;
|
||||
|
||||
for (arg = 0; arg < argc; arg++)
|
||||
{
|
||||
if (strchr (argv[arg], ' '))
|
||||
{
|
||||
buf << '"' << argv[arg] << "\" ";
|
||||
}
|
||||
else
|
||||
{
|
||||
buf << argv[arg] << ' ';
|
||||
}
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// SubstituteAliasParams
|
||||
|
|
|
@ -59,6 +59,7 @@ void C_SetAlias (const char *name, const char *cmd);
|
|||
|
||||
// build a single string out of multiple strings
|
||||
FString BuildString (int argc, char **argv);
|
||||
FString BuildString (int argc, FString *argv);
|
||||
|
||||
// Class that can parse command lines
|
||||
class FCommandLine
|
||||
|
|
|
@ -148,17 +148,13 @@ int Q_filelength (FILE *f)
|
|||
|
||||
bool FileExists (const char *filename)
|
||||
{
|
||||
FILE *f;
|
||||
struct stat buff;
|
||||
|
||||
// [RH] Empty filenames are never there
|
||||
if (filename == NULL || *filename == 0)
|
||||
return false;
|
||||
|
||||
f = fopen (filename, "r");
|
||||
if (!f)
|
||||
return false;
|
||||
fclose (f);
|
||||
return true;
|
||||
return stat(filename, &buff) == 0 && !(buff.st_mode & S_IFDIR);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -2135,20 +2135,7 @@ static int PatchText (int oldSize)
|
|||
|
||||
if (!good)
|
||||
{
|
||||
// search cluster text background flats (only if no user-defined MAPINFO is used!)
|
||||
if (strlen(newStr) <= 8 && Wads.CheckNumForName("MAPINFO") >= 0)
|
||||
{
|
||||
for (unsigned int i = 0; i < wadclusterinfos.Size(); i++)
|
||||
{
|
||||
if (!strcmp(wadclusterinfos[i].finaleflat, oldStr))
|
||||
{
|
||||
strcpy(wadclusterinfos[i].finaleflat, newStr);
|
||||
good = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!good) DPrintf (" (Unmatched)\n");
|
||||
DPrintf (" (Unmatched)\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2904,6 +2891,12 @@ bool ADehackedPickup::TryPickup (AActor *&toucher)
|
|||
RealPickup = static_cast<AInventory *>(Spawn (type, x, y, z, NO_REPLACE));
|
||||
if (RealPickup != NULL)
|
||||
{
|
||||
// The internally spawned item should never count towards statistics.
|
||||
if (RealPickup->flags & MF_COUNTITEM)
|
||||
{
|
||||
RealPickup->flags &= ~MF_COUNTITEM;
|
||||
level.total_items--;
|
||||
}
|
||||
if (!(flags & MF_DROPPED))
|
||||
{
|
||||
RealPickup->flags &= ~MF_DROPPED;
|
||||
|
|
141
src/d_main.cpp
141
src/d_main.cpp
|
@ -129,7 +129,7 @@ void D_CheckNetGame ();
|
|||
void D_ProcessEvents ();
|
||||
void G_BuildTiccmd (ticcmd_t* cmd);
|
||||
void D_DoAdvanceDemo ();
|
||||
void D_AddWildFile (const char *pattern);
|
||||
void D_AddWildFile (TArray<FString> &wadfiles, const char *pattern);
|
||||
|
||||
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
||||
|
||||
|
@ -657,6 +657,7 @@ void D_Display ()
|
|||
switch (gamestate)
|
||||
{
|
||||
case GS_FULLCONSOLE:
|
||||
R_UpdateAnimations(I_FPSTime());
|
||||
screen->SetBlendingRect(0,0,0,0);
|
||||
hw2d = screen->Begin2D(false);
|
||||
C_DrawConsole (false);
|
||||
|
@ -721,6 +722,7 @@ void D_Display ()
|
|||
break;
|
||||
|
||||
case GS_INTERMISSION:
|
||||
R_UpdateAnimations(I_FPSTime());
|
||||
screen->SetBlendingRect(0,0,0,0);
|
||||
hw2d = screen->Begin2D(false);
|
||||
WI_Drawer ();
|
||||
|
@ -728,6 +730,7 @@ void D_Display ()
|
|||
break;
|
||||
|
||||
case GS_FINALE:
|
||||
R_UpdateAnimations(I_FPSTime());
|
||||
screen->SetBlendingRect(0,0,0,0);
|
||||
hw2d = screen->Begin2D(false);
|
||||
F_Drawer ();
|
||||
|
@ -735,6 +738,7 @@ void D_Display ()
|
|||
break;
|
||||
|
||||
case GS_DEMOSCREEN:
|
||||
R_UpdateAnimations(I_FPSTime());
|
||||
screen->SetBlendingRect(0,0,0,0);
|
||||
hw2d = screen->Begin2D(false);
|
||||
D_PageDrawer ();
|
||||
|
@ -1478,27 +1482,22 @@ static const char *BaseFileSearch (const char *file, const char *ext, bool lookf
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
bool ConsiderPatches (const char *arg, const char *ext)
|
||||
bool ConsiderPatches (const char *arg)
|
||||
{
|
||||
bool noDef = false;
|
||||
DArgs *files = Args->GatherFiles (arg, ext, false);
|
||||
int i, argc;
|
||||
FString *args;
|
||||
const char *f;
|
||||
|
||||
if (files->NumArgs() > 0)
|
||||
argc = Args->CheckParmList(arg, &args);
|
||||
for (i = 0; i < argc; ++i)
|
||||
{
|
||||
int i;
|
||||
const char *f;
|
||||
|
||||
for (i = 0; i < files->NumArgs(); ++i)
|
||||
if ( (f = BaseFileSearch(args[i], ".deh")) ||
|
||||
(f = BaseFileSearch(args[i], ".bex")) )
|
||||
{
|
||||
if ( (f = BaseFileSearch (files->GetArg (i), ".deh")) )
|
||||
D_LoadDehFile(f);
|
||||
else if ( (f = BaseFileSearch (files->GetArg (i), ".bex")) )
|
||||
D_LoadDehFile(f);
|
||||
D_LoadDehFile(f);
|
||||
}
|
||||
noDef = true;
|
||||
}
|
||||
files->Destroy();
|
||||
return noDef;
|
||||
return argc > 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -1591,40 +1590,18 @@ void D_MultiExec (DArgs *list, bool usePullin)
|
|||
|
||||
static void GetCmdLineFiles(TArray<FString> &wadfiles)
|
||||
{
|
||||
DArgs *files = Args->GatherFiles ("-file", ".wad", true);
|
||||
DArgs *files1 = Args->GatherFiles (NULL, ".zip", false);
|
||||
DArgs *files2 = Args->GatherFiles (NULL, ".pk3", false);
|
||||
DArgs *files3 = Args->GatherFiles (NULL, ".txt", false);
|
||||
if (files->NumArgs() > 0 || files1->NumArgs() > 0 || files2->NumArgs() > 0 || files3->NumArgs() > 0)
|
||||
{
|
||||
// Check for -file in shareware
|
||||
if (gameinfo.flags & GI_SHAREWARE)
|
||||
{
|
||||
I_FatalError ("You cannot -file with the shareware version. Register!");
|
||||
}
|
||||
FString *args;
|
||||
int i, argc;
|
||||
|
||||
// the files gathered are wadfile/lump names
|
||||
for (int i = 0; i < files->NumArgs(); i++)
|
||||
{
|
||||
D_AddWildFile (wadfiles, files->GetArg (i));
|
||||
}
|
||||
for (int i = 0; i < files1->NumArgs(); i++)
|
||||
{
|
||||
D_AddWildFile (wadfiles, files1->GetArg (i));
|
||||
}
|
||||
for (int i = 0; i < files2->NumArgs(); i++)
|
||||
{
|
||||
D_AddWildFile (wadfiles, files2->GetArg (i));
|
||||
}
|
||||
for (int i = 0; i < files3->NumArgs(); i++)
|
||||
{
|
||||
D_AddWildFile (wadfiles, files3->GetArg (i));
|
||||
}
|
||||
argc = Args->CheckParmList("-file", &args);
|
||||
if ((gameinfo.flags & GI_SHAREWARE) && argc > 0)
|
||||
{
|
||||
I_FatalError ("You cannot -file with the shareware version. Register!");
|
||||
}
|
||||
for (i = 0; i < argc; ++i)
|
||||
{
|
||||
D_AddWildFile(wadfiles, args[i]);
|
||||
}
|
||||
files->Destroy();
|
||||
files1->Destroy();
|
||||
files2->Destroy();
|
||||
files3->Destroy();
|
||||
}
|
||||
|
||||
static void CopyFiles(TArray<FString> &to, TArray<FString> &from)
|
||||
|
@ -1753,10 +1730,12 @@ static FString CheckGameInfo(TArray<FString> & pwads)
|
|||
void D_DoomMain (void)
|
||||
{
|
||||
int p, flags;
|
||||
char *v;
|
||||
const char *v;
|
||||
const char *wad;
|
||||
DArgs *execFiles;
|
||||
TArray<FString> pwads;
|
||||
FString *args;
|
||||
int argcount;
|
||||
|
||||
// Set the FPU precision to 53 significant bits. This is the default
|
||||
// for Visual C++, but not for GCC, so some slight math variances
|
||||
|
@ -1775,6 +1754,13 @@ void D_DoomMain (void)
|
|||
#endif
|
||||
#endif
|
||||
|
||||
// Combine different file parameters with their pre-switch bits.
|
||||
Args->CollectFiles("-deh", ".deh");
|
||||
Args->CollectFiles("-bex", ".bex");
|
||||
Args->CollectFiles("-exec", ".cfg");
|
||||
Args->CollectFiles("-playdemo", ".lmp");
|
||||
Args->CollectFiles("-file", NULL); // anythnig left goes after -file
|
||||
|
||||
PClass::StaticInit ();
|
||||
atterm (C_DeinitConsole);
|
||||
|
||||
|
@ -1861,16 +1847,21 @@ void D_DoomMain (void)
|
|||
D_MultiExec (execFiles, true);
|
||||
|
||||
// Run .cfg files at the start of the command line.
|
||||
execFiles = Args->GatherFiles (NULL, ".cfg", false);
|
||||
execFiles = Args->GatherFiles ("-exec");
|
||||
D_MultiExec (execFiles, true);
|
||||
|
||||
C_ExecCmdLineParams (); // [RH] do all +set commands on the command line
|
||||
|
||||
CopyFiles(allwads, pwads);
|
||||
|
||||
// Since this function will never leave we must delete this array here manually.
|
||||
pwads.Clear();
|
||||
pwads.ShrinkToFit();
|
||||
|
||||
Printf ("W_Init: Init WADfiles.\n");
|
||||
Wads.InitMultipleFiles (allwads);
|
||||
allwads.Clear();
|
||||
allwads.ShrinkToFit();
|
||||
|
||||
// [RH] Initialize localizable strings.
|
||||
GStrings.LoadStrings (false);
|
||||
|
@ -1963,21 +1954,23 @@ void D_DoomMain (void)
|
|||
autostart = true;
|
||||
}
|
||||
|
||||
// [RH] Hack to handle +map
|
||||
p = Args->CheckParm ("+map");
|
||||
if (p && p < Args->NumArgs()-1)
|
||||
// [RH] Hack to handle +map. The standard console command line handler
|
||||
// won't be able to handle it, so we take it out of the command line and set
|
||||
// it up like -warp.
|
||||
FString mapvalue = Args->TakeValue("+map");
|
||||
if (mapvalue.IsNotEmpty())
|
||||
{
|
||||
if (!P_CheckMapData(Args->GetArg (p+1)))
|
||||
if (!P_CheckMapData(mapvalue))
|
||||
{
|
||||
Printf ("Can't find map %s\n", Args->GetArg (p+1));
|
||||
Printf ("Can't find map %s\n", mapvalue.GetChars());
|
||||
}
|
||||
else
|
||||
{
|
||||
startmap = Args->GetArg (p + 1);
|
||||
Args->GetArg (p)[0] = '-';
|
||||
startmap = mapvalue;
|
||||
autostart = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (devparm)
|
||||
{
|
||||
Printf ("%s", GStrings("D_DEVSTR"));
|
||||
|
@ -1995,17 +1988,12 @@ void D_DoomMain (void)
|
|||
#endif
|
||||
|
||||
// turbo option // [RH] (now a cvar)
|
||||
v = Args->CheckValue("-turbo");
|
||||
if (v != NULL)
|
||||
{
|
||||
UCVarValue value;
|
||||
static char one_hundred[] = "100";
|
||||
|
||||
value.String = Args->CheckValue ("-turbo");
|
||||
if (value.String == NULL)
|
||||
value.String = one_hundred;
|
||||
else
|
||||
Printf ("turbo scale: %s%%\n", value.String);
|
||||
|
||||
turbo.SetGenericRepDefault (value, CVAR_String);
|
||||
double amt = atof(v);
|
||||
Printf ("turbo scale: %.0f%%\n", amt);
|
||||
turbo = (float)amt;
|
||||
}
|
||||
|
||||
v = Args->CheckValue ("-timer");
|
||||
|
@ -2039,6 +2027,9 @@ void D_DoomMain (void)
|
|||
StartScreen->AppendStatusLine(temp);
|
||||
}
|
||||
|
||||
// [RH] Load sound environments
|
||||
S_ParseReverbDef ();
|
||||
|
||||
// [RH] Parse through all loaded mapinfo lumps
|
||||
Printf ("G_ParseMapInfo: Load map definitions.\n");
|
||||
G_ParseMapInfo (iwad_info->MapInfo);
|
||||
|
@ -2047,7 +2038,6 @@ void D_DoomMain (void)
|
|||
Printf ("S_InitData: Load sound definitions.\n");
|
||||
S_InitData ();
|
||||
|
||||
|
||||
Printf ("Texman.Init: Init texture manager.\n");
|
||||
TexMan.Init();
|
||||
|
||||
|
@ -2083,7 +2073,7 @@ void D_DoomMain (void)
|
|||
// If there are none, try adding any in the config file.
|
||||
// Note that the command line overrides defaults from the config.
|
||||
|
||||
if ((ConsiderPatches("-deh", ".deh") | ConsiderPatches("-bex", ".bex")) == 0 &&
|
||||
if ((ConsiderPatches("-deh") | ConsiderPatches("-bex")) == 0 &&
|
||||
gameinfo.gametype == GAME_Doom && GameConfig->SetSection ("Doom.DefaultDehacked"))
|
||||
{
|
||||
const char *key;
|
||||
|
@ -2121,10 +2111,10 @@ void D_DoomMain (void)
|
|||
}
|
||||
|
||||
//Added by MC:
|
||||
DArgs *bots = Args->GatherFiles("-bots", "", false);
|
||||
for (p = 0; p < bots->NumArgs(); ++p)
|
||||
argcount = Args->CheckParmList("-bots", &args);
|
||||
for (p = 0; p < argcount; ++p)
|
||||
{
|
||||
bglobal.getspawned.Push(bots->GetArg(p));
|
||||
bglobal.getspawned.Push(args[p]);
|
||||
}
|
||||
bglobal.spawn_tries = 0;
|
||||
bglobal.wanted_botnum = bglobal.getspawned.Size();
|
||||
|
@ -2174,14 +2164,13 @@ void D_DoomMain (void)
|
|||
|
||||
V_Init2();
|
||||
|
||||
DArgs *files = Args->GatherFiles ("-playdemo", ".lmp", false);
|
||||
if (files->NumArgs() > 0)
|
||||
v = Args->CheckValue("-playdemo");
|
||||
if (v != NULL)
|
||||
{
|
||||
singledemo = true; // quit after one demo
|
||||
G_DeferedPlayDemo (files->GetArg (0));
|
||||
G_DeferedPlayDemo (v);
|
||||
D_DoomLoop (); // never returns
|
||||
}
|
||||
files->Destroy();
|
||||
|
||||
v = Args->CheckValue ("-timedemo");
|
||||
if (v)
|
||||
|
|
|
@ -54,7 +54,8 @@ void D_DoServerInfoChange (BYTE **stream, bool singlebit);
|
|||
void D_WriteUserInfoStrings (int player, BYTE **stream, bool compact=false);
|
||||
void D_ReadUserInfoStrings (int player, BYTE **stream, bool update);
|
||||
|
||||
void D_GetPlayerColor (int player, float *h, float *s, float *v);
|
||||
struct FPlayerColorSet;
|
||||
void D_GetPlayerColor (int player, float *h, float *s, float *v, FPlayerColorSet **colorset);
|
||||
void D_PickRandomTeam (int player);
|
||||
int D_PickRandomTeam ();
|
||||
class player_t;
|
||||
|
|
|
@ -65,6 +65,7 @@ EXTERN_CVAR (Bool, teamplay)
|
|||
CVAR (Float, autoaim, 5000.f, CVAR_USERINFO | CVAR_ARCHIVE);
|
||||
CVAR (String, name, "Player", CVAR_USERINFO | CVAR_ARCHIVE);
|
||||
CVAR (Color, color, 0x40cf00, CVAR_USERINFO | CVAR_ARCHIVE);
|
||||
CVAR (Int, colorset, 0, CVAR_USERINFO | CVAR_ARCHIVE);
|
||||
CVAR (String, skin, "base", CVAR_USERINFO | CVAR_ARCHIVE);
|
||||
CVAR (Int, team, TEAM_NONE, CVAR_USERINFO | CVAR_ARCHIVE);
|
||||
CVAR (String, gender, "male", CVAR_USERINFO | CVAR_ARCHIVE);
|
||||
|
@ -85,6 +86,7 @@ enum
|
|||
INFO_MoveBob,
|
||||
INFO_StillBob,
|
||||
INFO_PlayerClass,
|
||||
INFO_ColorSet,
|
||||
};
|
||||
|
||||
const char *GenderNames[3] = { "male", "female", "other" };
|
||||
|
@ -101,6 +103,7 @@ static const char *UserInfoStrings[] =
|
|||
"movebob",
|
||||
"stillbob",
|
||||
"playerclass",
|
||||
"colorset",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -184,10 +187,24 @@ int D_PlayerClassToInt (const char *classname)
|
|||
}
|
||||
}
|
||||
|
||||
void D_GetPlayerColor (int player, float *h, float *s, float *v)
|
||||
void D_GetPlayerColor (int player, float *h, float *s, float *v, FPlayerColorSet **set)
|
||||
{
|
||||
userinfo_t *info = &players[player].userinfo;
|
||||
int color = info->color;
|
||||
FPlayerColorSet *colorset = NULL;
|
||||
int color;
|
||||
|
||||
if (players[player].mo != NULL)
|
||||
{
|
||||
colorset = P_GetPlayerColorSet(players[player].mo->GetClass()->TypeName, info->colorset);
|
||||
}
|
||||
if (colorset != NULL)
|
||||
{
|
||||
color = GPalette.BaseColors[GPalette.Remap[colorset->RepresentativeColor]];
|
||||
}
|
||||
else
|
||||
{
|
||||
color = info->color;
|
||||
}
|
||||
|
||||
RGBtoHSV (RPART(color)/255.f, GPART(color)/255.f, BPART(color)/255.f,
|
||||
h, s, v);
|
||||
|
@ -206,6 +223,10 @@ void D_GetPlayerColor (int player, float *h, float *s, float *v)
|
|||
*s = clamp(ts + *s * 0.15f - 0.075f, 0.f, 1.f);
|
||||
*v = clamp(tv + *v * 0.5f - 0.25f, 0.f, 1.f);
|
||||
}
|
||||
if (set != NULL)
|
||||
{
|
||||
*set = colorset;
|
||||
}
|
||||
}
|
||||
|
||||
// Find out which teams are present. If there is only one,
|
||||
|
@ -379,6 +400,7 @@ void D_SetupUserInfo ()
|
|||
coninfo->aimdist = abs ((int)(autoaim * (float)ANGLE_1));
|
||||
}
|
||||
coninfo->color = color;
|
||||
coninfo->colorset = colorset;
|
||||
coninfo->skin = R_FindSkin (skin, 0);
|
||||
coninfo->gender = D_GenderToInt (gender);
|
||||
coninfo->neverswitch = neverswitchonpickup;
|
||||
|
@ -564,6 +586,7 @@ void D_WriteUserInfoStrings (int i, BYTE **stream, bool compact)
|
|||
"\\name\\%s"
|
||||
"\\autoaim\\%g"
|
||||
"\\color\\%x %x %x"
|
||||
"\\colorset\\%d"
|
||||
"\\skin\\%s"
|
||||
"\\team\\%d"
|
||||
"\\gender\\%s"
|
||||
|
@ -574,6 +597,7 @@ void D_WriteUserInfoStrings (int i, BYTE **stream, bool compact)
|
|||
,
|
||||
D_EscapeUserInfo(info->netname).GetChars(),
|
||||
(double)info->aimdist / (float)ANGLE_1,
|
||||
info->colorset,
|
||||
RPART(info->color), GPART(info->color), BPART(info->color),
|
||||
D_EscapeUserInfo(skins[info->skin].name).GetChars(),
|
||||
info->team,
|
||||
|
@ -599,6 +623,7 @@ void D_WriteUserInfoStrings (int i, BYTE **stream, bool compact)
|
|||
"\\%g" // movebob
|
||||
"\\%g" // stillbob
|
||||
"\\%s" // playerclass
|
||||
"\\%d" // colorset
|
||||
,
|
||||
D_EscapeUserInfo(info->netname).GetChars(),
|
||||
(double)info->aimdist / (float)ANGLE_1,
|
||||
|
@ -610,7 +635,8 @@ void D_WriteUserInfoStrings (int i, BYTE **stream, bool compact)
|
|||
info->neverswitch,
|
||||
(float)(info->MoveBob) / 65536.f,
|
||||
(float)(info->StillBob) / 65536.f,
|
||||
info->PlayerClass == -1 ? "Random" : D_EscapeUserInfo(type->DisplayName).GetChars()
|
||||
info->PlayerClass == -1 ? "Random" : D_EscapeUserInfo(type->DisplayName).GetChars(),
|
||||
info->colorset
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -714,7 +740,15 @@ void D_ReadUserInfoStrings (int i, BYTE **stream, bool update)
|
|||
break;
|
||||
|
||||
case INFO_Color:
|
||||
info->color = V_GetColorFromString (NULL, value);
|
||||
case INFO_ColorSet:
|
||||
if (infotype == INFO_Color)
|
||||
{
|
||||
info->color = V_GetColorFromString (NULL, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
info->colorset = atoi(value);
|
||||
}
|
||||
R_BuildPlayerTranslation (i);
|
||||
if (StatusBar != NULL && i == StatusBar->GetPlayer())
|
||||
{
|
||||
|
@ -804,6 +838,10 @@ FArchive &operator<< (FArchive &arc, userinfo_t &info)
|
|||
arc.Read (&info.netname, sizeof(info.netname));
|
||||
}
|
||||
arc << info.team << info.aimdist << info.color << info.skin << info.gender << info.neverswitch;
|
||||
if (SaveVersion >= 2193)
|
||||
{
|
||||
arc << info.colorset;
|
||||
}
|
||||
return arc;
|
||||
}
|
||||
|
||||
|
@ -829,6 +867,7 @@ CCMD (playerinfo)
|
|||
Printf ("Team: %s (%d)\n", ui->team == TEAM_NONE ? "None" : Teams[ui->team].GetName (), ui->team);
|
||||
Printf ("Aimdist: %d\n", ui->aimdist);
|
||||
Printf ("Color: %06x\n", ui->color);
|
||||
Printf ("ColorSet: %d\n", ui->colorset);
|
||||
Printf ("Skin: %s (%d)\n", skins[ui->skin].name, ui->skin);
|
||||
Printf ("Gender: %s (%d)\n", GenderNames[ui->gender], ui->gender);
|
||||
Printf ("NeverSwitch: %d\n", ui->neverswitch);
|
||||
|
|
|
@ -65,6 +65,11 @@ public:
|
|||
BYTE ColorRangeEnd;
|
||||
};
|
||||
|
||||
FPlayerColorSet *P_GetPlayerColorSet(FName classname, int setnum);
|
||||
void P_EnumPlayerColorSets(FName classname, TArray<int> *out);
|
||||
|
||||
class player_t;
|
||||
|
||||
class APlayerPawn : public AActor
|
||||
{
|
||||
DECLARE_CLASS_WITH_META(APlayerPawn, AActor, PClassPlayerPawn)
|
||||
|
@ -215,6 +220,7 @@ struct userinfo_t
|
|||
BYTE team;
|
||||
int aimdist;
|
||||
int color;
|
||||
int colorset;
|
||||
int skin;
|
||||
int gender;
|
||||
bool neverswitch;
|
||||
|
|
|
@ -227,10 +227,10 @@ struct mapseg_t
|
|||
{
|
||||
WORD v1;
|
||||
WORD v2;
|
||||
short angle;
|
||||
SWORD angle;
|
||||
WORD linedef;
|
||||
short side;
|
||||
short offset;
|
||||
SWORD side;
|
||||
SWORD offset;
|
||||
};
|
||||
|
||||
|
||||
|
@ -242,11 +242,11 @@ struct mapseg_t
|
|||
|
||||
struct mapnode_t
|
||||
{
|
||||
short x,y,dx,dy; // partition line
|
||||
short bbox[2][4]; // bounding box for each child
|
||||
SWORD x,y,dx,dy; // partition line
|
||||
SWORD bbox[2][4]; // bounding box for each child
|
||||
// If NF_SUBSECTOR is or'ed in, it's a subsector,
|
||||
// else it's a node of another subtree.
|
||||
unsigned short children[2];
|
||||
WORD children[2];
|
||||
};
|
||||
|
||||
|
||||
|
@ -256,23 +256,23 @@ struct mapnode_t
|
|||
// plus skill/visibility flags and attributes.
|
||||
struct mapthing_t
|
||||
{
|
||||
short x;
|
||||
short y;
|
||||
short angle;
|
||||
short type;
|
||||
short options;
|
||||
SWORD x;
|
||||
SWORD y;
|
||||
SWORD angle;
|
||||
SWORD type;
|
||||
SWORD options;
|
||||
};
|
||||
|
||||
// [RH] Hexen-compatible MapThing.
|
||||
struct mapthinghexen_t
|
||||
{
|
||||
unsigned short thingid;
|
||||
short x;
|
||||
short y;
|
||||
short z;
|
||||
short angle;
|
||||
short type;
|
||||
short flags;
|
||||
SWORD thingid;
|
||||
SWORD x;
|
||||
SWORD y;
|
||||
SWORD z;
|
||||
SWORD angle;
|
||||
SWORD type;
|
||||
SWORD flags;
|
||||
BYTE special;
|
||||
BYTE args[5];
|
||||
};
|
||||
|
|
|
@ -117,6 +117,10 @@ void F_StartFinale (const char *music, int musicorder, int cdtrack, unsigned int
|
|||
}
|
||||
|
||||
FinaleFlat = (flat != NULL && *flat != 0) ? flat : gameinfo.finaleFlat;
|
||||
if (FinaleFlat != NULL && FinaleFlat[0] == '$')
|
||||
{
|
||||
FinaleFlat = GStrings(FinaleFlat + 1);
|
||||
}
|
||||
|
||||
if (textInLump)
|
||||
{
|
||||
|
@ -758,7 +762,7 @@ void F_CastDrawer (void)
|
|||
FTexture* pic;
|
||||
|
||||
// erase the entire screen to a background
|
||||
screen->DrawTexture (TexMan["BOSSBACK"], 0, 0,
|
||||
screen->DrawTexture (TexMan[GStrings("bgcastcall")], 0, 0,
|
||||
DTA_DestWidth, screen->GetWidth(),
|
||||
DTA_DestHeight, screen->GetHeight(),
|
||||
TAG_DONE);
|
||||
|
|
|
@ -126,7 +126,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CPosRefire)
|
|||
if (!self->target
|
||||
|| P_HitFriend (self)
|
||||
|| self->target->health <= 0
|
||||
|| !P_CheckSight (self, self->target, 0) )
|
||||
|| !P_CheckSight (self, self->target, SF_SEEPASTBLOCKEVERYTHING|SF_SEEPASTSHOOTABLELINES))
|
||||
{
|
||||
self->SetState (self->SeeState);
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpidRefire)
|
|||
if (!self->target
|
||||
|| P_HitFriend (self)
|
||||
|| self->target->health <= 0
|
||||
|| !P_CheckSight (self, self->target, 0) )
|
||||
|| !P_CheckSight (self, self->target, SF_SEEPASTBLOCKEVERYTHING|SF_SEEPASTSHOOTABLELINES))
|
||||
{
|
||||
self->SetState (self->SeeState);
|
||||
}
|
||||
|
|
|
@ -2192,18 +2192,14 @@ void G_WriteDemoTiccmd (ticcmd_t *cmd, int player, int buf)
|
|||
//
|
||||
// G_RecordDemo
|
||||
//
|
||||
void G_RecordDemo (char* name)
|
||||
void G_RecordDemo (const char* name)
|
||||
{
|
||||
char *v;
|
||||
|
||||
usergame = false;
|
||||
strcpy (demoname, name);
|
||||
FixPathSeperator (demoname);
|
||||
DefaultExtension (demoname, ".lmp");
|
||||
v = Args->CheckValue ("-maxdemo");
|
||||
maxdemosize = 0x20000;
|
||||
demobuffer = (BYTE *)M_Malloc (maxdemosize);
|
||||
|
||||
demorecording = true;
|
||||
}
|
||||
|
||||
|
@ -2288,7 +2284,7 @@ void G_BeginRecording (const char *startmap)
|
|||
|
||||
FString defdemoname;
|
||||
|
||||
void G_DeferedPlayDemo (char *name)
|
||||
void G_DeferedPlayDemo (const char *name)
|
||||
{
|
||||
defdemoname = name;
|
||||
gameaction = ga_playdemo;
|
||||
|
@ -2516,7 +2512,7 @@ void G_DoPlayDemo (void)
|
|||
//
|
||||
// G_TimeDemo
|
||||
//
|
||||
void G_TimeDemo (char* name)
|
||||
void G_TimeDemo (const char* name)
|
||||
{
|
||||
nodrawers = !!Args->CheckParm ("-nodraw");
|
||||
noblit = !!Args->CheckParm ("-noblit");
|
||||
|
|
|
@ -32,7 +32,7 @@ struct PNGHandle;
|
|||
//
|
||||
void G_DeathMatchSpawnPlayer (int playernum);
|
||||
|
||||
void G_DeferedPlayDemo (char* demo);
|
||||
void G_DeferedPlayDemo (const char* demo);
|
||||
|
||||
// Can be called by the startup code or M_Responder,
|
||||
// calls P_SetupLevel or W_EnterWorld.
|
||||
|
@ -44,12 +44,12 @@ void G_DoLoadGame (void);
|
|||
void G_SaveGame (const char *filename, const char *description);
|
||||
|
||||
// Only called by startup code.
|
||||
void G_RecordDemo (char* name);
|
||||
void G_RecordDemo (const char* name);
|
||||
|
||||
void G_BeginRecording (const char *startmap);
|
||||
|
||||
void G_PlayDemo (char* name);
|
||||
void G_TimeDemo (char* name);
|
||||
void G_TimeDemo (const char* name);
|
||||
bool G_CheckDemoStatus (void);
|
||||
|
||||
void G_WorldDone (void);
|
||||
|
|
|
@ -69,7 +69,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CStaffCheck)
|
|||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
angle = pmo->angle+i*(ANG45/16);
|
||||
slope = P_AimLineAttack (pmo, angle, fixed_t(1.5*MELEERANGE), &linetarget, 0, false, true);
|
||||
slope = P_AimLineAttack (pmo, angle, fixed_t(1.5*MELEERANGE), &linetarget, 0, ALF_CHECK3D);
|
||||
if (linetarget)
|
||||
{
|
||||
P_LineAttack (pmo, angle, fixed_t(1.5*MELEERANGE), slope, damage, NAME_Melee, PClass::FindActor("CStaffPuff"));
|
||||
|
@ -93,7 +93,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CStaffCheck)
|
|||
break;
|
||||
}
|
||||
angle = pmo->angle-i*(ANG45/16);
|
||||
slope = P_AimLineAttack (player->mo, angle, fixed_t(1.5*MELEERANGE), &linetarget, 0, false, true);
|
||||
slope = P_AimLineAttack (player->mo, angle, fixed_t(1.5*MELEERANGE), &linetarget, 0, ALF_CHECK3D);
|
||||
if (linetarget)
|
||||
{
|
||||
P_LineAttack (pmo, angle, fixed_t(1.5*MELEERANGE), slope, damage, NAME_Melee, PClass::FindActor("CStaffPuff"));
|
||||
|
|
|
@ -50,7 +50,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FHammerAttack)
|
|||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
angle = pmo->angle + i*(ANG45/32);
|
||||
slope = P_AimLineAttack (pmo, angle, HAMMER_RANGE, &linetarget, 0, false, true);
|
||||
slope = P_AimLineAttack (pmo, angle, HAMMER_RANGE, &linetarget, 0, ALF_CHECK3D);
|
||||
if (linetarget)
|
||||
{
|
||||
P_LineAttack (pmo, angle, HAMMER_RANGE, slope, damage, NAME_Melee, hammertime, true);
|
||||
|
@ -63,7 +63,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FHammerAttack)
|
|||
goto hammerdone;
|
||||
}
|
||||
angle = pmo->angle-i*(ANG45/32);
|
||||
slope = P_AimLineAttack(pmo, angle, HAMMER_RANGE, &linetarget, 0, false, true);
|
||||
slope = P_AimLineAttack(pmo, angle, HAMMER_RANGE, &linetarget, 0, ALF_CHECK3D);
|
||||
if(linetarget)
|
||||
{
|
||||
P_LineAttack(pmo, angle, HAMMER_RANGE, slope, damage, NAME_Melee, hammertime, true);
|
||||
|
@ -78,7 +78,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FHammerAttack)
|
|||
}
|
||||
// didn't find any targets in meleerange, so set to throw out a hammer
|
||||
angle = pmo->angle;
|
||||
slope = P_AimLineAttack (pmo, angle, HAMMER_RANGE, &linetarget, 0, false, true);
|
||||
slope = P_AimLineAttack (pmo, angle, HAMMER_RANGE, &linetarget, 0, ALF_CHECK3D);
|
||||
if (P_LineAttack (pmo, angle, HAMMER_RANGE, slope, damage, NAME_Melee, hammertime, true) != NULL)
|
||||
{
|
||||
pmo->special1 = false;
|
||||
|
|
|
@ -79,7 +79,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireConePL1)
|
|||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
angle = self->angle+i*(ANG45/16);
|
||||
slope = P_AimLineAttack (self, angle, MELEERANGE, &linetarget, 0, false, true);
|
||||
slope = P_AimLineAttack (self, angle, MELEERANGE, &linetarget, 0, ALF_CHECK3D);
|
||||
if (linetarget)
|
||||
{
|
||||
P_DamageMobj (linetarget, self, self, damage, NAME_Ice);
|
||||
|
|
|
@ -572,7 +572,7 @@ void G_ChangeLevel(const char *levelname, int position, bool keepFacing, int nex
|
|||
|
||||
if (strncmp(levelname, "enDSeQ", 6) != 0)
|
||||
{
|
||||
nextinfo = FindLevelInfo (nextlevel);
|
||||
nextinfo = FindLevelInfo (levelname);
|
||||
if (nextinfo != NULL)
|
||||
{
|
||||
level_info_t *nextredir = nextinfo->CheckLevelRedirect();
|
||||
|
@ -1039,7 +1039,7 @@ void G_WorldDone (void)
|
|||
{
|
||||
F_StartFinale (thiscluster->MessageMusic, thiscluster->musicorder,
|
||||
thiscluster->cdtrack, thiscluster->cdid,
|
||||
thiscluster->finaleflat, thiscluster->ExitText,
|
||||
thiscluster->FinaleFlat, thiscluster->ExitText,
|
||||
thiscluster->flags & CLUSTER_EXITTEXTINLUMP,
|
||||
thiscluster->flags & CLUSTER_FINALEPIC,
|
||||
thiscluster->flags & CLUSTER_LOOKUPEXITTEXT,
|
||||
|
@ -1057,7 +1057,7 @@ void G_WorldDone (void)
|
|||
{
|
||||
F_StartFinale (nextcluster->MessageMusic, nextcluster->musicorder,
|
||||
nextcluster->cdtrack, nextcluster->cdid,
|
||||
nextcluster->finaleflat, nextcluster->EnterText,
|
||||
nextcluster->FinaleFlat, nextcluster->EnterText,
|
||||
nextcluster->flags & CLUSTER_ENTERTEXTINLUMP,
|
||||
nextcluster->flags & CLUSTER_FINALEPIC,
|
||||
nextcluster->flags & CLUSTER_LOOKUPENTERTEXT,
|
||||
|
@ -1067,7 +1067,7 @@ void G_WorldDone (void)
|
|||
{
|
||||
F_StartFinale (thiscluster->MessageMusic, thiscluster->musicorder,
|
||||
thiscluster->cdtrack, nextcluster->cdid,
|
||||
thiscluster->finaleflat, thiscluster->ExitText,
|
||||
thiscluster->FinaleFlat, thiscluster->ExitText,
|
||||
thiscluster->flags & CLUSTER_EXITTEXTINLUMP,
|
||||
thiscluster->flags & CLUSTER_FINALEPIC,
|
||||
thiscluster->flags & CLUSTER_LOOKUPEXITTEXT,
|
||||
|
@ -1319,6 +1319,8 @@ void G_InitLevelLocals ()
|
|||
compatflags.Callback();
|
||||
|
||||
NormalLight.ChangeFade (level.fadeto);
|
||||
|
||||
level.DefaultEnvironment = info->DefaultEnvironment;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -66,15 +66,16 @@ struct FMapInfoParser
|
|||
int format_type;
|
||||
bool HexenHack;
|
||||
|
||||
FMapInfoParser()
|
||||
FMapInfoParser(int format = FMT_Unknown)
|
||||
{
|
||||
format_type = FMT_Unknown;
|
||||
format_type = format;
|
||||
HexenHack = false;
|
||||
}
|
||||
|
||||
bool ParseLookupName(FString &dest);
|
||||
void ParseMusic(FString &name, int &order);
|
||||
void ParseLumpOrTextureName(char *name);
|
||||
void ParseLumpOrTextureName(FString &name);
|
||||
|
||||
void ParseCluster();
|
||||
void ParseNextMap(char *mapname);
|
||||
|
@ -276,6 +277,7 @@ struct level_info_t
|
|||
DWORD compatflags;
|
||||
DWORD compatmask;
|
||||
FString Translator; // for converting Doom-format linedef and sector types.
|
||||
int DefaultEnvironment; // Default sound environment for the map.
|
||||
|
||||
// Redirection: If any player is carrying the specified item, then
|
||||
// you go to the RedirectMap instead of this one.
|
||||
|
@ -388,6 +390,7 @@ struct FLevelLocals
|
|||
fixed_t aircontrol;
|
||||
fixed_t airfriction;
|
||||
int airsupply;
|
||||
int DefaultEnvironment; // Default sound environment.
|
||||
|
||||
FSectorScrollValues *Scrolls; // NULL if no DScrollers in this level
|
||||
|
||||
|
@ -437,7 +440,7 @@ extern TArray<EndSequence> EndSequences;
|
|||
struct cluster_info_t
|
||||
{
|
||||
int cluster;
|
||||
char finaleflat[9];
|
||||
FString FinaleFlat;
|
||||
FString ExitText;
|
||||
FString EnterText;
|
||||
FString MessageMusic;
|
||||
|
|
|
@ -265,6 +265,7 @@ void level_info_t::Reset()
|
|||
bordertexture[0] = 0;
|
||||
teamdamage = 0.f;
|
||||
specialactions.Clear();
|
||||
DefaultEnvironment = 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -389,7 +390,7 @@ bool level_info_t::isValid()
|
|||
void cluster_info_t::Reset()
|
||||
{
|
||||
cluster = 0;
|
||||
finaleflat[0] = 0;
|
||||
FinaleFlat = "";
|
||||
ExitText = "";
|
||||
EnterText = "";
|
||||
MessageMusic = "";
|
||||
|
@ -615,6 +616,12 @@ void FMapInfoParser::ParseLumpOrTextureName(char *name)
|
|||
name[8]=0;
|
||||
}
|
||||
|
||||
void FMapInfoParser::ParseLumpOrTextureName(FString &name)
|
||||
{
|
||||
sc.MustGetString();
|
||||
name = sc.String;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
@ -691,12 +698,12 @@ void FMapInfoParser::ParseCluster()
|
|||
else if (sc.Compare("flat"))
|
||||
{
|
||||
ParseAssign();
|
||||
ParseLumpOrTextureName(clusterinfo->finaleflat);
|
||||
ParseLumpOrTextureName(clusterinfo->FinaleFlat);
|
||||
}
|
||||
else if (sc.Compare("pic"))
|
||||
{
|
||||
ParseAssign();
|
||||
ParseLumpOrTextureName(clusterinfo->finaleflat);
|
||||
ParseLumpOrTextureName(clusterinfo->FinaleFlat);
|
||||
clusterinfo->flags |= CLUSTER_FINALEPIC;
|
||||
}
|
||||
else if (sc.Compare("hub"))
|
||||
|
@ -1244,6 +1251,36 @@ DEFINE_MAP_OPTION(mapbackground, true)
|
|||
parse.ParseLumpOrTextureName(info->mapbg);
|
||||
}
|
||||
|
||||
DEFINE_MAP_OPTION(defaultenvironment, false)
|
||||
{
|
||||
int id;
|
||||
|
||||
parse.ParseAssign();
|
||||
if (parse.sc.CheckNumber())
|
||||
{ // Numeric ID XXX [, YYY]
|
||||
id = parse.sc.Number << 8;
|
||||
if (parse.CheckNumber())
|
||||
{
|
||||
id |= parse.sc.Number;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // Named environment
|
||||
parse.sc.MustGetString();
|
||||
ReverbContainer *reverb = S_FindEnvironment(parse.sc.String);
|
||||
if (reverb == NULL)
|
||||
{
|
||||
parse.sc.ScriptMessage("Unknown sound environment '%s'\n", parse.sc.String);
|
||||
id = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
id = reverb->ID;
|
||||
}
|
||||
}
|
||||
info->DefaultEnvironment = id;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
@ -1923,10 +1960,23 @@ void G_ParseMapInfo (const char *basemapinfo)
|
|||
parse.ParseMapInfo(Wads.GetNumForFullName(basemapinfo), gamedefaults, defaultinfo);
|
||||
}
|
||||
|
||||
static const char *mapinfonames[] = { "MAPINFO", "ZMAPINFO", NULL };
|
||||
int nindex;
|
||||
|
||||
// Parse any extra MAPINFOs.
|
||||
while ((lump = Wads.FindLump ("MAPINFO", &lastlump)) != -1)
|
||||
while ((lump = Wads.FindLumpMulti (mapinfonames, &lastlump, false, &nindex)) != -1)
|
||||
{
|
||||
FMapInfoParser parse;
|
||||
if (nindex == 0)
|
||||
{
|
||||
// If this lump is named MAPINFO we need to check if the same WAD contains a ZMAPINFO lump.
|
||||
// If that exists we need to skip this one.
|
||||
|
||||
int wad = Wads.GetLumpFile(lump);
|
||||
int altlump = Wads.CheckNumForName("ZMAPINFO", ns_global, wad, true);
|
||||
|
||||
if (altlump >= 0) continue;
|
||||
}
|
||||
FMapInfoParser parse(nindex == 1? FMapInfoParser::FMT_New : FMapInfoParser::FMT_Unknown);
|
||||
level_info_t defaultinfo;
|
||||
parse.ParseMapInfo(lump, gamedefaults, defaultinfo);
|
||||
}
|
||||
|
|
|
@ -193,6 +193,12 @@ void APowerup::DoEffect ()
|
|||
|
||||
void APowerup::EndEffect ()
|
||||
{
|
||||
int colormap = GetSpecialColormap(BlendColor);
|
||||
|
||||
if (colormap != NOFIXEDCOLORMAP && Owner && Owner->player && Owner->player->fixedcolormap == colormap)
|
||||
{ // only unset if the fixed colormap comes from this item
|
||||
Owner->player->fixedcolormap = NOFIXEDCOLORMAP;
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
@ -347,6 +353,7 @@ IMPLEMENT_CLASS (APowerInvulnerable)
|
|||
|
||||
void APowerInvulnerable::InitEffect ()
|
||||
{
|
||||
Super::InitEffect();
|
||||
Owner->effects &= ~FX_RESPAWNINVUL;
|
||||
Owner->flags2 |= MF2_INVULNERABLE;
|
||||
if (Mode == NAME_None && Owner->IsKindOf(RUNTIME_CLASS(APlayerPawn)))
|
||||
|
@ -421,6 +428,8 @@ void APowerInvulnerable::DoEffect ()
|
|||
|
||||
void APowerInvulnerable::EndEffect ()
|
||||
{
|
||||
Super::EndEffect();
|
||||
|
||||
if (Owner == NULL)
|
||||
{
|
||||
return;
|
||||
|
@ -498,6 +507,7 @@ bool APowerStrength::HandlePickup (AInventory *item)
|
|||
|
||||
void APowerStrength::InitEffect ()
|
||||
{
|
||||
Super::InitEffect();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
@ -537,7 +547,6 @@ PalEntry APowerStrength::GetBlend ()
|
|||
// Invisibility Powerup ------------------------------------------------------
|
||||
|
||||
IMPLEMENT_CLASS (APowerInvisibility)
|
||||
IMPLEMENT_CLASS (APowerShadow)
|
||||
|
||||
// Invisibility flag combos
|
||||
#define INVISIBILITY_FLAGS1 (MF_SHADOW)
|
||||
|
@ -552,6 +561,7 @@ IMPLEMENT_CLASS (APowerShadow)
|
|||
|
||||
void APowerInvisibility::InitEffect ()
|
||||
{
|
||||
Super::InitEffect();
|
||||
// This used to call CommonInit(), which used to contain all the code that's repeated every
|
||||
// tic, plus the following code that needs to happen once and only once.
|
||||
// The CommonInit() code has been moved to DoEffect(), so this now ends with a call to DoEffect(),
|
||||
|
@ -615,6 +625,7 @@ void APowerInvisibility::DoEffect ()
|
|||
|
||||
void APowerInvisibility::EndEffect ()
|
||||
{
|
||||
Super::EndEffect();
|
||||
if (Owner != NULL)
|
||||
{
|
||||
Owner->flags &= ~(flags & INVISIBILITY_FLAGS1);
|
||||
|
@ -822,6 +833,7 @@ void APowerLightAmp::DoEffect ()
|
|||
|
||||
void APowerLightAmp::EndEffect ()
|
||||
{
|
||||
Super::EndEffect();
|
||||
if (Owner != NULL && Owner->player != NULL && Owner->player->fixedcolormap < NUMCOLORMAPS)
|
||||
{
|
||||
Owner->player->fixedlightlevel = -1;
|
||||
|
@ -914,6 +926,7 @@ void APowerFlight::Serialize (FArchive &arc)
|
|||
|
||||
void APowerFlight::InitEffect ()
|
||||
{
|
||||
Super::InitEffect();
|
||||
Owner->flags2 |= MF2_FLY;
|
||||
Owner->flags |= MF_NOGRAVITY;
|
||||
if (Owner->z <= Owner->floorz)
|
||||
|
@ -955,6 +968,7 @@ void APowerFlight::Tick ()
|
|||
|
||||
void APowerFlight::EndEffect ()
|
||||
{
|
||||
Super::EndEffect();
|
||||
if (Owner == NULL || Owner->player == NULL)
|
||||
{
|
||||
return;
|
||||
|
@ -1035,6 +1049,8 @@ void APowerWeaponLevel2::InitEffect ()
|
|||
{
|
||||
AWeapon *weapon, *sister;
|
||||
|
||||
Super::InitEffect();
|
||||
|
||||
if (Owner->player == NULL)
|
||||
return;
|
||||
|
||||
|
@ -1071,6 +1087,7 @@ void APowerWeaponLevel2::EndEffect ()
|
|||
{
|
||||
player_t *player = Owner != NULL ? Owner->player : NULL;
|
||||
|
||||
Super::EndEffect();
|
||||
if (player != NULL)
|
||||
{
|
||||
|
||||
|
@ -1199,6 +1216,8 @@ void APowerTargeter::InitEffect ()
|
|||
{
|
||||
player_t *player;
|
||||
|
||||
Super::InitEffect();
|
||||
|
||||
if ((player = Owner->player) == NULL)
|
||||
return;
|
||||
|
||||
|
@ -1250,6 +1269,7 @@ void APowerTargeter::DoEffect ()
|
|||
|
||||
void APowerTargeter::EndEffect ()
|
||||
{
|
||||
Super::EndEffect();
|
||||
if (Owner != NULL && Owner->player != NULL)
|
||||
{
|
||||
P_SetPsprite (Owner->player, ps_targetcenter, NULL);
|
||||
|
@ -1281,6 +1301,8 @@ IMPLEMENT_CLASS (APowerFrightener)
|
|||
|
||||
void APowerFrightener::InitEffect ()
|
||||
{
|
||||
Super::InitEffect();
|
||||
|
||||
if (Owner== NULL || Owner->player == NULL)
|
||||
return;
|
||||
|
||||
|
@ -1295,6 +1317,8 @@ void APowerFrightener::InitEffect ()
|
|||
|
||||
void APowerFrightener::EndEffect ()
|
||||
{
|
||||
Super::EndEffect();
|
||||
|
||||
if (Owner== NULL || Owner->player == NULL)
|
||||
return;
|
||||
|
||||
|
@ -1319,6 +1343,8 @@ void APowerTimeFreezer::InitEffect( )
|
|||
{
|
||||
int ulIdx;
|
||||
|
||||
Super::InitEffect();
|
||||
|
||||
if (Owner== NULL || Owner->player == NULL)
|
||||
return;
|
||||
|
||||
|
@ -1394,6 +1420,8 @@ void APowerTimeFreezer::EndEffect( )
|
|||
{
|
||||
int ulIdx;
|
||||
|
||||
Super::EndEffect();
|
||||
|
||||
// Allow other actors to move about freely once again.
|
||||
level.flags2 &= ~LEVEL2_FROZEN;
|
||||
|
||||
|
@ -1432,6 +1460,8 @@ IMPLEMENT_CLASS( APowerDamage)
|
|||
|
||||
void APowerDamage::InitEffect( )
|
||||
{
|
||||
Super::InitEffect();
|
||||
|
||||
// Use sound channel 5 to avoid interference with other actions.
|
||||
if (Owner != NULL) S_Sound(Owner, 5, SeeSound, 1.0f, ATTN_NONE);
|
||||
}
|
||||
|
@ -1444,6 +1474,7 @@ void APowerDamage::InitEffect( )
|
|||
|
||||
void APowerDamage::EndEffect( )
|
||||
{
|
||||
Super::EndEffect();
|
||||
// Use sound channel 5 to avoid interference with other actions.
|
||||
if (Owner != NULL) S_Sound(Owner, 5, DeathSound, 1.0f, ATTN_NONE);
|
||||
}
|
||||
|
@ -1495,6 +1526,8 @@ IMPLEMENT_CLASS(APowerProtection)
|
|||
|
||||
void APowerProtection::InitEffect( )
|
||||
{
|
||||
Super::InitEffect();
|
||||
|
||||
if (Owner != NULL)
|
||||
{
|
||||
S_Sound(Owner, CHAN_AUTO, SeeSound, 1.0f, ATTN_NONE);
|
||||
|
@ -1518,6 +1551,7 @@ void APowerProtection::InitEffect( )
|
|||
|
||||
void APowerProtection::EndEffect( )
|
||||
{
|
||||
Super::EndEffect();
|
||||
if (Owner != NULL)
|
||||
{
|
||||
S_Sound(Owner, CHAN_AUTO, DeathSound, 1.0f, ATTN_NONE);
|
||||
|
@ -1570,6 +1604,8 @@ IMPLEMENT_CLASS(APowerDrain)
|
|||
|
||||
void APowerDrain::InitEffect( )
|
||||
{
|
||||
Super::InitEffect();
|
||||
|
||||
if (Owner== NULL || Owner->player == NULL)
|
||||
return;
|
||||
|
||||
|
@ -1585,6 +1621,8 @@ void APowerDrain::InitEffect( )
|
|||
|
||||
void APowerDrain::EndEffect( )
|
||||
{
|
||||
Super::EndEffect();
|
||||
|
||||
// Nothing to do if there's no owner.
|
||||
if (Owner != NULL && Owner->player != NULL)
|
||||
{
|
||||
|
@ -1606,6 +1644,8 @@ IMPLEMENT_CLASS(APowerRegeneration)
|
|||
|
||||
void APowerRegeneration::InitEffect( )
|
||||
{
|
||||
Super::InitEffect();
|
||||
|
||||
if (Owner== NULL || Owner->player == NULL)
|
||||
return;
|
||||
|
||||
|
@ -1621,6 +1661,7 @@ void APowerRegeneration::InitEffect( )
|
|||
|
||||
void APowerRegeneration::EndEffect( )
|
||||
{
|
||||
Super::EndEffect();
|
||||
// Nothing to do if there's no owner.
|
||||
if (Owner != NULL && Owner->player != NULL)
|
||||
{
|
||||
|
@ -1641,6 +1682,8 @@ IMPLEMENT_CLASS(APowerHighJump)
|
|||
|
||||
void APowerHighJump::InitEffect( )
|
||||
{
|
||||
Super::InitEffect();
|
||||
|
||||
if (Owner== NULL || Owner->player == NULL)
|
||||
return;
|
||||
|
||||
|
@ -1656,6 +1699,7 @@ void APowerHighJump::InitEffect( )
|
|||
|
||||
void APowerHighJump::EndEffect( )
|
||||
{
|
||||
Super::EndEffect();
|
||||
// Nothing to do if there's no owner.
|
||||
if (Owner != NULL && Owner->player != NULL)
|
||||
{
|
||||
|
@ -1676,6 +1720,8 @@ IMPLEMENT_CLASS(APowerDoubleFiringSpeed)
|
|||
|
||||
void APowerDoubleFiringSpeed::InitEffect( )
|
||||
{
|
||||
Super::InitEffect();
|
||||
|
||||
if (Owner== NULL || Owner->player == NULL)
|
||||
return;
|
||||
|
||||
|
@ -1691,6 +1737,7 @@ void APowerDoubleFiringSpeed::InitEffect( )
|
|||
|
||||
void APowerDoubleFiringSpeed::EndEffect( )
|
||||
{
|
||||
Super::EndEffect();
|
||||
// Nothing to do if there's no owner.
|
||||
if (Owner != NULL && Owner->player != NULL)
|
||||
{
|
||||
|
@ -1724,6 +1771,8 @@ void APowerMorph::Serialize (FArchive &arc)
|
|||
|
||||
void APowerMorph::InitEffect( )
|
||||
{
|
||||
Super::InitEffect();
|
||||
|
||||
if (Owner != NULL && Owner->player != NULL && PlayerClass != NAME_None)
|
||||
{
|
||||
player_t *realplayer = Owner->player; // Remember the identity of the player
|
||||
|
@ -1751,6 +1800,8 @@ void APowerMorph::InitEffect( )
|
|||
|
||||
void APowerMorph::EndEffect( )
|
||||
{
|
||||
Super::EndEffect();
|
||||
|
||||
// Abort if owner already destroyed
|
||||
if (Owner == NULL)
|
||||
{
|
||||
|
@ -1806,6 +1857,8 @@ IMPLEMENT_CLASS(APowerInfiniteAmmo)
|
|||
|
||||
void APowerInfiniteAmmo::InitEffect( )
|
||||
{
|
||||
Super::InitEffect();
|
||||
|
||||
if (Owner== NULL || Owner->player == NULL)
|
||||
return;
|
||||
|
||||
|
@ -1821,6 +1874,8 @@ void APowerInfiniteAmmo::InitEffect( )
|
|||
|
||||
void APowerInfiniteAmmo::EndEffect( )
|
||||
{
|
||||
Super::EndEffect();
|
||||
|
||||
// Nothing to do if there's no owner.
|
||||
if (Owner != NULL && Owner->player != NULL)
|
||||
{
|
||||
|
|
|
@ -81,12 +81,6 @@ protected:
|
|||
// fixed_t OwnersNormalAlpha;
|
||||
};
|
||||
|
||||
// Needed only for m_cheat.cpp now
|
||||
class APowerShadow : public APowerInvisibility
|
||||
{
|
||||
DECLARE_CLASS (APowerShadow, APowerInvisibility)
|
||||
};
|
||||
|
||||
class APowerIronFeet : public APowerup
|
||||
{
|
||||
DECLARE_CLASS (APowerIronFeet, APowerup)
|
||||
|
|
|
@ -53,7 +53,6 @@ class ASecurityCamera : public AActor
|
|||
public:
|
||||
void PostBeginPlay ();
|
||||
void Tick ();
|
||||
angle_t AngleIncrements ();
|
||||
|
||||
void Serialize (FArchive &arc);
|
||||
protected:
|
||||
|
@ -71,11 +70,6 @@ void ASecurityCamera::Serialize (FArchive &arc)
|
|||
arc << Center << Acc << Delta << Range;
|
||||
}
|
||||
|
||||
angle_t ASecurityCamera::AngleIncrements ()
|
||||
{
|
||||
return ANGLE_1;
|
||||
}
|
||||
|
||||
void ASecurityCamera::PostBeginPlay ()
|
||||
{
|
||||
Super::PostBeginPlay ();
|
||||
|
|
|
@ -43,7 +43,6 @@ class AHateTarget : public AActor
|
|||
DECLARE_CLASS (AHateTarget, AActor)
|
||||
public:
|
||||
void BeginPlay ();
|
||||
angle_t AngleIncrements (void);
|
||||
int TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, FName damagetype);
|
||||
};
|
||||
|
||||
|
@ -77,7 +76,3 @@ int AHateTarget::TakeSpecialDamage (AActor *inflictor, AActor *source, int damag
|
|||
}
|
||||
}
|
||||
|
||||
angle_t AHateTarget::AngleIncrements (void)
|
||||
{
|
||||
return ANGLE_1;
|
||||
}
|
||||
|
|
|
@ -68,6 +68,7 @@ struct Lock
|
|||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else for(unsigned int i=0;i<keylist.Size();i++)
|
||||
{
|
||||
|
|
|
@ -42,17 +42,11 @@ class ASpark : public AActor
|
|||
{
|
||||
DECLARE_CLASS (ASpark, AActor)
|
||||
public:
|
||||
angle_t AngleIncrements ();
|
||||
void Activate (AActor *activator);
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS (ASpark)
|
||||
|
||||
angle_t ASpark::AngleIncrements ()
|
||||
{
|
||||
return ANGLE_1;
|
||||
}
|
||||
|
||||
void ASpark::Activate (AActor *activator)
|
||||
{
|
||||
Super::Activate (activator);
|
||||
|
|
|
@ -542,6 +542,10 @@ void SBarInfo::ParseSBarInfo(int lump)
|
|||
sc.MustGetToken(TK_Identifier);
|
||||
barNum = sc.MustMatchString(StatusBars);
|
||||
}
|
||||
if (this->huds[barNum] != NULL)
|
||||
{
|
||||
delete this->huds[barNum];
|
||||
}
|
||||
this->huds[barNum] = new SBarInfoMainBlock(this);
|
||||
if(barNum == STBAR_AUTOMAP)
|
||||
{
|
||||
|
|
|
@ -166,20 +166,23 @@ static void DrawHudText(FFont *font, int color, char * text, int x, int y, int t
|
|||
{
|
||||
int width;
|
||||
FTexture *texc = font->GetChar(text[i], &width);
|
||||
int offset = texc->TopOffset - tex_zero->TopOffset + tex_zero->GetHeight();
|
||||
screen->DrawChar(font, color, x, y, text[i],
|
||||
DTA_KeepRatio, true,
|
||||
DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight, DTA_Alpha, trans,
|
||||
DTA_LeftOffset, width/2, DTA_TopOffset, offset,
|
||||
/*DTA_CenterBottomOffset, 1,*/ TAG_DONE);
|
||||
x+=zerowidth;
|
||||
if (texc != NULL)
|
||||
{
|
||||
int offset = texc->TopOffset - tex_zero->TopOffset + tex_zero->GetHeight();
|
||||
screen->DrawChar(font, color, x, y, text[i],
|
||||
DTA_KeepRatio, true,
|
||||
DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight, DTA_Alpha, trans,
|
||||
DTA_LeftOffset, width/2, DTA_TopOffset, offset,
|
||||
/*DTA_CenterBottomOffset, 1,*/ TAG_DONE);
|
||||
}
|
||||
x += zerowidth;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Draws a numberses a fixed widh for all characters
|
||||
// Draws a number with a fixed width for all digits
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include "thingdef/thingdef.h"
|
||||
*/
|
||||
|
||||
bool Sys_1ed64 (AActor *self)
|
||||
static bool CrusaderCheckRange (AActor *self)
|
||||
{
|
||||
if (P_CheckSight (self, self->target) && self->reactiontime == 0)
|
||||
{
|
||||
|
@ -25,7 +25,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CrusaderChoose)
|
|||
if (self->target == NULL)
|
||||
return 0;
|
||||
|
||||
if (Sys_1ed64 (self))
|
||||
if (CrusaderCheckRange (self))
|
||||
{
|
||||
A_FaceTarget (self);
|
||||
self->angle -= ANGLE_180/16;
|
||||
|
|
|
@ -87,7 +87,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SentinelRefire)
|
|||
{
|
||||
if (self->target == NULL ||
|
||||
self->target->health <= 0 ||
|
||||
!P_CheckSight (self, self->target) ||
|
||||
!P_CheckSight (self, self->target, SF_SEEPASTBLOCKEVERYTHING|SF_SEEPASTSHOOTABLELINES) ||
|
||||
P_HitFriend(self) ||
|
||||
pr_sentinelrefire() < 40)
|
||||
{
|
||||
|
|
|
@ -536,13 +536,14 @@ void FGameConfigFile::ArchiveGlobalData ()
|
|||
|
||||
FString FGameConfigFile::GetConfigPath (bool tryProg)
|
||||
{
|
||||
char *pathval;
|
||||
const char *pathval;
|
||||
FString path;
|
||||
|
||||
pathval = Args->CheckValue ("-config");
|
||||
if (pathval != NULL)
|
||||
{
|
||||
return FString(pathval);
|
||||
|
||||
}
|
||||
#ifdef _WIN32
|
||||
path = NULL;
|
||||
HRESULT hr;
|
||||
|
|
|
@ -418,7 +418,7 @@ void HU_DrawColorBar(int x, int y, int height, int playernum)
|
|||
{
|
||||
float h, s, v, r, g, b;
|
||||
|
||||
D_GetPlayerColor (playernum, &h, &s, &v);
|
||||
D_GetPlayerColor (playernum, &h, &s, &v, NULL);
|
||||
HSVtoRGB (&r, &g, &b, h, s, v);
|
||||
|
||||
screen->Clear (x, y, x + 24*CleanXfac, y + height, -1,
|
||||
|
|
|
@ -338,20 +338,21 @@ void PreSend (const void *buffer, int bufferlen, const sockaddr_in *to)
|
|||
sendto (mysocket, (const char *)buffer, bufferlen, 0, (const sockaddr *)to, sizeof(*to));
|
||||
}
|
||||
|
||||
void BuildAddress (sockaddr_in *address, char *name)
|
||||
void BuildAddress (sockaddr_in *address, const char *name)
|
||||
{
|
||||
hostent *hostentry; // host information entry
|
||||
u_short port;
|
||||
char *portpart;
|
||||
const char *portpart;
|
||||
bool isnamed = false;
|
||||
int curchar;
|
||||
char c;
|
||||
FString target;
|
||||
|
||||
address->sin_family = AF_INET;
|
||||
|
||||
if ( (portpart = strchr (name, ':')) )
|
||||
{
|
||||
*portpart = 0;
|
||||
target = FString(name, portpart - name);
|
||||
port = atoi (portpart + 1);
|
||||
if (!port)
|
||||
{
|
||||
|
@ -361,11 +362,12 @@ void BuildAddress (sockaddr_in *address, char *name)
|
|||
}
|
||||
else
|
||||
{
|
||||
target = name;
|
||||
port = DOOMPORT;
|
||||
}
|
||||
address->sin_port = htons(port);
|
||||
|
||||
for (curchar = 0; (c = name[curchar]) ; curchar++)
|
||||
for (curchar = 0; (c = target[curchar]) ; curchar++)
|
||||
{
|
||||
if ((c < '0' || c > '9') && c != '.')
|
||||
{
|
||||
|
@ -376,21 +378,18 @@ void BuildAddress (sockaddr_in *address, char *name)
|
|||
|
||||
if (!isnamed)
|
||||
{
|
||||
address->sin_addr.s_addr = inet_addr (name);
|
||||
Printf ("Node number %d, address %s\n", doomcom.numnodes, name);
|
||||
address->sin_addr.s_addr = inet_addr (target);
|
||||
Printf ("Node number %d, address %s\n", doomcom.numnodes, target.GetChars());
|
||||
}
|
||||
else
|
||||
{
|
||||
hostentry = gethostbyname (name);
|
||||
hostentry = gethostbyname (target);
|
||||
if (!hostentry)
|
||||
I_FatalError ("gethostbyname: couldn't find %s\n%s", name, neterror());
|
||||
I_FatalError ("gethostbyname: couldn't find %s\n%s", target.GetChars(), neterror());
|
||||
address->sin_addr.s_addr = *(int *)hostentry->h_addr_list[0];
|
||||
Printf ("Node number %d, hostname %s\n",
|
||||
doomcom.numnodes, hostentry->h_name);
|
||||
}
|
||||
|
||||
if (portpart)
|
||||
*portpart = ':';
|
||||
}
|
||||
|
||||
void CloseNetwork (void)
|
||||
|
@ -910,7 +909,7 @@ static bool NodesOnSameNetwork()
|
|||
bool I_InitNetwork (void)
|
||||
{
|
||||
int i;
|
||||
char *v;
|
||||
const char *v;
|
||||
|
||||
memset (&doomcom, 0, sizeof(doomcom));
|
||||
|
||||
|
|
36
src/info.cpp
36
src/info.cpp
|
@ -460,18 +460,11 @@ PClassActor *PClassActor::GetReplacee(bool lookskill)
|
|||
|
||||
void PClassActor::SetDamageFactor(FName type, fixed_t factor)
|
||||
{
|
||||
if (factor != FRACUNIT)
|
||||
if (DamageFactors == NULL)
|
||||
{
|
||||
if (DamageFactors == NULL)
|
||||
{
|
||||
DamageFactors = new DmgFactors;
|
||||
}
|
||||
DamageFactors->Insert(type, factor);
|
||||
}
|
||||
else if (DamageFactors != NULL)
|
||||
{
|
||||
DamageFactors->Remove(type);
|
||||
DamageFactors = new DmgFactors;
|
||||
}
|
||||
DamageFactors->Insert(type, factor);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -488,7 +481,7 @@ void PClassActor::SetPainChance(FName type, int chance)
|
|||
{
|
||||
PainChances = new PainChanceList;
|
||||
}
|
||||
PainChances->Insert(type, MIN(chance, 255));
|
||||
PainChances->Insert(type, MIN(chance, 256));
|
||||
}
|
||||
else if (PainChances != NULL)
|
||||
{
|
||||
|
@ -501,6 +494,25 @@ void PClassActor::SetPainChance(FName type, int chance)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void PClassActor::SetColorSet(int index, const FPlayerColorSet *set)
|
||||
{
|
||||
if (set != NULL)
|
||||
{
|
||||
if (ColorSets == NULL) ColorSets = new FPlayerColorSetMap;
|
||||
ColorSets->Insert(index, *set);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ColorSets != NULL)
|
||||
ColorSets->Remove(index);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FDoomEdMap DoomEdMap;
|
||||
|
||||
FDoomEdMap::FDoomEdEntry *FDoomEdMap::DoomEdHash[DOOMED_HASHSIZE];
|
||||
|
@ -678,4 +690,4 @@ CCMD (summonmbf)
|
|||
CCMD (summonfoe)
|
||||
{
|
||||
SummonActor (DEM_SUMMONFOE, DEM_SUMMONFOE2, argv);
|
||||
}
|
||||
}
|
17
src/info.h
17
src/info.h
|
@ -123,8 +123,21 @@ FArchive &operator<< (FArchive &arc, FState *&state);
|
|||
|
||||
#include "gametype.h"
|
||||
|
||||
// Standard pre-defined skin colors
|
||||
struct FPlayerColorSet
|
||||
{
|
||||
FName Name; // Name of this color
|
||||
|
||||
int Lump; // Lump to read the translation from, otherwise use next 2 fields
|
||||
BYTE FirstColor, LastColor; // Describes the range of colors to use for the translation
|
||||
|
||||
BYTE RepresentativeColor; // A palette entry representative of this translation,
|
||||
// for map arrows and status bar backgrounds and such
|
||||
};
|
||||
|
||||
typedef TMap<FName, fixed_t> DmgFactors;
|
||||
typedef TMap<FName, BYTE> PainChanceList;
|
||||
typedef TMap<FName, int> PainChanceList;
|
||||
typedef TMap<int, FPlayerColorSet> FPlayerColorSetMap;
|
||||
class DDropItem;
|
||||
|
||||
class PClassActor : public PClass
|
||||
|
@ -145,6 +158,7 @@ public:
|
|||
void RegisterIDs();
|
||||
void SetDamageFactor(FName type, fixed_t factor);
|
||||
void SetPainChance(FName type, int chance);
|
||||
void SetColorSet(int index, const FPlayerColorSet *set);
|
||||
size_t PropagateMark();
|
||||
void InitializeNativeDefaults();
|
||||
|
||||
|
@ -168,6 +182,7 @@ public:
|
|||
FStateLabels *StateList;
|
||||
DmgFactors *DamageFactors;
|
||||
PainChanceList *PainChances;
|
||||
FPlayerColorSetMap *ColorSets;
|
||||
FString Obituary; // Player was killed by this actor
|
||||
FString HitObituary; // Player was killed by this actor in melee
|
||||
fixed_t DeathHeight; // Height on normal death
|
||||
|
|
431
src/m_argv.cpp
431
src/m_argv.cpp
|
@ -38,161 +38,348 @@
|
|||
|
||||
IMPLEMENT_CLASS (DArgs)
|
||||
|
||||
DArgs::DArgs ()
|
||||
//===========================================================================
|
||||
//
|
||||
// DArgs Default Constructor
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
DArgs::DArgs()
|
||||
{
|
||||
m_ArgC = 0;
|
||||
m_ArgV = NULL;
|
||||
}
|
||||
|
||||
DArgs::DArgs (int argc, char **argv)
|
||||
//===========================================================================
|
||||
//
|
||||
// DArgs Copy Constructor
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
DArgs::DArgs(const DArgs &other)
|
||||
{
|
||||
CopyArgs (argc, argv);
|
||||
Argv = other.Argv;
|
||||
}
|
||||
|
||||
DArgs::DArgs (const DArgs &other)
|
||||
//===========================================================================
|
||||
//
|
||||
// DArgs Argv Constructor
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
DArgs::DArgs(int argc, char **argv)
|
||||
{
|
||||
CopyArgs (other.m_ArgC, other.m_ArgV);
|
||||
SetArgs(argc, argv);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// DArgs String Argv Constructor
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
DArgs::DArgs(int argc, FString *argv)
|
||||
{
|
||||
AppendArgs(argc, argv);
|
||||
}
|
||||
|
||||
|
||||
DArgs::~DArgs ()
|
||||
{
|
||||
FlushArgs ();
|
||||
}
|
||||
|
||||
DArgs &DArgs::operator= (const DArgs &other)
|
||||
//===========================================================================
|
||||
//
|
||||
// DArgs Copy Operator
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
DArgs &DArgs::operator=(const DArgs &other)
|
||||
{
|
||||
FlushArgs ();
|
||||
CopyArgs (other.m_ArgC, other.m_ArgV);
|
||||
Argv = other.Argv;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void DArgs::SetArgs (int argc, char **argv)
|
||||
{
|
||||
FlushArgs ();
|
||||
CopyArgs (argc, argv);
|
||||
}
|
||||
|
||||
void DArgs::CopyArgs (int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
m_ArgC = argc;
|
||||
m_ArgV = new char *[argc];
|
||||
for (i = 0; i < argc; i++)
|
||||
m_ArgV[i] = copystring (argv[i]);
|
||||
}
|
||||
|
||||
void DArgs::FlushArgs ()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < m_ArgC; i++)
|
||||
delete[] m_ArgV[i];
|
||||
delete[] m_ArgV;
|
||||
m_ArgC = 0;
|
||||
m_ArgV = NULL;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// DArgs :: SetArgs
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void DArgs::SetArgs(int argc, char **argv)
|
||||
{
|
||||
Argv.Resize(argc);
|
||||
for (int i = 0; i < argc; ++i)
|
||||
{
|
||||
Argv[i] = argv[i];
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// DArgs :: FlushArgs
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void DArgs::FlushArgs()
|
||||
{
|
||||
Argv.Clear();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// DArgs :: CheckParm
|
||||
//
|
||||
// CheckParm
|
||||
// Checks for the given parameter in the program's command line arguments.
|
||||
// Returns the argument number (1 to argc-1) or 0 if not present
|
||||
//
|
||||
int DArgs::CheckParm (const char *check, int start) const
|
||||
{
|
||||
for (int i = start; i < m_ArgC; ++i)
|
||||
if (!stricmp (check, m_ArgV[i]))
|
||||
return i;
|
||||
//===========================================================================
|
||||
|
||||
int DArgs::CheckParm(const char *check, int start) const
|
||||
{
|
||||
for (unsigned i = start; i < Argv.Size(); ++i)
|
||||
{
|
||||
if (0 == stricmp(check, Argv[i]))
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *DArgs::CheckValue (const char *check) const
|
||||
{
|
||||
int i = CheckParm (check);
|
||||
//===========================================================================
|
||||
//
|
||||
// DArgs :: CheckParmList
|
||||
//
|
||||
// Returns the number of arguments after the parameter (if found) and also
|
||||
// returns a pointer to the first argument.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
if (i > 0 && i < m_ArgC - 1)
|
||||
return m_ArgV[i+1][0] != '+' && m_ArgV[i+1][0] != '-' ? m_ArgV[i+1] : NULL;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *DArgs::GetArg (int arg) const
|
||||
int DArgs::CheckParmList(const char *check, FString **strings, int start) const
|
||||
{
|
||||
if (arg >= 0 && arg < m_ArgC)
|
||||
return m_ArgV[arg];
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
unsigned int i, parmat = CheckParm(check, start);
|
||||
|
||||
char **DArgs::GetArgList (int arg) const
|
||||
{
|
||||
if (arg >= 0 && arg < m_ArgC)
|
||||
return &m_ArgV[arg];
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int DArgs::NumArgs () const
|
||||
{
|
||||
return m_ArgC;
|
||||
}
|
||||
|
||||
void DArgs::AppendArg (const char *arg)
|
||||
{
|
||||
char **temp = new char *[m_ArgC + 1];
|
||||
if (m_ArgV)
|
||||
if (parmat == 0)
|
||||
{
|
||||
memcpy (temp, m_ArgV, sizeof(*m_ArgV) * m_ArgC);
|
||||
delete[] m_ArgV;
|
||||
}
|
||||
temp[m_ArgC] = copystring (arg);
|
||||
m_ArgV = temp;
|
||||
m_ArgC++;
|
||||
}
|
||||
|
||||
DArgs *DArgs::GatherFiles (const char *param, const char *extension, bool acceptNoExt) const
|
||||
{
|
||||
DArgs *out = new DArgs;
|
||||
int i;
|
||||
size_t extlen = strlen (extension);
|
||||
|
||||
if (extlen > 0)
|
||||
{
|
||||
for (i = 1; i < m_ArgC && *m_ArgV[i] != '-' && *m_ArgV[i] != '+'; i++)
|
||||
if (strings != NULL)
|
||||
{
|
||||
size_t len = strlen (m_ArgV[i]);
|
||||
if (len >= extlen && stricmp (m_ArgV[i] + len - extlen, extension) == 0)
|
||||
out->AppendArg (m_ArgV[i]);
|
||||
else if (acceptNoExt)
|
||||
{
|
||||
const char *src = m_ArgV[i] + len - 1;
|
||||
|
||||
while (src != m_ArgV[i] && *src != '/'
|
||||
#ifdef _WIN32
|
||||
&& *src != '\\'
|
||||
#endif
|
||||
)
|
||||
{
|
||||
if (*src == '.')
|
||||
goto morefor; // it has an extension
|
||||
src--;
|
||||
}
|
||||
out->AppendArg (m_ArgV[i]);
|
||||
morefor:
|
||||
;
|
||||
}
|
||||
*strings = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
for (i = ++parmat; i < Argv.Size(); ++i)
|
||||
{
|
||||
if (Argv[i][0] == '-' || Argv[i][1] == '+')
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (param != NULL)
|
||||
if (strings != NULL)
|
||||
{
|
||||
i = 1;
|
||||
while (0 != (i = CheckParm (param, i)))
|
||||
*strings = &Argv[parmat];
|
||||
}
|
||||
return i - parmat;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// DArgs :: CheckValue
|
||||
//
|
||||
// Like CheckParm, but it also checks that the parameter has a value after
|
||||
// it and returns that or NULL if not present.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
const char *DArgs::CheckValue(const char *check) const
|
||||
{
|
||||
int i = CheckParm(check);
|
||||
|
||||
if (i > 0 && i < (int)Argv.Size() - 1)
|
||||
{
|
||||
i++;
|
||||
return Argv[i][0] != '+' && Argv[i][0] != '-' ? Argv[i].GetChars() : NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// DArgs :: TakeValue
|
||||
//
|
||||
// Like CheckValue, except it also removes the parameter and its argument
|
||||
// (if present) from argv.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
FString DArgs::TakeValue(const char *check)
|
||||
{
|
||||
int i = CheckParm(check);
|
||||
FString out;
|
||||
|
||||
if (i > 0 && i < (int)Argv.Size())
|
||||
{
|
||||
if (i < (int)Argv.Size() - 1 && Argv[i+1][0] != '+' && Argv[i+1][0] != '-')
|
||||
{
|
||||
for (++i; i < m_ArgC && *m_ArgV[i] != '-' && *m_ArgV[i] != '+'; ++i)
|
||||
out->AppendArg (m_ArgV[i]);
|
||||
out = Argv[i+1];
|
||||
Argv.Delete(i, 2); // Delete the parm and its value.
|
||||
}
|
||||
else
|
||||
{
|
||||
Argv.Delete(i); // Just delete the parm, since it has no value.
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// DArgs :: GetArg
|
||||
//
|
||||
// Gets the argument at a particular position.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
const char *DArgs::GetArg(int arg) const
|
||||
{
|
||||
return ((unsigned)arg < Argv.Size()) ? Argv[arg].GetChars() : NULL;
|
||||
return Argv[arg];
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// DArgs :: GetArgList
|
||||
//
|
||||
// Returns a pointer to the FString at a particular position.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
FString *DArgs::GetArgList(int arg) const
|
||||
{
|
||||
return ((unsigned)arg < Argv.Size()) ? &Argv[arg] : NULL;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// DArgs :: NumArgs
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
int DArgs::NumArgs() const
|
||||
{
|
||||
return (int)Argv.Size();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// DArgs :: AppendArg
|
||||
//
|
||||
// Adds another argument to argv. Invalidates any previous results from
|
||||
// GetArgList().
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void DArgs::AppendArg(FString arg)
|
||||
{
|
||||
Argv.Push(arg);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// DArgs :: AppendArgs
|
||||
//
|
||||
// Adds an array of FStrings to argv.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void DArgs::AppendArgs(int argc, const FString *argv)
|
||||
{
|
||||
if (argv != NULL && argc > 0)
|
||||
{
|
||||
Argv.Grow(argc);
|
||||
for (int i = 0; i < argc; ++i)
|
||||
{
|
||||
Argv.Push(argv[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// DArgs :: CollectFiles
|
||||
//
|
||||
// Takes all arguments after any instance of -param and any arguments before
|
||||
// all switches that end in .extension and combines them into a single
|
||||
// -switch block at the end of the arguments. If extension is NULL, then
|
||||
// every parameter before the first switch is added after this -param.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void DArgs::CollectFiles(const char *param, const char *extension)
|
||||
{
|
||||
TArray<FString> work;
|
||||
DArgs *out = new DArgs;
|
||||
unsigned int i;
|
||||
size_t extlen = extension == NULL ? 0 : strlen(extension);
|
||||
|
||||
// Step 1: Find suitable arguments before the first switch.
|
||||
i = 1;
|
||||
while (i < Argv.Size() && Argv[i][0] != '-' && Argv[i][0] != '+')
|
||||
{
|
||||
bool useit;
|
||||
|
||||
if (extlen > 0)
|
||||
{ // Argument's extension must match.
|
||||
size_t len = Argv[i].Len();
|
||||
useit = (len >= extlen && stricmp(&Argv[i][len - extlen], extension) == 0);
|
||||
}
|
||||
else
|
||||
{ // Anything will do so long as it's before the first switch.
|
||||
useit = true;
|
||||
}
|
||||
if (useit)
|
||||
{
|
||||
work.Push(Argv[i]);
|
||||
Argv.Delete(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 2: Find each occurence of -param and add its arguments to work.
|
||||
while ((i = CheckParm(param, i)) > 0)
|
||||
{
|
||||
Argv.Delete(i);
|
||||
while (i < Argv.Size() && Argv[i][0] != '-' && Argv[i][0] != '+')
|
||||
{
|
||||
work.Push(Argv[i]);
|
||||
Argv.Delete(i);
|
||||
}
|
||||
}
|
||||
|
||||
// Step 3: Add work back to Argv, as long as it's non-empty.
|
||||
if (work.Size() > 0)
|
||||
{
|
||||
Argv.Push(param);
|
||||
AppendArgs(work.Size(), &work[0]);
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// DArgs :: GatherFiles
|
||||
//
|
||||
// Returns all the arguments after the first instance of -param. If you want
|
||||
// to combine more than one or get switchless stuff included, you need to
|
||||
// call CollectFiles first.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
DArgs *DArgs::GatherFiles(const char *param) const
|
||||
{
|
||||
FString *files;
|
||||
int filecount;
|
||||
|
||||
filecount = CheckParmList(param, &files);
|
||||
return new DArgs(filecount, files);
|
||||
}
|
||||
|
|
44
src/m_argv.h
44
src/m_argv.h
|
@ -35,40 +35,40 @@
|
|||
#define __M_ARGV_H__
|
||||
|
||||
#include "dobject.h"
|
||||
#include "zstring.h"
|
||||
|
||||
//
|
||||
// MISC
|
||||
//
|
||||
class DArgs : public DObject
|
||||
{
|
||||
DECLARE_CLASS (DArgs, DObject)
|
||||
DECLARE_CLASS(DArgs, DObject)
|
||||
public:
|
||||
DArgs ();
|
||||
DArgs (const DArgs &args);
|
||||
DArgs (int argc, char **argv);
|
||||
~DArgs ();
|
||||
DArgs();
|
||||
DArgs(const DArgs &args);
|
||||
DArgs(int argc, char **argv);
|
||||
DArgs(int argc, FString *argv);
|
||||
|
||||
DArgs &operator= (const DArgs &other);
|
||||
DArgs &operator=(const DArgs &other);
|
||||
|
||||
void AppendArg (const char *arg);
|
||||
void SetArgs (int argc, char **argv);
|
||||
DArgs *GatherFiles (const char *param, const char *extension, bool acceptNoExt) const;
|
||||
void SetArg (int argnum, const char *arg);
|
||||
void AppendArg(FString arg);
|
||||
void AppendArgs(int argc, const FString *argv);
|
||||
void SetArgs(int argc, char **argv);
|
||||
void CollectFiles(const char *param, const char *extension);
|
||||
DArgs *GatherFiles(const char *param) const;
|
||||
void SetArg(int argnum, const char *arg);
|
||||
|
||||
// Returns the position of the given parameter
|
||||
// in the arg list (0 if not found).
|
||||
int CheckParm (const char *check, int start=1) const;
|
||||
char *CheckValue (const char *check) const;
|
||||
char *GetArg (int arg) const;
|
||||
char **GetArgList (int arg) const;
|
||||
int NumArgs () const;
|
||||
void FlushArgs ();
|
||||
int CheckParm(const char *check, int start=1) const; // Returns the position of the given parameter in the arg list (0 if not found).
|
||||
int CheckParmList(const char *check, FString **strings, int start=1) const;
|
||||
const char *CheckValue(const char *check) const;
|
||||
const char *GetArg(int arg) const;
|
||||
FString *GetArgList(int arg) const;
|
||||
FString TakeValue(const char *check);
|
||||
int NumArgs() const;
|
||||
void FlushArgs();
|
||||
|
||||
private:
|
||||
int m_ArgC;
|
||||
char **m_ArgV;
|
||||
|
||||
void CopyArgs (int argc, char **argv);
|
||||
TArray<FString> Argv;
|
||||
};
|
||||
|
||||
extern DArgs *Args;
|
||||
|
|
|
@ -52,17 +52,17 @@
|
|||
|
||||
void cht_DoCheat (player_t *player, int cheat)
|
||||
{
|
||||
static PClass *const *BeholdPowers[9] =
|
||||
static const char * const BeholdPowers[9] =
|
||||
{
|
||||
&RUNTIME_CLASS_CASTLESS(APowerInvulnerable),
|
||||
&RUNTIME_CLASS_CASTLESS(APowerStrength),
|
||||
&RUNTIME_CLASS_CASTLESS(APowerInvisibility),
|
||||
&RUNTIME_CLASS_CASTLESS(APowerIronFeet),
|
||||
NULL, // MapRevealer
|
||||
&RUNTIME_CLASS_CASTLESS(APowerLightAmp),
|
||||
&RUNTIME_CLASS_CASTLESS(APowerShadow),
|
||||
&RUNTIME_CLASS_CASTLESS(APowerMask),
|
||||
&RUNTIME_CLASS_CASTLESS(APowerTargeter)
|
||||
"PowerInvulnerable",
|
||||
"PowerStrength",
|
||||
"PowerInvisibility",
|
||||
"PowerIronFeet",
|
||||
"MapRevealer",
|
||||
"PowerLightAmp",
|
||||
"PowerShadow",
|
||||
"PowerMask",
|
||||
"PowerTargeter",
|
||||
};
|
||||
PClassActor *type;
|
||||
AInventory *item;
|
||||
|
@ -245,12 +245,12 @@ void cht_DoCheat (player_t *player, int cheat)
|
|||
}
|
||||
else if (player->mo != NULL && player->health >= 0)
|
||||
{
|
||||
item = player->mo->FindInventory(static_cast<PClassActor *>(*BeholdPowers[i]));
|
||||
item = player->mo->FindInventory(PClass::FindActor(BeholdPowers[i]));
|
||||
if (item == NULL)
|
||||
{
|
||||
if (i != 0)
|
||||
{
|
||||
player->mo->GiveInventoryType(static_cast<PClassActor *>(*BeholdPowers[i]));
|
||||
cht_Give(player, BeholdPowers[i]);
|
||||
if (cheat == CHT_BEHOLDS)
|
||||
{
|
||||
P_GiveBody (player->mo, -100);
|
||||
|
@ -259,7 +259,7 @@ void cht_DoCheat (player_t *player, int cheat)
|
|||
else
|
||||
{
|
||||
// Let's give the item here so that the power doesn't need colormap information.
|
||||
player->mo->GiveInventoryType(PClass::FindActor("InvulnerabilitySphere"));
|
||||
cht_Give(player, "InvulnerabilitySphere");
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -316,7 +316,10 @@ void cht_DoCheat (player_t *player, int cheat)
|
|||
player->mo->special1 = 0; // required for the Hexen fighter's fist attack.
|
||||
// This gets set by AActor::Die as flag for the wimpy death and must be reset here.
|
||||
player->mo->SetState (player->mo->SpawnState);
|
||||
player->mo->Translation = TRANSLATION(TRANSLATION_Players, BYTE(player-players));
|
||||
if (!(player->mo->flags2 & MF2_DONTTRANSLATE))
|
||||
{
|
||||
player->mo->Translation = TRANSLATION(TRANSLATION_Players, BYTE(player-players));
|
||||
}
|
||||
player->mo->DamageType = NAME_None;
|
||||
// player->mo->GiveDefaultInventory();
|
||||
if (player->ReadyWeapon != NULL)
|
||||
|
|
139
src/m_menu.cpp
139
src/m_menu.cpp
|
@ -118,7 +118,7 @@ protected:
|
|||
|
||||
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||||
|
||||
void R_GetPlayerTranslation (int color, FPlayerSkin *skin, FRemapTable *table);
|
||||
void R_GetPlayerTranslation (int color, const FPlayerColorSet *colorset, FPlayerSkin *skin, FRemapTable *table);
|
||||
|
||||
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
||||
|
||||
|
@ -188,6 +188,7 @@ static void M_EditPlayerName (int choice);
|
|||
static void M_ChangePlayerTeam (int choice);
|
||||
static void M_PlayerNameChanged (FSaveGameNode *dummy);
|
||||
static void M_PlayerNameNotChanged ();
|
||||
static void M_ChangeColorSet (int choice);
|
||||
static void M_SlidePlayerRed (int choice);
|
||||
static void M_SlidePlayerGreen (int choice);
|
||||
static void M_SlidePlayerBlue (int choice);
|
||||
|
@ -246,17 +247,10 @@ static char savegamestring[SAVESTRINGSIZE];
|
|||
static FString EndString;
|
||||
|
||||
static short itemOn; // menu item skull is on
|
||||
static short whichSkull; // which skull to draw
|
||||
static int MenuTime;
|
||||
static int InfoType;
|
||||
static int InfoTic;
|
||||
|
||||
static const char skullName[2][9] = {"M_SKULL1", "M_SKULL2"}; // graphic name of skulls
|
||||
static const char cursName[8][8] = // graphic names of Strife menu selector
|
||||
{
|
||||
"M_CURS1", "M_CURS2", "M_CURS3", "M_CURS4", "M_CURS5", "M_CURS6", "M_CURS7", "M_CURS8"
|
||||
};
|
||||
|
||||
static oldmenu_t *currentMenu; // current menudef
|
||||
static oldmenu_t *TopLevelMenu; // The main menu everything hangs off of
|
||||
|
||||
|
@ -269,6 +263,7 @@ static int PlayerSkin;
|
|||
static FState *PlayerState;
|
||||
static int PlayerTics;
|
||||
static int PlayerRotation;
|
||||
static TArray<int> PlayerColorSets;
|
||||
|
||||
static FTexture *SavePic;
|
||||
static FBrokenLines *SaveComment;
|
||||
|
@ -536,15 +531,24 @@ static oldmenuitem_t PlayerSetupMenu[] =
|
|||
{
|
||||
{ 1,0,'n',NULL,M_EditPlayerName, CR_UNTRANSLATED},
|
||||
{ 2,0,'t',NULL,M_ChangePlayerTeam, CR_UNTRANSLATED},
|
||||
{ 2,0,'c',NULL,M_ChangeColorSet, CR_UNTRANSLATED},
|
||||
{ 2,0,'r',NULL,M_SlidePlayerRed, CR_UNTRANSLATED},
|
||||
{ 2,0,'g',NULL,M_SlidePlayerGreen, CR_UNTRANSLATED},
|
||||
{ 2,0,'b',NULL,M_SlidePlayerBlue, CR_UNTRANSLATED},
|
||||
{ 2,0,'c',NULL,M_ChangeClass, CR_UNTRANSLATED},
|
||||
{ 2,0,'t',NULL,M_ChangeClass, CR_UNTRANSLATED},
|
||||
{ 2,0,'s',NULL,M_ChangeSkin, CR_UNTRANSLATED},
|
||||
{ 2,0,'e',NULL,M_ChangeGender, CR_UNTRANSLATED},
|
||||
{ 2,0,'a',NULL,M_ChangeAutoAim, CR_UNTRANSLATED}
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
// These must be changed if the menu definition is altered
|
||||
PSM_RED = 3,
|
||||
PSM_GREEN = 4,
|
||||
PSM_BLUE = 5,
|
||||
};
|
||||
|
||||
static oldmenu_t PSetupDef =
|
||||
{
|
||||
countof(PlayerSetupMenu),
|
||||
|
@ -2088,13 +2092,16 @@ void M_PlayerSetup (void)
|
|||
PlayerClass = &PlayerClasses[players[consoleplayer].CurrentPlayerClass];
|
||||
}
|
||||
PlayerSkin = players[consoleplayer].userinfo.skin;
|
||||
R_GetPlayerTranslation (players[consoleplayer].userinfo.color, &skins[PlayerSkin], translationtables[TRANSLATION_Players][MAXPLAYERS]);
|
||||
R_GetPlayerTranslation (players[consoleplayer].userinfo.color,
|
||||
P_GetPlayerColorSet(PlayerClass->Type->TypeName, players[consoleplayer].userinfo.colorset),
|
||||
&skins[PlayerSkin], translationtables[TRANSLATION_Players][MAXPLAYERS]);
|
||||
PlayerState = GetDefaultByType (PlayerClass->Type)->SeeState;
|
||||
PlayerTics = PlayerState->GetTics();
|
||||
if (FireTexture == NULL)
|
||||
{
|
||||
FireTexture = new FBackdropTexture;
|
||||
}
|
||||
P_EnumPlayerColorSets(PlayerClass->Type->TypeName, &PlayerColorSets);
|
||||
}
|
||||
|
||||
static void M_PlayerSetupTicker (void)
|
||||
|
@ -2112,6 +2119,7 @@ static void M_PlayerSetupTicker (void)
|
|||
item = (MenuTime>>2) % (ClassMenuDef.numitems-1);
|
||||
|
||||
PlayerClass = &PlayerClasses[D_PlayerClassToInt (ClassMenuItems[item].name)];
|
||||
P_EnumPlayerColorSets(PlayerClass->Type->TypeName, &PlayerColorSets);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2125,6 +2133,7 @@ static void M_PlayerSetupTicker (void)
|
|||
|
||||
PlayerSkin = R_FindSkin (skins[PlayerSkin].name, int(PlayerClass - &PlayerClasses[0]));
|
||||
R_GetPlayerTranslation (players[consoleplayer].userinfo.color,
|
||||
P_GetPlayerColorSet(PlayerClass->Type->TypeName, players[consoleplayer].userinfo.colorset),
|
||||
&skins[PlayerSkin], translationtables[TRANSLATION_Players][MAXPLAYERS]);
|
||||
}
|
||||
|
||||
|
@ -2280,19 +2289,27 @@ static void M_PlayerSetupDrawer ()
|
|||
DTA_Clean, true, TAG_DONE);
|
||||
}
|
||||
|
||||
// Draw player color sliders
|
||||
//V_DrawTextCleanMove (CR_GREY, PSetupDef.x, PSetupDef.y + LINEHEIGHT, "Color");
|
||||
// Draw player color selection and sliders
|
||||
FPlayerColorSet *colorset = P_GetPlayerColorSet(PlayerClass->Type->TypeName, players[consoleplayer].userinfo.colorset);
|
||||
x = SmallFont->StringWidth("Color") + 8 + PSetupDef.x;
|
||||
screen->DrawText(SmallFont, label, PSetupDef.x, PSetupDef.y + LINEHEIGHT*2+yo, "Color", DTA_Clean, true, TAG_DONE);
|
||||
screen->DrawText(SmallFont, value, x, PSetupDef.y + LINEHEIGHT*2+yo,
|
||||
colorset != NULL ? colorset->Name.GetChars() : "Custom", DTA_Clean, true, TAG_DONE);
|
||||
|
||||
screen->DrawText (SmallFont, label, PSetupDef.x, PSetupDef.y + LINEHEIGHT*2+yo, "Red", DTA_Clean, true, TAG_DONE);
|
||||
screen->DrawText (SmallFont, label, PSetupDef.x, PSetupDef.y + LINEHEIGHT*3+yo, "Green", DTA_Clean, true, TAG_DONE);
|
||||
screen->DrawText (SmallFont, label, PSetupDef.x, PSetupDef.y + LINEHEIGHT*4+yo, "Blue", DTA_Clean, true, TAG_DONE);
|
||||
// Only show the sliders for a custom color set.
|
||||
if (colorset == NULL)
|
||||
{
|
||||
screen->DrawText (SmallFont, label, PSetupDef.x, PSetupDef.y + int(LINEHEIGHT*2.875)+yo, "Red", DTA_Clean, true, TAG_DONE);
|
||||
screen->DrawText (SmallFont, label, PSetupDef.x, PSetupDef.y + int(LINEHEIGHT*3.5)+yo, "Green", DTA_Clean, true, TAG_DONE);
|
||||
screen->DrawText (SmallFont, label, PSetupDef.x, PSetupDef.y + int(LINEHEIGHT*4.125)+yo, "Blue", DTA_Clean, true, TAG_DONE);
|
||||
|
||||
x = SmallFont->StringWidth ("Green") + 8 + PSetupDef.x;
|
||||
color = players[consoleplayer].userinfo.color;
|
||||
x = SmallFont->StringWidth ("Green") + 8 + PSetupDef.x;
|
||||
color = players[consoleplayer].userinfo.color;
|
||||
|
||||
M_DrawPlayerSlider (x, PSetupDef.y + LINEHEIGHT*2+yo, RPART(color));
|
||||
M_DrawPlayerSlider (x, PSetupDef.y + LINEHEIGHT*3+yo, GPART(color));
|
||||
M_DrawPlayerSlider (x, PSetupDef.y + LINEHEIGHT*4+yo, BPART(color));
|
||||
M_DrawPlayerSlider (x, PSetupDef.y + int(LINEHEIGHT*2.875)+yo, RPART(color));
|
||||
M_DrawPlayerSlider (x, PSetupDef.y + int(LINEHEIGHT*3.5)+yo, GPART(color));
|
||||
M_DrawPlayerSlider (x, PSetupDef.y + int(LINEHEIGHT*4.125)+yo, BPART(color));
|
||||
}
|
||||
|
||||
// [GRB] Draw class setting
|
||||
int pclass = players[consoleplayer].userinfo.PlayerClass;
|
||||
|
@ -2586,7 +2603,9 @@ static void M_ChangeSkin (int choice)
|
|||
PlayerSkin = (PlayerSkin < (int)numskins - 1) ? PlayerSkin + 1 : 0;
|
||||
} while (!PlayerClass->CheckSkin (PlayerSkin));
|
||||
|
||||
R_GetPlayerTranslation (players[consoleplayer].userinfo.color, &skins[PlayerSkin], translationtables[TRANSLATION_Players][MAXPLAYERS]);
|
||||
R_GetPlayerTranslation (players[consoleplayer].userinfo.color,
|
||||
P_GetPlayerColorSet(PlayerClass->Type->TypeName, players[consoleplayer].userinfo.colorset),
|
||||
&skins[PlayerSkin], translationtables[TRANSLATION_Players][MAXPLAYERS]);
|
||||
|
||||
cvar_set ("skin", skins[PlayerSkin].name);
|
||||
}
|
||||
|
@ -2707,13 +2726,55 @@ static void M_ChangePlayerTeam (int choice)
|
|||
}
|
||||
}
|
||||
|
||||
static void M_ChangeColorSet (int choice)
|
||||
{
|
||||
int curpos = (int)PlayerColorSets.Size();
|
||||
int mycolorset = players[consoleplayer].userinfo.colorset;
|
||||
while (--curpos >= 0)
|
||||
{
|
||||
if (PlayerColorSets[curpos] == mycolorset)
|
||||
break;
|
||||
}
|
||||
if (choice == 0)
|
||||
{
|
||||
curpos--;
|
||||
}
|
||||
else
|
||||
{
|
||||
curpos++;
|
||||
}
|
||||
if (curpos < -1)
|
||||
{
|
||||
curpos = (int)PlayerColorSets.Size() - 1;
|
||||
}
|
||||
else if (curpos >= (int)PlayerColorSets.Size())
|
||||
{
|
||||
curpos = -1;
|
||||
}
|
||||
mycolorset = (curpos >= 0) ? PlayerColorSets[curpos] : -1;
|
||||
|
||||
// disable the sliders if a valid colorset is selected
|
||||
PlayerSetupMenu[PSM_RED].status =
|
||||
PlayerSetupMenu[PSM_GREEN].status =
|
||||
PlayerSetupMenu[PSM_BLUE].status = (mycolorset == -1? 2:-1);
|
||||
|
||||
char command[24];
|
||||
mysnprintf(command, countof(command), "colorset %d", mycolorset);
|
||||
C_DoCommand(command);
|
||||
R_GetPlayerTranslation(players[consoleplayer].userinfo.color,
|
||||
P_GetPlayerColorSet(PlayerClass->Type->TypeName, mycolorset),
|
||||
&skins[PlayerSkin], translationtables[TRANSLATION_Players][MAXPLAYERS]);
|
||||
}
|
||||
|
||||
static void SendNewColor (int red, int green, int blue)
|
||||
{
|
||||
char command[24];
|
||||
|
||||
mysnprintf (command, countof(command), "color \"%02x %02x %02x\"", red, green, blue);
|
||||
C_DoCommand (command);
|
||||
R_GetPlayerTranslation (MAKERGB (red, green, blue), &skins[PlayerSkin], translationtables[TRANSLATION_Players][MAXPLAYERS]);
|
||||
R_GetPlayerTranslation(MAKERGB (red, green, blue),
|
||||
P_GetPlayerColorSet(PlayerClass->Type->TypeName, players[consoleplayer].userinfo.colorset),
|
||||
&skins[PlayerSkin], translationtables[TRANSLATION_Players][MAXPLAYERS]);
|
||||
}
|
||||
|
||||
static void M_SlidePlayerRed (int choice)
|
||||
|
@ -3645,27 +3706,50 @@ void M_Drawer ()
|
|||
// [RH] Use options menu cursor for the player setup menu.
|
||||
if (skullAnimCounter < 6)
|
||||
{
|
||||
double item;
|
||||
// The green slider is halfway between lines, and the red and
|
||||
// blue ones are offset slightly to make room for it.
|
||||
if (itemOn < 3)
|
||||
{
|
||||
item = itemOn;
|
||||
}
|
||||
else if (itemOn > 5)
|
||||
{
|
||||
item = itemOn - 1;
|
||||
}
|
||||
else if (itemOn == 3)
|
||||
{
|
||||
item = 2.875;
|
||||
}
|
||||
else if (itemOn == 4)
|
||||
{
|
||||
item = 3.5;
|
||||
}
|
||||
else
|
||||
{
|
||||
item = 4.125;
|
||||
}
|
||||
screen->DrawText (ConFont, CR_RED, x - 16,
|
||||
currentMenu->y + itemOn*PLAYERSETUP_LINEHEIGHT +
|
||||
currentMenu->y + int(item*PLAYERSETUP_LINEHEIGHT) +
|
||||
(!(gameinfo.gametype & (GAME_DoomStrifeChex)) ? 6 : -1), "\xd",
|
||||
DTA_Clean, true, TAG_DONE);
|
||||
}
|
||||
}
|
||||
else if (gameinfo.gametype & GAME_DoomChex)
|
||||
{
|
||||
screen->DrawTexture (TexMan[skullName[whichSkull]],
|
||||
screen->DrawTexture (TexMan("M_SKULL1"),
|
||||
x + SKULLXOFF, currentMenu->y - 5 + itemOn*LINEHEIGHT,
|
||||
DTA_Clean, true, TAG_DONE);
|
||||
}
|
||||
else if (gameinfo.gametype == GAME_Strife)
|
||||
{
|
||||
screen->DrawTexture (TexMan[cursName[(MenuTime >> 2) & 7]],
|
||||
screen->DrawTexture (TexMan("M_CURS1"),
|
||||
x - 28, currentMenu->y - 5 + itemOn*LINEHEIGHT,
|
||||
DTA_Clean, true, TAG_DONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
screen->DrawTexture (TexMan[MenuTime & 16 ? "M_SLCTR1" : "M_SLCTR2"],
|
||||
screen->DrawTexture (TexMan("M_SLCTR1"),
|
||||
x + SELECTOR_XOFFSET,
|
||||
currentMenu->y + itemOn*LINEHEIGHT + SELECTOR_YOFFSET,
|
||||
DTA_Clean, true, TAG_DONE);
|
||||
|
@ -3859,7 +3943,6 @@ void M_Ticker (void)
|
|||
MenuTime++;
|
||||
if (--skullAnimCounter <= 0)
|
||||
{
|
||||
whichSkull ^= 1;
|
||||
skullAnimCounter = 8;
|
||||
}
|
||||
if (currentMenu == &PSetupDef || currentMenu == &ClassMenuDef)
|
||||
|
@ -3913,7 +3996,6 @@ void M_Init (void)
|
|||
menuactive = MENU_Off;
|
||||
InfoType = 0;
|
||||
itemOn = currentMenu->lastOn;
|
||||
whichSkull = 0;
|
||||
skullAnimCounter = 10;
|
||||
drawSkull = true;
|
||||
messageToPrint = 0;
|
||||
|
@ -4034,4 +4116,5 @@ static void PickPlayerClass ()
|
|||
}
|
||||
|
||||
PlayerClass = &PlayerClasses[pclass];
|
||||
P_EnumPlayerColorSets(PlayerClass->Type->TypeName, &PlayerColorSets);
|
||||
}
|
||||
|
|
|
@ -159,7 +159,6 @@ void M_FindResponseFile (void)
|
|||
char **argv;
|
||||
char *file;
|
||||
int argc;
|
||||
int argcinresp;
|
||||
FILE *handle;
|
||||
int size;
|
||||
long argsize;
|
||||
|
@ -183,23 +182,32 @@ void M_FindResponseFile (void)
|
|||
file[size] = 0;
|
||||
fclose (handle);
|
||||
|
||||
argsize = ParseCommandLine (file, &argcinresp, NULL);
|
||||
argc = argcinresp + Args->NumArgs() - 1;
|
||||
argsize = ParseCommandLine (file, &argc, NULL);
|
||||
argc = Args->NumArgs() - 1;
|
||||
|
||||
if (argc != 0)
|
||||
{
|
||||
argv = (char **)M_Malloc (argc*sizeof(char *) + argsize);
|
||||
argv[i] = (char *)argv + argc*sizeof(char *);
|
||||
ParseCommandLine (file, NULL, argv+i);
|
||||
argv[0] = (char *)argv + argc*sizeof(char *);
|
||||
ParseCommandLine (file, NULL, argv);
|
||||
|
||||
// Create a new argument vector
|
||||
DArgs *newargs = new DArgs;
|
||||
|
||||
// Copy parameters before response file.
|
||||
for (index = 0; index < i; ++index)
|
||||
argv[index] = Args->GetArg (index);
|
||||
newargs->AppendArg(Args->GetArg(index));
|
||||
|
||||
for (index = i + 1, i += argcinresp; index < Args->NumArgs (); ++index)
|
||||
argv[i++] = Args->GetArg (index);
|
||||
// Copy parameters from response file.
|
||||
for (index = 0; index < argc; ++i)
|
||||
newargs->AppendArg(argv[index]);
|
||||
|
||||
Args->Destroy();
|
||||
Args = new DArgs(i, argv);
|
||||
// Copy parameters after response file.
|
||||
for (index = i + 1, i = newargs->NumArgs(); index < Args->NumArgs(); ++index)
|
||||
newargs->AppendArg(Args->GetArg(index));
|
||||
|
||||
// Use the new argument vector as the global Args object.
|
||||
Args = newargs;
|
||||
}
|
||||
|
||||
delete[] file;
|
||||
|
|
|
@ -789,7 +789,7 @@ void FNodeBuilder::SplitSegs (DWORD set, node_t &node, DWORD splitseg, DWORD &ou
|
|||
newvert.y += fixed_t(frac * double(Vertices[seg->v2].y - newvert.y));
|
||||
vertnum = VertexMap->SelectVertexClose (newvert);
|
||||
|
||||
if (vertnum == seg->v1 || vertnum == seg->v2)
|
||||
if (vertnum == (unsigned int)seg->v1 || vertnum == (unsigned int)seg->v2)
|
||||
{
|
||||
Printf("SelectVertexClose selected endpoint of seg %u\n", set);
|
||||
}
|
||||
|
|
|
@ -3279,8 +3279,8 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args)
|
|||
|
||||
case ACSF_CheckActorClass:
|
||||
{
|
||||
AActor *a = args[0] == 0 ? (AActor *)activator : SingleActorFromTID(args[0], NULL);
|
||||
return a->GetClass()->TypeName == FName(FBehavior::StaticLookupString(args[1]));
|
||||
AActor *a = args[0] == 0 ? (AActor *)activator : SingleActorFromTID(args[0], NULL);
|
||||
return a == NULL ? false : a->GetClass()->TypeName == FName(FBehavior::StaticLookupString(args[1]));
|
||||
}
|
||||
|
||||
case ACSF_SoundSequenceOnActor:
|
||||
|
@ -5360,13 +5360,13 @@ int DLevelScript::RunScript ()
|
|||
break;
|
||||
|
||||
case PCD_CLEARACTORINVENTORY:
|
||||
if (STACK(3) == 0)
|
||||
if (STACK(1) == 0)
|
||||
{
|
||||
ClearInventory(NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
FActorIterator it(STACK(3));
|
||||
FActorIterator it(STACK(1));
|
||||
AActor *actor;
|
||||
for (actor = it.Next(); actor != NULL; actor = it.Next())
|
||||
{
|
||||
|
|
|
@ -109,6 +109,21 @@ struct spritetype
|
|||
SWORD lotag, hitag, extra;
|
||||
};
|
||||
|
||||
// I used to have all the Xobjects mapped out. Not anymore.
|
||||
// (Thanks for the great firmware, Seagate!)
|
||||
struct Xsprite
|
||||
{
|
||||
BYTE NotReallyPadding[16];
|
||||
WORD Data1;
|
||||
WORD Data2;
|
||||
WORD Data3;
|
||||
WORD ThisIsntPaddingEither;
|
||||
DWORD NorThis:2;
|
||||
DWORD Data4:16;
|
||||
DWORD WhatIsThisIDontEven:14;
|
||||
BYTE ThisNeedsToBe56Bytes[28];
|
||||
};
|
||||
|
||||
struct SlopeWork
|
||||
{
|
||||
walltype *wal;
|
||||
|
@ -128,7 +143,7 @@ void P_AdjustLine (line_t *line);
|
|||
static bool P_LoadBloodMap (BYTE *data, size_t len, FMapThing **sprites, int *numsprites);
|
||||
static void LoadSectors (sectortype *bsectors);
|
||||
static void LoadWalls (walltype *walls, int numwalls, sectortype *bsectors);
|
||||
static int LoadSprites (spritetype *sprites, int numsprites, sectortype *bsectors, FMapThing *mapthings);
|
||||
static int LoadSprites (spritetype *sprites, Xsprite *xsprites, int numsprites, sectortype *bsectors, FMapThing *mapthings);
|
||||
static vertex_t *FindVertex (fixed_t x, fixed_t y);
|
||||
static void CreateStartSpot (fixed_t *pos, FMapThing *start);
|
||||
static void CalcPlane (SlopeWork &slope, secplane_t &plane);
|
||||
|
@ -145,8 +160,10 @@ static void Decrypt (void *to, const void *from, int len, int key);
|
|||
bool P_IsBuildMap(MapData *map)
|
||||
{
|
||||
DWORD len = map->Size(ML_LABEL);
|
||||
if (len < 4) return false;
|
||||
|
||||
if (len < 4)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
BYTE *data = new BYTE[len];
|
||||
|
||||
map->Seek(ML_LABEL);
|
||||
|
@ -215,7 +232,7 @@ bool P_LoadBuildMap (BYTE *data, size_t len, FMapThing **sprites, int *numspr)
|
|||
*sprites = new FMapThing[numsprites + 1];
|
||||
CreateStartSpot ((fixed_t *)(data + 4), *sprites);
|
||||
*numspr = 1 + LoadSprites ((spritetype *)(data + 26 + numsectors*sizeof(sectortype) + numwalls*sizeof(walltype)),
|
||||
numsprites, (sectortype *)(data + 22), *sprites + 1);
|
||||
NULL, numsprites, (sectortype *)(data + 22), *sprites + 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -251,11 +268,11 @@ static bool P_LoadBloodMap (BYTE *data, size_t len, FMapThing **mapthings, int *
|
|||
{
|
||||
memcpy (infoBlock, data + 6, 37);
|
||||
}
|
||||
numRevisions = *(DWORD *)(infoBlock + 27);
|
||||
numsectors = *(WORD *)(infoBlock + 31);
|
||||
numWalls = *(WORD *)(infoBlock + 33);
|
||||
numsprites = *(WORD *)(infoBlock + 35);
|
||||
skyLen = 2 << *(WORD *)(infoBlock + 16);
|
||||
numRevisions = LittleLong(*(DWORD *)(infoBlock + 27));
|
||||
numsectors = LittleShort(*(WORD *)(infoBlock + 31));
|
||||
numWalls = LittleShort(*(WORD *)(infoBlock + 33));
|
||||
numsprites = LittleShort(*(WORD *)(infoBlock + 35));
|
||||
skyLen = 2 << LittleShort(*(WORD *)(infoBlock + 16));
|
||||
|
||||
if (mapver == 7)
|
||||
{
|
||||
|
@ -275,6 +292,7 @@ static bool P_LoadBloodMap (BYTE *data, size_t len, FMapThing **mapthings, int *
|
|||
sectortype *bsec = new sectortype[numsectors];
|
||||
walltype *bwal = new walltype[numWalls];
|
||||
spritetype *bspr = new spritetype[numsprites];
|
||||
Xsprite *xspr = new Xsprite[numsprites];
|
||||
|
||||
// Read sectors
|
||||
k = numRevisions * sizeof(sectortype);
|
||||
|
@ -327,9 +345,15 @@ static bool P_LoadBloodMap (BYTE *data, size_t len, FMapThing **mapthings, int *
|
|||
memcpy (&bspr[i], data, sizeof(spritetype));
|
||||
}
|
||||
data += sizeof(spritetype);
|
||||
if (bspr[i].extra > 0) // skip Xsprite
|
||||
if (bspr[i].extra > 0) // copy Xsprite
|
||||
{
|
||||
data += 56;
|
||||
assert(sizeof(Xsprite) == 56);
|
||||
memcpy(&xspr[i], data, sizeof(Xsprite));
|
||||
data += sizeof(Xsprite);
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(&xspr[i], 0, sizeof(Xsprite));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -339,11 +363,12 @@ static bool P_LoadBloodMap (BYTE *data, size_t len, FMapThing **mapthings, int *
|
|||
LoadWalls (bwal, numWalls, bsec);
|
||||
*mapthings = new FMapThing[numsprites + 1];
|
||||
CreateStartSpot ((fixed_t *)infoBlock, *mapthings);
|
||||
*numspr = 1 + LoadSprites (bspr, numsprites, bsec, *mapthings + 1);
|
||||
*numspr = 1 + LoadSprites (bspr, xspr, numsprites, bsec, *mapthings + 1);
|
||||
|
||||
delete[] bsec;
|
||||
delete[] bwal;
|
||||
delete[] bspr;
|
||||
delete[] xspr;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -363,6 +388,8 @@ static void LoadSectors (sectortype *bsec)
|
|||
sec = sectors = new sector_t[numsectors];
|
||||
memset (sectors, 0, sizeof(sector_t)*numsectors);
|
||||
|
||||
sectors[0].e = new extsector_t[numsectors];
|
||||
|
||||
for (int i = 0; i < numsectors; ++i, ++bsec, ++sec)
|
||||
{
|
||||
bsec->wallptr = WORD(bsec->wallptr);
|
||||
|
@ -370,6 +397,7 @@ static void LoadSectors (sectortype *bsec)
|
|||
bsec->ceilingstat = WORD(bsec->ceilingstat);
|
||||
bsec->floorstat = WORD(bsec->floorstat);
|
||||
|
||||
sec->e = §ors[0].e[i];
|
||||
sec->SetPlaneTexZ(sector_t::floor, -(LittleLong(bsec->floorz) << 8));
|
||||
sec->floorplane.d = -sec->GetPlaneTexZ(sector_t::floor);
|
||||
sec->floorplane.c = FRACUNIT;
|
||||
|
@ -512,6 +540,8 @@ static void LoadWalls (walltype *walls, int numwalls, sectortype *bsec)
|
|||
}
|
||||
|
||||
sides[i].TexelLength = walls[i].xrepeat * 8;
|
||||
sides[i].SetTextureYScale(walls[i].yrepeat << (FRACBITS - 3));
|
||||
sides[i].SetTextureXScale(FRACUNIT);
|
||||
sides[i].SetLight(SHADE2LIGHT(walls[i].shade));
|
||||
sides[i].Flags = WALLF_ABSLIGHTING;
|
||||
sides[i].RightSide = walls[i].point2;
|
||||
|
@ -631,14 +661,17 @@ static void LoadWalls (walltype *walls, int numwalls, sectortype *bsec)
|
|||
R_AlignFlat (linenum, sidenum == bsec->wallptr, 0);
|
||||
}
|
||||
}
|
||||
for(i = 0; i < numsides; i++)
|
||||
for (i = 0; i < numlines; i++)
|
||||
{
|
||||
sides[i].linedef = &lines[intptr_t(sides[i].linedef)];
|
||||
intptr_t front = intptr_t(lines[i].sidedef[0]);
|
||||
intptr_t back = intptr_t(lines[i].sidedef[1]);
|
||||
lines[i].sidedef[0] = front >= 0 ? &sides[front] : NULL;
|
||||
lines[i].sidedef[1] = back >= 0 ? &sides[back] : NULL;
|
||||
}
|
||||
for(i = 0; i < numlines; i++)
|
||||
for (i = 0; i < numsides; i++)
|
||||
{
|
||||
lines[i].sidedef[0] = &sides[intptr_t(lines[i].sidedef[0])];
|
||||
lines[i].sidedef[1] = &sides[intptr_t(lines[i].sidedef[1])];
|
||||
assert(sides[i].sector != NULL);
|
||||
sides[i].linedef = &lines[intptr_t(sides[i].linedef)];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -648,32 +681,46 @@ static void LoadWalls (walltype *walls, int numwalls, sectortype *bsec)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
static int LoadSprites (spritetype *sprites, int numsprites, sectortype *bsectors,
|
||||
FMapThing *mapthings)
|
||||
static int LoadSprites (spritetype *sprites, Xsprite *xsprites, int numsprites,
|
||||
sectortype *bsectors, FMapThing *mapthings)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
for (int i = 0; i < numsprites; ++i)
|
||||
{
|
||||
if (sprites[i].cstat & (16|32|32768)) continue;
|
||||
if (sprites[i].xrepeat == 0 || sprites[i].yrepeat == 0) continue;
|
||||
|
||||
mapthings[count].thingid = 0;
|
||||
mapthings[count].x = (sprites[i].x << 12);
|
||||
mapthings[count].y = -(sprites[i].y << 12);
|
||||
mapthings[count].z = (bsectors[sprites[i].sectnum].floorz - sprites[i].z) << 8;
|
||||
mapthings[count].angle = (((2048-sprites[i].ang) & 2047) * 360) >> 11;
|
||||
mapthings[count].type = 9988;
|
||||
mapthings[count].ClassFilter = 0xffff;
|
||||
mapthings[count].SkillFilter = 0xffff;
|
||||
mapthings[count].flags = MTF_SINGLE|MTF_COOPERATIVE|MTF_DEATHMATCH;
|
||||
mapthings[count].special = 0;
|
||||
|
||||
mapthings[count].args[0] = sprites[i].picnum & 255;
|
||||
mapthings[count].args[1] = sprites[i].picnum >> 8;
|
||||
mapthings[count].args[2] = sprites[i].xrepeat;
|
||||
mapthings[count].args[3] = sprites[i].yrepeat;
|
||||
mapthings[count].args[4] = (sprites[i].cstat & 14) | ((sprites[i].cstat >> 9) & 1);
|
||||
if (xsprites != NULL && sprites[i].lotag == 710)
|
||||
{ // Blood ambient sound
|
||||
mapthings[count].args[0] = xsprites[i].Data3;
|
||||
// I am totally guessing abount the volume level. 50 seems to be a pretty
|
||||
// typical value for Blood's standard maps, so I assume it's 100-based.
|
||||
mapthings[count].args[1] = xsprites[i].Data4;
|
||||
mapthings[count].args[2] = xsprites[i].Data1;
|
||||
mapthings[count].args[3] = xsprites[i].Data2;
|
||||
mapthings[count].args[4] = 0;
|
||||
mapthings[count].type = 14065;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sprites[i].cstat & (16|32|32768)) continue;
|
||||
if (sprites[i].xrepeat == 0 || sprites[i].yrepeat == 0) continue;
|
||||
|
||||
mapthings[count].type = 9988;
|
||||
mapthings[count].args[0] = sprites[i].picnum & 255;
|
||||
mapthings[count].args[1] = sprites[i].picnum >> 8;
|
||||
mapthings[count].args[2] = sprites[i].xrepeat;
|
||||
mapthings[count].args[3] = sprites[i].yrepeat;
|
||||
mapthings[count].args[4] = (sprites[i].cstat & 14) | ((sprites[i].cstat >> 9) & 1);
|
||||
}
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
|
|
|
@ -198,16 +198,16 @@ void P_RecursiveSound (sector_t *sec, AActor *soundtarget, bool splash, int soun
|
|||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void P_NoiseAlert (AActor *target, AActor *emmiter, bool splash)
|
||||
void P_NoiseAlert (AActor *target, AActor *emitter, bool splash)
|
||||
{
|
||||
if (emmiter == NULL)
|
||||
if (emitter == NULL)
|
||||
return;
|
||||
|
||||
if (target != NULL && target->player && (target->player->cheats & CF_NOTARGET))
|
||||
return;
|
||||
|
||||
validcount++;
|
||||
P_RecursiveSound (emmiter->Sector, target, splash, 0);
|
||||
P_RecursiveSound (emitter->Sector, target, splash, 0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -308,7 +308,7 @@ bool P_CheckMissileRange (AActor *actor)
|
|||
{
|
||||
fixed_t dist;
|
||||
|
||||
if (!P_CheckSight (actor, actor->target, 4))
|
||||
if (!P_CheckSight (actor, actor->target, SF_SEEPASTBLOCKEVERYTHING|SF_SEEPASTSHOOTABLELINES))
|
||||
return false;
|
||||
|
||||
if (actor->flags & MF_JUSTHIT)
|
||||
|
@ -1136,7 +1136,7 @@ bool P_IsVisible(AActor *lookee, AActor *other, INTBOOL allaround, FLookExParams
|
|||
}
|
||||
|
||||
// P_CheckSight is by far the most expensive operation in here so let's do it last.
|
||||
return P_CheckSight(lookee, other, 2);
|
||||
return P_CheckSight(lookee, other, SF_SEEPASTBLOCKEVERYTHING);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
@ -1154,7 +1154,7 @@ bool P_LookForMonsters (AActor *actor)
|
|||
AActor *mo;
|
||||
TThinkerIterator<AActor> iterator;
|
||||
|
||||
if (!P_CheckSight (players[0].mo, actor, 2))
|
||||
if (!P_CheckSight (players[0].mo, actor, SF_SEEPASTBLOCKEVERYTHING))
|
||||
{ // Player can't see monster
|
||||
return false;
|
||||
}
|
||||
|
@ -1178,11 +1178,11 @@ bool P_LookForMonsters (AActor *actor)
|
|||
{ // Stop searching
|
||||
return false;
|
||||
}
|
||||
if (mo->IsKindOf (actor->GetClass()) || actor->IsKindOf (mo->GetClass()))
|
||||
if (mo->GetSpecies() == actor->GetSpecies())
|
||||
{ // [RH] Don't go after same species
|
||||
continue;
|
||||
}
|
||||
if (!P_CheckSight (actor, mo, 2))
|
||||
if (!P_CheckSight (actor, mo, SF_SEEPASTBLOCKEVERYTHING))
|
||||
{ // Out of sight
|
||||
continue;
|
||||
}
|
||||
|
@ -1765,7 +1765,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Look)
|
|||
|
||||
if (self->flags & MF_AMBUSH)
|
||||
{
|
||||
if (P_CheckSight (self, self->target, 2))
|
||||
if (P_CheckSight (self, self->target, SF_SEEPASTBLOCKEVERYTHING))
|
||||
goto seeyou;
|
||||
}
|
||||
else
|
||||
|
@ -1933,7 +1933,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_LookEx)
|
|||
if (self->flags & MF_AMBUSH)
|
||||
{
|
||||
dist = P_AproxDistance (self->target->x - self->x, self->target->y - self->y);
|
||||
if (P_CheckSight (self, self->target, 2) &&
|
||||
if (P_CheckSight (self, self->target, SF_SEEPASTBLOCKEVERYTHING) &&
|
||||
(!minseedist || dist > minseedist) &&
|
||||
(!maxseedist || dist < maxseedist))
|
||||
{
|
||||
|
@ -2070,7 +2070,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Look2)
|
|||
{
|
||||
if (self->flags & MF_AMBUSH)
|
||||
{
|
||||
if (!P_CheckSight (self, targ, 2))
|
||||
if (!P_CheckSight (self, targ, SF_SEEPASTBLOCKEVERYTHING))
|
||||
goto nosee;
|
||||
}
|
||||
self->target = targ;
|
||||
|
@ -2745,7 +2745,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MonsterRail)
|
|||
self->target->x,
|
||||
self->target->y);
|
||||
|
||||
self->pitch = P_AimLineAttack (self, self->angle, MISSILERANGE, &linetarget, ANGLE_1*60, false, false, false, self->target);
|
||||
self->pitch = P_AimLineAttack (self, self->angle, MISSILERANGE, &linetarget, ANGLE_1*60, 0, self->target);
|
||||
if (linetarget == NULL)
|
||||
{
|
||||
// We probably won't hit the target, but aim at it anyway so we don't look stupid.
|
||||
|
|
|
@ -1274,7 +1274,7 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage
|
|||
painchance = target->PainChance;
|
||||
if (pc != NULL)
|
||||
{
|
||||
BYTE * ppc = pc->CheckKey(mod);
|
||||
int *ppc = pc->CheckKey(mod);
|
||||
if (ppc != NULL)
|
||||
{
|
||||
painchance = *ppc;
|
||||
|
|
|
@ -189,8 +189,11 @@ FUNC(LS_Door_CloseWaitOpen)
|
|||
}
|
||||
|
||||
FUNC(LS_Door_Animated)
|
||||
// Door_Animated (tag, speed, delay)
|
||||
// Door_Animated (tag, speed, delay, lock)
|
||||
{
|
||||
if (arg3 != 0 && !P_CheckKeys (it, arg3, arg0 != 0))
|
||||
return false;
|
||||
|
||||
return EV_SlidingDoor (ln, it, arg0, arg1, arg2);
|
||||
}
|
||||
|
||||
|
|
|
@ -394,6 +394,15 @@ void P_SlideMove (AActor* mo, fixed_t tryx, fixed_t tryy, int numsteps);
|
|||
bool P_BounceWall (AActor *mo);
|
||||
bool P_BounceActor (AActor *mo, AActor * BlockingMobj);
|
||||
bool P_CheckSight (const AActor* t1, const AActor* t2, int flags=0);
|
||||
|
||||
enum ESightFlags
|
||||
{
|
||||
SF_IGNOREVISIBILITY=1,
|
||||
SF_SEEPASTSHOOTABLELINES=2,
|
||||
SF_SEEPASTBLOCKEVERYTHING=4,
|
||||
SF_IGNOREWATERBOUNDARY=8
|
||||
};
|
||||
|
||||
void P_ResetSightCounters (bool full);
|
||||
bool P_TalkFacing (AActor *player);
|
||||
void P_UseLines (player_t* player);
|
||||
|
@ -402,7 +411,16 @@ void P_FindFloorCeiling (AActor *actor, bool onlymidtex = false);
|
|||
|
||||
bool P_ChangeSector (sector_t* sector, int crunch, int amt, int floorOrCeil, bool isreset);
|
||||
|
||||
fixed_t P_AimLineAttack (AActor *t1, angle_t angle, fixed_t distance, AActor **pLineTarget = NULL, fixed_t vrange=0, bool forcenosmart=false, bool check3d = false, bool checknonshootable = false, AActor *target=NULL);
|
||||
fixed_t P_AimLineAttack (AActor *t1, angle_t angle, fixed_t distance, AActor **pLineTarget = NULL, fixed_t vrange=0, int flags = 0, AActor *target=NULL);
|
||||
|
||||
enum
|
||||
{
|
||||
ALF_FORCENOSMART = 1,
|
||||
ALF_CHECK3D = 2,
|
||||
ALF_CHECKNONSHOOTABLE = 4,
|
||||
ALF_CHECKCONVERSATION = 8,
|
||||
};
|
||||
|
||||
AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, int pitch, int damage, FName damageType, PClassActor *pufftype, bool ismelee = false);
|
||||
AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, int pitch, int damage, FName damageType, FName pufftype, bool ismelee = false);
|
||||
void P_TraceBleed (int damage, fixed_t x, fixed_t y, fixed_t z, AActor *target, angle_t angle, int pitch);
|
||||
|
|
115
src/p_map.cpp
115
src/p_map.cpp
|
@ -2807,8 +2807,7 @@ struct aim_t
|
|||
AActor * linetarget;
|
||||
AActor * thing_friend, * thing_other;
|
||||
angle_t pitch_friend, pitch_other;
|
||||
bool notsmart;
|
||||
bool check3d;
|
||||
int flags;
|
||||
#ifdef _3DFLOORS
|
||||
sector_t * lastsector;
|
||||
secplane_t * lastfloorplane;
|
||||
|
@ -2819,7 +2818,7 @@ struct aim_t
|
|||
bool AimTraverse3DFloors(const divline_t &trace, intercept_t * in);
|
||||
#endif
|
||||
|
||||
void AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t endy, bool checknonshootable = false, AActor *target=NULL);
|
||||
void AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t endy, AActor *target=NULL);
|
||||
|
||||
};
|
||||
|
||||
|
@ -2936,7 +2935,7 @@ bool aim_t::AimTraverse3DFloors(const divline_t &trace, intercept_t * in)
|
|||
//
|
||||
//============================================================================
|
||||
|
||||
void aim_t::AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t endy, bool checknonshootable, AActor *target)
|
||||
void aim_t::AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t endy, AActor *target)
|
||||
{
|
||||
FPathTraverse it(startx, starty, endx, endy, PT_ADDLINES|PT_ADDTHINGS);
|
||||
intercept_t *in;
|
||||
|
@ -2994,18 +2993,23 @@ void aim_t::AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t e
|
|||
if (target != NULL && th != target)
|
||||
continue; // only care about target, and you're not it
|
||||
|
||||
if (!checknonshootable) // For info CCMD, ignore stuff about GHOST and SHOOTABLE flags
|
||||
// If we want to start a conversation anything that has one should be
|
||||
// found, regardless of other settings.
|
||||
if (!(flags & ALF_CHECKCONVERSATION) || th->Conversation == NULL)
|
||||
{
|
||||
if (!(th->flags&MF_SHOOTABLE))
|
||||
continue; // corpse or something
|
||||
|
||||
// check for physical attacks on a ghost
|
||||
if ((th->flags3 & MF3_GHOST) &&
|
||||
shootthing->player && // [RH] Be sure shootthing is a player
|
||||
shootthing->player->ReadyWeapon &&
|
||||
(shootthing->player->ReadyWeapon->flags2 & MF2_THRUGHOST))
|
||||
if (!(flags & ALF_CHECKNONSHOOTABLE)) // For info CCMD, ignore stuff about GHOST and SHOOTABLE flags
|
||||
{
|
||||
continue;
|
||||
if (!(th->flags&MF_SHOOTABLE))
|
||||
continue; // corpse or something
|
||||
|
||||
// check for physical attacks on a ghost
|
||||
if ((th->flags3 & MF3_GHOST) &&
|
||||
shootthing->player && // [RH] Be sure shootthing is a player
|
||||
shootthing->player->ReadyWeapon &&
|
||||
(shootthing->player->ReadyWeapon->flags2 & MF2_THRUGHOST))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
dist = FixedMul (attackrange, in->frac);
|
||||
|
@ -3053,7 +3057,7 @@ void aim_t::AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t e
|
|||
if (crossedffloors)
|
||||
{
|
||||
// if 3D floors were in the way do an extra visibility check for safety
|
||||
if (!P_CheckSight(shootthing, th, 1))
|
||||
if (!P_CheckSight(shootthing, th, SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY))
|
||||
{
|
||||
// the thing can't be seen so we can safely exclude its range from our aiming field
|
||||
if (thingtoppitch<toppitch)
|
||||
|
@ -3079,7 +3083,7 @@ void aim_t::AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t e
|
|||
|
||||
thingpitch = thingtoppitch/2 + thingbottompitch/2;
|
||||
|
||||
if (check3d)
|
||||
if (flags & ALF_CHECK3D)
|
||||
{
|
||||
// We need to do a 3D distance check here because this is nearly always used in
|
||||
// combination with P_LineAttack. P_LineAttack uses 3D distance but FPathTraverse
|
||||
|
@ -3096,7 +3100,7 @@ void aim_t::AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t e
|
|||
}
|
||||
}
|
||||
|
||||
if (sv_smartaim && !notsmart)
|
||||
if (sv_smartaim != 0 && !(flags & ALF_FORCENOSMART))
|
||||
{
|
||||
// try to be a little smarter about what to aim at!
|
||||
// In particular avoid autoaiming at friends amd barrels.
|
||||
|
@ -3131,11 +3135,6 @@ void aim_t::AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t e
|
|||
aimpitch = thingpitch;
|
||||
return;
|
||||
}
|
||||
if (checknonshootable)
|
||||
{
|
||||
linetarget = th;
|
||||
aimpitch = thingpitch;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3145,15 +3144,16 @@ void aim_t::AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t e
|
|||
//
|
||||
//============================================================================
|
||||
|
||||
fixed_t P_AimLineAttack (AActor *t1, angle_t angle, fixed_t distance, AActor **pLineTarget, fixed_t vrange, bool forcenosmart, bool check3d, bool checknonshootable, AActor *target)
|
||||
fixed_t P_AimLineAttack (AActor *t1, angle_t angle, fixed_t distance, AActor **pLineTarget, fixed_t vrange,
|
||||
int flags, AActor *target)
|
||||
{
|
||||
fixed_t x2;
|
||||
fixed_t y2;
|
||||
aim_t aim;
|
||||
|
||||
angle >>= ANGLETOFINESHIFT;
|
||||
aim.flags = flags;
|
||||
aim.shootthing = t1;
|
||||
aim.check3d = check3d;
|
||||
|
||||
x2 = t1->x + (distance>>FRACBITS)*finecosine[angle];
|
||||
y2 = t1->y + (distance>>FRACBITS)*finesine[angle];
|
||||
|
@ -3194,7 +3194,6 @@ fixed_t P_AimLineAttack (AActor *t1, angle_t angle, fixed_t distance, AActor **p
|
|||
}
|
||||
aim.toppitch = t1->pitch - vrange;
|
||||
aim.bottompitch = t1->pitch + vrange;
|
||||
aim.notsmart = forcenosmart;
|
||||
|
||||
aim.attackrange = distance;
|
||||
aim.linetarget = NULL;
|
||||
|
@ -3223,7 +3222,7 @@ fixed_t P_AimLineAttack (AActor *t1, angle_t angle, fixed_t distance, AActor **p
|
|||
}
|
||||
#endif
|
||||
|
||||
aim.AimTraverse (t1->x, t1->y, x2, y2, checknonshootable, target);
|
||||
aim.AimTraverse (t1->x, t1->y, x2, y2, target);
|
||||
|
||||
if (!aim.linetarget)
|
||||
{
|
||||
|
@ -3239,7 +3238,9 @@ fixed_t P_AimLineAttack (AActor *t1, angle_t angle, fixed_t distance, AActor **p
|
|||
}
|
||||
}
|
||||
if (pLineTarget)
|
||||
{
|
||||
*pLineTarget = aim.linetarget;
|
||||
}
|
||||
return aim.linetarget ? aim.aimpitch : t1->pitch;
|
||||
}
|
||||
|
||||
|
@ -3588,7 +3589,7 @@ void P_TraceBleed (int damage, fixed_t x, fixed_t y, fixed_t z, AActor *actor, a
|
|||
{
|
||||
if (bleedtrace.HitType == TRACE_HitWall)
|
||||
{
|
||||
PalEntry bloodcolor = actor->GetClass()->BloodColor;
|
||||
PalEntry bloodcolor = actor->GetBloodColor();
|
||||
if (bloodcolor != 0)
|
||||
{
|
||||
bloodcolor.r>>=1; // the full color is too bright for blood decals
|
||||
|
@ -3921,13 +3922,13 @@ bool P_TalkFacing(AActor *player)
|
|||
{
|
||||
AActor *linetarget;
|
||||
|
||||
P_AimLineAttack(player, player->angle, TALKRANGE, &linetarget, ANGLE_1*35, true);
|
||||
P_AimLineAttack(player, player->angle, TALKRANGE, &linetarget, ANGLE_1*35, ALF_FORCENOSMART|ALF_CHECKCONVERSATION);
|
||||
if (linetarget == NULL)
|
||||
{
|
||||
P_AimLineAttack(player, player->angle + (ANGLE_90 >> 4), TALKRANGE, &linetarget, ANGLE_1*35, true);
|
||||
P_AimLineAttack(player, player->angle + (ANGLE_90 >> 4), TALKRANGE, &linetarget, ANGLE_1*35, ALF_FORCENOSMART|ALF_CHECKCONVERSATION);
|
||||
if (linetarget == NULL)
|
||||
{
|
||||
P_AimLineAttack(player, player->angle - (ANGLE_90 >> 4), TALKRANGE, &linetarget, ANGLE_1*35, true);
|
||||
P_AimLineAttack(player, player->angle - (ANGLE_90 >> 4), TALKRANGE, &linetarget, ANGLE_1*35, ALF_FORCENOSMART|ALF_CHECKCONVERSATION);
|
||||
if (linetarget == NULL)
|
||||
{
|
||||
return false;
|
||||
|
@ -4327,7 +4328,7 @@ void P_RadiusAttack (AActor *bombspot, AActor *bombsource, int bombdamage, int b
|
|||
}
|
||||
points *= thing->GetClass()->RDFactor/(float)FRACUNIT;
|
||||
|
||||
if (points > 0.f && P_CheckSight (thing, bombspot, 1))
|
||||
if (points > 0.f && P_CheckSight (thing, bombspot, SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY))
|
||||
{ // OK to damage; target is in direct path
|
||||
float velz;
|
||||
float thrust;
|
||||
|
@ -4385,7 +4386,7 @@ void P_RadiusAttack (AActor *bombspot, AActor *bombsource, int bombdamage, int b
|
|||
if (dist >= bombdistance)
|
||||
continue; // out of range
|
||||
|
||||
if (P_CheckSight (thing, bombspot, 1))
|
||||
if (P_CheckSight (thing, bombspot, SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY))
|
||||
{ // OK to damage; target is in direct path
|
||||
dist = clamp<int>(dist - fulldamagedistance, 0, dist);
|
||||
int damage = Scale (bombdamage, bombdistance-dist, bombdistance);
|
||||
|
@ -4595,34 +4596,40 @@ void P_DoCrunch (AActor *thing, FChangePosition *cpos)
|
|||
P_DamageMobj (thing, NULL, NULL, cpos->crushchange, NAME_Crush);
|
||||
|
||||
// spray blood in a random direction
|
||||
if ((!(thing->flags&MF_NOBLOOD)) &&
|
||||
(!(thing->flags2&(MF2_INVULNERABLE|MF2_DORMANT))))
|
||||
if (!(thing->flags2&(MF2_INVULNERABLE|MF2_DORMANT)))
|
||||
{
|
||||
PalEntry bloodcolor = thing->GetClass()->BloodColor;
|
||||
PClassActor *bloodcls = PClass::FindActor(thing->GetClass()->BloodType);
|
||||
|
||||
P_TraceBleed (cpos->crushchange, thing);
|
||||
if (cl_bloodtype <= 1 && bloodcls != NULL)
|
||||
if (!(thing->flags&MF_NOBLOOD))
|
||||
{
|
||||
AActor *mo;
|
||||
|
||||
mo = Spawn (bloodcls, thing->x, thing->y,
|
||||
thing->z + thing->height/2, ALLOW_REPLACE);
|
||||
|
||||
mo->velx = pr_crunch.Random2 () << 12;
|
||||
mo->vely = pr_crunch.Random2 () << 12;
|
||||
if (bloodcolor != 0 && !(mo->flags2 & MF2_DONTTRANSLATE))
|
||||
PalEntry bloodcolor = thing->GetBloodColor();
|
||||
PClassActor *bloodcls = thing->GetBloodType();
|
||||
|
||||
P_TraceBleed (cpos->crushchange, thing);
|
||||
if (cl_bloodtype <= 1 && bloodcls != NULL)
|
||||
{
|
||||
mo->Translation = TRANSLATION(TRANSLATION_Blood, bloodcolor.a);
|
||||
AActor *mo;
|
||||
|
||||
mo = Spawn (bloodcls, thing->x, thing->y,
|
||||
thing->z + thing->height/2, ALLOW_REPLACE);
|
||||
|
||||
mo->velx = pr_crunch.Random2 () << 12;
|
||||
mo->vely = pr_crunch.Random2 () << 12;
|
||||
if (bloodcolor != 0 && !(mo->flags2 & MF2_DONTTRANSLATE))
|
||||
{
|
||||
mo->Translation = TRANSLATION(TRANSLATION_Blood, bloodcolor.a);
|
||||
}
|
||||
}
|
||||
if (cl_bloodtype >= 1)
|
||||
{
|
||||
angle_t an;
|
||||
|
||||
an = (M_Random () - 128) << 24;
|
||||
P_DrawSplash2 (32, thing->x, thing->y,
|
||||
thing->z + thing->height/2, an, 2, bloodcolor);
|
||||
}
|
||||
}
|
||||
if (cl_bloodtype >= 1)
|
||||
if (thing->CrushPainSound != 0 && !S_GetSoundPlayingInfo(thing, thing->CrushPainSound))
|
||||
{
|
||||
angle_t an;
|
||||
|
||||
an = (M_Random () - 128) << 24;
|
||||
P_DrawSplash2 (32, thing->x, thing->y,
|
||||
thing->z + thing->height/2, an, 2, bloodcolor);
|
||||
S_Sound(thing, CHAN_VOICE, thing->CrushPainSound, 1.f, ATTN_NORM);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -270,8 +270,12 @@ void AActor::Serialize (FArchive &arc)
|
|||
<< ActiveSound
|
||||
<< UseSound
|
||||
<< BounceSound
|
||||
<< WallBounceSound
|
||||
<< Speed
|
||||
<< WallBounceSound;
|
||||
if (SaveVersion >= 2234)
|
||||
{
|
||||
arc << CrushPainSound;
|
||||
}
|
||||
arc << Speed
|
||||
<< FloatSpeed
|
||||
<< Mass
|
||||
<< PainChance
|
||||
|
@ -1069,7 +1073,7 @@ bool AActor::Grind(bool items)
|
|||
if (isgeneric) // Not a custom crush state, so colorize it appropriately.
|
||||
{
|
||||
S_Sound (this, CHAN_BODY, "misc/fallingsplat", 1, ATTN_IDLE);
|
||||
PalEntry bloodcolor = GetClass()->BloodColor;
|
||||
PalEntry bloodcolor = GetBloodColor();
|
||||
if (bloodcolor!=0) Translation = TRANSLATION(TRANSLATION_Blood, bloodcolor.a);
|
||||
}
|
||||
return false;
|
||||
|
@ -1113,7 +1117,7 @@ bool AActor::Grind(bool items)
|
|||
}
|
||||
S_Sound (this, CHAN_BODY, "misc/fallingsplat", 1, ATTN_IDLE);
|
||||
|
||||
PalEntry bloodcolor = GetClass()->BloodColor;
|
||||
PalEntry bloodcolor = GetBloodColor();
|
||||
if (bloodcolor!=0) gib->Translation = TRANSLATION(TRANSLATION_Blood, bloodcolor.a);
|
||||
}
|
||||
if (flags & MF_ICECORPSE)
|
||||
|
@ -2129,8 +2133,9 @@ void P_ZMovement (AActor *mo, fixed_t oldfloorz)
|
|||
{
|
||||
fixed_t dist;
|
||||
fixed_t delta;
|
||||
fixed_t oldz = mo->z;
|
||||
|
||||
fixed_t oldz = mo->z;
|
||||
fixed_t grav = mo->GetGravity();
|
||||
|
||||
//
|
||||
// check for smooth step up
|
||||
//
|
||||
|
@ -2155,8 +2160,6 @@ void P_ZMovement (AActor *mo, fixed_t oldfloorz)
|
|||
if (!mo->waterlevel || mo->flags & MF_CORPSE || (mo->player &&
|
||||
!(mo->player->cmd.ucmd.forwardmove | mo->player->cmd.ucmd.sidemove)))
|
||||
{
|
||||
fixed_t grav = mo->GetGravity();
|
||||
|
||||
// [RH] Double gravity only if running off a ledge. Coming down from
|
||||
// an upward thrust (e.g. a jump) should not double it.
|
||||
if (mo->velz == 0 && oldfloorz > mo->floorz && mo->z == oldfloorz)
|
||||
|
@ -2230,12 +2233,7 @@ void P_ZMovement (AActor *mo, fixed_t oldfloorz)
|
|||
// teleported the actor so it is no longer below the floor.
|
||||
if (mo->z <= mo->floorz)
|
||||
{
|
||||
// old code for boss cube disabled
|
||||
//if ((mo->flags & MF_MISSILE) && (!(gameinfo.gametype & GAME_DoomChex) || !(mo->flags & MF_NOCLIP)))
|
||||
|
||||
// We can't remove this completely because it was abused by some DECORATE definitions
|
||||
// (e.g. the monster pack's Afrit)
|
||||
if ((mo->flags & MF_MISSILE) && ((mo->flags & MF_NOGRAVITY) || !(mo->flags & MF_NOCLIP)))
|
||||
if ((mo->flags & MF_MISSILE) && !(mo->flags & MF_NOCLIP))
|
||||
{
|
||||
mo->z = mo->floorz;
|
||||
if (mo->BounceFlags & BOUNCE_Floors)
|
||||
|
@ -2297,7 +2295,10 @@ void P_ZMovement (AActor *mo, fixed_t oldfloorz)
|
|||
mo->HitFloor ();
|
||||
if (mo->player)
|
||||
{
|
||||
mo->player->jumpTics = 7; // delay any jumping for a short while
|
||||
if (mo->player->jumpTics != 0 && mo->velz < -grav*4)
|
||||
{ // delay any jumping for a short while
|
||||
mo->player->jumpTics = 7;
|
||||
}
|
||||
if (mo->velz < minvel && !(mo->flags & MF_NOGRAVITY))
|
||||
{
|
||||
// Squat down.
|
||||
|
@ -2346,8 +2347,7 @@ void P_ZMovement (AActor *mo, fixed_t oldfloorz)
|
|||
}
|
||||
if (mo->velz > 0)
|
||||
mo->velz = 0;
|
||||
if (mo->flags & MF_MISSILE)
|
||||
//&& (!(gameinfo.gametype & GAME_DoomChex) || !(mo->flags & MF_NOCLIP)))
|
||||
if ((mo->flags & MF_MISSILE) && !(mo->flags & MF_NOCLIP))
|
||||
{
|
||||
if (mo->flags3 & MF3_CEILINGHUGGER)
|
||||
{
|
||||
|
@ -2615,11 +2615,6 @@ void AActor::RemoveFromHash ()
|
|||
tid = 0;
|
||||
}
|
||||
|
||||
angle_t AActor::AngleIncrements ()
|
||||
{
|
||||
return ANGLE_45;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// AActor :: GetMissileDamage
|
||||
|
@ -3022,7 +3017,7 @@ void AActor::Tick ()
|
|||
&& !players[i].enemy
|
||||
&& player ? !IsTeammate (players[i].mo) : true
|
||||
&& P_AproxDistance (players[i].mo->x-x, players[i].mo->y-y) < MAX_MONSTER_TARGET_DIST
|
||||
&& P_CheckSight (players[i].mo, this, 2))
|
||||
&& P_CheckSight (players[i].mo, this, SF_SEEPASTBLOCKEVERYTHING))
|
||||
{ //Probably a monster, so go kill it.
|
||||
players[i].enemy = this;
|
||||
}
|
||||
|
@ -3700,8 +3695,6 @@ void AActor::LevelSpawned ()
|
|||
{
|
||||
if (tics > 0 && !(flags4 & MF4_SYNCHRONIZED))
|
||||
tics = 1 + (pr_spawnmapthing() % tics);
|
||||
angle_t incs = AngleIncrements ();
|
||||
angle -= angle % incs;
|
||||
flags &= ~MF_DROPPED; // [RH] clear MF_DROPPED flag
|
||||
HandleSpawnFlags ();
|
||||
}
|
||||
|
@ -3960,7 +3953,15 @@ APlayerPawn *P_SpawnPlayer (FMapThing *mthing, bool tempplayer)
|
|||
{
|
||||
spawn_x = mthing->x;
|
||||
spawn_y = mthing->y;
|
||||
spawn_angle = ANG45 * (mthing->angle/45);
|
||||
// Allow full angular precision but avoid roundoff errors for multiples of 45 degrees.
|
||||
if (mthing->angle % 45 != 0)
|
||||
{
|
||||
spawn_angle = mthing->angle * (ANG45 / 45);
|
||||
}
|
||||
else
|
||||
{
|
||||
spawn_angle = ANG45 * (mthing->angle / 45);
|
||||
}
|
||||
}
|
||||
|
||||
mobj = static_cast<APlayerPawn *>
|
||||
|
@ -3986,11 +3987,15 @@ APlayerPawn *P_SpawnPlayer (FMapThing *mthing, bool tempplayer)
|
|||
p->userinfo.skin = R_FindSkin (skins[p->userinfo.skin].name, p->CurrentPlayerClass);
|
||||
StatusBar->SetFace (&skins[p->userinfo.skin]);
|
||||
|
||||
// [RH] Be sure the player has the right translation
|
||||
R_BuildPlayerTranslation (playernum);
|
||||
|
||||
// [RH] set color translations for player sprites
|
||||
mobj->Translation = TRANSLATION(TRANSLATION_Players,playernum);
|
||||
if (!(mobj->flags2 & MF2_DONTTRANSLATE))
|
||||
{
|
||||
// [RH] Be sure the player has the right translation
|
||||
R_BuildPlayerTranslation (playernum);
|
||||
|
||||
// [RH] set color translations for player sprites
|
||||
mobj->Translation = TRANSLATION(TRANSLATION_Players,playernum);
|
||||
}
|
||||
|
||||
mobj->angle = spawn_angle;
|
||||
mobj->pitch = mobj->roll = 0;
|
||||
|
@ -4506,8 +4511,8 @@ AActor *P_SpawnPuff (AActor *source, PClassActor *pufftype, fixed_t x, fixed_t y
|
|||
void P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, angle_t dir, int damage, AActor *originator)
|
||||
{
|
||||
AActor *th;
|
||||
PalEntry bloodcolor = originator->GetClass()->BloodColor;
|
||||
PClassActor *bloodcls = PClass::FindActor(originator->GetClass()->BloodType);
|
||||
PalEntry bloodcolor = originator->GetBloodColor();
|
||||
PClassActor *bloodcls = originator->GetBloodType();
|
||||
|
||||
int bloodtype = cl_bloodtype;
|
||||
|
||||
|
@ -4568,8 +4573,8 @@ void P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, angle_t dir, int damage, AAc
|
|||
|
||||
void P_BloodSplatter (fixed_t x, fixed_t y, fixed_t z, AActor *originator)
|
||||
{
|
||||
PalEntry bloodcolor = originator->GetClass()->BloodColor;
|
||||
PClassActor *bloodcls = PClass::FindActor(originator->GetClass()->BloodType2);
|
||||
PalEntry bloodcolor = originator->GetBloodColor();
|
||||
PClassActor *bloodcls = originator->GetBloodType(1);
|
||||
|
||||
int bloodtype = cl_bloodtype;
|
||||
|
||||
|
@ -4606,8 +4611,8 @@ void P_BloodSplatter (fixed_t x, fixed_t y, fixed_t z, AActor *originator)
|
|||
|
||||
void P_BloodSplatter2 (fixed_t x, fixed_t y, fixed_t z, AActor *originator)
|
||||
{
|
||||
PalEntry bloodcolor = originator->GetClass()->BloodColor;
|
||||
PClassActor *bloodcls = PClass::FindActor(originator->GetClass()->BloodType3);
|
||||
PalEntry bloodcolor = originator->GetBloodColor();
|
||||
PClassActor *bloodcls = originator->GetBloodType(2);
|
||||
|
||||
int bloodtype = cl_bloodtype;
|
||||
|
||||
|
@ -4645,8 +4650,8 @@ void P_BloodSplatter2 (fixed_t x, fixed_t y, fixed_t z, AActor *originator)
|
|||
void P_RipperBlood (AActor *mo, AActor *bleeder)
|
||||
{
|
||||
fixed_t x, y, z;
|
||||
PalEntry bloodcolor = bleeder->GetClass()->BloodColor;
|
||||
PClassActor *bloodcls = PClass::FindActor(bleeder->GetClass()->BloodType);
|
||||
PalEntry bloodcolor = bleeder->GetBloodColor();
|
||||
PClassActor *bloodcls = bleeder->GetBloodType();
|
||||
|
||||
x = mo->x + (pr_ripperblood.Random2 () << 12);
|
||||
y = mo->y + (pr_ripperblood.Random2 () << 12);
|
||||
|
|
|
@ -294,8 +294,10 @@ MapData *P_OpenMapData(const char * mapname)
|
|||
{
|
||||
// The following lump is from a different file so whatever this is,
|
||||
// it is not a multi-lump Doom level so let's assume it is a Build map.
|
||||
map->MapLumps[0].FilePos = Wads.GetLumpOffset(lump_name);
|
||||
map->MapLumps[0].FilePos = 0;
|
||||
map->MapLumps[0].Size = Wads.LumpLength(lump_name);
|
||||
map->file = Wads.ReopenLumpNum(lump_name);
|
||||
map->CloseOnDestruct = true;
|
||||
if (!P_IsBuildMap(map))
|
||||
{
|
||||
delete map;
|
||||
|
@ -312,6 +314,9 @@ MapData *P_OpenMapData(const char * mapname)
|
|||
|
||||
if (map->Encrypted)
|
||||
{ // If it's encrypted, then it's a Blood file, presumably a map.
|
||||
map->file = Wads.ReopenLumpNum(lump_name);
|
||||
map->CloseOnDestruct = true;
|
||||
map->MapLumps[0].FilePos = 0;
|
||||
if (!P_IsBuildMap(map))
|
||||
{
|
||||
delete map;
|
||||
|
@ -322,7 +327,7 @@ MapData *P_OpenMapData(const char * mapname)
|
|||
|
||||
int index = 0;
|
||||
|
||||
if (stricmp(Wads.GetLumpFullName(lump_name + 1), "TEXTMAP"))
|
||||
if (stricmp(Wads.GetLumpFullName(lump_name + 1), "TEXTMAP") != 0)
|
||||
{
|
||||
for(int i = 1;; i++)
|
||||
{
|
||||
|
@ -404,7 +409,8 @@ MapData *P_OpenMapData(const char * mapname)
|
|||
}
|
||||
}
|
||||
DWORD id;
|
||||
(*map->file) >> id;
|
||||
|
||||
map->file->Read(&id, sizeof(id));
|
||||
|
||||
if (id == IWAD_ID || id == PWAD_ID)
|
||||
{
|
||||
|
@ -705,9 +711,15 @@ void P_FloodZone (sector_t *sec, int zonenum)
|
|||
continue;
|
||||
|
||||
if (check->frontsector == sec)
|
||||
{
|
||||
assert(check->backsector != NULL);
|
||||
other = check->backsector;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(check->frontsector != NULL);
|
||||
other = check->frontsector;
|
||||
}
|
||||
|
||||
if (other->ZoneNumber != zonenum)
|
||||
P_FloodZone (other, zonenum);
|
||||
|
@ -717,6 +729,7 @@ void P_FloodZone (sector_t *sec, int zonenum)
|
|||
void P_FloodZones ()
|
||||
{
|
||||
int z = 0, i;
|
||||
ReverbContainer *reverb;
|
||||
|
||||
for (i = 0; i < numsectors; ++i)
|
||||
{
|
||||
|
@ -727,9 +740,15 @@ void P_FloodZones ()
|
|||
}
|
||||
numzones = z;
|
||||
zones = new zone_t[z];
|
||||
reverb = S_FindEnvironment(level.DefaultEnvironment);
|
||||
if (reverb == NULL)
|
||||
{
|
||||
Printf("Sound environment %d, %d not found\n", level.DefaultEnvironment >> 8, level.DefaultEnvironment & 255);
|
||||
reverb = DefaultEnvironments[0];
|
||||
}
|
||||
for (i = 0; i < z; ++i)
|
||||
{
|
||||
zones[i].Environment = DefaultEnvironments[0];
|
||||
zones[i].Environment = reverb;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3379,7 +3398,7 @@ void P_SetupLevel (char *lumpname, int position)
|
|||
P_FreeLevelData ();
|
||||
interpolator.ClearInterpolations(); // [RH] Nothing to interpolate on a fresh level.
|
||||
|
||||
MapData * map = P_OpenMapData(lumpname);
|
||||
MapData *map = P_OpenMapData(lumpname);
|
||||
if (map == NULL)
|
||||
{
|
||||
I_Error("Unable to open map '%s'\n", lumpname);
|
||||
|
@ -3395,11 +3414,9 @@ void P_SetupLevel (char *lumpname, int position)
|
|||
BYTE *mapdata = new BYTE[map->MapLumps[0].Size];
|
||||
map->Seek(0);
|
||||
map->file->Read(mapdata, map->MapLumps[0].Size);
|
||||
if (map->Encrypted)
|
||||
{
|
||||
BloodCrypt (mapdata, 0, MIN<int> (map->MapLumps[0].Size, 256));
|
||||
}
|
||||
times[0].Clock();
|
||||
buildmap = P_LoadBuildMap (mapdata, map->MapLumps[0].Size, &buildthings, &numbuildthings);
|
||||
times[0].Unclock();
|
||||
delete[] mapdata;
|
||||
}
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ class SightCheck
|
|||
fixed_t lastzbottom; // z at last line
|
||||
sector_t * lastsector; // last sector being entered by trace
|
||||
fixed_t topslope, bottomslope; // slopes to top and bottom of target
|
||||
int SeePastBlockEverything, SeePastShootableLines;
|
||||
int Flags;
|
||||
divline_t trace;
|
||||
int myseethrough;
|
||||
|
||||
|
@ -73,9 +73,8 @@ public:
|
|||
seeingthing=t2;
|
||||
bottomslope = t2->z - sightzstart;
|
||||
topslope = bottomslope + t2->height;
|
||||
Flags = flags;
|
||||
|
||||
SeePastBlockEverything = flags & 6;
|
||||
SeePastShootableLines = flags & 4;
|
||||
myseethrough = FF_SEETHROUGH;
|
||||
}
|
||||
};
|
||||
|
@ -144,6 +143,7 @@ bool SightCheck::PTR_SightTraverse (intercept_t *in)
|
|||
F3DFloor* rover=s->e->XFloor.ffloors[j];
|
||||
|
||||
if((rover->flags & FF_SEETHROUGH) == myseethrough || !(rover->flags & FF_EXISTS)) continue;
|
||||
if ((Flags & SF_IGNOREWATERBOUNDARY) && (rover->flags & FF_SOLID) == 0) continue;
|
||||
|
||||
fixed_t ff_bottom=rover->bottom.plane->ZatPoint(trX, trY);
|
||||
fixed_t ff_top=rover->top.plane->ZatPoint(trX, trY);
|
||||
|
@ -176,6 +176,7 @@ bool SightCheck::PTR_SightTraverse (intercept_t *in)
|
|||
F3DFloor* rover2=sb->e->XFloor.ffloors[k];
|
||||
|
||||
if((rover2->flags & FF_SEETHROUGH) == myseethrough || !(rover2->flags & FF_EXISTS)) continue;
|
||||
if ((Flags & SF_IGNOREWATERBOUNDARY) && (rover->flags & FF_SOLID) == 0) continue;
|
||||
|
||||
fixed_t ffb_bottom=rover2->bottom.plane->ZatPoint(trX, trY);
|
||||
fixed_t ffb_top=rover2->top.plane->ZatPoint(trX, trY);
|
||||
|
@ -255,7 +256,7 @@ bool SightCheck::P_SightCheckLine (line_t *ld)
|
|||
// [RH] don't see past block everything lines
|
||||
if (ld->flags & ML_BLOCKEVERYTHING)
|
||||
{
|
||||
if (!SeePastBlockEverything)
|
||||
if (!(Flags & SF_SEEPASTBLOCKEVERYTHING))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -263,7 +264,7 @@ bool SightCheck::P_SightCheckLine (line_t *ld)
|
|||
// that runs a script on the current map. Used to prevent monsters
|
||||
// from trying to attack through a block everything line unless
|
||||
// there's a chance their attack will make it nonblocking.
|
||||
if (!SeePastShootableLines)
|
||||
if (!(Flags & SF_SEEPASTSHOOTABLELINES))
|
||||
{
|
||||
if (!(ld->activation & SPAC_Impact))
|
||||
{
|
||||
|
@ -407,6 +408,7 @@ bool SightCheck::P_SightTraverseIntercepts ()
|
|||
F3DFloor* rover = lastsector->e->XFloor.ffloors[i];
|
||||
|
||||
if((rover->flags & FF_SOLID) == myseethrough || !(rover->flags & FF_EXISTS)) continue;
|
||||
if ((Flags & SF_IGNOREWATERBOUNDARY) && (rover->flags & FF_SOLID) == 0) continue;
|
||||
|
||||
fixed_t ff_bottom=rover->bottom.plane->ZatPoint(seeingthing->x, seeingthing->y);
|
||||
fixed_t ff_top=rover->top.plane->ZatPoint(seeingthing->x, seeingthing->y);
|
||||
|
@ -670,7 +672,7 @@ sightcounts[0]++;
|
|||
//
|
||||
// [RH] Andy Baker's stealth monsters:
|
||||
// Cannot see an invisible object
|
||||
if ((flags & 1) == 0 && ((t2->renderflags & RF_INVISIBLE) || !t2->RenderStyle.IsVisible(t2->alpha)))
|
||||
if ((flags & SF_IGNOREVISIBILITY) == 0 && ((t2->renderflags & RF_INVISIBLE) || !t2->RenderStyle.IsVisible(t2->alpha)))
|
||||
{ // small chance of an attack being made anyway
|
||||
if ((bglobal.m_Thinking ? pr_botchecksight() : pr_checksight()) > 50)
|
||||
{
|
||||
|
@ -681,20 +683,23 @@ sightcounts[0]++;
|
|||
|
||||
// killough 4/19/98: make fake floors and ceilings block monster view
|
||||
|
||||
if ((s1->GetHeightSec() &&
|
||||
((t1->z + t1->height <= s1->heightsec->floorplane.ZatPoint (t1->x, t1->y) &&
|
||||
t2->z >= s1->heightsec->floorplane.ZatPoint (t2->x, t2->y)) ||
|
||||
(t1->z >= s1->heightsec->ceilingplane.ZatPoint (t1->x, t1->y) &&
|
||||
t2->z + t1->height <= s1->heightsec->ceilingplane.ZatPoint (t2->x, t2->y))))
|
||||
||
|
||||
(s2->GetHeightSec() &&
|
||||
((t2->z + t2->height <= s2->heightsec->floorplane.ZatPoint (t2->x, t2->y) &&
|
||||
t1->z >= s2->heightsec->floorplane.ZatPoint (t1->x, t1->y)) ||
|
||||
(t2->z >= s2->heightsec->ceilingplane.ZatPoint (t2->x, t2->y) &&
|
||||
t1->z + t2->height <= s2->heightsec->ceilingplane.ZatPoint (t1->x, t1->y)))))
|
||||
if (!(flags & SF_IGNOREWATERBOUNDARY))
|
||||
{
|
||||
res = false;
|
||||
goto done;
|
||||
if ((s1->GetHeightSec() &&
|
||||
((t1->z + t1->height <= s1->heightsec->floorplane.ZatPoint (t1->x, t1->y) &&
|
||||
t2->z >= s1->heightsec->floorplane.ZatPoint (t2->x, t2->y)) ||
|
||||
(t1->z >= s1->heightsec->ceilingplane.ZatPoint (t1->x, t1->y) &&
|
||||
t2->z + t1->height <= s1->heightsec->ceilingplane.ZatPoint (t2->x, t2->y))))
|
||||
||
|
||||
(s2->GetHeightSec() &&
|
||||
((t2->z + t2->height <= s2->heightsec->floorplane.ZatPoint (t2->x, t2->y) &&
|
||||
t1->z >= s2->heightsec->floorplane.ZatPoint (t1->x, t1->y)) ||
|
||||
(t2->z >= s2->heightsec->ceilingplane.ZatPoint (t2->x, t2->y) &&
|
||||
t1->z + t2->height <= s2->heightsec->ceilingplane.ZatPoint (t1->x, t1->y)))))
|
||||
{
|
||||
res = false;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
// An unobstructed LOS is possible.
|
||||
|
|
|
@ -1939,7 +1939,7 @@ void DPusher::Tick ()
|
|||
// If speed <= 0, you're outside the effective radius. You also have
|
||||
// to be able to see the push/pull source point.
|
||||
|
||||
if ((speed > 0) && (P_CheckSight (thing, m_Source, 1)))
|
||||
if ((speed > 0) && (P_CheckSight (thing, m_Source, SF_IGNOREVISIBILITY)))
|
||||
{
|
||||
angle_t pushangle = R_PointToAngle2 (thing->x, thing->y, sx, sy);
|
||||
if (m_Source->GetClass()->TypeName == NAME_PointPusher)
|
||||
|
|
|
@ -55,7 +55,6 @@
|
|||
|
||||
static FRandom pr_skullpop ("SkullPop");
|
||||
|
||||
|
||||
// [RH] # of ticks to complete a turn180
|
||||
#define TURN180_TICKS ((TICRATE / 4) + 1)
|
||||
|
||||
|
@ -2671,3 +2670,47 @@ void player_t::Serialize (FArchive &arc)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static FPlayerColorSetMap *GetPlayerColors(FName classname)
|
||||
{
|
||||
PClassPlayerPawn *cls = dyn_cast<PClassPlayerPawn>(PClass::FindClass(classname));
|
||||
|
||||
if (cls != NULL)
|
||||
{
|
||||
return cls->ColorSets;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FPlayerColorSet *P_GetPlayerColorSet(FName classname, int setnum)
|
||||
{
|
||||
FPlayerColorSetMap *map = GetPlayerColors(classname);
|
||||
if (map == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return map->CheckKey(setnum);
|
||||
}
|
||||
|
||||
static int STACK_ARGS intcmp(const void *a, const void *b)
|
||||
{
|
||||
return *(const int *)a - *(const int *)b;
|
||||
}
|
||||
|
||||
void P_EnumPlayerColorSets(FName classname, TArray<int> *out)
|
||||
{
|
||||
out->Clear();
|
||||
FPlayerColorSetMap *map = GetPlayerColors(classname);
|
||||
if (map != NULL)
|
||||
{
|
||||
FPlayerColorSetMap::Iterator it(*map);
|
||||
FPlayerColorSetMap::Pair *pair;
|
||||
|
||||
while (it.NextPair(pair))
|
||||
{
|
||||
out->Push(pair->Key);
|
||||
}
|
||||
qsort(&(*out)[0], out->Size(), sizeof(int), intcmp);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -795,25 +795,25 @@ static void UpdateSegBBox (seg_t *seg)
|
|||
|
||||
line = seg->linedef;
|
||||
|
||||
if (seg->v1->x < seg->v2->x)
|
||||
if (line->v1->x < line->v2->x)
|
||||
{
|
||||
line->bbox[BOXLEFT] = seg->v1->x;
|
||||
line->bbox[BOXRIGHT] = seg->v2->x;
|
||||
line->bbox[BOXLEFT] = line->v1->x;
|
||||
line->bbox[BOXRIGHT] = line->v2->x;
|
||||
}
|
||||
else
|
||||
{
|
||||
line->bbox[BOXLEFT] = seg->v2->x;
|
||||
line->bbox[BOXRIGHT] = seg->v1->x;
|
||||
line->bbox[BOXLEFT] = line->v2->x;
|
||||
line->bbox[BOXRIGHT] = line->v1->x;
|
||||
}
|
||||
if (seg->v1->y < seg->v2->y)
|
||||
if (line->v1->y < line->v2->y)
|
||||
{
|
||||
line->bbox[BOXBOTTOM] = seg->v1->y;
|
||||
line->bbox[BOXTOP] = seg->v2->y;
|
||||
line->bbox[BOXBOTTOM] = line->v1->y;
|
||||
line->bbox[BOXTOP] = line->v2->y;
|
||||
}
|
||||
else
|
||||
{
|
||||
line->bbox[BOXBOTTOM] = seg->v2->y;
|
||||
line->bbox[BOXTOP] = seg->v1->y;
|
||||
line->bbox[BOXBOTTOM] = line->v2->y;
|
||||
line->bbox[BOXTOP] = line->v1->y;
|
||||
}
|
||||
|
||||
// Update the line's slopetype
|
||||
|
|
|
@ -2181,7 +2181,7 @@ ESPSResult R_SetPatchStyle (FRenderStyle style, fixed_t alpha, int translation,
|
|||
if (translation != 0)
|
||||
{
|
||||
FRemapTable *table = TranslationToTable(translation);
|
||||
if (table != NULL)
|
||||
if (table != NULL && !table->Inactive)
|
||||
{
|
||||
dc_translation = table->Remap;
|
||||
}
|
||||
|
|
|
@ -1081,7 +1081,7 @@ void R_SetupFrame (AActor *actor)
|
|||
iview->otic = nowtic;
|
||||
}
|
||||
|
||||
R_UpdateAnimations (I_MSTime());
|
||||
R_UpdateAnimations (I_FPSTime());
|
||||
r_TicFrac = I_GetTimeFrac (&r_FrameTime);
|
||||
if (cl_capfps || r_NoInterpolate)
|
||||
{
|
||||
|
|
|
@ -2346,7 +2346,7 @@ CUSTOM_CVAR( Int, r_maxparticles, 4000, CVAR_ARCHIVE )
|
|||
|
||||
void R_InitParticles ()
|
||||
{
|
||||
char *i;
|
||||
const char *i;
|
||||
|
||||
if ((i = Args->CheckValue ("-numparticles")))
|
||||
NumParticles = atoi (i);
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include "sc_man.h"
|
||||
#include "doomerrors.h"
|
||||
#include "i_system.h"
|
||||
#include "w_wad.h"
|
||||
|
||||
#include "gi.h"
|
||||
#include "stats.h"
|
||||
|
@ -78,7 +79,7 @@ const BYTE IcePalette[16][3] =
|
|||
FRemapTable::FRemapTable(int count)
|
||||
{
|
||||
assert(count <= 256);
|
||||
|
||||
Inactive = false;
|
||||
Alloc(count);
|
||||
|
||||
// Note that the tables are left uninitialized. It is assumed that
|
||||
|
@ -163,6 +164,7 @@ FRemapTable &FRemapTable::operator=(const FRemapTable &o)
|
|||
{
|
||||
Alloc(o.NumEntries);
|
||||
}
|
||||
Inactive = o.Inactive;
|
||||
memcpy(Remap, o.Remap, NumEntries*sizeof(*Remap) + NumEntries*sizeof(*Palette));
|
||||
return *this;
|
||||
}
|
||||
|
@ -892,7 +894,8 @@ static void SetRemap(FRemapTable *table, int i, float r, float g, float b)
|
|||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
static void R_CreatePlayerTranslation (float h, float s, float v, FPlayerSkin *skin, FRemapTable *table, FRemapTable *alttable)
|
||||
static void R_CreatePlayerTranslation (float h, float s, float v, const FPlayerColorSet *colorset,
|
||||
FPlayerSkin *skin, FRemapTable *table, FRemapTable *alttable)
|
||||
{
|
||||
int i;
|
||||
BYTE start = skin->range0start;
|
||||
|
@ -915,7 +918,7 @@ static void R_CreatePlayerTranslation (float h, float s, float v, FPlayerSkin *s
|
|||
{
|
||||
for (i = 0; i < table->NumEntries; ++i)
|
||||
{
|
||||
table->Remap[i] = i;
|
||||
table->Remap[i] = GPalette.Remap[i];
|
||||
}
|
||||
memcpy(table->Palette, GPalette.BaseColors, sizeof(*table->Palette) * table->NumEntries);
|
||||
}
|
||||
|
@ -927,16 +930,63 @@ static void R_CreatePlayerTranslation (float h, float s, float v, FPlayerSkin *s
|
|||
// [GRB] Don't translate skins with color range 0-0 (APlayerPawn default)
|
||||
if (start == 0 && end == 0)
|
||||
{
|
||||
table->Inactive = true;
|
||||
table->UpdateNative();
|
||||
return;
|
||||
}
|
||||
|
||||
table->Inactive = false;
|
||||
range = (float)(end-start+1);
|
||||
|
||||
bases = s;
|
||||
basev = v;
|
||||
|
||||
if (gameinfo.gametype & GAME_DoomStrifeChex)
|
||||
if (colorset != NULL && colorset->Lump >= 0 && Wads.LumpLength(colorset->Lump) < 256)
|
||||
{ // Bad table length. Ignore it.
|
||||
colorset = NULL;
|
||||
}
|
||||
|
||||
if (colorset != NULL)
|
||||
{
|
||||
bool identity = true;
|
||||
// Use the pre-defined range instead of a custom one.
|
||||
if (colorset->Lump < 0)
|
||||
{
|
||||
int first = colorset->FirstColor;
|
||||
if (start == end)
|
||||
{
|
||||
table->Remap[i] = (first + colorset->LastColor) / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
int palrange = colorset->LastColor - first;
|
||||
for (i = start; i <= end; ++i)
|
||||
{
|
||||
int pi = first + palrange * (i - start) / (end - start);
|
||||
table->Remap[i] = GPalette.Remap[pi];
|
||||
if (pi != i) identity = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FMemLump translump = Wads.ReadLump(colorset->Lump);
|
||||
const BYTE *trans = (const BYTE *)translump.GetMem();
|
||||
for (i = start; i <= end; ++i)
|
||||
{
|
||||
table->Remap[i] = GPalette.Remap[trans[i]];
|
||||
if (trans[i] != i) identity = false;
|
||||
}
|
||||
}
|
||||
for (i = start; i <= end; ++i)
|
||||
{
|
||||
table->Palette[i] = GPalette.BaseColors[table->Remap[i]];
|
||||
table->Palette[i].a = 255;
|
||||
}
|
||||
// If the colorset created an identity translation mark it as inactive
|
||||
table->Inactive = identity;
|
||||
}
|
||||
else if (gameinfo.gametype & GAME_DoomStrifeChex)
|
||||
{
|
||||
// Build player sprite translation
|
||||
s -= 0.23f;
|
||||
|
@ -1014,9 +1064,19 @@ static void R_CreatePlayerTranslation (float h, float s, float v, FPlayerSkin *s
|
|||
SetRemap(table, i, r, g, b);
|
||||
}
|
||||
}
|
||||
|
||||
// Build lifegem translation
|
||||
if (alttable)
|
||||
}
|
||||
if (gameinfo.gametype == GAME_Hexen && alttable != NULL)
|
||||
{
|
||||
// Build Hexen's lifegem translation.
|
||||
|
||||
// Is the player's translation range the same as the gem's and we are using a
|
||||
// predefined translation? If so, then use the same one for the gem. Otherwise,
|
||||
// build one as per usual.
|
||||
if (colorset != NULL && start == 164 && end == 185)
|
||||
{
|
||||
*alttable = *table;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 164; i <= 185; ++i)
|
||||
{
|
||||
|
@ -1027,8 +1087,8 @@ static void R_CreatePlayerTranslation (float h, float s, float v, FPlayerSkin *s
|
|||
HSVtoRGB (&r, &g, &b, h, s*bases, v*basev);
|
||||
SetRemap(alttable, i, r, g, b);
|
||||
}
|
||||
alttable->UpdateNative();
|
||||
}
|
||||
alttable->UpdateNative();
|
||||
}
|
||||
table->UpdateNative();
|
||||
}
|
||||
|
@ -1042,10 +1102,11 @@ static void R_CreatePlayerTranslation (float h, float s, float v, FPlayerSkin *s
|
|||
void R_BuildPlayerTranslation (int player)
|
||||
{
|
||||
float h, s, v;
|
||||
FPlayerColorSet *colorset;
|
||||
|
||||
D_GetPlayerColor (player, &h, &s, &v);
|
||||
D_GetPlayerColor (player, &h, &s, &v, &colorset);
|
||||
|
||||
R_CreatePlayerTranslation (h, s, v,
|
||||
R_CreatePlayerTranslation (h, s, v, colorset,
|
||||
&skins[players[player].userinfo.skin],
|
||||
translationtables[TRANSLATION_Players][player],
|
||||
translationtables[TRANSLATION_PlayersExtra][player]);
|
||||
|
@ -1057,13 +1118,17 @@ void R_BuildPlayerTranslation (int player)
|
|||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void R_GetPlayerTranslation (int color, FPlayerSkin *skin, FRemapTable *table)
|
||||
void R_GetPlayerTranslation (int color, const FPlayerColorSet *colorset, FPlayerSkin *skin, FRemapTable *table)
|
||||
{
|
||||
float h, s, v;
|
||||
|
||||
if (colorset != NULL)
|
||||
{
|
||||
color = colorset->RepresentativeColor;
|
||||
}
|
||||
RGBtoHSV (RPART(color)/255.f, GPART(color)/255.f, BPART(color)/255.f,
|
||||
&h, &s, &v);
|
||||
|
||||
R_CreatePlayerTranslation (h, s, v, skin, table, NULL);
|
||||
R_CreatePlayerTranslation (h, s, v, colorset, skin, table, NULL);
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ struct FRemapTable
|
|||
PalEntry *Palette; // The ideal palette this maps to
|
||||
FNativePalette *Native; // The Palette stored in a HW texture
|
||||
int NumEntries; // # of elements in this table (usually 256)
|
||||
bool Inactive; // This table is inactive and should be treated as if it was passed as NULL
|
||||
|
||||
private:
|
||||
void Free();
|
||||
|
|
|
@ -56,13 +56,15 @@ struct RFFInfo
|
|||
|
||||
struct RFFLump
|
||||
{
|
||||
BYTE IDontKnow[16];
|
||||
DWORD DontKnow1[4];
|
||||
DWORD FilePos;
|
||||
DWORD Size;
|
||||
BYTE IStillDontKnow[8];
|
||||
DWORD DontKnow2;
|
||||
DWORD Time;
|
||||
BYTE Flags;
|
||||
char Extension[3];
|
||||
char Name[8+4]; // 4 bytes that I don't know what they are for
|
||||
char Name[8];
|
||||
DWORD IndexNum; // Used by .sfx, possibly others
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
|
@ -75,6 +77,10 @@ struct FRFFLump : public FUncompressedLump
|
|||
{
|
||||
virtual FileReader *GetReader();
|
||||
virtual int FillCache();
|
||||
|
||||
DWORD IndexNum;
|
||||
|
||||
int GetIndexNum() const { return IndexNum; }
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
|
@ -149,33 +155,34 @@ bool FRFFFile::Open(bool quiet)
|
|||
if (!quiet) Printf(", %d lumps\n", NumLumps);
|
||||
for (DWORD i = 0; i < NumLumps; ++i)
|
||||
{
|
||||
if (lumps[i].Extension[0] == 'S' && lumps[i].Extension[1] == 'F' &&
|
||||
lumps[i].Extension[2] == 'X')
|
||||
{
|
||||
Lumps[i].Namespace = ns_bloodsfx;
|
||||
}
|
||||
else if (lumps[i].Extension[0] == 'R' && lumps[i].Extension[1] == 'A' &&
|
||||
lumps[i].Extension[2] == 'W')
|
||||
{
|
||||
Lumps[i].Namespace = ns_bloodraw;
|
||||
}
|
||||
else
|
||||
{
|
||||
Lumps[i].Namespace = ns_global;
|
||||
}
|
||||
|
||||
Lumps[i].Position = LittleLong(lumps[i].FilePos);
|
||||
Lumps[i].LumpSize = LittleLong(lumps[i].Size);
|
||||
Lumps[i].Owner = this;
|
||||
if (lumps[i].Flags & 0x10) Lumps[i].Flags |= LUMPF_BLOODCRYPT;
|
||||
|
||||
// Rearrange the name and extension in a part of the lump record
|
||||
// that I don't have any use for in order to cnstruct the fullname.
|
||||
lumps[i].Name[8] = '\0';
|
||||
strcpy ((char *)lumps[i].IDontKnow, lumps[i].Name);
|
||||
strcat ((char *)lumps[i].IDontKnow, ".");
|
||||
strcat ((char *)lumps[i].IDontKnow, lumps[i].Extension);
|
||||
Lumps[i].LumpNameSetup((char *)lumps[i].IDontKnow);
|
||||
if (lumps[i].Flags & 0x10)
|
||||
{
|
||||
Lumps[i].Flags |= LUMPF_BLOODCRYPT;
|
||||
}
|
||||
Lumps[i].IndexNum = LittleLong(lumps[i].IndexNum);
|
||||
// Rearrange the name and extension to construct the fullname.
|
||||
char name[13];
|
||||
strncpy(name, lumps[i].Name, 8);
|
||||
name[8] = 0;
|
||||
size_t len = strlen(name);
|
||||
assert(len + 4 <= 12);
|
||||
name[len+0] = '.';
|
||||
name[len+1] = lumps[i].Extension[0];
|
||||
name[len+2] = lumps[i].Extension[1];
|
||||
name[len+3] = lumps[i].Extension[2];
|
||||
name[len+4] = 0;
|
||||
Lumps[i].LumpNameSetup(name);
|
||||
if (name[len+1] == 'S' && name[len+2] == 'F' && name[len+3] == 'X')
|
||||
{
|
||||
Lumps[i].Namespace = ns_bloodsfx;
|
||||
}
|
||||
else if (name[len+1] == 'R' && name[len+2] == 'A' && name[len+3] == 'W')
|
||||
{
|
||||
Lumps[i].Namespace = ns_bloodraw;
|
||||
}
|
||||
}
|
||||
delete[] lumps;
|
||||
return true;
|
||||
|
@ -183,7 +190,10 @@ bool FRFFFile::Open(bool quiet)
|
|||
|
||||
FRFFFile::~FRFFFile()
|
||||
{
|
||||
if (Lumps != NULL) delete [] Lumps;
|
||||
if (Lumps != NULL)
|
||||
{
|
||||
delete[] Lumps;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -197,8 +207,14 @@ FileReader *FRFFLump::GetReader()
|
|||
{
|
||||
// Don't return the reader if this lump is encrypted
|
||||
// In that case always force caching of the lump
|
||||
if (!(Flags & LUMPF_BLOODCRYPT)) return FUncompressedLump::GetReader();
|
||||
else return NULL;
|
||||
if (!(Flags & LUMPF_BLOODCRYPT))
|
||||
{
|
||||
return FUncompressedLump::GetReader();
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -41,6 +41,7 @@ struct FResourceLump
|
|||
virtual FileReader *GetReader();
|
||||
virtual FileReader *NewReader();
|
||||
virtual int GetFileOffset() { return -1; }
|
||||
virtual int GetIndexNum() const { return 0; }
|
||||
void LumpNameSetup(const char *iname);
|
||||
void CheckEmbedded();
|
||||
|
||||
|
|
|
@ -114,7 +114,7 @@ protected:
|
|||
void Free ();
|
||||
};
|
||||
|
||||
static struct AmbientSound
|
||||
struct FAmbientSound
|
||||
{
|
||||
unsigned type; // type of ambient sound
|
||||
int periodmin; // # of tics between repeats
|
||||
|
@ -122,7 +122,8 @@ static struct AmbientSound
|
|||
float volume; // relative volume of sound
|
||||
float attenuation;
|
||||
FString sound; // Logical name of sound to play
|
||||
} *Ambients[256];
|
||||
};
|
||||
TMap<int, FAmbientSound> Ambients;
|
||||
|
||||
enum SICommands
|
||||
{
|
||||
|
@ -509,6 +510,7 @@ int S_AddSoundLump (const char *logicalname, int lump)
|
|||
newsfx.Rolloff.RolloffType = ROLLOFF_Doom;
|
||||
newsfx.Rolloff.MinDistance = 0;
|
||||
newsfx.Rolloff.MaxDistance = 0;
|
||||
newsfx.LoopStart = -1;
|
||||
|
||||
return (int)S_sfx.Push (newsfx);
|
||||
}
|
||||
|
@ -836,15 +838,7 @@ static void S_ClearSoundData()
|
|||
S_UnloadSound(&S_sfx[i]);
|
||||
}
|
||||
S_sfx.Clear();
|
||||
|
||||
for(i = 0; i < countof(Ambients); i++)
|
||||
{
|
||||
if (Ambients[i] != NULL)
|
||||
{
|
||||
delete Ambients[i];
|
||||
Ambients[i] = NULL;
|
||||
}
|
||||
}
|
||||
Ambients.Clear();
|
||||
while (MusicVolumes != NULL)
|
||||
{
|
||||
FMusicVolume *me = MusicVolumes;
|
||||
|
@ -967,23 +961,10 @@ static void S_AddSNDINFO (int lump)
|
|||
// $ambient <num> <logical name> [point [atten] | surround | [world]]
|
||||
// <continuous | random <minsecs> <maxsecs> | periodic <secs>>
|
||||
// <volume>
|
||||
AmbientSound *ambient, dummy;
|
||||
FAmbientSound *ambient;
|
||||
|
||||
sc.MustGetNumber ();
|
||||
if (sc.Number < 0 || sc.Number > 255)
|
||||
{
|
||||
Printf ("Bad ambient index (%d)\n", sc.Number);
|
||||
ambient = &dummy;
|
||||
}
|
||||
else if (Ambients[sc.Number] == NULL)
|
||||
{
|
||||
ambient = new AmbientSound;
|
||||
Ambients[sc.Number] = ambient;
|
||||
}
|
||||
else
|
||||
{
|
||||
ambient = Ambients[sc.Number];
|
||||
}
|
||||
ambient = &Ambients[sc.Number];
|
||||
ambient->type = 0;
|
||||
ambient->periodmin = 0;
|
||||
ambient->periodmax = 0;
|
||||
|
@ -1366,18 +1347,15 @@ static void S_AddSNDINFO (int lump)
|
|||
|
||||
static void S_AddBloodSFX (int lumpnum)
|
||||
{
|
||||
char name[13];
|
||||
FMemLump sfxlump = Wads.ReadLump (lumpnum);
|
||||
FMemLump sfxlump = Wads.ReadLump(lumpnum);
|
||||
const FBloodSFX *sfx = (FBloodSFX *)sfxlump.GetMem();
|
||||
int rawlump = Wads.CheckNumForName (sfx->RawName, ns_bloodraw);
|
||||
int rawlump = Wads.CheckNumForName(sfx->RawName, ns_bloodraw);
|
||||
int sfxnum;
|
||||
|
||||
if (rawlump != -1)
|
||||
{
|
||||
Wads.GetLumpName (name, lumpnum);
|
||||
name[8] = 0;
|
||||
strcat (name, ".SFX");
|
||||
sfxnum = S_AddSound (name, rawlump);
|
||||
const char *name = Wads.GetLumpFullName(lumpnum);
|
||||
sfxnum = S_AddSound(name, rawlump);
|
||||
if (sfx->Format == 5)
|
||||
{
|
||||
S_sfx[sfxnum].bForce22050 = true;
|
||||
|
@ -1387,6 +1365,17 @@ static void S_AddBloodSFX (int lumpnum)
|
|||
S_sfx[sfxnum].bForce11025 = true;
|
||||
}
|
||||
S_sfx[sfxnum].bLoadRAW = true;
|
||||
S_sfx[sfxnum].LoopStart = LittleLong(sfx->LoopStart);
|
||||
// Make an ambient sound out of it, whether it has a loop point
|
||||
// defined or not. (Because none of the standard Blood ambient
|
||||
// sounds are explicitly defined as looping.)
|
||||
FAmbientSound *ambient = &Ambients[Wads.GetLumpIndexNum(lumpnum)];
|
||||
ambient->type = CONTINUOUS;
|
||||
ambient->periodmin = 0;
|
||||
ambient->periodmax = 0;
|
||||
ambient->volume = 1;
|
||||
ambient->attenuation = 1;
|
||||
ambient->sound = name;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1906,12 +1895,18 @@ public:
|
|||
protected:
|
||||
bool bActive;
|
||||
private:
|
||||
void SetTicker (struct AmbientSound *ambient);
|
||||
void SetTicker (struct FAmbientSound *ambient);
|
||||
int NextCheck;
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS (AAmbientSound)
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// AmbientSound :: Serialize
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void AAmbientSound::Serialize (FArchive &arc)
|
||||
{
|
||||
Super::Serialize (arc);
|
||||
|
@ -1948,6 +1943,11 @@ void AAmbientSound::Serialize (FArchive &arc)
|
|||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// AmbientSound :: Tick
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void AAmbientSound::Tick ()
|
||||
{
|
||||
|
@ -1956,17 +1956,47 @@ void AAmbientSound::Tick ()
|
|||
if (!bActive || gametic < NextCheck)
|
||||
return;
|
||||
|
||||
AmbientSound *ambient = Ambients[args[0]];
|
||||
FAmbientSound *ambient;
|
||||
int loop = 0;
|
||||
|
||||
ambient = Ambients.CheckKey(args[0]);
|
||||
if (ambient == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ((ambient->type & CONTINUOUS) == CONTINUOUS)
|
||||
{
|
||||
loop = CHAN_LOOP;
|
||||
}
|
||||
|
||||
if (ambient->sound[0])
|
||||
if (ambient->sound.IsNotEmpty())
|
||||
{
|
||||
S_Sound(this, CHAN_BODY | loop, ambient->sound, ambient->volume, ambient->attenuation);
|
||||
// The second argument scales the ambient sound's volume.
|
||||
// 0 and 100 are normal volume. The maximum volume level
|
||||
// possible is always 1.
|
||||
float volscale = args[1] == 0 ? 1 : args[1] / 100.f;
|
||||
float usevol = clamp(ambient->volume * volscale, 0.f, 1.f);
|
||||
|
||||
// The third argument is the minimum distance for audible fading, and
|
||||
// the fourth argument is the maximum distance for audibility. Setting
|
||||
// either of these to 0 or setting min distance > max distance will
|
||||
// use the standard rolloff.
|
||||
if ((args[2] | args[3]) == 0 || args[2] > args[3])
|
||||
{
|
||||
S_Sound(this, CHAN_BODY | loop, ambient->sound, usevol, ambient->attenuation);
|
||||
}
|
||||
else
|
||||
{
|
||||
float min = float(args[2]), max = float(args[3]);
|
||||
// The fifth argument acts as a scalar for the preceding two, if it's non-zero.
|
||||
if (args[4] > 0)
|
||||
{
|
||||
min *= args[4];
|
||||
max *= args[4];
|
||||
}
|
||||
S_SoundMinMaxDist(this, CHAN_BODY | loop, ambient->sound, usevol, min, max);
|
||||
}
|
||||
if (!loop)
|
||||
{
|
||||
SetTicker (ambient);
|
||||
|
@ -1982,8 +2012,13 @@ void AAmbientSound::Tick ()
|
|||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// AmbientSound :: SetTicker
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void AAmbientSound::SetTicker (struct AmbientSound *ambient)
|
||||
void AAmbientSound::SetTicker (struct FAmbientSound *ambient)
|
||||
{
|
||||
if ((ambient->type & CONTINUOUS) == CONTINUOUS)
|
||||
{
|
||||
|
@ -2001,17 +2036,31 @@ void AAmbientSound::SetTicker (struct AmbientSound *ambient)
|
|||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// AmbientSound :: BeginPlay
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void AAmbientSound::BeginPlay ()
|
||||
{
|
||||
Super::BeginPlay ();
|
||||
Activate (NULL);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// AmbientSound :: Activate
|
||||
//
|
||||
// Starts playing a sound (or does nothing of the sound is already playing).
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void AAmbientSound::Activate (AActor *activator)
|
||||
{
|
||||
Super::Activate (activator);
|
||||
|
||||
AmbientSound *amb = Ambients[args[0]];
|
||||
FAmbientSound *amb = Ambients.CheckKey(args[0]);
|
||||
|
||||
if (amb == NULL)
|
||||
{
|
||||
|
@ -2040,13 +2089,23 @@ void AAmbientSound::Activate (AActor *activator)
|
|||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// AmbientSound :: Deactivate
|
||||
//
|
||||
// Stops playing CONTINUOUS sounds immediately. Also prevents further
|
||||
// occurrences of repeated sounds.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void AAmbientSound::Deactivate (AActor *activator)
|
||||
{
|
||||
Super::Deactivate (activator);
|
||||
if (bActive)
|
||||
{
|
||||
bActive = false;
|
||||
if ((Ambients[args[0]]->type & CONTINUOUS) == CONTINUOUS)
|
||||
FAmbientSound *ambient = Ambients.CheckKey(args[0]);
|
||||
if (ambient != NULL && (ambient->type & CONTINUOUS) == CONTINUOUS)
|
||||
{
|
||||
S_StopSound (this, CHAN_BODY);
|
||||
}
|
||||
|
|
|
@ -198,7 +198,7 @@ int FPlayList::Advance ()
|
|||
|
||||
int FPlayList::Backup ()
|
||||
{
|
||||
if (--Position < 0)
|
||||
if (Position-- == 0)
|
||||
{
|
||||
Position = Songs.Size() - 1;
|
||||
}
|
||||
|
|
|
@ -108,7 +108,7 @@ static void CalcPosVel(int type, const AActor *actor, const sector_t *sector, co
|
|||
static void CalcSectorSoundOrg(const sector_t *sec, int channum, fixed_t *x, fixed_t *y, fixed_t *z);
|
||||
static void CalcPolyobjSoundOrg(const FPolyObj *poly, fixed_t *x, fixed_t *y, fixed_t *z);
|
||||
static FSoundChan *S_StartSound(AActor *mover, const sector_t *sec, const FPolyObj *poly,
|
||||
const FVector3 *pt, int channel, FSoundID sound_id, float volume, float attenuation);
|
||||
const FVector3 *pt, int channel, FSoundID sound_id, float volume, float attenuation, FRolloffInfo *rolloff);
|
||||
static void S_SetListener(SoundListener &listener, AActor *listenactor);
|
||||
|
||||
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||
|
@ -165,6 +165,7 @@ void S_NoiseDebug (void)
|
|||
screen->DrawText (SmallFont, CR_GOLD, 340, y, "pri", TAG_DONE);
|
||||
screen->DrawText (SmallFont, CR_GOLD, 380, y, "flags", TAG_DONE);
|
||||
screen->DrawText (SmallFont, CR_GOLD, 460, y, "aud", TAG_DONE);
|
||||
screen->DrawText (SmallFont, CR_GOLD, 520, y, "pos", TAG_DONE);
|
||||
y += 8;
|
||||
|
||||
if (Channels == NULL)
|
||||
|
@ -253,6 +254,11 @@ void S_NoiseDebug (void)
|
|||
mysnprintf(temp, countof(temp), "%.4f", GSnd->GetAudibility(chan));
|
||||
screen->DrawText(SmallFont, color, 460, y, temp, TAG_DONE);
|
||||
|
||||
// Position
|
||||
mysnprintf(temp, countof(temp), "%u", GSnd->GetPosition(chan));
|
||||
screen->DrawText(SmallFont, color, 520, y, temp, TAG_DONE);
|
||||
|
||||
|
||||
y += 8;
|
||||
if (chan->PrevChan == &Channels)
|
||||
{
|
||||
|
@ -317,7 +323,6 @@ void S_InitData ()
|
|||
LastLocalSndInfo = LastLocalSndSeq = "";
|
||||
S_ParseSndInfo ();
|
||||
S_ParseSndSeq (-1);
|
||||
S_ParseReverbDef ();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -808,7 +813,8 @@ static void CalcPolyobjSoundOrg(const FPolyObj *poly, fixed_t *x, fixed_t *y, fi
|
|||
//==========================================================================
|
||||
|
||||
static FSoundChan *S_StartSound(AActor *actor, const sector_t *sec, const FPolyObj *poly,
|
||||
const FVector3 *pt, int channel, FSoundID sound_id, double volume, double attenuation)
|
||||
const FVector3 *pt, int channel, FSoundID sound_id, float volume, float attenuation,
|
||||
FRolloffInfo *forcedrolloff=NULL)
|
||||
{
|
||||
sfxinfo_t *sfx;
|
||||
int chanflags;
|
||||
|
@ -866,7 +872,7 @@ static FSoundChan *S_StartSound(AActor *actor, const sector_t *sec, const FPolyO
|
|||
sfx = &S_sfx[sound_id];
|
||||
|
||||
// Scale volume according to SNDINFO data.
|
||||
volume = MIN(volume * sfx->Volume, 1.0);
|
||||
volume = MIN(volume * sfx->Volume, 1.f);
|
||||
if (volume <= 0)
|
||||
return NULL;
|
||||
|
||||
|
@ -894,7 +900,10 @@ static FSoundChan *S_StartSound(AActor *actor, const sector_t *sec, const FPolyO
|
|||
near_limit = S_sfx[sound_id].NearLimit;
|
||||
limit_range = S_sfx[sound_id].LimitRange;
|
||||
}
|
||||
if (rolloff->MinDistance == 0) rolloff = &S_sfx[sound_id].Rolloff;
|
||||
if (rolloff->MinDistance == 0)
|
||||
{
|
||||
rolloff = &S_sfx[sound_id].Rolloff;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -904,13 +913,25 @@ static FSoundChan *S_StartSound(AActor *actor, const sector_t *sec, const FPolyO
|
|||
near_limit = S_sfx[sound_id].NearLimit;
|
||||
limit_range = S_sfx[sound_id].LimitRange;
|
||||
}
|
||||
if (rolloff->MinDistance == 0) rolloff = &S_sfx[sound_id].Rolloff;
|
||||
if (rolloff->MinDistance == 0)
|
||||
{
|
||||
rolloff = &S_sfx[sound_id].Rolloff;
|
||||
}
|
||||
}
|
||||
sfx = &S_sfx[sound_id];
|
||||
}
|
||||
|
||||
// If no valid rolloff was set use the global default
|
||||
if (rolloff->MinDistance == 0) rolloff = &S_Rolloff;
|
||||
// The passed rolloff overrides any sound-specific rolloff.
|
||||
if (forcedrolloff != NULL && forcedrolloff->MinDistance != 0)
|
||||
{
|
||||
rolloff = forcedrolloff;
|
||||
}
|
||||
|
||||
// If no valid rolloff was set, use the global default.
|
||||
if (rolloff->MinDistance == 0)
|
||||
{
|
||||
rolloff = &S_Rolloff;
|
||||
}
|
||||
|
||||
// If this is a singular sound, don't play it if it's already playing.
|
||||
if (sfx->bSingular && S_CheckSingular(sound_id))
|
||||
|
@ -1162,7 +1183,7 @@ void S_RestartSound(FSoundChan *chan)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void S_Sound (int channel, FSoundID sound_id, double volume, double attenuation)
|
||||
void S_Sound (int channel, FSoundID sound_id, float volume, float attenuation)
|
||||
{
|
||||
S_StartSound (NULL, NULL, NULL, NULL, channel, sound_id, volume, attenuation);
|
||||
}
|
||||
|
@ -1173,20 +1194,41 @@ void S_Sound (int channel, FSoundID sound_id, double volume, double attenuation)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void S_Sound (AActor *ent, int channel, FSoundID sound_id, double volume, double attenuation)
|
||||
void S_Sound (AActor *ent, int channel, FSoundID sound_id, float volume, float attenuation)
|
||||
{
|
||||
if (ent == NULL || ent->Sector->Flags & SECF_SILENT)
|
||||
return;
|
||||
S_StartSound (ent, NULL, NULL, NULL, channel, sound_id, volume, attenuation);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// S_SoundMinMaxDist - An actor is source
|
||||
//
|
||||
// Attenuation is specified as min and max distances, rather than a scalar.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void S_SoundMinMaxDist(AActor *ent, int channel, FSoundID sound_id, float volume, float mindist, float maxdist)
|
||||
{
|
||||
if (ent == NULL || ent->Sector->Flags & SECF_SILENT)
|
||||
return;
|
||||
|
||||
FRolloffInfo rolloff;
|
||||
|
||||
rolloff.RolloffType = ROLLOFF_Linear;
|
||||
rolloff.MinDistance = mindist;
|
||||
rolloff.MaxDistance = maxdist;
|
||||
S_StartSound(ent, NULL, NULL, NULL, channel, sound_id, volume, 1, &rolloff);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// S_Sound - A polyobject is source
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void S_Sound (const FPolyObj *poly, int channel, FSoundID sound_id, double volume, double attenuation)
|
||||
void S_Sound (const FPolyObj *poly, int channel, FSoundID sound_id, float volume, float attenuation)
|
||||
{
|
||||
S_StartSound (NULL, NULL, poly, NULL, channel, sound_id, volume, attenuation);
|
||||
}
|
||||
|
@ -1197,7 +1239,7 @@ void S_Sound (const FPolyObj *poly, int channel, FSoundID sound_id, double volum
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void S_Sound (fixed_t x, fixed_t y, fixed_t z, int channel, FSoundID sound_id, double volume, double attenuation)
|
||||
void S_Sound (fixed_t x, fixed_t y, fixed_t z, int channel, FSoundID sound_id, float volume, float attenuation)
|
||||
{
|
||||
FVector3 pt(FIXED2FLOAT(x), FIXED2FLOAT(z), FIXED2FLOAT(y));
|
||||
S_StartSound (NULL, NULL, NULL, &pt, channel, sound_id, volume, attenuation);
|
||||
|
@ -1209,7 +1251,7 @@ void S_Sound (fixed_t x, fixed_t y, fixed_t z, int channel, FSoundID sound_id, d
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void S_Sound (const sector_t *sec, int channel, FSoundID sfxid, double volume, double attenuation)
|
||||
void S_Sound (const sector_t *sec, int channel, FSoundID sfxid, float volume, float attenuation)
|
||||
{
|
||||
S_StartSound (NULL, sec, NULL, NULL, channel, sfxid, volume, attenuation);
|
||||
}
|
||||
|
@ -1285,7 +1327,7 @@ sfxinfo_t *S_LoadSound(sfxinfo_t *sfx)
|
|||
}
|
||||
sfxstart = sfxdata + 8;
|
||||
}
|
||||
sfx->data = GSnd->LoadSoundRaw(sfxstart, len, frequency, 1, 8);
|
||||
sfx->data = GSnd->LoadSoundRaw(sfxstart, len, frequency, 1, 8, sfx->LoopStart);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1879,8 +1921,8 @@ static void S_SetListener(SoundListener &listener, AActor *listenactor)
|
|||
*/
|
||||
listener.velocity.Zero();
|
||||
listener.position.X = FIXED2FLOAT(listenactor->x);
|
||||
listener.position.Y = FIXED2FLOAT(listenactor->y);
|
||||
listener.position.Z = FIXED2FLOAT(listenactor->z);
|
||||
listener.position.Y = FIXED2FLOAT(listenactor->z);
|
||||
listener.position.Z = FIXED2FLOAT(listenactor->y);
|
||||
listener.underwater = listenactor->waterlevel == 3;
|
||||
assert(zones != NULL);
|
||||
listener.Environment = zones[listenactor->Sector->ZoneNumber].Environment;
|
||||
|
|
|
@ -59,6 +59,8 @@ struct sfxinfo_t
|
|||
WORD bSingular:1;
|
||||
WORD bTentative:1;
|
||||
|
||||
int LoopStart; // -1 means no specific loop defined
|
||||
|
||||
unsigned int link;
|
||||
enum { NO_LINK = 0xffffffff };
|
||||
|
||||
|
@ -216,11 +218,12 @@ void S_PrecacheLevel ();
|
|||
void S_CacheSound (sfxinfo_t *sfx);
|
||||
|
||||
// Start sound for thing at <ent>
|
||||
void S_Sound (int channel, FSoundID sfxid, double volume, double attenuation);
|
||||
void S_Sound (AActor *ent, int channel, FSoundID sfxid, double volume, double attenuation);
|
||||
void S_Sound (const FPolyObj *poly, int channel, FSoundID sfxid, double volume, double attenuation);
|
||||
void S_Sound (const sector_t *sec, int channel, FSoundID sfxid, double volume, double attenuation);
|
||||
void S_Sound (fixed_t x, fixed_t y, fixed_t z, int channel, FSoundID sfxid, double volume, double attenuation);
|
||||
void S_Sound (int channel, FSoundID sfxid, float volume, float attenuation);
|
||||
void S_Sound (AActor *ent, int channel, FSoundID sfxid, float volume, float attenuation);
|
||||
void S_SoundMinMaxDist (AActor *ent, int channel, FSoundID sfxid, float volume, float mindist, float maxdist);
|
||||
void S_Sound (const FPolyObj *poly, int channel, FSoundID sfxid, float volume, float attenuation);
|
||||
void S_Sound (const sector_t *sec, int channel, FSoundID sfxid, float volume, float attenuation);
|
||||
void S_Sound (fixed_t x, fixed_t y, fixed_t z, int channel, FSoundID sfxid, float volume, float attenuation);
|
||||
|
||||
// sound channels
|
||||
// channel 0 never willingly overrides
|
||||
|
|
|
@ -1737,7 +1737,7 @@ bool FMODSoundRenderer::HandleChannelDelay(FMOD::Channel *chan, FISoundChannel *
|
|||
if (FMOD_OK == chan->getCurrentSound(&sound))
|
||||
{
|
||||
unsigned int len;
|
||||
if (FMOD_OK == sound->getLength(&len, FMOD_TIMEUNIT_MS))
|
||||
if (FMOD_OK == sound->getLength(&len, FMOD_TIMEUNIT_MS) && len)
|
||||
{
|
||||
difftime %= len;
|
||||
}
|
||||
|
@ -1994,11 +1994,11 @@ void FMODSoundRenderer::UpdateListener(SoundListener *listener)
|
|||
// Set velocity to 0 to prevent crazy doppler shifts just from running.
|
||||
|
||||
vel.x = listener->velocity.X;
|
||||
vel.z = listener->velocity.Y;
|
||||
vel.y = listener->velocity.Z;
|
||||
vel.y = listener->velocity.Y;
|
||||
vel.z = listener->velocity.Z;
|
||||
pos.x = listener->position.X;
|
||||
pos.z = listener->position.Y;
|
||||
pos.y = listener->position.Z;
|
||||
pos.y = listener->position.Y;
|
||||
pos.z = listener->position.Z;
|
||||
|
||||
float angle = listener->angle;
|
||||
forward.x = cos(angle);
|
||||
|
@ -2190,12 +2190,16 @@ void FMODSoundRenderer::UpdateSounds()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
SoundHandle FMODSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits)
|
||||
SoundHandle FMODSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart)
|
||||
{
|
||||
FMOD_CREATESOUNDEXINFO exinfo;
|
||||
SoundHandle retval = { NULL };
|
||||
int numsamples;
|
||||
|
||||
if (length == 0) return retval;
|
||||
if (length <= 0)
|
||||
{
|
||||
return retval;
|
||||
}
|
||||
|
||||
InitCreateSoundExInfo(&exinfo);
|
||||
exinfo.length = length;
|
||||
|
@ -2212,14 +2216,17 @@ SoundHandle FMODSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int frequ
|
|||
|
||||
case -8:
|
||||
exinfo.format = FMOD_SOUND_FORMAT_PCM8;
|
||||
numsamples = length;
|
||||
break;
|
||||
|
||||
case 16:
|
||||
exinfo.format = FMOD_SOUND_FORMAT_PCM16;
|
||||
numsamples = length >> 1;
|
||||
break;
|
||||
|
||||
case 32:
|
||||
exinfo.format = FMOD_SOUND_FORMAT_PCM32;
|
||||
numsamples = length >> 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -2236,6 +2243,12 @@ SoundHandle FMODSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int frequ
|
|||
DPrintf("Failed to allocate sample: Error %d\n", result);
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (loopstart >= 0)
|
||||
{
|
||||
sample->setLoopPoints(loopstart, FMOD_TIMEUNIT_PCM, numsamples - 1, FMOD_TIMEUNIT_PCM);
|
||||
}
|
||||
|
||||
retval.data = sample;
|
||||
return retval;
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ public:
|
|||
void SetSfxVolume (float volume);
|
||||
void SetMusicVolume (float volume);
|
||||
SoundHandle LoadSound(BYTE *sfxdata, int length);
|
||||
SoundHandle LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits);
|
||||
SoundHandle LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart);
|
||||
void UnloadSound (SoundHandle sfx);
|
||||
unsigned int GetMSLength(SoundHandle sfx);
|
||||
unsigned int GetSampleLength(SoundHandle sfx);
|
||||
|
|
|
@ -112,7 +112,10 @@ CUSTOM_CVAR (Float, snd_musicvolume, 0.5f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
|||
else
|
||||
{
|
||||
// Set general music volume.
|
||||
GSnd->SetMusicVolume(clamp<float>(self * relative_volume, 0, 1));
|
||||
if (GSnd != NULL)
|
||||
{
|
||||
GSnd->SetMusicVolume(clamp<float>(self * relative_volume, 0, 1));
|
||||
}
|
||||
// For music not implemented through the digital sound system,
|
||||
// let them know about the change.
|
||||
if (currSong != NULL)
|
||||
|
|
|
@ -123,7 +123,7 @@ public:
|
|||
SoundHandle retval = { NULL };
|
||||
return retval;
|
||||
}
|
||||
SoundHandle LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits)
|
||||
SoundHandle LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart)
|
||||
{
|
||||
SoundHandle retval = { NULL };
|
||||
return retval;
|
||||
|
|
|
@ -92,7 +92,7 @@ public:
|
|||
virtual void SetSfxVolume (float volume) = 0;
|
||||
virtual void SetMusicVolume (float volume) = 0;
|
||||
virtual SoundHandle LoadSound(BYTE *sfxdata, int length) = 0;
|
||||
virtual SoundHandle LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits) = 0;
|
||||
virtual SoundHandle LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart) = 0;
|
||||
virtual void UnloadSound (SoundHandle sfx) = 0; // unloads a sound from memory
|
||||
virtual unsigned int GetMSLength(SoundHandle sfx) = 0; // Gets the length of a sound at its default frequency
|
||||
virtual unsigned int GetSampleLength(SoundHandle sfx) = 0; // Gets the length of a sound at its default frequency
|
||||
|
|
|
@ -171,7 +171,7 @@ static BYTE CheatDigitalCafe[] = { 'd','i','g','i','t','a','l','c','a','f','e',2
|
|||
static BYTE CheatJoshuaStorms[] = { 'j','o','s','h','u','a','s','t','o','r','m','s',255 };
|
||||
static BYTE CheatLeeSnyder[] = { 'l','e','e','s','n','y','d','e','r',0,0,255 };
|
||||
static BYTE CheatKimHyers[] = { 'k','i','m','h','y','e','r','s',255 };
|
||||
static BYTE CheatShrrill[] = { 's','h','r','r','i','l','l',255 };
|
||||
static BYTE CheatShrrill[] = { 's','h','e','r','r','i','l','l',255 };
|
||||
|
||||
static BYTE CheatTNTem[] = { 't','n','t','e','m',255 };
|
||||
|
||||
|
@ -274,8 +274,8 @@ static cheatseq_t ChexCheats[] =
|
|||
{ CheatKimHyers, 0, 1, 0, {0,0}, Cht_MyPos },
|
||||
{ CheatShrrill, 0, 0, 0, {0,0}, Cht_AutoMap },
|
||||
{ CheatDavidBrus, 0, 0, 0, {CHT_IDDQD,0}, Cht_Generic },
|
||||
{ CheatMikeKoenigs, 0, 0, 0, {CHT_IDKFA,0}, Cht_Generic },
|
||||
{ CheatScottHolman, 0, 0, 0, {CHT_IDFA,0}, Cht_Generic },
|
||||
{ CheatScottHolman, 0, 0, 0, {CHT_IDKFA,0}, Cht_Generic },
|
||||
{ CheatMikeKoenigs, 0, 0, 0, {CHT_IDFA,0}, Cht_Generic },
|
||||
{ CheatCharlesJacobi, 0, 0, 0, {CHT_NOCLIP,0}, Cht_Generic },
|
||||
{ CheatAndrewBenson, 0, 0, 0, {CHT_BEHOLDV,0}, Cht_Generic },
|
||||
{ CheatDeanHyers, 0, 0, 0, {CHT_BEHOLDS,0}, Cht_Generic },
|
||||
|
|
|
@ -745,7 +745,11 @@ protected:
|
|||
Node *mp = MainPosition(key), **mpp;
|
||||
HashTraits Traits;
|
||||
|
||||
if (!mp->IsNil() && !Traits.Compare(mp->Pair.Key, key)) /* the key is in its main position */
|
||||
if (mp->IsNil())
|
||||
{
|
||||
/* the key is definitely not present, because there is nothing at its main position */
|
||||
}
|
||||
else if (!Traits.Compare(mp->Pair.Key, key)) /* the key is in its main position */
|
||||
{
|
||||
if (mp->Next != NULL) /* move next node to its main position */
|
||||
{
|
||||
|
|
|
@ -158,7 +158,7 @@ const BYTE *FBuildTexture::GetColumn (unsigned int column, const Span **spans_ou
|
|||
//
|
||||
//===========================================================================
|
||||
|
||||
static void AddTiles (void *tiles)
|
||||
void AddTiles (void *tiles)
|
||||
{
|
||||
// int numtiles = LittleLong(((DWORD *)tiles)[1]); // This value is not reliable
|
||||
int tilestart = LittleLong(((DWORD *)tiles)[2]);
|
||||
|
@ -224,29 +224,29 @@ static void AddTiles (void *tiles)
|
|||
if (rotType == 1)
|
||||
{
|
||||
spriteframe_t rot;
|
||||
rot.Texture[0] = texnum;
|
||||
rot.Texture[0] =
|
||||
rot.Texture[1] = texnum;
|
||||
for (int j = 1; j < 4; ++j)
|
||||
{
|
||||
rot.Texture[j*2] = texnum + j;
|
||||
rot.Texture[j*2+1] = texnum + j;
|
||||
rot.Texture[16-j*2] = texnum + j;
|
||||
rot.Texture[17-j*2] = texnum + j;
|
||||
rot.Texture[j*2] =
|
||||
rot.Texture[j*2+1] =
|
||||
rot.Texture[16-j*2] =
|
||||
rot.Texture[17-j*2] = texnum.GetIndex() + j;
|
||||
}
|
||||
rot.Texture[8] = texnum + 4;
|
||||
rot.Texture[9] = texnum + 4;
|
||||
rot.Texture[8] =
|
||||
rot.Texture[9] = texnum.GetIndex() + 4;
|
||||
rot.Flip = 0x00FC;
|
||||
tex->Rotations = SpriteFrames.Push (rot);
|
||||
}
|
||||
else if (rotType == 2)
|
||||
{
|
||||
spriteframe_t rot;
|
||||
rot.Texture[0] = texnum;
|
||||
rot.Texture[0] =
|
||||
rot.Texture[1] = texnum;
|
||||
for (int j = 1; j < 8; ++j)
|
||||
{
|
||||
rot.Texture[16-j*2] = texnum + j;
|
||||
rot.Texture[17-j*2] = texnum + j;
|
||||
rot.Texture[16-j*2] =
|
||||
rot.Texture[17-j*2] = texnum.GetIndex() + j;
|
||||
}
|
||||
rot.Flip = 0;
|
||||
tex->Rotations = SpriteFrames.Push (rot);
|
||||
|
|
|
@ -634,7 +634,7 @@ void FDDSTexture::DecompressDXT1 (FWadLump &lump, BYTE *tcbuf)
|
|||
bMasked = true;
|
||||
}
|
||||
// Pick colors from the palette for each of the four colors.
|
||||
if (!tcbuf) for (i = 3; i >= 0; --i)
|
||||
/*if (!tcbuf)*/ for (i = 3; i >= 0; --i)
|
||||
{
|
||||
palcol[i] = color[i].a ? RGB32k[color[i].r >> 3][color[i].g >> 3][color[i].b >> 3] : 0;
|
||||
}
|
||||
|
@ -652,18 +652,18 @@ void FDDSTexture::DecompressDXT1 (FWadLump &lump, BYTE *tcbuf)
|
|||
{
|
||||
break;
|
||||
}
|
||||
int ci = (yslice >> (x + x)) & 3;
|
||||
if (!tcbuf)
|
||||
{
|
||||
Pixels[oy + y + (ox + x) * Height] = palcol[(yslice >> (x + x)) & 3];
|
||||
Pixels[oy + y + (ox + x) * Height] = palcol[ci];
|
||||
}
|
||||
else
|
||||
{
|
||||
BYTE * tcp = &tcbuf[ox + x + (oy + y) * Width*4];
|
||||
int c = (yslice >> (x + x)) & 3;
|
||||
tcp[0] = color[c].r;
|
||||
tcp[1] = color[c].g;
|
||||
tcp[2] = color[c].b;
|
||||
tcp[3] = color[c].a;
|
||||
BYTE * tcp = &tcbuf[(ox + x)*4 + (oy + y) * Width*4];
|
||||
tcp[0] = color[ci].r;
|
||||
tcp[1] = color[ci].g;
|
||||
tcp[2] = color[ci].b;
|
||||
tcp[3] = color[ci].a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -740,7 +740,7 @@ void FDDSTexture::DecompressDXT3 (FWadLump &lump, bool premultiplied, BYTE *tcbu
|
|||
}
|
||||
else
|
||||
{
|
||||
BYTE * tcp = &tcbuf[ox + x + (oy + y) * Width*4];
|
||||
BYTE * tcp = &tcbuf[(ox + x)*4 + (oy + y) * Width*4];
|
||||
int c = (yslice >> (x + x)) & 3;
|
||||
tcp[0] = color[c].r;
|
||||
tcp[1] = color[c].g;
|
||||
|
@ -769,7 +769,7 @@ void FDDSTexture::DecompressDXT5 (FWadLump &lump, bool premultiplied, BYTE *tcbu
|
|||
BYTE *block;
|
||||
PalEntry color[4];
|
||||
BYTE palcol[4];
|
||||
DWORD yalphaslice;
|
||||
DWORD yalphaslice = 0;
|
||||
int ox, oy, x, y, i;
|
||||
|
||||
for (oy = 0; oy < Height; oy += 4)
|
||||
|
@ -831,7 +831,7 @@ void FDDSTexture::DecompressDXT5 (FWadLump &lump, bool premultiplied, BYTE *tcbu
|
|||
break;
|
||||
}
|
||||
// Alpha values are stored in 3 bytes for 2 rows
|
||||
if ((y & 0) == 0)
|
||||
if ((y & 1) == 0)
|
||||
{
|
||||
yalphaslice = block[y*3] | (block[y*3+1] << 8) | (block[y*3+2] << 16);
|
||||
}
|
||||
|
@ -853,7 +853,7 @@ void FDDSTexture::DecompressDXT5 (FWadLump &lump, bool premultiplied, BYTE *tcbu
|
|||
}
|
||||
else
|
||||
{
|
||||
BYTE * tcp = &tcbuf[ox + x + (oy + y) * Width*4];
|
||||
BYTE * tcp = &tcbuf[(ox + x)*4 + (oy + y) * Width*4];
|
||||
int c = (yslice >> (x + x)) & 3;
|
||||
tcp[0] = color[c].r;
|
||||
tcp[1] = color[c].g;
|
||||
|
|
|
@ -140,7 +140,9 @@ FTextureID FTextureManager::CheckForTexture (const char *name, int usetype, BITF
|
|||
else
|
||||
{
|
||||
if (firsttype == FTexture::TEX_Null ||
|
||||
(firsttype == FTexture::TEX_MiscPatch && tex->UseType != FTexture::TEX_Null)
|
||||
(firsttype == FTexture::TEX_MiscPatch &&
|
||||
tex->UseType != firsttype &&
|
||||
tex->UseType != FTexture::TEX_Null)
|
||||
)
|
||||
{
|
||||
firstfound = i;
|
||||
|
@ -1005,7 +1007,7 @@ FArchive &operator<< (FArchive &arc, FTextureID &tex)
|
|||
//==========================================================================
|
||||
//
|
||||
// FTextureID::operator+
|
||||
// Does not return incvalid texture IDs
|
||||
// Does not return invalid texture IDs
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
|
|
|
@ -41,6 +41,8 @@ protected:
|
|||
FTextureID(int num) { texnum = num; }
|
||||
private:
|
||||
int texnum;
|
||||
|
||||
friend void AddTiles (void *tiles);
|
||||
};
|
||||
|
||||
class FNullTextureID : public FTextureID
|
||||
|
|
|
@ -153,6 +153,12 @@ PClassActor *CreateNewActor(const FScriptPosition &sc, FName typeName, FName par
|
|||
ti->PainChances = new PainChanceList;
|
||||
*ti->PainChances = *parent->PainChances;
|
||||
}
|
||||
if (parent->ColorSets != NULL)
|
||||
{
|
||||
// copy color sets from parent
|
||||
ti->ColorSets = new FPlayerColorSetMap;
|
||||
*ti->ColorSets = *parent->ColorSets;
|
||||
}
|
||||
ti->Replacee = ti->Replacement = NULL;
|
||||
ti->DoomEdNum = -1;
|
||||
return ti;
|
||||
|
|
|
@ -1280,7 +1280,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomRailgun)
|
|||
self->target->x,
|
||||
self->target->y);
|
||||
}
|
||||
self->pitch = P_AimLineAttack (self, self->angle, MISSILERANGE, &linetarget, ANGLE_1*60, false, false, false, aim ? self->target : NULL);
|
||||
self->pitch = P_AimLineAttack (self, self->angle, MISSILERANGE, &linetarget, ANGLE_1*60, 0, aim ? self->target : NULL);
|
||||
if (linetarget == NULL && aim)
|
||||
{
|
||||
// We probably won't hit the target, but aim at it anyway so we don't look stupid.
|
||||
|
@ -2016,7 +2016,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckSight)
|
|||
|
||||
for (int i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i] && P_CheckSight(players[i].camera, self, true))
|
||||
if (playeringame[i] && P_CheckSight(players[i].camera, self, SF_IGNOREVISIBILITY))
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2024,6 +2024,61 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckSight)
|
|||
return 0;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// A_CheckSightOrRange
|
||||
// Jumps if this actor is out of range of all players *and* out of sight.
|
||||
// Useful for maps with many multi-actor special effects.
|
||||
//
|
||||
//===========================================================================
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckSightOrRange)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
PARAM_FLOAT(range);
|
||||
PARAM_STATE(jump);
|
||||
|
||||
ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains!
|
||||
|
||||
range = range * range * (double(FRACUNIT) * FRACUNIT); // no need for square roots
|
||||
for (int i = 0; i < MAXPLAYERS; ++i)
|
||||
{
|
||||
if (playeringame[i])
|
||||
{
|
||||
AActor *camera = players[i].camera;
|
||||
|
||||
// Check distance first, since it's cheaper than checking sight.
|
||||
double dx = self->x - camera->x;
|
||||
double dy = self->y - camera->y;
|
||||
double dz;
|
||||
fixed_t eyez = (camera->z + camera->height - (camera->height>>2)); // same eye height as P_CheckSight
|
||||
if (eyez > self->z + self->height)
|
||||
{
|
||||
dz = self->z + self->height - eyez;
|
||||
}
|
||||
else if (eyez < self->z)
|
||||
{
|
||||
dz = self->z - eyez;
|
||||
}
|
||||
else
|
||||
{
|
||||
dz = 0;
|
||||
}
|
||||
if ((dx*dx) + (dy*dy) + (dz*dz) <= range)
|
||||
{ // Within range
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Now check LOS.
|
||||
if (P_CheckSight(camera, self, SF_IGNOREVISIBILITY))
|
||||
{ // Visible
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
ACTION_JUMP(jump);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
|
@ -2493,7 +2548,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS)
|
|||
if (target == NULL)
|
||||
return 0; // [KS] Let's not call P_CheckSight unnecessarily in this case.
|
||||
|
||||
if (!P_CheckSight (self, target, 1))
|
||||
if (!P_CheckSight (self, target, SF_IGNOREVISIBILITY))
|
||||
return 0;
|
||||
|
||||
if (fov && (fov < ANGLE_MAX))
|
||||
|
@ -2555,7 +2610,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfInTargetLOS)
|
|||
if (target == NULL)
|
||||
return 0; // [KS] Let's not call P_CheckSight unnecessarily in this case.
|
||||
|
||||
if (!P_CheckSight (target, self, 1))
|
||||
if (!P_CheckSight (target, self, SF_IGNOREVISIBILITY))
|
||||
return 0;
|
||||
|
||||
if (fov && (fov < ANGLE_MAX))
|
||||
|
@ -2963,7 +3018,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_MonsterRefire)
|
|||
if (self->target == NULL
|
||||
|| P_HitFriend (self)
|
||||
|| self->target->health <= 0
|
||||
|| !P_CheckSight(self, self->target, 0) )
|
||||
|| !P_CheckSight (self, self->target, SF_SEEPASTBLOCKEVERYTHING|SF_SEEPASTSHOOTABLELINES) )
|
||||
{
|
||||
ACTION_JUMP(jump);
|
||||
}
|
||||
|
@ -3132,16 +3187,16 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetUserVar)
|
|||
PARAM_NAME (varname);
|
||||
PARAM_INT (value);
|
||||
|
||||
PSymbolVariable *var = dyn_cast<PSymbolVariable>(self->GetClass()->Symbols.FindSymbol(varname, true));
|
||||
PSymbolVariable *var = dyn_cast<PSymbolVariable>(stateowner->GetClass()->Symbols.FindSymbol(varname, true));
|
||||
|
||||
if (var == NULL || !var->bUserVar || var->ValueType.Type != VAL_Int)
|
||||
{
|
||||
Printf("%s is not a user variable in class %s\n", varname.GetChars(),
|
||||
self->GetClass()->TypeName.GetChars());
|
||||
stateowner->GetClass()->TypeName.GetChars());
|
||||
return 0;
|
||||
}
|
||||
// Set the value of the specified user variable.
|
||||
*(int *)(reinterpret_cast<BYTE *>(self) + var->offset) = value;
|
||||
*(int *)(reinterpret_cast<BYTE *>(stateowner) + var->offset) = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -3158,22 +3213,22 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetUserArray)
|
|||
PARAM_INT (pos);
|
||||
PARAM_INT (value);
|
||||
|
||||
PSymbolVariable *var = dyn_cast<PSymbolVariable>(self->GetClass()->Symbols.FindSymbol(varname, true));
|
||||
PSymbolVariable *var = dyn_cast<PSymbolVariable>(stateowner->GetClass()->Symbols.FindSymbol(varname, true));
|
||||
|
||||
if (var == NULL || !var->bUserVar || var->ValueType.Type != VAL_Array || var->ValueType.BaseType != VAL_Int)
|
||||
{
|
||||
Printf("%s is not a user array in class %s\n", varname.GetChars(),
|
||||
self->GetClass()->TypeName.GetChars());
|
||||
stateowner->GetClass()->TypeName.GetChars());
|
||||
return 0;
|
||||
}
|
||||
if (pos < 0 || pos >= var->ValueType.size)
|
||||
{
|
||||
Printf("%d is out of bounds in array %s in class %s\n", pos, varname.GetChars(),
|
||||
self->GetClass()->TypeName.GetChars());
|
||||
stateowner->GetClass()->TypeName.GetChars());
|
||||
return 0;
|
||||
}
|
||||
// Set the value of the specified user array at index pos.
|
||||
((int *)(reinterpret_cast<BYTE *>(self) + var->offset))[pos] = value;
|
||||
((int *)(reinterpret_cast<BYTE *>(stateowner) + var->offset))[pos] = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -310,6 +310,7 @@ static FFlagDef WeaponFlags[] =
|
|||
DEFINE_FLAG(WIF, NOAUTOAIM, AWeapon, WeaponFlags),
|
||||
|
||||
DEFINE_DUMMY_FLAG(NOLMS),
|
||||
DEFINE_DUMMY_FLAG(ALLOW_WITH_RESPAWN_INVUL),
|
||||
};
|
||||
|
||||
static FFlagDef PlayerPawnFlags[] =
|
||||
|
@ -612,3 +613,4 @@ void InitThingdef()
|
|||
qsort(&variables[0], variables.Size(), sizeof(variables[0]), varcmp);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -370,8 +370,7 @@ DEFINE_PROPERTY(painchance, ZI, Actor)
|
|||
if (!stricmp(str, "Normal")) painType = NAME_None;
|
||||
else painType=str;
|
||||
|
||||
if (info->PainChances == NULL) info->PainChances=new PainChanceList;
|
||||
(*info->PainChances)[painType] = (BYTE)id;
|
||||
info->SetPainChance(painType, id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -568,6 +567,15 @@ DEFINE_PROPERTY(howlsound, S, Actor)
|
|||
static_cast<PClassActor *>(info)->HowlSound = str;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//==========================================================================
|
||||
DEFINE_PROPERTY(crushpainsound, S, Actor)
|
||||
{
|
||||
PROP_STRING_PARM(str, 0);
|
||||
defaults->CrushPainSound = str;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//==========================================================================
|
||||
|
@ -978,13 +986,11 @@ DEFINE_PROPERTY(damagefactor, ZF, Actor)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (info->DamageFactors == NULL) info->DamageFactors=new DmgFactors;
|
||||
|
||||
FName dmgType;
|
||||
if (!stricmp(str, "Normal")) dmgType = NAME_None;
|
||||
else dmgType=str;
|
||||
|
||||
(*info->DamageFactors)[dmgType]=id;
|
||||
info->SetDamageFactor(dmgType, id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1606,6 +1612,15 @@ DEFINE_CLASS_PROPERTY(slotpriority, F, Weapon)
|
|||
static_cast<PClassWeapon *>(info)->SlotPriority = i;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//==========================================================================
|
||||
DEFINE_CLASS_PROPERTY(preferredskin, S, Weapon)
|
||||
{
|
||||
PROP_STRING_PARM(str, 0);
|
||||
// NoOp - only for Skulltag compatibility
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//==========================================================================
|
||||
|
@ -1892,6 +1907,75 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, colorrange, I_I, PlayerPawn)
|
|||
static_cast<PClassPlayerPawn *>(info)->ColorRangeEnd = end;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//==========================================================================
|
||||
DEFINE_CLASS_PROPERTY_PREFIX(player, colorset, ISIII, PlayerPawn)
|
||||
{
|
||||
PROP_INT_PARM(setnum, 0);
|
||||
PROP_STRING_PARM(setname, 1);
|
||||
PROP_INT_PARM(rangestart, 2);
|
||||
PROP_INT_PARM(rangeend, 3);
|
||||
PROP_INT_PARM(representative_color, 4);
|
||||
|
||||
FPlayerColorSet color;
|
||||
color.Name = setname;
|
||||
color.Lump = -1;
|
||||
color.FirstColor = rangestart;
|
||||
color.LastColor = rangeend;
|
||||
color.RepresentativeColor = representative_color;
|
||||
|
||||
if (setnum < 0)
|
||||
{
|
||||
bag.ScriptPosition.Message(MSG_WARNING, "Color set number must not be negative.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
info->SetColorSet(setnum, &color);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//==========================================================================
|
||||
DEFINE_CLASS_PROPERTY_PREFIX(player, colorsetfile, ISSI, PlayerPawn)
|
||||
{
|
||||
PROP_INT_PARM(setnum, 0);
|
||||
PROP_STRING_PARM(setname, 1);
|
||||
PROP_STRING_PARM(rangefile, 2);
|
||||
PROP_INT_PARM(representative_color, 3);
|
||||
|
||||
FPlayerColorSet color;
|
||||
color.Name = setname;
|
||||
color.Lump = Wads.CheckNumForName(rangefile);
|
||||
color.RepresentativeColor = representative_color;
|
||||
if (setnum < 0)
|
||||
{
|
||||
bag.ScriptPosition.Message(MSG_WARNING, "Color set number must not be negative.\n");
|
||||
}
|
||||
else if (color.Lump >= 0)
|
||||
{
|
||||
info->SetColorSet(setnum, &color);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//==========================================================================
|
||||
DEFINE_CLASS_PROPERTY_PREFIX(player, clearcolorset, I, PlayerPawn)
|
||||
{
|
||||
PROP_INT_PARM(setnum, 0);
|
||||
|
||||
if (setnum < 0)
|
||||
{
|
||||
bag.ScriptPosition.Message(MSG_WARNING, "Color set number must not be negative.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
info->SetColorSet(setnum, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//==========================================================================
|
||||
|
|
|
@ -527,6 +527,10 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, double x, double y, DWORD tag
|
|||
|
||||
case DTA_Translation:
|
||||
parms->remap = va_arg(tags, FRemapTable *);
|
||||
if (parms->remap != NULL && parms->remap->Inactive)
|
||||
{ // If it's inactive, pretend we were passed NULL instead.
|
||||
parms->remap = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
case DTA_ColorOverlay:
|
||||
|
|
421
src/v_font.cpp
421
src/v_font.cpp
|
@ -130,7 +130,10 @@ protected:
|
|||
bool rescale, PalEntry *out_palette);
|
||||
void LoadFON1 (int lump, const BYTE *data);
|
||||
void LoadFON2 (int lump, const BYTE *data);
|
||||
void LoadBMF (int lump, const BYTE *data);
|
||||
void CreateFontFromPic (FTextureID picnum);
|
||||
|
||||
static int STACK_ARGS BMFCompare(const void *a, const void *b);
|
||||
};
|
||||
|
||||
class FSinglePicFont : public FFont
|
||||
|
@ -175,7 +178,7 @@ protected:
|
|||
class FFontChar2 : public FTexture
|
||||
{
|
||||
public:
|
||||
FFontChar2 (int sourcelump, const BYTE *sourceremap, int sourcepos, int width, int height);
|
||||
FFontChar2 (int sourcelump, const BYTE *sourceremap, int sourcepos, int width, int height, int leftofs=0, int topofs=0);
|
||||
~FFontChar2 ();
|
||||
|
||||
const BYTE *GetColumn (unsigned int column, const Span **spans_out);
|
||||
|
@ -261,12 +264,13 @@ FFont *V_GetFont(const char *name)
|
|||
|
||||
if (lump != -1)
|
||||
{
|
||||
char head[3];
|
||||
uint32 head;
|
||||
{
|
||||
FWadLump lumpy = Wads.OpenLumpNum (lump);
|
||||
lumpy.Read (head, 3);
|
||||
lumpy.Read (&head, 4);
|
||||
}
|
||||
if (head[0] == 'F' && head[1] == 'O' && head[2] == 'N')
|
||||
if ((head & MAKE_ID(255,255,255,0)) == MAKE_ID('F','O','N',0) ||
|
||||
head == MAKE_ID(0xE1,0xE6,0xD5,0x1A))
|
||||
{
|
||||
font = new FSingleLumpFont (name, lump);
|
||||
}
|
||||
|
@ -399,21 +403,26 @@ FFont::FFont (const char *name, const char *nametemplate, int first, int count,
|
|||
if (charlumps[i] != NULL)
|
||||
{
|
||||
Chars[i].Pic = new FFontChar1 (charlumps[i], PatchRemap);
|
||||
Chars[i].XMove = Chars[i].Pic->GetScaledWidth();
|
||||
}
|
||||
else
|
||||
{
|
||||
Chars[i].Pic = NULL;
|
||||
Chars[i].XMove = INT_MIN;
|
||||
}
|
||||
}
|
||||
|
||||
if ('N'-first>=0 && 'N'-first<count && Chars['N' - first].Pic)
|
||||
if ('N'-first >= 0 && 'N'-first < count && Chars['N' - first].Pic != NULL)
|
||||
{
|
||||
SpaceWidth = (Chars['N' - first].Pic->GetScaledWidth() + 1) / 2;
|
||||
SpaceWidth = (Chars['N' - first].XMove + 1) / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
SpaceWidth = 4;
|
||||
}
|
||||
|
||||
FixXMoves();
|
||||
|
||||
BuildTranslations (luminosity, identity, &TranslationParms[0][0], ActiveColors, NULL);
|
||||
|
||||
delete[] luminosity;
|
||||
|
@ -717,6 +726,33 @@ FRemapTable *FFont::GetColorTranslation (EColorRange range) const
|
|||
return &Ranges[range];
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FFont :: GetCharCode
|
||||
//
|
||||
// If the character code is in the font, returns it. If it is not, but it
|
||||
// is lowercase and has an uppercase variant present, return that. Otherwise
|
||||
// return -1.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int FFont::GetCharCode(int code, bool needpic) const
|
||||
{
|
||||
if (code >= FirstChar && code <= LastChar && (!needpic || Chars[code - FirstChar].Pic != NULL))
|
||||
{
|
||||
return code;
|
||||
}
|
||||
if (myislower[code])
|
||||
{
|
||||
code -= 32;
|
||||
if (code >= FirstChar && code <= LastChar && (!needpic || Chars[code - FirstChar].Pic != NULL))
|
||||
{
|
||||
return code;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FFont :: GetChar
|
||||
|
@ -725,31 +761,28 @@ FRemapTable *FFont::GetColorTranslation (EColorRange range) const
|
|||
|
||||
FTexture *FFont::GetChar (int code, int *const width) const
|
||||
{
|
||||
if (code < FirstChar ||
|
||||
code > LastChar ||
|
||||
Chars[code - FirstChar].Pic == NULL)
|
||||
code = GetCharCode(code, false);
|
||||
int xmove = SpaceWidth;
|
||||
|
||||
if (code >= 0)
|
||||
{
|
||||
if (myislower[code])
|
||||
code -= FirstChar;
|
||||
xmove = Chars[code].XMove;
|
||||
if (Chars[code].Pic == NULL)
|
||||
{
|
||||
code -= 32;
|
||||
if (code < FirstChar ||
|
||||
code > LastChar ||
|
||||
Chars[code - FirstChar].Pic == NULL)
|
||||
code = GetCharCode(code + FirstChar, true);
|
||||
if (code >= 0)
|
||||
{
|
||||
if (width != NULL) *width = SpaceWidth;
|
||||
return NULL;
|
||||
code -= FirstChar;
|
||||
xmove = Chars[code].XMove;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (width != NULL) *width = SpaceWidth;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
code -= FirstChar;
|
||||
if (width != NULL) *width = Chars[code].Pic->GetScaledWidth();
|
||||
return Chars[code].Pic;
|
||||
if (width != NULL)
|
||||
{
|
||||
*width = xmove;
|
||||
}
|
||||
return (code < 0) ? NULL : Chars[code].Pic;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -760,27 +793,8 @@ FTexture *FFont::GetChar (int code, int *const width) const
|
|||
|
||||
int FFont::GetCharWidth (int code) const
|
||||
{
|
||||
if (code < FirstChar ||
|
||||
code > LastChar ||
|
||||
Chars[code - FirstChar].Pic == NULL)
|
||||
{
|
||||
if (myislower[code])
|
||||
{
|
||||
code -= 32;
|
||||
if (code < FirstChar ||
|
||||
code > LastChar ||
|
||||
Chars[code - FirstChar].Pic == NULL)
|
||||
{
|
||||
return SpaceWidth;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return SpaceWidth;
|
||||
}
|
||||
}
|
||||
|
||||
return Chars[code - FirstChar].Pic->GetScaledWidth();
|
||||
code = GetCharCode(code, false);
|
||||
return (code < 0) ? SpaceWidth : Chars[code - FirstChar].XMove;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -858,7 +872,11 @@ FSingleLumpFont::FSingleLumpFont (const char *name, int lump)
|
|||
FMemLump data1 = Wads.ReadLump (lump);
|
||||
const BYTE *data = (const BYTE *)data1.GetMem();
|
||||
|
||||
if (data[0] != 'F' || data[1] != 'O' || data[2] != 'N' ||
|
||||
if (data[0] == 0xE1 && data[1] == 0xE6 && data[2] == 0xD5 && data[3] == 0x1A)
|
||||
{
|
||||
LoadBMF(lump, data);
|
||||
}
|
||||
else if (data[0] != 'F' || data[1] != 'O' || data[2] != 'N' ||
|
||||
(data[3] != '1' && data[3] != '2'))
|
||||
{
|
||||
I_FatalError ("%s is not a recognizable font", name);
|
||||
|
@ -1012,6 +1030,7 @@ void FSingleLumpFont::LoadFON2 (int lump, const BYTE *data)
|
|||
for (i = 0; i < count; ++i)
|
||||
{
|
||||
int destSize = widths2[i] * FontHeight;
|
||||
Chars[i].XMove = widths2[i];
|
||||
if (destSize <= 0)
|
||||
{
|
||||
Chars[i].Pic = NULL;
|
||||
|
@ -1045,6 +1064,157 @@ void FSingleLumpFont::LoadFON2 (int lump, const BYTE *data)
|
|||
delete[] widths2;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FSingleLumpFont :: LoadBMF
|
||||
//
|
||||
// Loads a BMF font. The file format is described at
|
||||
// <http://bmf.wz.cz/bmf-format.htm>
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FSingleLumpFont::LoadBMF(int lump, const BYTE *data)
|
||||
{
|
||||
const BYTE *chardata;
|
||||
int numchars, count, totalwidth, nwidth;
|
||||
int infolen;
|
||||
int i, chari;
|
||||
BYTE raw_palette[256*3];
|
||||
PalEntry sort_palette[256];
|
||||
PalEntry local_palette[256];
|
||||
double luminosity[256];
|
||||
BYTE identity[256];
|
||||
|
||||
FontHeight = data[5];
|
||||
GlobalKerning = (SBYTE)data[8];
|
||||
ActiveColors = data[16];
|
||||
SpaceWidth = -1;
|
||||
nwidth = -1;
|
||||
|
||||
infolen = data[17 + ActiveColors*3];
|
||||
chardata = data + 18 + ActiveColors*3 + infolen;
|
||||
numchars = chardata[0] + 256*chardata[1];
|
||||
chardata += 2;
|
||||
|
||||
// Scan for lowest and highest characters defined and total font width.
|
||||
FirstChar = 256;
|
||||
LastChar = 0;
|
||||
totalwidth = 0;
|
||||
for (i = chari = 0; i < numchars; ++i, chari += 6 + chardata[chari+1] * chardata[chari+2])
|
||||
{
|
||||
if ((chardata[chari+1] == 0 || chardata[chari+2] == 0) && chardata[chari+5] == 0)
|
||||
{ // Don't count empty characters.
|
||||
continue;
|
||||
}
|
||||
if (chardata[chari] < FirstChar)
|
||||
{
|
||||
FirstChar = chardata[chari];
|
||||
}
|
||||
if (chardata[chari] > LastChar)
|
||||
{
|
||||
LastChar = chardata[chari];
|
||||
}
|
||||
totalwidth += chardata[chari+1];
|
||||
}
|
||||
if (LastChar < FirstChar)
|
||||
{
|
||||
I_FatalError("BMF font defines no characters");
|
||||
}
|
||||
count = LastChar - FirstChar + 1;
|
||||
Chars = new CharData[count];
|
||||
for (i = 0; i < count; ++i)
|
||||
{
|
||||
Chars[i].Pic = NULL;
|
||||
Chars[i].XMove = INT_MIN;
|
||||
}
|
||||
|
||||
// BMF palettes are only six bits per component. Fix that.
|
||||
for (i = 0; i < ActiveColors*3; ++i)
|
||||
{
|
||||
raw_palette[i] = (data[17 + i] << 2) | (data[17 + i] >> 4);
|
||||
}
|
||||
|
||||
// Sort the palette by increasing brightness
|
||||
for (i = 0; i < ActiveColors; ++i)
|
||||
{
|
||||
PalEntry *pal = &sort_palette[i];
|
||||
pal->a = i; // Use alpha part to point back to original entry
|
||||
pal->r = raw_palette[i*3 + 0];
|
||||
pal->g = raw_palette[i*3 + 1];
|
||||
pal->b = raw_palette[i*3 + 2];
|
||||
}
|
||||
qsort(sort_palette + 1, ActiveColors - 1, sizeof(PalEntry), BMFCompare);
|
||||
|
||||
// Create the PatchRemap table from the sorted "alpha" values.
|
||||
PatchRemap = new BYTE[ActiveColors];
|
||||
PatchRemap[0] = 0;
|
||||
for (i = 1; i < ActiveColors; ++i)
|
||||
{
|
||||
PatchRemap[sort_palette[i].a] = i;
|
||||
}
|
||||
|
||||
FixupPalette(identity, luminosity, raw_palette, true, local_palette);
|
||||
|
||||
// Now scan through the characters again, creating glyphs for each one.
|
||||
for (i = chari = 0; i < numchars; ++i, chari += 6 + chardata[chari+1] * chardata[chari+2])
|
||||
{
|
||||
assert(chardata[chari] - FirstChar >= 0);
|
||||
assert(chardata[chari] - FirstChar < count);
|
||||
if (chardata[chari] == ' ')
|
||||
{
|
||||
SpaceWidth = chardata[chari+5];
|
||||
}
|
||||
else if (chardata[chari] == 'N')
|
||||
{
|
||||
nwidth = chardata[chari+5];
|
||||
}
|
||||
Chars[chardata[chari] - FirstChar].XMove = chardata[chari+5];
|
||||
if (chardata[chari+1] == 0 || chardata[chari+2] == 0)
|
||||
{ // Empty character: skip it.
|
||||
continue;
|
||||
}
|
||||
Chars[chardata[chari] - FirstChar].Pic = new FFontChar2(lump, PatchRemap, int(chardata + chari + 6 - data),
|
||||
chardata[chari+1], // width
|
||||
chardata[chari+2], // height
|
||||
-(SBYTE)chardata[chari+3], // x offset
|
||||
-(SBYTE)chardata[chari+4] // y offset
|
||||
);
|
||||
}
|
||||
|
||||
// If the font did not define a space character, determine a suitable space width now.
|
||||
if (SpaceWidth < 0)
|
||||
{
|
||||
if (nwidth >= 0)
|
||||
{
|
||||
SpaceWidth = nwidth;
|
||||
}
|
||||
else
|
||||
{
|
||||
SpaceWidth = totalwidth * 2 / (3 * count);
|
||||
}
|
||||
}
|
||||
|
||||
FixXMoves();
|
||||
BuildTranslations(luminosity, identity, &TranslationParms[0][0], ActiveColors, local_palette);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FSingleLumpFont :: BMFCompare STATIC
|
||||
//
|
||||
// Helper to sort BMF palettes.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int STACK_ARGS FSingleLumpFont::BMFCompare(const void *a, const void *b)
|
||||
{
|
||||
const PalEntry *pa = (const PalEntry *)a;
|
||||
const PalEntry *pb = (const PalEntry *)b;
|
||||
|
||||
return (pa->r * 299 + pa->g * 587 + pa->b * 114) -
|
||||
(pb->r * 299 + pb->g * 587 + pb->b * 114);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FSingleLumpFont :: CheckFON1Chars
|
||||
|
@ -1069,6 +1239,7 @@ void FSingleLumpFont::CheckFON1Chars (int lump, const BYTE *data, double *lumino
|
|||
int destSize = SpaceWidth * FontHeight;
|
||||
|
||||
Chars[i].Pic = new FFontChar2 (lump, PatchRemap, int(data_p - data), SpaceWidth, FontHeight);
|
||||
Chars[i].XMove = SpaceWidth;
|
||||
|
||||
// Advance to next char's data and count the used colors.
|
||||
do
|
||||
|
@ -1181,8 +1352,8 @@ FSinglePicFont::FSinglePicFont(const char *picname)
|
|||
FTexture *pic = TexMan[picnum];
|
||||
|
||||
Name = copystring(picname);
|
||||
FontHeight = pic->GetHeight();
|
||||
SpaceWidth = pic->GetWidth();
|
||||
FontHeight = pic->GetScaledHeight();
|
||||
SpaceWidth = pic->GetScaledWidth();
|
||||
GlobalKerning = 0;
|
||||
FirstChar = LastChar = 'A';
|
||||
ActiveColors = 0;
|
||||
|
@ -1332,14 +1503,14 @@ FFontChar1::~FFontChar1 ()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FFontChar2::FFontChar2 (int sourcelump, const BYTE *sourceremap, int sourcepos, int width, int height)
|
||||
FFontChar2::FFontChar2 (int sourcelump, const BYTE *sourceremap, int sourcepos, int width, int height, int leftofs, int topofs)
|
||||
: SourceLump (sourcelump), SourcePos (sourcepos), Pixels (0), Spans (0), SourceRemap(sourceremap)
|
||||
{
|
||||
UseType = TEX_FontChar;
|
||||
Width = width;
|
||||
Height = height;
|
||||
TopOffset = 0;
|
||||
LeftOffset = 0;
|
||||
LeftOffset = leftofs;
|
||||
TopOffset = topofs;
|
||||
CalcBitSize ();
|
||||
}
|
||||
|
||||
|
@ -1427,10 +1598,11 @@ void FFontChar2::MakeTexture ()
|
|||
FWadLump lump = Wads.OpenLumpNum (SourceLump);
|
||||
int destSize = Width * Height;
|
||||
BYTE max = 255;
|
||||
bool rle = true;
|
||||
|
||||
// This is to "fix" bad fonts
|
||||
{
|
||||
BYTE buff[8];
|
||||
BYTE buff[16];
|
||||
lump.Read (buff, 4);
|
||||
if (buff[3] == '2')
|
||||
{
|
||||
|
@ -1438,6 +1610,13 @@ void FFontChar2::MakeTexture ()
|
|||
max = buff[6];
|
||||
lump.Seek (SourcePos - 11, SEEK_CUR);
|
||||
}
|
||||
else if (buff[3] == 0x1A)
|
||||
{
|
||||
lump.Read(buff, 13);
|
||||
max = buff[12] - 1;
|
||||
lump.Seek (SourcePos - 17, SEEK_CUR);
|
||||
rle = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
lump.Seek (SourcePos - 4, SEEK_CUR);
|
||||
|
@ -1452,55 +1631,81 @@ void FFontChar2::MakeTexture ()
|
|||
int dest_adv = Height;
|
||||
int dest_rew = destSize - 1;
|
||||
|
||||
for (int y = Height; y != 0; --y)
|
||||
if (rle)
|
||||
{
|
||||
for (int x = Width; x != 0; )
|
||||
for (int y = Height; y != 0; --y)
|
||||
{
|
||||
if (runlen != 0)
|
||||
for (int x = Width; x != 0; )
|
||||
{
|
||||
BYTE color;
|
||||
|
||||
lump >> color;
|
||||
*dest_p = MIN (color, max);
|
||||
if (SourceRemap != NULL)
|
||||
{
|
||||
*dest_p = SourceRemap[*dest_p];
|
||||
}
|
||||
dest_p += dest_adv;
|
||||
x--;
|
||||
runlen--;
|
||||
}
|
||||
else if (setlen != 0)
|
||||
{
|
||||
*dest_p = setval;
|
||||
dest_p += dest_adv;
|
||||
x--;
|
||||
setlen--;
|
||||
}
|
||||
else
|
||||
{
|
||||
SBYTE code;
|
||||
|
||||
lump >> code;
|
||||
if (code >= 0)
|
||||
{
|
||||
runlen = code + 1;
|
||||
}
|
||||
else if (code != -128)
|
||||
if (runlen != 0)
|
||||
{
|
||||
BYTE color;
|
||||
|
||||
lump >> color;
|
||||
setlen = (-code) + 1;
|
||||
setval = MIN (color, max);
|
||||
color = MIN (color, max);
|
||||
if (SourceRemap != NULL)
|
||||
{
|
||||
setval = SourceRemap[setval];
|
||||
color = SourceRemap[color];
|
||||
}
|
||||
*dest_p = color;
|
||||
dest_p += dest_adv;
|
||||
x--;
|
||||
runlen--;
|
||||
}
|
||||
else if (setlen != 0)
|
||||
{
|
||||
*dest_p = setval;
|
||||
dest_p += dest_adv;
|
||||
x--;
|
||||
setlen--;
|
||||
}
|
||||
else
|
||||
{
|
||||
SBYTE code;
|
||||
|
||||
lump >> code;
|
||||
if (code >= 0)
|
||||
{
|
||||
runlen = code + 1;
|
||||
}
|
||||
else if (code != -128)
|
||||
{
|
||||
BYTE color;
|
||||
|
||||
lump >> color;
|
||||
setlen = (-code) + 1;
|
||||
setval = MIN (color, max);
|
||||
if (SourceRemap != NULL)
|
||||
{
|
||||
setval = SourceRemap[setval];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
dest_p -= dest_rew;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int y = Height; y != 0; --y)
|
||||
{
|
||||
for (int x = Width; x != 0; --x)
|
||||
{
|
||||
BYTE color;
|
||||
lump >> color;
|
||||
if (color > max)
|
||||
{
|
||||
color = max;
|
||||
}
|
||||
if (SourceRemap != NULL)
|
||||
{
|
||||
color = SourceRemap[color];
|
||||
}
|
||||
*dest_p = color;
|
||||
dest_p += dest_adv;
|
||||
}
|
||||
dest_p -= dest_rew;
|
||||
}
|
||||
dest_p -= dest_rew;
|
||||
}
|
||||
|
||||
if (destSize < 0)
|
||||
|
@ -1593,23 +1798,27 @@ FSpecialFont::FSpecialFont (const char *name, int first, int count, FTexture **l
|
|||
if (charlumps[i] != NULL)
|
||||
{
|
||||
Chars[i].Pic = new FFontChar1 (charlumps[i], PatchRemap);
|
||||
Chars[i].XMove = Chars[i].Pic->GetScaledWidth();
|
||||
}
|
||||
else
|
||||
{
|
||||
Chars[i].Pic = NULL;
|
||||
Chars[i].XMove = INT_MIN;
|
||||
}
|
||||
}
|
||||
|
||||
// Special fonts normally don't have all characters so be careful here!
|
||||
if ('N'-first>=0 && 'N'-first<count && Chars['N' - first].Pic)
|
||||
if ('N'-first >= 0 && 'N'-first < count && Chars['N' - first].Pic != NULL)
|
||||
{
|
||||
SpaceWidth = (Chars['N' - first].Pic->GetScaledWidth() + 1) / 2;
|
||||
SpaceWidth = (Chars['N' - first].XMove + 1) / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
SpaceWidth = 4;
|
||||
}
|
||||
|
||||
FixXMoves();
|
||||
|
||||
BuildTranslations (luminosity, identity, &TranslationParms[0][0], TotalColors, NULL);
|
||||
|
||||
// add the untranslated colors to the Ranges tables
|
||||
|
@ -1632,6 +1841,36 @@ FSpecialFont::FSpecialFont (const char *name, int first, int count, FTexture **l
|
|||
delete[] charlumps;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FFont :: FixXMoves
|
||||
//
|
||||
// If a font has gaps in its characters, set the missing characters'
|
||||
// XMoves to either SpaceWidth or the uppercase variant's XMove. Missing
|
||||
// XMoves must be initialized with INT_MIN beforehand.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FFont::FixXMoves()
|
||||
{
|
||||
for (int i = 0; i <= LastChar - FirstChar; ++i)
|
||||
{
|
||||
if (Chars[i].XMove == INT_MIN)
|
||||
{
|
||||
if (myislower[i + FirstChar])
|
||||
{
|
||||
int upper = i - 32;
|
||||
if (upper >= 0)
|
||||
{
|
||||
Chars[i].XMove = Chars[upper].XMove;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
Chars[i].XMove = SpaceWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
|
|
@ -94,11 +94,14 @@ public:
|
|||
int StringWidth (const BYTE *str) const;
|
||||
inline int StringWidth (const char *str) const { return StringWidth ((const BYTE *)str); }
|
||||
|
||||
int GetCharCode(int code, bool needpic) const;
|
||||
|
||||
protected:
|
||||
FFont ();
|
||||
|
||||
void BuildTranslations (const double *luminosity, const BYTE *identity,
|
||||
const void *ranges, int total_colors, const PalEntry *palette);
|
||||
void FixXMoves();
|
||||
|
||||
static int SimpleTranslation (BYTE *colorsused, BYTE *translation,
|
||||
BYTE *identity, double **luminosity);
|
||||
|
@ -110,6 +113,7 @@ protected:
|
|||
struct CharData
|
||||
{
|
||||
FTexture *Pic;
|
||||
int XMove;
|
||||
} *Chars;
|
||||
int ActiveColors;
|
||||
TArray<FRemapTable> Ranges;
|
||||
|
|
|
@ -276,7 +276,7 @@ int FFont::StringWidth (const BYTE *string) const
|
|||
++string;
|
||||
}
|
||||
}
|
||||
else if (*string != '\0')
|
||||
if (*string != '\0')
|
||||
{
|
||||
++string;
|
||||
}
|
||||
|
@ -317,14 +317,15 @@ FBrokenLines *V_BreakLines (FFont *font, int maxwidth, const BYTE *string)
|
|||
FBrokenLines lines[128]; // Support up to 128 lines (should be plenty)
|
||||
|
||||
const BYTE *space = NULL, *start = string;
|
||||
int i, c, w, nw;
|
||||
size_t i, ii;
|
||||
int c, w, nw;
|
||||
FString lastcolor, linecolor;
|
||||
bool lastWasSpace = false;
|
||||
int kerning = font->GetDefaultKerning ();
|
||||
|
||||
i = w = 0;
|
||||
|
||||
while ( (c = *string++) && i < 128 )
|
||||
while ( (c = *string++) && i < countof(lines) )
|
||||
{
|
||||
if (c == TEXTCOLOR_ESCAPE)
|
||||
{
|
||||
|
@ -400,7 +401,7 @@ FBrokenLines *V_BreakLines (FFont *font, int maxwidth, const BYTE *string)
|
|||
}
|
||||
|
||||
// String here is pointing one character after the '\0'
|
||||
if (i < 128 && --string - start >= 1)
|
||||
if (i < countof(lines) && --string - start >= 1)
|
||||
{
|
||||
const BYTE *s = start;
|
||||
|
||||
|
@ -418,11 +419,11 @@ FBrokenLines *V_BreakLines (FFont *font, int maxwidth, const BYTE *string)
|
|||
// Make a copy of the broken lines and return them
|
||||
FBrokenLines *broken = new FBrokenLines[i+1];
|
||||
|
||||
for (c = 0; c < i; ++c)
|
||||
for (ii = 0; ii < i; ++ii)
|
||||
{
|
||||
broken[c] = lines[c];
|
||||
broken[ii] = lines[ii];
|
||||
}
|
||||
broken[c].Width = -1;
|
||||
broken[ii].Width = -1;
|
||||
|
||||
return broken;
|
||||
}
|
||||
|
|
|
@ -1523,7 +1523,7 @@ CCMD (vid_setmode)
|
|||
|
||||
void V_Init (void)
|
||||
{
|
||||
char *i;
|
||||
const char *i;
|
||||
int width, height, bits;
|
||||
|
||||
atterm (V_Shutdown);
|
||||
|
|
|
@ -848,6 +848,46 @@ int FWadCollection::FindLump (const char *name, int *lastlump, bool anyns)
|
|||
return -1;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// W_FindLumpMulti
|
||||
//
|
||||
// Find a named lump. Specifically allows duplicates for merging of e.g.
|
||||
// SNDINFO lumps. Returns everything having one of the passed names.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int FWadCollection::FindLumpMulti (const char **names, int *lastlump, bool anyns, int *nameindex)
|
||||
{
|
||||
LumpRecord *lump_p;
|
||||
|
||||
assert(lastlump != NULL && *lastlump >= 0);
|
||||
lump_p = &LumpInfo[*lastlump];
|
||||
while (lump_p < &LumpInfo[NumLumps])
|
||||
{
|
||||
FResourceLump *lump = lump_p->lump;
|
||||
|
||||
if (anyns || lump->Namespace == ns_global)
|
||||
{
|
||||
|
||||
for(const char **name = names; *name != NULL; name++)
|
||||
{
|
||||
if (!strnicmp(*name, lump->Name, 8))
|
||||
{
|
||||
int lump = int(lump_p - &LumpInfo[0]);
|
||||
*lastlump = lump + 1;
|
||||
if (nameindex != NULL) *nameindex = int(name - names);
|
||||
return lump;
|
||||
}
|
||||
}
|
||||
}
|
||||
lump_p++;
|
||||
}
|
||||
|
||||
*lastlump = NumLumps;
|
||||
return -1;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// W_CheckLumpName
|
||||
|
@ -927,6 +967,24 @@ int FWadCollection::GetLumpNamespace (int lump) const
|
|||
return LumpInfo[lump].lump->Namespace;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FWadCollection :: GetLumpIndexNum
|
||||
//
|
||||
// Returns the index number for this lump. This is *not* the lump's position
|
||||
// in the lump directory, but rather a special value that RFF can associate
|
||||
// with files. Other archive types will return 0, since they don't have it.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int FWadCollection::GetLumpIndexNum(int lump) const
|
||||
{
|
||||
if ((size_t)lump >= NumLumps)
|
||||
return 0;
|
||||
else
|
||||
return LumpInfo[lump].lump->GetIndexNum();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// W_GetLumpFile
|
||||
|
|
|
@ -182,6 +182,7 @@ public:
|
|||
FileReader * GetFileReader(int wadnum); // Gets a FileReader object to the entire WAD
|
||||
|
||||
int FindLump (const char *name, int *lastlump, bool anyns=false); // [RH] Find lumps with duplication
|
||||
int FindLumpMulti (const char **names, int *lastlump, bool anyns = false, int *nameindex = NULL); // same with multiple possible names
|
||||
bool CheckLumpName (int lump, const char *name); // [RH] True if lump's name == name
|
||||
|
||||
static DWORD LumpNameHash (const char *name); // [RH] Create hash key from an 8-char name
|
||||
|
@ -194,6 +195,7 @@ public:
|
|||
FString GetLumpFullPath (int lump) const; // [RH] Returns wad's name + lump's full name
|
||||
int GetLumpFile (int lump) const; // [RH] Returns wadnum for a specified lump
|
||||
int GetLumpNamespace (int lump) const; // [RH] Returns the namespace a lump belongs to
|
||||
int GetLumpIndexNum (int lump) const; // Returns the RFF index number for this lump
|
||||
bool CheckLumpName (int lump, const char *name) const; // [RH] Returns true if the names match
|
||||
|
||||
bool IsUncompressedFile(int lump) const;
|
||||
|
|
|
@ -1935,15 +1935,13 @@ void WI_loadData(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
int dummywidth;
|
||||
star = BigFont->GetChar('*', &dummywidth); // just a dummy to avoid an error if it is being used
|
||||
star = BigFont->GetChar('*', NULL);
|
||||
bstar = star;
|
||||
}
|
||||
}
|
||||
else // Strife needs some handling, too!
|
||||
{
|
||||
int dummywidth;
|
||||
star = BigFont->GetChar('*', &dummywidth); // just a dummy to avoid an error if it is being used
|
||||
star = BigFont->GetChar('*', NULL);
|
||||
bstar = star;
|
||||
}
|
||||
|
||||
|
|
|
@ -503,6 +503,71 @@ void __cdecl Writef (HANDLE file, const char *format, ...)
|
|||
WriteFile (file, buffer, len, &len, NULL);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// WriteLogFileStreamer
|
||||
//
|
||||
// The callback function to stream a Rich Edit's contents to a file.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static DWORD CALLBACK WriteLogFileStreamer(DWORD_PTR cookie, LPBYTE buffer, LONG cb, LONG *pcb)
|
||||
{
|
||||
DWORD didwrite;
|
||||
LONG p, pp;
|
||||
|
||||
// Replace gray foreground color with black.
|
||||
static const char *badfg = "\\red223\\green223\\blue223;";
|
||||
// 4321098 765432109 876543210
|
||||
// 2 1 0
|
||||
for (p = pp = 0; p < cb; ++p)
|
||||
{
|
||||
if (buffer[p] == badfg[pp])
|
||||
{
|
||||
++pp;
|
||||
if (pp == 25)
|
||||
{
|
||||
buffer[p - 1] = buffer[p - 2] = buffer[p - 3] =
|
||||
buffer[p - 9] = buffer[p -10] = buffer[p -11] =
|
||||
buffer[p -18] = buffer[p -19] = buffer[p -20] = '0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pp = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!WriteFile((HANDLE)cookie, buffer, cb, &didwrite, NULL))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
*pcb = didwrite;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// WriteLogFile
|
||||
//
|
||||
// Writes the contents of a Rich Edit control to a file.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
HANDLE WriteLogFile(HWND edit)
|
||||
{
|
||||
HANDLE file;
|
||||
|
||||
file = CreateTempFile();
|
||||
if (file != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
EDITSTREAM streamer = { (DWORD_PTR)file, 0, WriteLogFileStreamer };
|
||||
SendMessage(edit, EM_STREAMOUT, SF_RTF, (LPARAM)&streamer);
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// CreateCrashLog
|
||||
|
@ -511,7 +576,7 @@ void __cdecl Writef (HANDLE file, const char *format, ...)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void CreateCrashLog (char *custominfo, DWORD customsize)
|
||||
void CreateCrashLog (char *custominfo, DWORD customsize, HWND richlog)
|
||||
{
|
||||
// Do not collect information more than once.
|
||||
if (NumFiles != 0)
|
||||
|
@ -561,6 +626,10 @@ void CreateCrashLog (char *custominfo, DWORD customsize)
|
|||
AddFile (file, "local.txt");
|
||||
}
|
||||
}
|
||||
if (richlog != NULL)
|
||||
{
|
||||
AddFile (WriteLogFile(richlog), "log.rtf");
|
||||
}
|
||||
CloseHandle (DbgProcess);
|
||||
}
|
||||
|
||||
|
@ -1984,7 +2053,6 @@ static INT_PTR CALLBACK CrashDlgProc (HWND hDlg, UINT message, WPARAM wParam, LP
|
|||
|
||||
static INT_PTR CALLBACK DetailsDlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
HGDIOBJ font;
|
||||
HWND ctrl;
|
||||
int i, j;
|
||||
|
||||
|
@ -1996,15 +2064,9 @@ static INT_PTR CALLBACK DetailsDlgProc (HWND hDlg, UINT message, WPARAM wParam,
|
|||
pEnableThemeDialogTexture (hDlg, ETDT_ENABLETAB);
|
||||
}
|
||||
|
||||
// Set up the file contents display: Use a fixed width font,
|
||||
// no undos. The control's userdata stores the index of the
|
||||
// file currently displayed.
|
||||
// Set up the file contents display: No undos. The control's
|
||||
// userdata stores the index of the file currently displayed.
|
||||
ctrl = GetDlgItem (hDlg, IDC_CRASHFILECONTENTS);
|
||||
font = GetStockObject (ANSI_FIXED_FONT);
|
||||
if (font != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
SendMessage (ctrl, WM_SETFONT, (WPARAM)font, FALSE);
|
||||
}
|
||||
SendMessage (ctrl, EM_SETUNDOLIMIT, 0, 0);
|
||||
SetWindowLongPtr (ctrl, GWLP_USERDATA, -1);
|
||||
SetEditControl (ctrl, GetDlgItem(hDlg, IDC_CRASHFILESIZE), 0);
|
||||
|
@ -2178,6 +2240,8 @@ static void SetEditControl (HWND edit, HWND sizedisplay, int filenum)
|
|||
EDITSTREAM stream;
|
||||
DWORD size;
|
||||
POINT pt = { 0, 0 };
|
||||
const char *rtf = NULL;
|
||||
HGDIOBJ font;
|
||||
|
||||
// Don't refresh the control if it's already showing the file we want.
|
||||
if (GetWindowLongPtr (edit, GWLP_USERDATA) == filenum)
|
||||
|
@ -2201,10 +2265,19 @@ static void SetEditControl (HWND edit, HWND sizedisplay, int filenum)
|
|||
SetFilePointer (TarFiles[filenum].File, 0, NULL, FILE_BEGIN);
|
||||
SendMessage (edit, EM_SETSCROLLPOS, 0, (LPARAM)&pt);
|
||||
|
||||
// Set the font now, in case log.rtf was previously viewed, because
|
||||
// that file changes it.
|
||||
font = GetStockObject (ANSI_FIXED_FONT);
|
||||
if (font != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
SendMessage (edit, WM_SETFONT, (WPARAM)font, FALSE);
|
||||
}
|
||||
|
||||
// Text files are streamed in as-is.
|
||||
// Binary files are streamed in as color-coded hex dumps.
|
||||
stream.dwError = 0;
|
||||
if (strstr (TarFiles[filenum].Filename, ".txt") != NULL)
|
||||
if (strstr (TarFiles[filenum].Filename, ".txt") != NULL ||
|
||||
(rtf = strstr (TarFiles[filenum].Filename, ".rtf")) != NULL)
|
||||
{
|
||||
CHARFORMAT beBlack;
|
||||
|
||||
|
@ -2215,7 +2288,7 @@ static void SetEditControl (HWND edit, HWND sizedisplay, int filenum)
|
|||
SendMessage (edit, EM_SETCHARFORMAT, 0, (LPARAM)&beBlack);
|
||||
stream.dwCookie = (DWORD_PTR)TarFiles[filenum].File;
|
||||
stream.pfnCallback = StreamEditText;
|
||||
SendMessage (edit, EM_STREAMIN, SF_TEXT, (LPARAM)&stream);
|
||||
SendMessage (edit, EM_STREAMIN, rtf ? SF_RTF : SF_TEXT | SF_USECODEPAGE | (1252 << 16), (LPARAM)&stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue