- Sync scriptbranch with trunk.

SVN r2269 (scripting)
This commit is contained in:
Randy Heit 2010-04-04 04:09:24 +00:00
commit 42ac75e894
127 changed files with 2567 additions and 994 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

@ -0,0 +1 @@
This version of ZDoom must be compiled with any version between 4.22 and 4.28 inclusive.

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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);
}
//==========================================================================

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -68,6 +68,7 @@ struct Lock
return true;
}
}
return false;
}
else for(unsigned int i=0;i<keylist.Size();i++)
{

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View 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);
}

View file

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

View file

@ -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 = &sectors[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;

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -198,7 +198,7 @@ int FPlayList::Advance ()
int FPlayList::Backup ()
{
if (--Position < 0)
if (Position-- == 0)
{
Position = Songs.Size() - 1;
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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 */
{

View file

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

View file

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

View file

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

View file

@ -41,6 +41,8 @@ protected:
FTextureID(int num) { texnum = num; }
private:
int texnum;
friend void AddTiles (void *tiles);
};
class FNullTextureID : public FTextureID

View file

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

View file

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

View file

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

View file

@ -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);
}
}
//==========================================================================
//
//==========================================================================

View file

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

View file

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

View file

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

View file

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

View file

@ -1523,7 +1523,7 @@ CCMD (vid_setmode)
void V_Init (void)
{
char *i;
const char *i;
int width, height, bits;
atterm (V_Shutdown);

View file

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

View file

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

View file

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

View file

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