- Update to latest version in trunk.

SVN r3890 (scripting)
This commit is contained in:
Randy Heit 2012-10-17 04:24:54 +00:00
commit e7efa1d802
117 changed files with 2261 additions and 788 deletions

View file

@ -30,9 +30,7 @@
#include "dthinker.h"
// States are tied to finite states are
// tied to animation frames.
// Needs precompiled tables/data structures.
// States are tied to finite states are tied to animation frames.
#include "info.h"
#include "doomdef.h"
@ -40,6 +38,7 @@
#include "r_data/renderstyle.h"
#include "s_sound.h"
#include "memarena.h"
#include "g_level.h"
struct subsector_t;
class PClassAmmo;
@ -550,15 +549,14 @@ public:
bool AdjustReflectionAngle (AActor *thing, angle_t &angle);
// Returns true if this actor is within melee range of its target
bool CheckMeleeRange ();
bool CheckMeleeRange();
// BeginPlay: Called just after the actor is created
virtual void BeginPlay ();
virtual void PostBeginPlay ();
// LevelSpawned: Called after BeginPlay if this actor was spawned by the world
virtual void LevelSpawned ();
// Translates SpawnFlags into in-game flags.
virtual void HandleSpawnFlags ();
virtual void BeginPlay(); // Called immediately after the actor is created
virtual void PostBeginPlay(); // Called immediately before the actor's first tick
virtual void LevelSpawned(); // Called after BeginPlay if this actor was spawned by the world
virtual void HandleSpawnFlags(); // Translates SpawnFlags into in-game flags.
virtual void MarkPrecacheSounds() const; // Marks sounds used by this actor for precaching.
virtual void Activate (AActor *activator);
virtual void Deactivate (AActor *activator);
@ -679,9 +677,20 @@ public:
// Do I hate the other actor?
bool IsHostile (AActor *other);
inline bool IsNoClip2() const;
// What species am I?
virtual FName GetSpecies();
fixed_t GetBobOffset(fixed_t ticfrac=0) const
{
if (!(flags2 & MF2_FLOATBOB))
{
return 0;
}
return finesine[MulScale22(((FloatBobPhase + level.maptime) << FRACBITS) + ticfrac, FINEANGLES) & FINEMASK] * 8;
}
// Enter the crash state
void Crash();
@ -938,6 +947,7 @@ private:
static FSharedStringArena mStringPropertyData;
friend class FActorIterator;
friend bool P_IsTIDUsed(int tid);
sector_t *LinkToWorldForMapThing ();
@ -1032,6 +1042,9 @@ public:
}
};
bool P_IsTIDUsed(int tid);
int P_FindUniqueTID(int start_tid, int limit);
inline AActor *Spawn (PClassActor *type, fixed_t x, fixed_t y, fixed_t z, replace_t allowreplacement)
{
return AActor::StaticSpawn (type, x, y, z, allowreplacement);

View file

@ -173,6 +173,15 @@ CCMD (noclip)
Net_WriteByte (CHT_NOCLIP);
}
CCMD (noclip2)
{
if (CheckCheatmode())
return;
Net_WriteByte (DEM_GENERICCHEAT);
Net_WriteByte (CHT_NOCLIP2);
}
CCMD (powerup)
{
if (CheckCheatmode ())
@ -243,7 +252,7 @@ CCMD (chase)
else
{
// Check if we're allowed to use chasecam.
if (gamestate != GS_LEVEL || (!(dmflags2 & DF2_CHASECAM) && CheckCheatmode ()))
if (gamestate != GS_LEVEL || (!(dmflags2 & DF2_CHASECAM) && deathmatch && CheckCheatmode ()))
return;
Net_WriteByte (DEM_GENERICCHEAT);
@ -947,9 +956,16 @@ CCMD(thaw)
//-----------------------------------------------------------------------------
CCMD(nextmap)
{
char * next=NULL;
if (netgame)
{
Printf ("Use "TEXTCOLOR_BOLD"changemap"TEXTCOLOR_NORMAL" instead. "TEXTCOLOR_BOLD"Nextmap"
TEXTCOLOR_NORMAL" is for single-player only.\n");
return;
}
char *next = NULL;
if (*level.nextmap) next = level.nextmap;
if (*level.nextmap)
next = level.nextmap;
if (next != NULL && strncmp(next, "enDSeQ", 6))
{
@ -968,9 +984,16 @@ CCMD(nextmap)
//-----------------------------------------------------------------------------
CCMD(nextsecret)
{
char * next=NULL;
if (netgame)
{
Printf ("Use "TEXTCOLOR_BOLD"changemap"TEXTCOLOR_NORMAL" instead. "TEXTCOLOR_BOLD"Nextsecret"
TEXTCOLOR_NORMAL" is for single-player only.\n");
return;
}
char *next = NULL;
if (*level.secretmap) next = level.secretmap;
if (*level.secretmap)
next = level.secretmap;
if (next != NULL && strncmp(next, "enDSeQ", 6))
{

View file

@ -273,7 +273,9 @@ void CT_Drawer (void)
if (players[consoleplayer].camera != NULL &&
(Button_ShowScores.bDown ||
players[consoleplayer].camera->health <= 0))
players[consoleplayer].camera->health <= 0) &&
// Don't draw during intermission, since it has its own scoreboard in wi_stuff.cpp.
gamestate != GS_INTERMISSION)
{
HU_DrawScores (&players[consoleplayer]);
}

View file

@ -1354,7 +1354,7 @@ static int PatchFrame (int frameNum)
if (keylen == 8 && stricmp (Line1, "Duration") == 0)
{
tics = clamp (val, -1, 65534);
tics = clamp (val, -1, SHRT_MAX);
}
else if (keylen == 9 && stricmp (Line1, "Unknown 1") == 0)
{

View file

@ -804,17 +804,21 @@ void D_Display ()
if (hud_althud && viewheight == SCREENHEIGHT && screenblocks > 10)
{
StatusBar->DrawBottomStuff (HUD_None);
if (DrawFSHUD || automapactive) DrawHUD();
StatusBar->DrawTopStuff (HUD_None);
}
else
if (viewheight == SCREENHEIGHT && viewactive && screenblocks > 10)
{
StatusBar->Draw (DrawFSHUD ? HUD_Fullscreen : HUD_None);
StatusBar->DrawTopStuff (DrawFSHUD ? HUD_Fullscreen : HUD_None);
EHudState state = DrawFSHUD ? HUD_Fullscreen : HUD_None;
StatusBar->DrawBottomStuff (state);
StatusBar->Draw (state);
StatusBar->DrawTopStuff (state);
}
else
{
StatusBar->DrawBottomStuff (HUD_StatusBar);
StatusBar->Draw (HUD_StatusBar);
StatusBar->DrawTopStuff (HUD_StatusBar);
}
@ -2207,14 +2211,17 @@ void D_DoomMain (void)
// [RH] Load sound environments
S_ParseReverbDef ();
// [RH] Parse any SNDINFO lumps
Printf ("S_InitData: Load sound definitions.\n");
S_InitData ();
// [RH] Parse through all loaded mapinfo lumps
Printf ("G_ParseMapInfo: Load map definitions.\n");
G_ParseMapInfo (iwad_info->MapInfo);
ReadStatistics();
// [RH] Parse any SNDINFO lumps
Printf ("S_InitData: Load sound definitions.\n");
S_InitData ();
// MUSINFO must be parsed after MAPINFO
S_ParseMusInfo();
Printf ("Texman.Init: Init texture manager.\n");
TexMan.Init();

View file

@ -60,6 +60,7 @@
#include "p_lnspec.h"
#include "v_video.h"
#include "p_spec.h"
#include "hardware.h"
#include "intermission/intermission.h"
EXTERN_CVAR (Int, disableautosave)
@ -135,7 +136,18 @@ static int oldentertics;
extern bool advancedemo;
CVAR (Bool, cl_capfps, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CUSTOM_CVAR (Bool, cl_capfps, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
{
// Do not use the separate FPS limit timer if we are limiting FPS with this.
if (self)
{
I_SetFPSLimit(0);
}
else
{
I_SetFPSLimit(-1);
}
}
// [RH] Special "ticcmds" get stored in here
static struct TicSpecial

View file

@ -65,7 +65,9 @@ struct FPlayerColorSet
BYTE NumExtraRanges;
ExtraRange Extra[6];
};
typedef TMap<int, FPlayerColorSet> FPlayerColorSetMap;
typedef TMap<FName, PalEntry> PainFlashList;
class PClassPlayerPawn : public PClassActor
{
@ -76,6 +78,8 @@ public:
PClassPlayerPawn();
void EnumColorSets(TArray<int> *out);
FPlayerColorSet *GetColorSet(int setnum) { return ColorSets.CheckKey(setnum); }
void SetPainFlash(FName type, PalEntry color);
bool GetPainFlash(FName type, PalEntry *color) const;
FString DisplayName; // Display name (used in menus, etc.)
FString SoundClass; // Sound class
@ -88,6 +92,7 @@ public:
BYTE ColorRangeStart; // Skin color range
BYTE ColorRangeEnd;
FPlayerColorSetMap ColorSets;
PainFlashList PainFlashes;
};
FString GetPrintableDisplayName(PClassPlayerPawn *cls);
@ -105,6 +110,7 @@ public:
virtual void AddInventory (AInventory *item);
virtual void RemoveInventory (AInventory *item);
virtual bool UseInventory (AInventory *item);
virtual void MarkPrecacheSounds () const;
virtual void PlayIdle ();
virtual void PlayRunning ();
@ -122,7 +128,7 @@ public:
void GiveDefaultInventory ();
void PlayAttacking ();
void PlayAttacking2 ();
const char *GetSoundClass ();
const char *GetSoundClass () const;
enum EInvulState
{
@ -145,6 +151,8 @@ public:
// [GRB] Player class properties
fixed_t JumpZ;
fixed_t GruntSpeed;
fixed_t FallingScreamMinSpeed, FallingScreamMaxSpeed;
fixed_t ViewHeight;
fixed_t ForwardMove1, ForwardMove2;
fixed_t SideMove1, SideMove2;
@ -221,6 +229,7 @@ typedef enum
CF_BUDDHA = 1 << 27, // [SP] Buddha mode - take damage, but don't die
CF_WEAPONRELOADOK = 1 << 28, // [XA] Okay to reload this weapon.
CF_WEAPONZOOMOK = 1 << 29, // [XA] Okay to use weapon zoom function.
CF_NOCLIP2 = 1 << 30, // [RH] More Quake-like noclip
} cheat_t;
#define WPIECE1 1
@ -452,6 +461,14 @@ inline void AActor::SetFriendPlayer(player_t *player)
}
}
inline bool AActor::IsNoClip2() const
{
if (player != NULL && player->mo == this)
{
return (player->cheats & CF_NOCLIP2) != 0;
}
return false;
}
#define CROUCHSPEED (FRACUNIT/12)

View file

@ -218,7 +218,8 @@ enum ECheatCommand
CHT_GIMMIEI,
CHT_GIMMIEJ,
CHT_GIMMIEZ,
CHT_BUDDHA
CHT_BUDDHA,
CHT_NOCLIP2
};
void StartChunk (int id, BYTE **stream);

View file

@ -3367,7 +3367,7 @@ void FParser::SF_RadiusAttack()
if (spot && source)
{
P_RadiusAttack(spot, source, damage, damage, NAME_None, true);
P_RadiusAttack(spot, source, damage, damage, NAME_None, RADF_HURTSOURCE);
}
}
}

View file

@ -342,7 +342,7 @@ void T_LoadScripts(MapData *map)
// the default translator is being used.
// Custom translators will not be patched.
if ((gameinfo.gametype == GAME_Doom || gameinfo.gametype == GAME_Heretic) && level.info->Translator.IsEmpty() &&
level.maptype == MAPTYPE_DOOM && SimpleLineTranslations[272 - 2*HasScripts].special == FS_Execute)
level.maptype == MAPTYPE_DOOM && SimpleLineTranslations.Size() > 272 && SimpleLineTranslations[272 - 2*HasScripts].special == FS_Execute)
{
FLineTrans t = SimpleLineTranslations[270];
SimpleLineTranslations[270] = SimpleLineTranslations[272];

View file

@ -145,7 +145,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_VileAttack)
target->y - FixedMul (24*FRACUNIT, finesine[an]),
target->z);
P_RadiusAttack (fire, self, blastdmg, blastrad, dmgtype, false);
P_RadiusAttack (fire, self, blastdmg, blastrad, dmgtype, 0);
}
target->velz = Scale(thrust, 1000, target->Mass);
return 0;

View file

@ -151,7 +151,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Mushroom)
spawntype = PClass::FindActor("FatShot");
}
P_RadiusAttack (self, self->target, 128, 128, self->DamageType, !(flags & MSF_DontHurt));
P_RadiusAttack (self, self->target, 128, 128, self->DamageType, (flags & MSF_DontHurt) ? 0 : RADF_HURTSOURCE);
P_CheckSplash(self, 128<<FRACBITS);
// Now launch mushroom cloud

View file

@ -52,7 +52,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_TimeBomb)
self->z += 32*FRACUNIT;
self->RenderStyle = STYLE_Add;
self->alpha = FRACUNIT;
P_RadiusAttack (self, self->target, 128, 128, self->DamageType, true);
P_RadiusAttack (self, self->target, 128, 128, self->DamageType, RADF_HURTSOURCE);
P_CheckSplash(self, 128<<FRACBITS);
return 0;
}

View file

@ -213,7 +213,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_VolcBallImpact)
self->z += 28*FRACUNIT;
//self->velz = 3*FRACUNIT;
}
P_RadiusAttack (self, self->target, 25, 25, NAME_Fire, true);
P_RadiusAttack (self, self->target, 25, 25, NAME_Fire, RADF_HURTSOURCE);
for (i = 0; i < 4; i++)
{
tiny = Spawn("VolcanoTBlast", self->x, self->y, self->z, ALLOW_REPLACE);

View file

@ -98,8 +98,8 @@ DEFINE_ACTION_FUNCTION_PARAMS (AActor, A_Blast)
{
PARAM_ACTION_PROLOGUE;
PARAM_INT_OPT (blastflags) { blastflags = 0; }
PARAM_FIXED_OPT (strength) { strength = 255; }
PARAM_FIXED_OPT (radius) { radius = 255; }
PARAM_INT_OPT (strength) { strength = 255; }
PARAM_INT_OPT (radius) { radius = 255; }
PARAM_FIXED_OPT (speed) { speed = 20; }
PARAM_CLASS_OPT (blasteffect, AActor) { blasteffect = PClass::FindActor("BlastEffect"); }
PARAM_SOUND_OPT (blastsound) { blastsound = "BlastRadius"; }

View file

@ -418,7 +418,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_PoisonBagDamage)
int bobIndex;
P_RadiusAttack (self, self->target, 4, 40, self->DamageType, true);
P_RadiusAttack (self, self->target, 4, 40, self->DamageType, RADF_HURTSOURCE);
bobIndex = self->special2;
self->z += finesine[bobIndex << BOBTOFINESHIFT] >> 1;
self->special2 = (bobIndex + 1) & 63;

View file

@ -737,7 +737,14 @@ void G_DoCompleted (void)
if (mode == FINISH_SameHub)
{ // Remember the level's state for re-entry.
G_SnapshotLevel ();
if (!(level.flags2 & LEVEL2_FORGETSTATE))
{
G_SnapshotLevel ();
}
else
{ // Make sure we don't have a snapshot lying around from before.
level.info->ClearSnapshot();
}
}
else
{ // Forget the states of all existing levels.

View file

@ -36,8 +36,8 @@
#include "doomtype.h"
#include "doomdef.h"
//#include "autosegs.h"
#include "sc_man.h"
#include "s_sound.h"
struct level_info_t;
struct cluster_info_t;
@ -179,7 +179,7 @@ enum ELevelFlags
LEVEL2_KEEPFULLINVENTORY = 0x00000040, // doesn't reduce the amount of inventory items to 1
LEVEL2_MUSICDEFINED = 0x00000080, // a marker to disable the $map command in SNDINFO for this map
/* = 0x00000080, */
LEVEL2_MONSTERFALLINGDAMAGE = 0x00000100,
LEVEL2_CLIPMIDTEX = 0x00000200,
LEVEL2_WRAPMIDTEX = 0x00000400,
@ -211,6 +211,7 @@ enum ELevelFlags
LEVEL2_NOSTATISTICS = 0x10000000, // This level should not have statistics collected
LEVEL2_ENDGAME = 0x20000000, // This is an epilogue level that cannot be quit.
LEVEL2_NOAUTOSAVEHINT = 0x40000000, // tell the game that an autosave for this level does not need to be kept
LEVEL2_FORGETSTATE = 0x80000000, // forget this map's state in a hub
};
@ -325,6 +326,8 @@ struct level_info_t
TArray<FSpecialAction> specialactions;
TArray<FSoundID> PrecacheSounds;
level_info_t()
{
Reset();

View file

@ -61,6 +61,8 @@ static cluster_info_t TheDefaultClusterInfo;
TArray<FEpisode> AllEpisodes;
extern TMap<int, FString> HexenMusic;
//==========================================================================
//
//
@ -269,6 +271,7 @@ void level_info_t::Reset()
teamdamage = 0.f;
specialactions.Clear();
DefaultEnvironment = 0;
PrecacheSounds.Clear();
}
@ -917,8 +920,6 @@ DEFINE_MAP_OPTION(music, true)
{
parse.ParseAssign();
parse.ParseMusic(info->Music, info->musicorder);
// Flag the level so that the $MAP command doesn't override this.
info->flags2 |= LEVEL2_MUSICDEFINED;
}
DEFINE_MAP_OPTION(intermusic, true)
@ -1029,7 +1030,7 @@ DEFINE_MAP_OPTION(specialaction, true)
sa->Action = P_FindLineSpecial(parse.sc.String, &min_arg, &max_arg);
if (sa->Action == 0 || min_arg < 0)
{
parse.sc.ScriptError("Unknown specialaction '%s'");
parse.sc.ScriptError("Unknown specialaction '%s'", parse.sc.String);
}
int j = 0;
while (j < 5 && parse.sc.CheckString(","))
@ -1040,6 +1041,25 @@ DEFINE_MAP_OPTION(specialaction, true)
if (parse.format_type == parse.FMT_Old) parse.sc.SetCMode(false);
}
DEFINE_MAP_OPTION(PrecacheSounds, true)
{
parse.ParseAssign();
do
{
parse.sc.MustGetString();
FSoundID snd = parse.sc.String;
if (snd == 0)
{
parse.sc.ScriptMessage("Unknown sound \"%s\"", parse.sc.String);
}
else
{
info->PrecacheSounds.Push(snd);
}
} while (parse.sc.CheckString(","));
}
DEFINE_MAP_OPTION(redirect, true)
{
parse.ParseAssign();
@ -1244,6 +1264,8 @@ MapFlagHandlers[] =
{ "endofgame", MITYPE_SETFLAG2, LEVEL2_ENDGAME, 0 },
{ "nostatistics", MITYPE_SETFLAG2, LEVEL2_NOSTATISTICS, 0 },
{ "noautosavehint", MITYPE_SETFLAG2, LEVEL2_NOAUTOSAVEHINT, 0 },
{ "forgetstate", MITYPE_SETFLAG2, LEVEL2_FORGETSTATE, 0 },
{ "rememberstate", MITYPE_CLRFLAG2, LEVEL2_FORGETSTATE, 0 },
{ "unfreezesingleplayerconversations",MITYPE_SETFLAG2, LEVEL2_CONV_SINGLE_UNFREEZE, 0 },
{ "nobotnodes", MITYPE_IGNORE, 0, 0 }, // Skulltag option: nobotnodes
{ "compat_shorttex", MITYPE_COMPATFLAG, COMPATF_SHORTTEX, 0 },
@ -1516,6 +1538,14 @@ level_info_t *FMapInfoParser::ParseMapHeader(level_info_t &defaultinfo)
// to teleport to maps with standard names without needing a levelnum.
levelinfo->levelnum = GetDefaultLevelNum(levelinfo->mapname);
// Does this map have a song defined via SNDINFO's $map command?
// Set that as this map's default music if it does.
FString *song;
if ((song = HexenMusic.CheckKey(levelinfo->levelnum)) != NULL)
{
levelinfo->Music = *song;
}
return levelinfo;
}
@ -1810,7 +1840,6 @@ void FMapInfoParser::ParseMapInfo (int lump, level_info_t &gamedefaults, level_i
}
}
//==========================================================================
//
//

View file

@ -47,12 +47,12 @@ bool P_MorphPlayer (player_t *activator, player_t *p, PClassPlayerPawn *spawntyp
}
if (p->morphTics)
{ // Player is already a beast
if ((p->mo->GetClass() == spawntype)
&& (p->mo->PlayerFlags & PPF_CANSUPERMORPH)
&& (p->morphTics < (((duration) ? duration : MORPHTICS) - TICRATE))
&& (p->mo->FindInventory (RUNTIME_CLASS(APowerWeaponLevel2), true) == NULL))
{ // Make a super chicken
p->mo->GiveInventoryType (RUNTIME_CLASS(APowerWeaponLevel2));
if ((p->mo->GetClass() == spawntype)
&& (p->mo->PlayerFlags & PPF_CANSUPERMORPH)
&& (p->morphTics < (((duration) ? duration : MORPHTICS) - TICRATE))
&& (p->mo->FindInventory (RUNTIME_CLASS(APowerWeaponLevel2), true) == NULL))
{ // Make a super chicken
p->mo->GiveInventoryType (RUNTIME_CLASS(APowerWeaponLevel2));
}
return false;
}

View file

@ -505,6 +505,18 @@ void AInventory::Serialize (FArchive &arc)
arc << Owner << Amount << MaxAmount << RespawnTics << ItemFlags << Icon << PickupSound << SpawnPointClass;
}
//===========================================================================
//
// AInventory :: MarkPrecacheSounds
//
//===========================================================================
void AInventory::MarkPrecacheSounds() const
{
Super::MarkPrecacheSounds();
PickupSound.MarkUsed();
}
//===========================================================================
//
// AInventory :: SpecialDropAction
@ -532,6 +544,7 @@ bool AInventory::SpecialDropAction (AActor *dropper)
bool AInventory::ShouldRespawn ()
{
if ((ItemFlags & IF_BIGPOWERUP) && !(dmflags & DF_RESPAWN_SUPER)) return false;
if (ItemFlags & IF_NEVERRESPAWN) return false;
return !!(dmflags & DF_ITEMS_RESPAWN);
}

View file

@ -123,6 +123,7 @@ enum
IF_NOATTENPICKUPSOUND = 1<<17, // Play pickup sound with ATTN_NONE
IF_PERSISTENTPOWER = 1<<18, // Powerup is kept when travelling between levels
IF_RESTRICTABSOLUTELY = 1<<19, // RestrictedTo and ForbiddenTo do not allow pickup in any form by other classes
IF_NEVERRESPAWN = 1<<20, // Never, ever respawns
};
@ -147,6 +148,7 @@ public:
virtual void Touch (AActor *toucher);
virtual void Serialize (FArchive &arc);
virtual void MarkPrecacheSounds() const;
virtual void BeginPlay ();
virtual void Destroy ();
virtual void Tick ();
@ -296,6 +298,7 @@ public:
bool bAltFire; // Set when this weapon's alternate fire is used.
virtual void MarkPrecacheSounds() const;
virtual void Serialize (FArchive &arc);
virtual bool ShouldStay ();
virtual void AttachToOwner (AActor *other);

View file

@ -105,6 +105,7 @@ public:
void PostBeginPlay ();
void Activate (AActor *activator);
void Deactivate (AActor *activator);
void MarkPrecacheSounds () const;
};
IMPLEMENT_CLASS (ASoundSequence)
@ -154,6 +155,18 @@ void ASoundSequence::PostBeginPlay ()
}
}
//==========================================================================
//
// ASoundSequence :: MarkPrecacheSounds
//
//==========================================================================
void ASoundSequence::MarkPrecacheSounds() const
{
Super::MarkPrecacheSounds();
SN_MarkPrecacheSounds(args[0], SEQ_ENVIRONMENT);
}
//==========================================================================
//
// ASoundSequence :: Activate
@ -175,4 +188,3 @@ void ASoundSequence::Deactivate (AActor *activator)
{
SN_StopSequence (this);
}

View file

@ -85,6 +85,19 @@ void AWeapon::Serialize (FArchive &arc)
<< Crosshair;
}
//===========================================================================
//
// AWeapon :: MarkPrecacheSounds
//
//===========================================================================
void AWeapon::MarkPrecacheSounds() const
{
Super::MarkPrecacheSounds();
UpSound.MarkUsed();
ReadySound.MarkUsed();
}
//===========================================================================
//
// AWeapon :: TryPickup
@ -732,6 +745,7 @@ bool AWeaponGiver::TryPickup(AActor *&toucher)
if (weap != NULL)
{
weap->ItemFlags &= ~IF_ALWAYSPICKUP; // use the flag of this item only.
weap->flags = (weap->flags & ~MF_DROPPED) | (this->flags & MF_DROPPED);
if (AmmoGive1 >= 0) weap->AmmoGive1 = AmmoGive1;
if (AmmoGive2 >= 0) weap->AmmoGive2 = AmmoGive2;
weap->BecomeItem();
@ -741,7 +755,11 @@ bool AWeaponGiver::TryPickup(AActor *&toucher)
weap = barrier_cast<AWeapon*>(master);
bool res = weap->CallTryPickup(toucher);
if (res) GoAwayAndDie();
if (res)
{
GoAwayAndDie();
master = NULL;
}
return res;
}
}

View file

@ -140,6 +140,9 @@ DHUDMessage::DHUDMessage (FFont *font, const char *text, float x, float y, int h
State = 0;
SourceText = copystring (text);
Font = font;
VisibilityFlags = 0;
Style = STYLE_Translucent;
Alpha = FRACUNIT;
ResetText (SourceText);
}
@ -184,6 +187,23 @@ void DHUDMessage::Serialize (FArchive &arc)
Lines = NULL;
ResetText (SourceText);
}
if (SaveVersion < 3821)
{
VisibilityFlags = 0;
}
else
{
arc << VisibilityFlags;
}
if (SaveVersion < 3824)
{
Style = STYLE_Translucent;
Alpha = FRACUNIT;
}
else
{
arc << Style << Alpha;
}
}
//============================================================================
@ -262,7 +282,7 @@ bool DHUDMessage::Tick ()
//
//============================================================================
void DHUDMessage::Draw (int bottom)
void DHUDMessage::Draw (int bottom, int visibility)
{
int xscale, yscale;
int x, y;
@ -271,6 +291,12 @@ void DHUDMessage::Draw (int bottom)
bool clean = false;
int hudheight;
// If any of the visibility flags match, do NOT draw this message.
if (VisibilityFlags & visibility)
{
return;
}
DrawSetup ();
int screen_width = SCREENWIDTH;
@ -395,6 +421,8 @@ void DHUDMessage::DoDraw (int linenum, int x, int y, bool clean, int hudheight)
{
screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text,
DTA_CleanNoMove, clean,
DTA_Alpha, Alpha,
DTA_RenderStyle, Style,
TAG_DONE);
}
else
@ -402,6 +430,8 @@ void DHUDMessage::DoDraw (int linenum, int x, int y, bool clean, int hudheight)
screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text,
DTA_VirtualWidth, SCREENWIDTH/2,
DTA_VirtualHeight, SCREENHEIGHT/2,
DTA_Alpha, Alpha,
DTA_RenderStyle, Style,
DTA_KeepRatio, true,
TAG_DONE);
}
@ -411,6 +441,8 @@ void DHUDMessage::DoDraw (int linenum, int x, int y, bool clean, int hudheight)
screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text,
DTA_VirtualWidth, HUDWidth,
DTA_VirtualHeight, hudheight,
DTA_Alpha, Alpha,
DTA_RenderStyle, Style,
TAG_DONE);
}
}
@ -482,6 +514,7 @@ void DHUDMessageFadeOut::DoDraw (int linenum, int x, int y, bool clean, int hudh
else
{
fixed_t trans = -(Tics - FadeOutTics) * FRACUNIT / FadeOutTics;
trans = FixedMul(trans, Alpha);
if (hudheight == 0)
{
if (con_scaletext <= 1)
@ -489,6 +522,7 @@ void DHUDMessageFadeOut::DoDraw (int linenum, int x, int y, bool clean, int hudh
screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text,
DTA_CleanNoMove, clean,
DTA_Alpha, trans,
DTA_RenderStyle, Style,
TAG_DONE);
}
else
@ -497,6 +531,7 @@ void DHUDMessageFadeOut::DoDraw (int linenum, int x, int y, bool clean, int hudh
DTA_VirtualWidth, SCREENWIDTH/2,
DTA_VirtualHeight, SCREENHEIGHT/2,
DTA_Alpha, trans,
DTA_RenderStyle, Style,
DTA_KeepRatio, true,
TAG_DONE);
}
@ -507,6 +542,7 @@ void DHUDMessageFadeOut::DoDraw (int linenum, int x, int y, bool clean, int hudh
DTA_VirtualWidth, HUDWidth,
DTA_VirtualHeight, hudheight,
DTA_Alpha, trans,
DTA_RenderStyle, Style,
TAG_DONE);
}
BorderNeedRefresh = screen->GetPageCount ();
@ -575,6 +611,7 @@ void DHUDMessageFadeInOut::DoDraw (int linenum, int x, int y, bool clean, int hu
if (State == 0)
{
fixed_t trans = Tics * FRACUNIT / FadeInTics;
trans = FixedMul(trans, Alpha);
if (hudheight == 0)
{
if (con_scaletext <= 1)
@ -582,6 +619,7 @@ void DHUDMessageFadeInOut::DoDraw (int linenum, int x, int y, bool clean, int hu
screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text,
DTA_CleanNoMove, clean,
DTA_Alpha, trans,
DTA_RenderStyle, Style,
TAG_DONE);
}
else
@ -590,6 +628,7 @@ void DHUDMessageFadeInOut::DoDraw (int linenum, int x, int y, bool clean, int hu
DTA_VirtualWidth, SCREENWIDTH/2,
DTA_VirtualHeight, SCREENHEIGHT/2,
DTA_Alpha, trans,
DTA_RenderStyle, Style,
DTA_KeepRatio, true,
TAG_DONE);
}
@ -600,6 +639,7 @@ void DHUDMessageFadeInOut::DoDraw (int linenum, int x, int y, bool clean, int hu
DTA_VirtualWidth, HUDWidth,
DTA_VirtualHeight, hudheight,
DTA_Alpha, trans,
DTA_RenderStyle, Style,
TAG_DONE);
}
BorderNeedRefresh = screen->GetPageCount ();
@ -753,6 +793,8 @@ void DHUDMessageTypeOnFadeOut::DoDraw (int linenum, int x, int y, bool clean, in
screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text,
DTA_CleanNoMove, clean,
DTA_TextLen, LineVisible,
DTA_Alpha, Alpha,
DTA_RenderStyle, Style,
TAG_DONE);
}
else
@ -762,6 +804,8 @@ void DHUDMessageTypeOnFadeOut::DoDraw (int linenum, int x, int y, bool clean, in
DTA_VirtualHeight, SCREENHEIGHT/2,
DTA_KeepRatio, true,
DTA_TextLen, LineVisible,
DTA_Alpha, Alpha,
DTA_RenderStyle, Style,
TAG_DONE);
}
}
@ -770,7 +814,9 @@ void DHUDMessageTypeOnFadeOut::DoDraw (int linenum, int x, int y, bool clean, in
screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text,
DTA_VirtualWidth, HUDWidth,
DTA_VirtualHeight, hudheight,
DTA_Alpha, Alpha,
DTA_TextLen, LineVisible,
DTA_RenderStyle, Style,
TAG_DONE);
}
}

View file

@ -66,13 +66,26 @@ public:
virtual void Serialize (FArchive &arc);
void Draw (int bottom);
void Draw (int bottom, int visibility);
virtual void ResetText (const char *text);
virtual void DrawSetup ();
virtual void DoDraw (int linenum, int x, int y, bool clean, int hudheight);
virtual bool Tick (); // Returns true to indicate time for removal
virtual void ScreenSizeChanged ();
void SetVisibility(int vis)
{
VisibilityFlags = vis;
}
void SetRenderStyle(ERenderStyle style)
{
Style = style;
}
void SetAlpha(fixed_t alpha)
{
Alpha = alpha;
}
protected:
FBrokenLines *Lines;
int Width, Height, NumLines;
@ -81,9 +94,12 @@ protected:
int HoldTics;
int Tics;
int State;
int VisibilityFlags;
int HUDWidth, HUDHeight;
EColorRange TextColor;
FFont *Font;
FRenderStyle Style;
fixed_t Alpha;
DHUDMessage () : SourceText(NULL) {}
@ -95,6 +111,14 @@ private:
friend class DBaseStatusBar;
};
// HUD message visibility flags
enum
{
HUDMSG_NotWith3DView = 1,
HUDMSG_NotWithFullMap = 2,
HUDMSG_NotWithOverlayMap = 4,
};
// HUD Message; appear instantly, then fade out type ------------------------
class DHUDMessageFadeOut : public DHUDMessage
@ -242,6 +266,16 @@ int FindMugShotStateIndex(FName state);
class FTexture;
class AAmmo;
enum
{
HUDMSGLayer_OverHUD,
HUDMSGLayer_UnderHUD,
HUDMSGLayer_OverMap,
NUM_HUDMSGLAYERS,
HUDMSGLayer_Default = HUDMSGLayer_OverHUD,
};
class DBaseStatusBar : public DObject
{
DECLARE_CLASS (DBaseStatusBar, DObject)
@ -281,11 +315,10 @@ public:
void SetScaled (bool scale, bool force=false);
void AttachMessage (DHUDMessage *msg, uint32 id=0);
void AttachMessage (DHUDMessage *msg, uint32 id=0, int layer=HUDMSGLayer_Default);
DHUDMessage *DetachMessage (DHUDMessage *msg);
DHUDMessage *DetachMessage (uint32 id);
void DetachAllMessages ();
bool CheckMessage (DHUDMessage *msg);
void ShowPlayerName ();
fixed_t GetDisplacement () { return Displacement; }
int GetPlayer ();
@ -296,6 +329,7 @@ public:
virtual void Tick ();
virtual void Draw (EHudState state);
void DrawBottomStuff (EHudState state);
void DrawTopStuff (EHudState state);
virtual void FlashItem (const PClass *itemtype);
virtual void AttachToPlayer (player_t *player);
@ -343,6 +377,7 @@ public:
bool Scaled;
bool Centering;
bool FixedOrigin;
bool CompleteBorder;
fixed_t CrosshairSize;
fixed_t Displacement;
@ -363,10 +398,10 @@ public:
private:
DBaseStatusBar() {}
bool RepositionCoords (int &x, int &y, int xo, int yo, const int w, const int h) const;
void DrawMessages (int bottom);
void DrawMessages (int layer, int bottom);
void DrawConsistancy () const;
TObjPtr<DHUDMessage> Messages;
TObjPtr<DHUDMessage> Messages[NUM_HUDMSGLAYERS];
bool ShowLog;
};

View file

@ -149,6 +149,8 @@ class SBarInfoCommand
virtual void Reset() {}
virtual void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged) {}
SBarInfo *GetScript() { return script; }
protected:
void GetCoordinates(FScanner &sc, bool fullScreenOffsets, SBarInfoCoordinate &x, SBarInfoCoordinate &y)
{
@ -798,6 +800,8 @@ void SBarInfo::Init()
spacingAlignment = ALIGN_CENTER;
resW = 320;
resH = 200;
cleanX = -1;
cleanY = -1;
for(unsigned int i = 0;i < NUMHUDS;i++)
huds[i] = new SBarInfoMainBlock(this);
@ -978,6 +982,8 @@ public:
}
invBarOffset = script->Images.Size();
Images.Init(&patchnames[0], patchnames.Size());
CompleteBorder = script->completeBorder;
}
~DSBarInfo ()
@ -985,19 +991,22 @@ public:
Images.Uninit();
}
void ScreenSizeChanged()
{
Super::ScreenSizeChanged();
V_CalcCleanFacs(script->resW, script->resH, SCREENWIDTH, SCREENHEIGHT, &script->cleanX, &script->cleanY);
}
void Draw (EHudState state)
{
DBaseStatusBar::Draw(state);
if (script->cleanX <= 0)
{ // Calculate cleanX and cleanY
ScreenSizeChanged();
}
int hud = STBAR_NORMAL;
if(state == HUD_StatusBar)
{
if(script->completeBorder) //Fill the statusbar with the border before we draw.
{
FTexture *b = TexMan[gameinfo.border->b];
V_DrawBorder(viewwindowx, viewwindowy + viewheight + b->GetHeight(), viewwindowx + viewwidth, SCREENHEIGHT);
if(screenblocks == 10)
screen->FlatFill(viewwindowx, viewwindowy + viewheight, viewwindowx + viewwidth, viewwindowy + viewheight + b->GetHeight(), b, true);
}
if(script->automapbar && automapactive)
{
hud = STBAR_AUTOMAP;
@ -1250,8 +1259,8 @@ public:
{
double rx, ry, rcx=0, rcy=0, rcr=INT_MAX, rcb=INT_MAX;
double xScale = !hud_scale ? 1.0 : (double) CleanXfac*320.0/(double) script->resW;//(double) SCREENWIDTH/(double) script->resW;
double yScale = !hud_scale ? 1.0 : (double) CleanYfac*200.0/(double) script->resH;//(double) SCREENHEIGHT/(double) script->resH;
double xScale = !hud_scale ? 1 : script->cleanX;
double yScale = !hud_scale ? 1 : script->cleanY;
adjustRelCenter(x.RelCenter(), y.RelCenter(), dx, dy, rx, ry, xScale, yScale);
@ -1283,34 +1292,6 @@ public:
rcy = cy == 0 ? 0 : ry+(((double) cy/FRACUNIT)*yScale);
rcr = cr == 0 ? INT_MAX : rx+w-(((double) cr/FRACUNIT)*xScale);
rcb = cb == 0 ? INT_MAX : ry+h-(((double) cb/FRACUNIT)*yScale);
// Fix the clipping for fullscreenoffsets.
/*if(ry < 0)
{
if(rcy != 0)
rcy = hud_scale ? SCREENHEIGHT + (int) (rcy*CleanYfac*200.0/script->resH) : SCREENHEIGHT + rcy;
if(rcb != INT_MAX)
rcb = hud_scale ? SCREENHEIGHT + (int) (rcb*CleanYfac*200.0/script->resH) : SCREENHEIGHT + rcb;
}
else if(hud_scale)
{
rcy *= (int) (CleanYfac*200.0/script->resH);
if(rcb != INT_MAX)
rcb *= (int) (CleanYfac*200.0/script->resH);
}
if(rx < 0)
{
if(rcx != 0)
rcx = hud_scale ? SCREENWIDTH + (int) (rcx*CleanXfac*320.0/script->resW) : SCREENWIDTH + rcx;
if(rcr != INT_MAX)
rcr = hud_scale ? SCREENWIDTH + (int) (rcr*CleanXfac*320.0/script->resW) : SCREENWIDTH + rcr;
}
else if(hud_scale)
{
rcx *= (int) (CleanXfac*320.0/script->resW);
if(rcr != INT_MAX)
rcr *= (int) (CleanXfac*320.0/script->resW);
}*/
}
if(clearDontDraw)
@ -1370,8 +1351,8 @@ public:
{
if(hud_scale)
{
xScale = (double) CleanXfac*320.0/(double) script->resW;//(double) SCREENWIDTH/(double) script->resW;
yScale = (double) CleanYfac*200.0/(double) script->resH;//(double) SCREENWIDTH/(double) script->resW;
xScale = script->cleanX;
yScale = script->cleanY;
}
adjustRelCenter(x.RelCenter(), y.RelCenter(), *x, *y, ax, ay, xScale, yScale);
}

View file

@ -108,6 +108,8 @@ struct SBarInfo
FMugShot MugShot;
int resW;
int resH;
int cleanX;
int cleanY;
int GetGameType() { return gameType; }
void ParseSBarInfo(int lump);

View file

@ -61,7 +61,9 @@
#define POWERUPICONSIZE 32
IMPLEMENT_POINTY_CLASS(DBaseStatusBar)
DECLARE_POINTER(Messages)
DECLARE_POINTER(Messages[0])
DECLARE_POINTER(Messages[1])
DECLARE_POINTER(Messages[2])
END_POINTERS
EXTERN_CVAR (Bool, am_showmonsters)
@ -70,7 +72,6 @@ EXTERN_CVAR (Bool, am_showitems)
EXTERN_CVAR (Bool, am_showtime)
EXTERN_CVAR (Bool, am_showtotaltime)
EXTERN_CVAR (Bool, noisedebug)
EXTERN_CVAR (Bool, hud_scale)
EXTERN_CVAR (Int, con_scaletext)
DBaseStatusBar *StatusBar;
@ -216,11 +217,12 @@ void ST_Clear()
DBaseStatusBar::DBaseStatusBar (int reltop, int hres, int vres)
{
CompleteBorder = false;
Centering = false;
FixedOrigin = false;
CrosshairSize = FRACUNIT;
RelTop = reltop;
Messages = NULL;
memset(Messages, 0, sizeof(Messages));
Displacement = 0;
CPlayer = NULL;
ShowLog = false;
@ -238,16 +240,17 @@ DBaseStatusBar::DBaseStatusBar (int reltop, int hres, int vres)
void DBaseStatusBar::Destroy ()
{
DHUDMessage *msg;
msg = Messages;
while (msg)
for (int i = 0; i < countof(Messages); ++i)
{
DHUDMessage *next = msg->Next;
msg->Destroy();
msg = next;
DHUDMessage *msg = Messages[i];
while (msg)
{
DHUDMessage *next = msg->Next;
msg->Destroy();
msg = next;
}
Messages[i] = NULL;
}
Messages = NULL;
Super::Destroy();
}
@ -339,32 +342,35 @@ void DBaseStatusBar::MultiplayerChanged ()
void DBaseStatusBar::Tick ()
{
DHUDMessage *msg = Messages;
DHUDMessage **prev = &Messages;
while (msg)
for (int i = 0; i < countof(Messages); ++i)
{
DHUDMessage *next = msg->Next;
DHUDMessage *msg = Messages[i];
DHUDMessage **prev = &Messages[i];
if (msg->Tick ())
while (msg)
{
*prev = next;
msg->Destroy();
}
else
{
prev = &msg->Next;
}
msg = next;
}
DHUDMessage *next = msg->Next;
// If the crosshair has been enlarged, shrink it.
if (CrosshairSize > FRACUNIT)
{
CrosshairSize -= XHAIRSHRINKSIZE;
if (CrosshairSize < FRACUNIT)
if (msg->Tick ())
{
*prev = next;
msg->Destroy();
}
else
{
prev = &msg->Next;
}
msg = next;
}
// If the crosshair has been enlarged, shrink it.
if (CrosshairSize > FRACUNIT)
{
CrosshairSize = FRACUNIT;
CrosshairSize -= XHAIRSHRINKSIZE;
if (CrosshairSize < FRACUNIT)
{
CrosshairSize = FRACUNIT;
}
}
}
}
@ -375,7 +381,7 @@ void DBaseStatusBar::Tick ()
//
//---------------------------------------------------------------------------
void DBaseStatusBar::AttachMessage (DHUDMessage *msg, DWORD id)
void DBaseStatusBar::AttachMessage (DHUDMessage *msg, DWORD id, int layer)
{
DHUDMessage *old = NULL;
DHUDMessage **prev;
@ -387,7 +393,13 @@ void DBaseStatusBar::AttachMessage (DHUDMessage *msg, DWORD id)
old->Destroy();
}
prev = &Messages;
// Merge unknown layers into the default layer.
if ((size_t)layer >= countof(Messages))
{
layer = HUDMSGLayer_Default;
}
prev = &Messages[layer];
// The ID serves as a priority, where lower numbers appear in front of
// higher numbers. (i.e. The list is sorted in descending order, since
@ -412,48 +424,56 @@ void DBaseStatusBar::AttachMessage (DHUDMessage *msg, DWORD id)
DHUDMessage *DBaseStatusBar::DetachMessage (DHUDMessage *msg)
{
DHUDMessage *probe = Messages;
DHUDMessage **prev = &Messages;
for (int i = 0; i < countof(Messages); ++i)
{
DHUDMessage *probe = Messages[i];
DHUDMessage **prev = &Messages[i];
while (probe && probe != msg)
{
prev = &probe->Next;
probe = probe->Next;
}
if (probe != NULL)
{
*prev = probe->Next;
probe->Next = NULL;
// Redraw the status bar in case it was covered
if (screen != NULL)
while (probe && probe != msg)
{
SB_state = screen->GetPageCount();
prev = &probe->Next;
probe = probe->Next;
}
if (probe != NULL)
{
*prev = probe->Next;
probe->Next = NULL;
// Redraw the status bar in case it was covered
if (screen != NULL)
{
SB_state = screen->GetPageCount();
}
return probe;
}
}
return probe;
return NULL;
}
DHUDMessage *DBaseStatusBar::DetachMessage (DWORD id)
{
DHUDMessage *probe = Messages;
DHUDMessage **prev = &Messages;
for (int i = 0; i < countof(Messages); ++i)
{
DHUDMessage *probe = Messages[i];
DHUDMessage **prev = &Messages[i];
while (probe && probe->SBarID != id)
{
prev = &probe->Next;
probe = probe->Next;
}
if (probe != NULL)
{
*prev = probe->Next;
probe->Next = NULL;
// Redraw the status bar in case it was covered
if (screen != NULL)
while (probe && probe->SBarID != id)
{
SB_state = screen->GetPageCount();
prev = &probe->Next;
probe = probe->Next;
}
if (probe != NULL)
{
*prev = probe->Next;
probe->Next = NULL;
// Redraw the status bar in case it was covered
if (screen != NULL)
{
SB_state = screen->GetPageCount();
}
return probe;
}
}
return probe;
return NULL;
}
//---------------------------------------------------------------------------
@ -464,31 +484,18 @@ DHUDMessage *DBaseStatusBar::DetachMessage (DWORD id)
void DBaseStatusBar::DetachAllMessages ()
{
DHUDMessage *probe = Messages;
Messages = NULL;
while (probe != NULL)
for (int i = 0; i < countof(Messages); ++i)
{
DHUDMessage *next = probe->Next;
probe->Destroy();
probe = next;
}
}
DHUDMessage *probe = Messages[i];
//---------------------------------------------------------------------------
//
// PROC CheckMessage
//
//---------------------------------------------------------------------------
bool DBaseStatusBar::CheckMessage (DHUDMessage *msg)
{
DHUDMessage *probe = Messages;
while (probe && probe != msg)
{
probe = probe->Next;
Messages[i] = NULL;
while (probe != NULL)
{
DHUDMessage *next = probe->Next;
probe->Destroy();
probe = next;
}
}
return (probe == msg);
}
//---------------------------------------------------------------------------
@ -1037,27 +1044,46 @@ void DBaseStatusBar::RefreshBackground () const
{
int x, x2, y, ratio;
if (SCREENWIDTH > 320)
ratio = CheckRatio (SCREENWIDTH, SCREENHEIGHT);
x = (!(ratio & 3) || !Scaled) ? ST_X : SCREENWIDTH*(48-BaseRatioSizes[ratio][3])/(48*2);
y = x == ST_X && x > 0 ? ST_Y : ::ST_Y;
if(!CompleteBorder)
{
ratio = CheckRatio (SCREENWIDTH, SCREENHEIGHT);
x = (!(ratio & 3) || !Scaled) ? ST_X : SCREENWIDTH*(48-BaseRatioSizes[ratio][3])/(48*2);
if (x > 0)
if(y < SCREENHEIGHT)
{
V_DrawBorder (x+1, y, SCREENWIDTH, y+1);
V_DrawBorder (x+1, SCREENHEIGHT-1, SCREENWIDTH, SCREENHEIGHT);
}
}
else
{
x = SCREENWIDTH;
}
if (x > 0)
{
if(!CompleteBorder)
{
y = x == ST_X ? ST_Y : ::ST_Y;
x2 = !(ratio & 3) || !Scaled ? ST_X+HorizontalResolution :
SCREENWIDTH - (SCREENWIDTH*(48-BaseRatioSizes[ratio][3])+48*2-1)/(48*2);
V_DrawBorder (0, y, x, SCREENHEIGHT);
V_DrawBorder (x2, y, SCREENWIDTH, SCREENHEIGHT);
}
else
{
x2 = SCREENWIDTH;
}
if (setblocks >= 10)
{
const gameborder_t *border = gameinfo.border;
FTexture *p;
V_DrawBorder (0, y, x+1, SCREENHEIGHT);
V_DrawBorder (x2-1, y, SCREENWIDTH, SCREENHEIGHT);
p = TexMan[border->b];
screen->FlatFill(0, y, x, y + p->GetHeight(), p, true);
screen->FlatFill(x2, y, SCREENWIDTH, y + p->GetHeight(), p, true);
}
if (setblocks >= 10)
{
const gameborder_t *border = gameinfo.border;
FTexture *p;
p = TexMan[border->b];
screen->FlatFill(0, y, x, y + p->GetHeight(), p, true);
screen->FlatFill(x2, y, SCREENWIDTH, y + p->GetHeight(), p, true);
}
}
}
@ -1172,13 +1198,23 @@ void DBaseStatusBar::FlashCrosshair ()
//
//---------------------------------------------------------------------------
void DBaseStatusBar::DrawMessages (int bottom)
void DBaseStatusBar::DrawMessages (int layer, int bottom)
{
DHUDMessage *msg = Messages;
DHUDMessage *msg = Messages[layer];
int visibility = 0;
if (viewactive)
{
visibility |= HUDMSG_NotWith3DView;
}
if (automapactive)
{
visibility |= viewactive ? HUDMSG_NotWithOverlayMap : HUDMSG_NotWithFullMap;
}
while (msg)
{
DHUDMessage *next = msg->Next;
msg->Draw (bottom);
msg->Draw (bottom, visibility);
msg = next;
}
}
@ -1426,6 +1462,17 @@ void DBaseStatusBar::SetMugShotState(const char *stateName, bool waitTillDone, b
{
}
//---------------------------------------------------------------------------
//
// DrawBottomStuff
//
//---------------------------------------------------------------------------
void DBaseStatusBar::DrawBottomStuff (EHudState state)
{
DrawMessages (HUDMSGLayer_UnderHUD, (state == HUD_StatusBar) ? ::ST_Y : SCREENHEIGHT);
}
//---------------------------------------------------------------------------
//
// DrawTopStuff
@ -1443,16 +1490,11 @@ void DBaseStatusBar::DrawTopStuff (EHudState state)
}
DrawPowerups ();
if (state == HUD_StatusBar)
if (automapactive && !viewactive)
{
DrawMessages (::ST_Y);
DrawMessages (HUDMSGLayer_OverMap, (state == HUD_StatusBar) ? ::ST_Y : SCREENHEIGHT);
}
else
{
DrawMessages (SCREENHEIGHT);
}
DrawMessages (HUDMSGLayer_OverHUD, (state == HUD_StatusBar) ? ::ST_Y : SCREENHEIGHT);
DrawConsistancy ();
if (ShowLog && MustDrawLog(state)) DrawLog ();
@ -1578,7 +1620,18 @@ void DBaseStatusBar::ReceivedWeapon (AWeapon *weapon)
void DBaseStatusBar::Serialize (FArchive &arc)
{
arc << Messages;
if (SaveVersion < 3821)
{
memset(Messages, 0, sizeof(Messages));
arc << Messages[HUDMSGLayer_Default];
}
else
{
for (int i = 0; i < countof(Messages); ++i)
{
arc << Messages[i];
}
}
}
void DBaseStatusBar::ScreenSizeChanged ()
@ -1586,11 +1639,14 @@ void DBaseStatusBar::ScreenSizeChanged ()
st_scale.Callback ();
SB_state = screen->GetPageCount ();
DHUDMessage *message = Messages;
while (message != NULL)
for (int i = 0; i < countof(Messages); ++i)
{
message->ScreenSizeChanged ();
message = message->Next;
DHUDMessage *message = Messages[i];
while (message != NULL)
{
message->ScreenSizeChanged ();
message = message->Next;
}
}
}

View file

@ -89,6 +89,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SentinelRefire)
self->target->health <= 0 ||
!P_CheckSight (self, self->target, SF_SEEPASTBLOCKEVERYTHING|SF_SEEPASTSHOOTABLELINES) ||
P_HitFriend(self) ||
(self->MissileState == NULL && !self->CheckMeleeRange()) ||
pr_sentinelrefire() < 40)
{
self->SetState (self->SeeState);

View file

@ -721,7 +721,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_DropFire)
AActor *drop = Spawn("FireDroplet", self->x, self->y, self->z + 24*FRACUNIT, ALLOW_REPLACE);
drop->velz = -FRACUNIT;
P_RadiusAttack (self, self, 64, 64, NAME_Fire, false);
P_RadiusAttack (self, self, 64, 64, NAME_Fire, 0);
return 0;
}

View file

@ -605,7 +605,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BurnArea)
{
PARAM_ACTION_PROLOGUE;
P_RadiusAttack (self, self->target, 128, 128, self->DamageType, true);
P_RadiusAttack (self, self->target, 128, 128, self->DamageType, RADF_HURTSOURCE);
return 0;
}

View file

@ -79,7 +79,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Explode512)
{
PARAM_ACTION_PROLOGUE;
P_RadiusAttack (self, self->target, 512, 512, NAME_None, true);
P_RadiusAttack (self, self->target, 512, 512, NAME_None, RADF_HURTSOURCE);
if (self->target != NULL && self->target->player != NULL)
{
self->target->player->extralight = 5;

View file

@ -47,6 +47,7 @@
#include "v_palette.h"
#include "d_player.h"
#include "hu_stuff.h"
#include "gstrings.h"
// MACROS ------------------------------------------------------------------
@ -60,7 +61,7 @@
static void HU_DoDrawScores (player_t *, player_t *[MAXPLAYERS]);
static void HU_DrawTimeRemaining (int y);
static void HU_DrawPlayer (player_t *, bool, int, int, int, int, int, int, int);
static void HU_DrawPlayer (player_t *, bool, int, int, int, int, int, int, int, int);
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
@ -178,10 +179,11 @@ void HU_DrawScores (player_t *player)
//
//==========================================================================
void HU_GetPlayerWidths(int &maxnamewidth, int &maxscorewidth)
void HU_GetPlayerWidths(int &maxnamewidth, int &maxscorewidth, int &maxiconheight)
{
maxnamewidth = SmallFont->StringWidth("Name");
maxscorewidth = 0;
maxiconheight = 0;
for (int i = 0; i < MAXPLAYERS; i++)
{
@ -195,11 +197,18 @@ void HU_GetPlayerWidths(int &maxnamewidth, int &maxscorewidth)
if (players[i].mo->ScoreIcon.isValid())
{
FTexture *pic = TexMan[players[i].mo->ScoreIcon];
width = pic->GetWidth() - pic->GetScaledLeftOffset() + 2;
width = pic->GetScaledWidth() - pic->GetScaledLeftOffset() + 2;
if (width > maxscorewidth)
{
maxscorewidth = width;
}
// The icon's top offset does not count toward its height, because
// zdoom.pk3's standard Hexen class icons are designed that way.
int height = pic->GetScaledHeight() - pic->GetScaledTopOffset();
if (height > maxiconheight)
{
maxiconheight = height;
}
}
}
}
@ -214,11 +223,11 @@ void HU_GetPlayerWidths(int &maxnamewidth, int &maxscorewidth)
static void HU_DoDrawScores (player_t *player, player_t *sortedplayers[MAXPLAYERS])
{
int color;
int height = SmallFont->GetHeight() * CleanYfac;
int height, lineheight;
unsigned int i;
int maxnamewidth, maxscorewidth;
int maxnamewidth, maxscorewidth, maxiconheight;
int numTeams = 0;
int x, y, bottom;
int x, y, ypadding, bottom;
int col2, col3, col4;
if (deathmatch)
@ -233,7 +242,10 @@ static void HU_DoDrawScores (player_t *player, player_t *sortedplayers[MAXPLAYER
color = sb_cooperative_headingcolor;
}
HU_GetPlayerWidths(maxnamewidth, maxscorewidth);
HU_GetPlayerWidths(maxnamewidth, maxscorewidth, maxiconheight);
height = SmallFont->GetHeight() * CleanYfac;
lineheight = MAX(height, maxiconheight * CleanYfac);
ypadding = (lineheight - height + 1) / 2;
bottom = gamestate != GS_INTERMISSION ? ST_Y : SCREENHEIGHT;
y = MAX(48*CleanYfac, (bottom - MAXPLAYERS * (height + CleanYfac + 1)) / 2);
@ -299,18 +311,22 @@ static void HU_DoDrawScores (player_t *player, player_t *sortedplayers[MAXPLAYER
y += (BigFont->GetHeight() + 8) * CleanYfac;
}
col2 = (SmallFont->StringWidth("Color") + 8) * CleanXfac;
col3 = col2 + (SmallFont->StringWidth("Frags") + 8) * CleanXfac;
const char *text_color = GStrings("SCORE_COLOR"),
*text_frags = GStrings(deathmatch ? "SCORE_FRAGS" : "SCORE_KILLS"),
*text_name = GStrings("SCORE_NAME");
col2 = (SmallFont->StringWidth(text_color) + 8) * CleanXfac;
col3 = col2 + (SmallFont->StringWidth(text_frags) + 8) * CleanXfac;
col4 = col3 + maxscorewidth * CleanXfac;
x = (SCREENWIDTH >> 1) - ((maxnamewidth * CleanXfac + col4) >> 1);
screen->DrawText (SmallFont, color, x, y, "Color",
screen->DrawText (SmallFont, color, x, y, text_color,
DTA_CleanNoMove, true, TAG_DONE);
screen->DrawText (SmallFont, color, x + col2, y, deathmatch ? "Frags" : "Kills",
screen->DrawText (SmallFont, color, x + col2, y, text_frags,
DTA_CleanNoMove, true, TAG_DONE);
screen->DrawText (SmallFont, color, x + col4, y, "Name",
screen->DrawText (SmallFont, color, x + col4, y, text_name,
DTA_CleanNoMove, true, TAG_DONE);
y += height + 6 * CleanYfac;
@ -320,8 +336,8 @@ static void HU_DoDrawScores (player_t *player, player_t *sortedplayers[MAXPLAYER
{
if (playeringame[sortedplayers[i] - players])
{
HU_DrawPlayer (sortedplayers[i], player==sortedplayers[i], x, col2, col3, col4, maxnamewidth, y, height);
y += height + CleanYfac;
HU_DrawPlayer (sortedplayers[i], player==sortedplayers[i], x, col2, col3, col4, maxnamewidth, y, ypadding, lineheight);
y += lineheight + CleanYfac;
}
}
}
@ -365,7 +381,7 @@ static void HU_DrawTimeRemaining (int y)
//
//==========================================================================
static void HU_DrawPlayer (player_t *player, bool highlight, int col1, int col2, int col3, int col4, int maxnamewidth, int y, int height)
static void HU_DrawPlayer (player_t *player, bool highlight, int col1, int col2, int col3, int col4, int maxnamewidth, int y, int ypadding, int height)
{
int color;
char str[80];
@ -386,7 +402,7 @@ static void HU_DrawPlayer (player_t *player, bool highlight, int col1, int col2,
HU_DrawColorBar(col1, y, height, (int)(player - players));
mysnprintf (str, countof(str), "%d", deathmatch ? player->fragcount : player->killcount);
screen->DrawText (SmallFont, color, col2, y, player->playerstate == PST_DEAD && !deathmatch ? "DEAD" : str,
screen->DrawText (SmallFont, color, col2, y + ypadding, player->playerstate == PST_DEAD && !deathmatch ? "DEAD" : str,
DTA_CleanNoMove, true, TAG_DONE);
if (player->mo->ScoreIcon.isValid())
@ -397,13 +413,13 @@ static void HU_DrawPlayer (player_t *player, bool highlight, int col1, int col2,
TAG_DONE);
}
screen->DrawText (SmallFont, color, col4, y, player->userinfo.netname,
screen->DrawText (SmallFont, color, col4, y + ypadding, player->userinfo.netname,
DTA_CleanNoMove, true, TAG_DONE);
if (teamplay && Teams[player->userinfo.team].GetLogo ().IsNotEmpty ())
{
FTexture *pic = TexMan[Teams[player->userinfo.team].GetLogo ().GetChars ()];
screen->DrawTexture (pic, col1 - (pic->GetWidth() + 2) * CleanXfac, y,
screen->DrawTexture (pic, col1 - (pic->GetScaledWidth() + 2) * CleanXfac, y,
DTA_CleanNoMove, true, TAG_DONE);
}
}

View file

@ -46,7 +46,7 @@ extern int chatmodeon;
// [RH] Draw deathmatch scores
void HU_DrawScores (player_t *me);
void HU_GetPlayerWidths(int &maxnamewidth, int &maxscorewidth);
void HU_GetPlayerWidths(int &maxnamewidth, int &maxscorewidth, int &maxiconheight);
void HU_DrawColorBar(int x, int y, int height, int playernum);
int HU_GetRowColor(player_t *player, bool hightlight);

View file

@ -56,6 +56,7 @@ extern void InitBotStuff();
extern void ClearStrifeTypes();
TArray<PClassActor *> PClassActor::AllActorClasses;
FRandom FState::pr_statetics;
bool FState::CallAction(AActor *self, AActor *stateowner)
{
@ -505,19 +506,6 @@ void PClassActor::SetPainChance(FName type, int chance)
}
}
//==========================================================================
//
//
//==========================================================================
void PClassActor::SetPainFlash(FName type, PalEntry color)
{
if (PainFlashes == NULL)
PainFlashes = new PainFlashList;
PainFlashes->Insert(type, color);
}
//==========================================================================
//
// DmgFactors :: CheckFactor

View file

@ -47,6 +47,7 @@
#include "s_sound.h"
#include "m_fixed.h"
#include "m_random.h"
struct Baggage;
class FScanner;
@ -63,18 +64,19 @@ enum
struct FState
{
FState *NextState;
VMFunction *ActionFunc;
WORD sprite;
SWORD Tics;
int Misc1; // Was changed to SBYTE, reverted to long for MBF compat
int Misc2; // Was changed to BYTE, reverted to long for MBF compat
WORD TicRange;
BYTE Frame;
BYTE DefineFlags; // Unused byte so let's use it during state creation.
int Misc1; // Was changed to SBYTE, reverted to long for MBF compat
int Misc2; // Was changed to BYTE, reverted to long for MBF compat
short Light;
BYTE Fullbright:1; // State is fullbright
BYTE SameFrame:1; // Ignore Frame (except when spawning actor)
BYTE Fast:1;
FState *NextState;
VMFunction *ActionFunc;
inline int GetFrame() const
{
@ -90,7 +92,11 @@ struct FState
}
inline int GetTics() const
{
return Tics;
if (TicRange == 0)
{
return Tics;
}
return Tics + pr_statetics.GenRand32() % (TicRange + 1);
}
inline int GetMisc1() const
{
@ -112,6 +118,7 @@ struct FState
bool CallAction(AActor *self, AActor *stateowner);
static PClassActor *StaticFindStateOwner (const FState *state);
static PClassActor *StaticFindStateOwner (const FState *state, PClassActor *info);
static FRandom pr_statetics;
};
struct FStateLabels;
@ -143,7 +150,6 @@ struct DmgFactors : public TMap<FName, fixed_t>
fixed_t *CheckFactor(FName type);
};
typedef TMap<FName, int> PainChanceList;
typedef TMap<FName, PalEntry> PainFlashList;
struct DamageTypeDefinition
{
@ -190,7 +196,6 @@ public:
void SetPainChance(FName type, int chance);
size_t PropagateMark();
void InitializeNativeDefaults();
void SetPainFlash(FName type, PalEntry color);
FState *FindState(int numnames, FName *names, bool exact=false) const;
FState *FindStateByString(const char *name, bool exact=false);
@ -217,7 +222,6 @@ public:
FStateLabels *StateList;
DmgFactors *DamageFactors;
PainChanceList *PainChances;
PainFlashList *PainFlashes;
TArray<PClassPlayerPawn *> VisibleToPlayerClass;
TArray<PClassPlayerPawn *> RestrictedToPlayerClass;

View file

@ -45,6 +45,7 @@
#include "d_net.h"
#include "d_dehacked.h"
#include "gi.h"
#include "farchive.h"
// [RH] Actually handle the cheat. The cheat code in st_stuff.c now just
// writes some bytes to the network data stream, and the network code
@ -106,6 +107,20 @@ void cht_DoCheat (player_t *player, int cheat)
msg = GStrings("STSTR_NCOFF");
break;
case CHT_NOCLIP2:
player->cheats ^= CF_NOCLIP2;
if (player->cheats & CF_NOCLIP2)
{
player->cheats |= CF_NOCLIP;
msg = GStrings("STSTR_NC2ON");
}
else
{
player->cheats &= ~CF_NOCLIP;
msg = GStrings("STSTR_NCOFF");
}
break;
case CHT_NOVELOCITY:
player->cheats ^= CF_NOVELOCITY;
if (player->cheats & CF_NOVELOCITY)
@ -504,8 +519,8 @@ void cht_DoCheat (player_t *player, int cheat)
if (player == &players[consoleplayer])
Printf ("%s\n", msg);
else
Printf ("%s is a cheater: %s\n", player->userinfo.netname, msg);
else if (cheat != CHT_CHASECAM)
Printf ("%s cheats: %s\n", player->userinfo.netname, msg);
}
const char *cht_Morph (player_t *player, PClassPlayerPawn *morphclass, bool quickundo)
@ -1042,21 +1057,53 @@ void cht_Take (player_t *player, const char *name, int amount)
return;
}
class DSuicider : public DThinker
{
DECLARE_CLASS(DSuicider, DThinker)
HAS_OBJECT_POINTERS;
public:
TObjPtr<APlayerPawn> Pawn;
void Tick()
{
Pawn->flags |= MF_SHOOTABLE;
Pawn->flags2 &= ~MF2_INVULNERABLE;
// Store the player's current damage factor, to restore it later.
fixed_t plyrdmgfact = Pawn->DamageFactor;
Pawn->DamageFactor = 65536;
P_DamageMobj (Pawn, Pawn, Pawn, TELEFRAG_DAMAGE, NAME_Suicide);
Pawn->DamageFactor = plyrdmgfact;
if (Pawn->health <= 0)
{
Pawn->flags &= ~MF_SHOOTABLE;
}
Destroy();
}
// You'll probably never be able to catch this in a save game, but
// just in case, add a proper serializer.
void Serialize(FArchive &arc)
{
Super::Serialize(arc);
arc << Pawn;
}
};
IMPLEMENT_POINTY_CLASS(DSuicider)
DECLARE_POINTER(Pawn)
END_POINTERS
void cht_Suicide (player_t *plyr)
{
// If this cheat was initiated by the suicide ccmd, and this is a single
// player game, the CHT_SUICIDE will be processed before the tic is run,
// so the console has not gone up yet. Use a temporary thinker to delay
// the suicide until the game ticks so that death noises can be heard on
// the initial tick.
if (plyr->mo != NULL)
{
plyr->mo->flags |= MF_SHOOTABLE;
plyr->mo->flags2 &= ~MF2_INVULNERABLE;
//Store the players current damage factor, to restore it later.
fixed_t plyrdmgfact = plyr->mo->DamageFactor;
plyr->mo->DamageFactor = 65536;
P_DamageMobj (plyr->mo, plyr->mo, plyr->mo, TELEFRAG_DAMAGE, NAME_Suicide);
plyr->mo->DamageFactor = plyrdmgfact;
if (plyr->mo->health <= 0)
{
plyr->mo->flags &= ~MF_SHOOTABLE;
}
DSuicider *suicide = new DSuicider;
suicide->Pawn = plyr->mo;
GC::WriteBarrier(suicide, suicide->Pawn);
}
}

View file

@ -340,9 +340,41 @@ FString GetUserFile (const char *file)
struct stat info;
path = NicePath("~/" GAME_DIR "/");
if (stat (path, &info) == -1)
{
if (mkdir (path, S_IRUSR | S_IWUSR | S_IXUSR) == -1)
struct stat extrainfo;
// Sanity check for ~/.config
FString configPath = NicePath("~/.config/");
if (stat (configPath, &extrainfo) == -1)
{
if (mkdir (configPath, S_IRUSR | S_IWUSR | S_IXUSR) == -1)
{
I_FatalError ("Failed to create ~/.config directory:\n%s", strerror(errno));
}
}
else if (!S_ISDIR(extrainfo.st_mode))
{
I_FatalError ("~/.config must be a directory");
}
// This can be removed after a release or two
// Transfer the old zdoom directory to the new location
bool moved = false;
FString oldpath = NicePath("~/.zdoom/");
if (stat (oldpath, &extrainfo) != -1)
{
if (rename(oldpath, path) == -1)
{
I_Error ("Failed to move old zdoom directory (%s) to new location (%s).",
oldpath.GetChars(), path.GetChars());
}
else
moved = true;
}
if (!moved && mkdir (path, S_IRUSR | S_IWUSR | S_IXUSR) == -1)
{
I_FatalError ("Failed to create %s directory:\n%s",
path.GetChars(), strerror (errno));
@ -682,7 +714,7 @@ void M_ScreenShot (const char *filename)
if (dirlen == 0)
{
#ifdef unix
autoname = "~/.zdoom/screenshots/";
autoname = "~/" GAME_DIR "/screenshots/";
#elif defined(__APPLE__)
char cpath[PATH_MAX];
FSRef folder;
@ -702,7 +734,6 @@ void M_ScreenShot (const char *filename)
}
else if (dirlen > 0)
{
autoname = screenshot_dir;
if (autoname[dirlen-1] != '/' && autoname[dirlen-1] != '\\')
{
autoname += '/';

View file

@ -139,7 +139,6 @@ struct FOptionMenuSettings
EColorRange mFontColorHighlight;
EColorRange mFontColorSelection;
int mLinespacing;
int mLabelOffset;
};
struct FOptionMenuDescriptor : public FMenuDescriptor

View file

@ -605,7 +605,7 @@ static void ParseOptionSettings(FScanner &sc)
else if (sc.Compare("LabelOffset"))
{
sc.MustGetNumber();
OptionSettings.mLabelOffset = sc.Number;
// ignored
}
else
{

View file

@ -214,7 +214,7 @@ void DMessageBoxMenu::Drawer ()
{
screen->DrawText(ConFont, OptionSettings.mFontColorSelection,
(150 - 160) * CleanXfac + screen->GetWidth() / 2,
(y + (fontheight + 1) * messageSelection - 100) * CleanYfac + screen->GetHeight() / 2,
(y + (fontheight + 1) * messageSelection - 100 + fontheight/2 - 5) * CleanYfac + screen->GetHeight() / 2,
"\xd",
DTA_CellX, 8 * CleanXfac,
DTA_CellY, 8 * CleanYfac,
@ -466,19 +466,7 @@ IMPLEMENT_CLASS(DEndGameMenu)
DEndGameMenu::DEndGameMenu(bool playsound)
{
int messageindex = gametic % gameinfo.quitmessages.Size();
FString EndString = gameinfo.quitmessages[messageindex];
if (netgame)
{
EndString = GStrings("NETEND");
return;
}
EndString = GStrings("ENDGAME");
Init(NULL, EndString, 0, playsound);
Init(NULL, GStrings(netgame ? "NETEND" : "ENDGAME"), 0, playsound);
}
//=============================================================================
@ -492,7 +480,10 @@ void DEndGameMenu::HandleResult(bool res)
if (res)
{
M_ClearMenus ();
D_StartTitle ();
if (!netgame)
{
D_StartTitle ();
}
}
else
{

View file

@ -58,8 +58,6 @@
void M_DrawConText (int color, int x, int y, const char *str)
{
int len = (int)strlen(str);
screen->DrawText (ConFont, color, x, y, str,
DTA_CellX, 8 * CleanXfac_1,
DTA_CellY, 8 * CleanYfac_1,
@ -400,8 +398,6 @@ void DOptionMenu::Drawer ()
}
}
mDesc->mDrawTop = y;
//int labelofs = OptionSettings.mLabelOffset * CleanXfac_1;
//int cursorspace = 14 * CleanXfac_1;
int fontheight = OptionSettings.mLinespacing * CleanYfac_1;
y *= CleanYfac_1;
@ -440,7 +436,7 @@ void DOptionMenu::Drawer ()
{
if (((DMenu::MenuTime%8) < 6) || DMenu::CurrentMenu != this)
{
M_DrawConText(OptionSettings.mFontColorSelection, cur_indent + 3 * CleanXfac_1, y-CleanYfac_1+OptionSettings.mLabelOffset, "\xd");
M_DrawConText(OptionSettings.mFontColorSelection, cur_indent + 3 * CleanXfac_1, y+fontheight-9*CleanYfac_1, "\xd");
}
}
}
@ -451,11 +447,11 @@ void DOptionMenu::Drawer ()
if (CanScrollUp)
{
M_DrawConText(CR_ORANGE, 3 * CleanXfac_1, ytop + OptionSettings.mLabelOffset, "\x1a");
M_DrawConText(CR_ORANGE, 3 * CleanXfac_1, ytop, "\x1a");
}
if (CanScrollDown)
{
M_DrawConText(CR_ORANGE, 3 * CleanXfac_1, y - 8*CleanYfac_1 + OptionSettings.mLabelOffset, "\x1b");
M_DrawConText(CR_ORANGE, 3 * CleanXfac_1, y - 8*CleanYfac_1, "\x1b");
}
Super::Drawer();
}

View file

@ -407,11 +407,11 @@ public:
C_NameKeys (description, Key1, Key2);
if (description[0])
{
M_DrawConText(CR_WHITE, indent + CURSORSPACE, y-1+OptionSettings.mLabelOffset, description);
M_DrawConText(CR_WHITE, indent + CURSORSPACE, y + (OptionSettings.mLinespacing-8)*CleanYfac_1, description);
}
else
{
screen->DrawText(SmallFont, CR_BLACK, indent + CURSORSPACE, y + OptionSettings.mLabelOffset, "---",
screen->DrawText(SmallFont, CR_BLACK, indent + CURSORSPACE, y + (OptionSettings.mLinespacing-8)*CleanYfac_1, "---",
DTA_CleanNoMove_1, true, TAG_DONE);
}
return indent;
@ -569,12 +569,13 @@ public:
//
//=============================================================================
void DrawSlider (int x, int y, double min, double max, double cur,int fracdigits, int indent)
void DrawSlider (int x, int y, double min, double max, double cur, int fracdigits, int indent)
{
char textbuf[16];
double range;
int maxlen = 0;
int right = x + (12*8 + 4) * CleanXfac_1;
int cy = y + (OptionSettings.mLinespacing-8)*CleanYfac_1;
range = max - min;
double ccur = clamp(cur, min, max) - min;
@ -589,14 +590,14 @@ public:
if (!mSliderShort)
{
M_DrawConText(CR_WHITE, x, y, "\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12");
M_DrawConText(CR_ORANGE, x + int((5 + ((ccur * 78) / range)) * CleanXfac_1), y, "\x13");
M_DrawConText(CR_WHITE, x, cy, "\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12");
M_DrawConText(CR_ORANGE, x + int((5 + ((ccur * 78) / range)) * CleanXfac_1), cy, "\x13");
}
else
{
// On 320x200 we need a shorter slider
M_DrawConText(CR_WHITE, x, y, "\x10\x11\x11\x11\x11\x11\x12");
M_DrawConText(CR_ORANGE, x + int((5 + ((ccur * 38) / range)) * CleanXfac_1), y, "\x13");
M_DrawConText(CR_WHITE, x, cy, "\x10\x11\x11\x11\x11\x11\x12");
M_DrawConText(CR_ORANGE, x + int((5 + ((ccur * 38) / range)) * CleanXfac_1), cy, "\x13");
right -= 5*8*CleanXfac_1;
}
@ -613,7 +614,7 @@ public:
{
drawLabel(indent, y, selected? OptionSettings.mFontColorSelection : OptionSettings.mFontColor);
mDrawX = indent + CURSORSPACE;
DrawSlider (mDrawX, y + OptionSettings.mLabelOffset, mMin, mMax, GetValue(), mShowValue, indent);
DrawSlider (mDrawX, y, mMin, mMax, GetValue(), mShowValue, indent);
return indent;
}
@ -777,8 +778,8 @@ public:
if (mCVar != NULL)
{
int box_x = indent + CURSORSPACE;
int box_y = y + OptionSettings.mLabelOffset * CleanYfac_1 / 2;
screen->Clear (box_x, box_y, box_x + 32*CleanXfac_1, box_y + (SmallFont->GetHeight() - 1) * CleanYfac_1,
int box_y = y + CleanYfac_1;
screen->Clear (box_x, box_y, box_x + 32*CleanXfac_1, box_y + OptionSettings.mLinespacing*CleanYfac_1,
-1, (uint32)*mCVar | 0xff000000);
}
return indent;

View file

@ -590,8 +590,8 @@ void FListMenuItemPlayerDisplay::Drawer(bool selected)
if (mTranslate) trans = translationtables[TRANSLATION_Players](MAXPLAYERS);
screen->DrawTexture (tex,
x + 36*CleanXfac, y + 71*CleanYfac,
DTA_DestWidth, MulScale16 (tex->GetWidth() * CleanXfac, scaleX),
DTA_DestHeight, MulScale16 (tex->GetHeight() * CleanYfac, scaleY),
DTA_DestWidth, MulScale16 (tex->GetScaledWidth() * CleanXfac, scaleX),
DTA_DestHeight, MulScale16 (tex->GetScaledHeight() * CleanYfac, scaleY),
DTA_Translation, trans,
DTA_FlipX, sprframe->Flip & (1 << mRotation),
TAG_DONE);

View file

@ -99,7 +99,7 @@ CUSTOM_CVAR (Int, menu_screenratios, -1, CVAR_ARCHIVE)
}
}
CUSTOM_CVAR (Bool, vid_tft, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CUSTOM_CVAR (Bool, vid_tft, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
{
FOptionMenuDescriptor *opt = GetVideoModeMenu();
if (opt != NULL)
@ -316,6 +316,7 @@ void M_InitVideoModesMenu ()
size_t currval = 0;
M_RefreshModesList();
vid_tft.Callback();
for (unsigned int i = 1; i <= 32 && currval < countof(BitTranslate); i++)
{

View file

@ -86,10 +86,24 @@ FRandom pr_acs ("ACS");
#define STACK_SIZE 4096
#define CLAMPCOLOR(c) (EColorRange)((unsigned)(c) >= NUM_TEXT_COLORS ? CR_UNTRANSLATED : (c))
#define HUDMSG_LOG (0x80000000)
#define HUDMSG_COLORSTRING (0x40000000)
#define LANGREGIONMASK MAKE_ID(0,0,0xff,0xff)
// HUD message flags
#define HUDMSG_LOG (0x80000000)
#define HUDMSG_COLORSTRING (0x40000000)
#define HUDMSG_ADDBLEND (0x20000000)
#define HUDMSG_ALPHA (0x10000000)
// HUD message layers; these are not flags
#define HUDMSG_LAYER_SHIFT 12
#define HUDMSG_LAYER_MASK (0x0000F000)
// See HUDMSGLayer enumerations in sbar.h
// HUD message visibility flags
#define HUDMSG_VISIBILITY_SHIFT 16
#define HUDMSG_VISIBILITY_MASK (0x00070000)
// See HUDMSG visibility enumerations in sbar.h
// Flags for ReplaceTextures
#define NOT_BOTTOM 1
#define NOT_MIDDLE 2
@ -99,13 +113,12 @@ FRandom pr_acs ("ACS");
struct CallReturn
{
CallReturn(int pc, ScriptFunction *func, FBehavior *module, SDWORD *locals, bool discard, FString &str)
CallReturn(int pc, ScriptFunction *func, FBehavior *module, SDWORD *locals, bool discard)
: ReturnFunction(func),
ReturnModule(module),
ReturnLocals(locals),
ReturnAddress(pc),
bDiscardResult(discard),
StringBuilder(str)
bDiscardResult(discard)
{}
ScriptFunction *ReturnFunction;
@ -113,7 +126,6 @@ struct CallReturn
SDWORD *ReturnLocals;
int ReturnAddress;
int bDiscardResult;
FString StringBuilder;
};
static DLevelScript *P_GetScriptGoing (AActor *who, line_t *where, int num, const ScriptPtr *code, FBehavior *module,
@ -157,8 +169,8 @@ TArray<FString>
ACS_StringsOnTheFly,
ACS_StringBuilderStack;
#define STRINGBUILDER_START(Builder) if (*Builder.GetChars() || ACS_StringBuilderStack.Size()) { ACS_StringBuilderStack.Push(Builder); Builder = ""; }
#define STRINGBUILDER_FINISH(Builder) if (!ACS_StringBuilderStack.Pop(Builder)) Builder = "";
#define STRINGBUILDER_START(Builder) if (Builder.IsNotEmpty() || ACS_StringBuilderStack.Size()) { ACS_StringBuilderStack.Push(Builder); Builder = ""; }
#define STRINGBUILDER_FINISH(Builder) if (!ACS_StringBuilderStack.Pop(Builder)) { Builder = ""; }
//============================================================================
//
@ -3362,6 +3374,11 @@ enum EACSFunctions
ACSF_ACS_NamedLockedExecuteDoor,
ACSF_ACS_NamedExecuteWithResult,
ACSF_ACS_NamedExecuteAlways,
ACSF_UniqueTID,
ACSF_IsTIDUsed,
ACSF_Sqrt,
ACSF_FixedSqrt,
ACSF_VectorLength,
// ZDaemon
ACSF_GetTeamScore = 19620,
@ -3874,6 +3891,23 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args)
}
break;
case ACSF_UniqueTID:
return P_FindUniqueTID(argCount > 0 ? args[0] : 0, argCount > 1 ? args[1] : 0);
break;
case ACSF_IsTIDUsed:
return P_IsTIDUsed(args[0]);
break;
case ACSF_Sqrt:
return xs_FloorToInt(sqrt(double(args[0])));
case ACSF_FixedSqrt:
return FLOAT2FIXED(sqrt(FIXED2DBL(args[0])));
case ACSF_VectorLength:
return FLOAT2FIXED(TVector2<double>(FIXED2DBL(args[0]), FIXED2DBL(args[1])).Length());
default:
break;
}
@ -4295,7 +4329,7 @@ int DLevelScript::RunScript ()
}
sp += i;
::new(&Stack[sp]) CallReturn(activeBehavior->PC2Ofs(pc), activeFunction,
activeBehavior, mylocals, pcd == PCD_CALLDISCARD, work);
activeBehavior, mylocals, pcd == PCD_CALLDISCARD);
sp += (sizeof(CallReturn) + sizeof(int) - 1) / sizeof(int);
pc = module->Ofs2PC (func->Address);
activeFunction = func;
@ -4334,7 +4368,6 @@ int DLevelScript::RunScript ()
{
Stack[sp++] = value;
}
work = ret->StringBuilder;
ret->~CallReturn();
}
break;
@ -5655,6 +5688,7 @@ scriptwait:
float x = FIXED2FLOAT(Stack[optstart-3]);
float y = FIXED2FLOAT(Stack[optstart-2]);
float holdTime = FIXED2FLOAT(Stack[optstart-1]);
fixed_t alpha;
DHUDMessage *msg;
if (type & HUDMSG_COLORSTRING)
@ -5666,14 +5700,16 @@ scriptwait:
color = CLAMPCOLOR(Stack[optstart-4]);
}
switch (type & 0xFFFF)
switch (type & 0xFF)
{
default: // normal
alpha = (optstart < sp) ? Stack[optstart] : FRACUNIT;
msg = new DHUDMessage (activefont, work, x, y, hudwidth, hudheight, color, holdTime);
break;
case 1: // fade out
{
float fadeTime = (optstart < sp) ? FIXED2FLOAT(Stack[optstart]) : 0.5f;
alpha = (optstart < sp-1) ? Stack[optstart+1] : FRACUNIT;
msg = new DHUDMessageFadeOut (activefont, work, x, y, hudwidth, hudheight, color, holdTime, fadeTime);
}
break;
@ -5681,6 +5717,7 @@ scriptwait:
{
float typeTime = (optstart < sp) ? FIXED2FLOAT(Stack[optstart]) : 0.05f;
float fadeTime = (optstart < sp-1) ? FIXED2FLOAT(Stack[optstart+1]) : 0.5f;
alpha = (optstart < sp-2) ? Stack[optstart+2] : FRACUNIT;
msg = new DHUDMessageTypeOnFadeOut (activefont, work, x, y, hudwidth, hudheight, color, typeTime, holdTime, fadeTime);
}
break;
@ -5688,11 +5725,22 @@ scriptwait:
{
float inTime = (optstart < sp) ? FIXED2FLOAT(Stack[optstart]) : 0.5f;
float outTime = (optstart < sp-1) ? FIXED2FLOAT(Stack[optstart+1]) : 0.5f;
alpha = (optstart < sp-2) ? Stack[optstart+2] : FRACUNIT;
msg = new DHUDMessageFadeInOut (activefont, work, x, y, hudwidth, hudheight, color, holdTime, inTime, outTime);
}
break;
}
StatusBar->AttachMessage (msg, id ? 0xff000000|id : 0);
msg->SetVisibility((type & HUDMSG_VISIBILITY_MASK) >> HUDMSG_VISIBILITY_SHIFT);
if (type & HUDMSG_ALPHA)
{
msg->SetAlpha(alpha);
}
if (type & HUDMSG_ADDBLEND)
{
msg->SetRenderStyle(STYLE_Add);
}
StatusBar->AttachMessage (msg, id ? 0xff000000|id : 0,
(type & HUDMSG_LAYER_MASK) >> HUDMSG_LAYER_SHIFT);
if (type & HUDMSG_LOG)
{
static const char bar[] = TEXTCOLOR_ORANGE "\n\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36"
@ -6340,7 +6388,18 @@ scriptwait:
case PCD_GETACTORZ:
{
AActor *actor = SingleActorFromTID(STACK(1), activator);
STACK(1) = actor == NULL ? 0 : (&actor->x)[pcd - PCD_GETACTORX];
if (actor == NULL)
{
STACK(1) = 0;
}
else if (pcd == PCD_GETACTORZ)
{
STACK(1) = actor->z + actor->GetBobOffset();
}
else
{
STACK(1) = (&actor->x)[pcd - PCD_GETACTORX];
}
}
break;
@ -6482,6 +6541,25 @@ scriptwait:
}
break;
case PCD_TRANSLATIONRANGE3:
{ // translation using desaturation
int start = STACK(8);
int end = STACK(7);
fixed_t r1 = STACK(6);
fixed_t g1 = STACK(5);
fixed_t b1 = STACK(4);
fixed_t r2 = STACK(3);
fixed_t g2 = STACK(2);
fixed_t b2 = STACK(1);
sp -= 8;
if (translation != NULL)
translation->AddDesaturation(start, end,
FIXED2DBL(r1), FIXED2DBL(g1), FIXED2DBL(b1),
FIXED2DBL(r2), FIXED2DBL(g2), FIXED2DBL(b2));
}
break;
case PCD_ENDTRANSLATION:
// This might be useful for hardware rendering, but
// for software it is superfluous.
@ -6886,7 +6964,8 @@ scriptwait:
}
else
{
userinfo_t *userinfo = &players[STACK(2)].userinfo;
player_t *pl = &players[STACK(2)];
userinfo_t *userinfo = &pl->userinfo;
switch (STACK(1))
{
case PLAYERINFO_TEAM: STACK(2) = userinfo->team; break;
@ -6897,6 +6976,8 @@ scriptwait:
case PLAYERINFO_MOVEBOB: STACK(2) = userinfo->MoveBob; break;
case PLAYERINFO_STILLBOB: STACK(2) = userinfo->StillBob; break;
case PLAYERINFO_PLAYERCLASS: STACK(2) = userinfo->PlayerClass; break;
case PLAYERINFO_DESIREDFOV: STACK(2) = (int)pl->DesiredFOV; break;
case PLAYERINFO_FOV: STACK(2) = (int)pl->FOV; break;
default: STACK(2) = 0; break;
}
}
@ -7519,6 +7600,3 @@ void DACSThinker::DumpScriptStatus ()
script = script->next;
}
}
#undef STRINGBUILDER_START
#undef STRINGBUILDER_FINISH

View file

@ -601,8 +601,9 @@ public:
PCD_PUSHFUNCTION, // from Eternity
/*360*/ PCD_CALLSTACK, // from Eternity
PCD_SCRIPTWAITNAMED,
PCD_TRANSLATIONRANGE3,
/*361*/ PCODE_COMMAND_COUNT
/*363*/ PCODE_COMMAND_COUNT
};
// Some constants used by ACS scripts
@ -664,7 +665,9 @@ public:
PLAYERINFO_NEVERSWITCH,
PLAYERINFO_MOVEBOB,
PLAYERINFO_STILLBOB,
PLAYERINFO_PLAYERCLASS
PLAYERINFO_PLAYERCLASS,
PLAYERINFO_FOV,
PLAYERINFO_DESIREDFOV,
};
enum EScriptState

View file

@ -926,7 +926,6 @@ public:
const char *speakerName;
int x, y, linesize;
int width, fontheight;
int labelofs;
player_t *cp = &players[consoleplayer];
@ -1015,8 +1014,6 @@ public:
}
y = mYpos;
labelofs = OptionSettings.mLabelOffset;
y -= labelofs;
fontheight = OptionSettings.mLinespacing;
int response = 0;
@ -1041,7 +1038,7 @@ public:
int color = ((DMenu::MenuTime%8) < 4) || DMenu::CurrentMenu != this ? CR_RED:CR_GREY;
x = (50 + 3 - 160) * CleanXfac + screen->GetWidth() / 2;
int yy = (y-1+labelofs - 100) * CleanYfac + screen->GetHeight() / 2;
int yy = (y + fontheight/2 - 5 - 100) * CleanYfac + screen->GetHeight() / 2;
screen->DrawText (ConFont, color, x, yy, "\xd",
DTA_CellX, 8 * CleanXfac,
DTA_CellY, 8 * CleanYfac,

View file

@ -1670,7 +1670,7 @@ bool P_LookForPlayers (AActor *actor, INTBOOL allaround, FLookExParams *params)
// [RC] Well, let's let special monsters with this flag active be able to see
// the player then, eh?
if(!(actor->flags & MF6_SEEINVISIBLE))
if(!(actor->flags6 & MF6_SEEINVISIBLE))
{
if ((player->mo->flags & MF_SHADOW && !(i_compatflags & COMPATF_INVISIBILITY)) ||
player->mo->flags3 & MF3_GHOST)
@ -3210,7 +3210,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Detonate)
{
PARAM_ACTION_PROLOGUE;
int damage = self->GetMissileDamage(0, 1);
P_RadiusAttack (self, self->target, damage, damage, self->DamageType, true);
P_RadiusAttack (self, self->target, damage, damage, self->DamageType, RADF_HURTSOURCE);
P_CheckSplash(self, damage<<FRACBITS);
return 0;
}

View file

@ -1088,7 +1088,7 @@ static FString GetCachePath()
path += "/zdoom/cache";
#else
// Don't use GAME_DIR and such so that ZDoom and its child ports can share the node cache.
path = NicePath("~/.zdoom/cache");
path = NicePath("~/.config/zdoom/cache");
#endif
return path;
}

View file

@ -86,7 +86,9 @@ void P_TouchSpecialThing (AActor *special, AActor *toucher)
{
fixed_t delta = special->z - toucher->z;
if (delta > toucher->height || delta < -32*FRACUNIT)
// The pickup is at or above the toucher's feet OR
// The pickup is below the toucher.
if (delta > toucher->height || delta < MIN(-32*FRACUNIT, -special->height))
{ // out of reach
return;
}

View file

@ -483,8 +483,15 @@ void P_PlaySpawnSound(AActor *missile, AActor *spawner);
void P_AimCamera (AActor *t1, fixed_t &x, fixed_t &y, fixed_t &z, sector_t *&sec);
// [RH] Means of death
enum
{
RADF_HURTSOURCE = 1,
RADF_NOIMPACTDAMAGE = 2,
RADF_SOURCEISSPOT = 4,
RADF_NODAMAGE = 8,
};
void P_RadiusAttack (AActor *spot, AActor *source, int damage, int distance,
FName damageType, bool hurtSelf, bool dodamage=true, int fulldamagedistance=0, bool noimpactdamage=false);
FName damageType, int flags, int fulldamagedistance=0);
void P_DelSector_List();
void P_DelSeclist(msecnode_t *); // phares 3/16/98

View file

@ -501,7 +501,11 @@ int P_GetFriction (const AActor *mo, int *frictionfactor)
const msecnode_t *m;
const sector_t *sec;
if (mo->flags2 & MF2_FLY && mo->flags & MF_NOGRAVITY)
if (mo->IsNoClip2())
{
// The default values are fine for noclip2 mode
}
else if (mo->flags2 & MF2_FLY && mo->flags & MF_NOGRAVITY)
{
friction = FRICTION_FLY;
}
@ -938,8 +942,11 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm)
|| ((thing->activationtype & THINGSPEC_MissileTrigger) && (tm.thing->flags & MF_MISSILE))
) && (level.maptime > thing->lastbump)) // Leave the bumper enough time to go away
{
if (P_ActivateThingSpecial(thing, tm.thing))
thing->lastbump = level.maptime + TICRATE;
if (tm.thing->player == NULL || !(tm.thing->player->cheats & CF_PREDICTING))
{
if (P_ActivateThingSpecial(thing, tm.thing))
thing->lastbump = level.maptime + TICRATE;
}
}
// Check for skulls slamming into things
@ -1298,7 +1305,7 @@ bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y, FCheckPosition &tm, b
#ifdef _3DFLOORS
//Check 3D floors
if(newsec->e->XFloor.ffloors.Size())
if (!thing->IsNoClip2() && newsec->e->XFloor.ffloors.Size())
{
F3DFloor* rover;
fixed_t delta1;
@ -1605,7 +1612,7 @@ void P_FakeZMovement (AActor *mo)
mo->z += mo->FloatSpeed;
}
}
if (mo->player && mo->flags&MF_NOGRAVITY && (mo->z > mo->floorz))
if (mo->player && mo->flags&MF_NOGRAVITY && (mo->z > mo->floorz) && !mo->IsNoClip2())
{
mo->z += finesine[(FINEANGLES/80*level.maptime)&FINEMASK]/8;
}
@ -4440,7 +4447,7 @@ CUSTOM_CVAR (Float, splashfactor, 1.f, CVAR_SERVERINFO)
//==========================================================================
void P_RadiusAttack (AActor *bombspot, AActor *bombsource, int bombdamage, int bombdistance, FName bombmod,
bool DamageSource, bool bombdodamage, int fulldamagedistance, bool noimpactdamage)
int flags, int fulldamagedistance)
{
if (bombdistance <= 0)
return;
@ -4454,6 +4461,11 @@ void P_RadiusAttack (AActor *bombspot, AActor *bombsource, int bombdamage, int b
FBlockThingsIterator it(FBoundingBox(bombspot->x, bombspot->y, bombdistance<<FRACBITS));
AActor *thing;
if (flags & RADF_SOURCEISSPOT)
{ // The source is actually the same as the spot, even if that wasn't what we receized.
bombsource = bombspot;
}
while ((thing = it.Next()))
{
// Vulnerable actors can be damaged by radius attacks even if not shootable
@ -4466,7 +4478,7 @@ void P_RadiusAttack (AActor *bombspot, AActor *bombsource, int bombdamage, int b
if (thing->flags3 & MF3_NORADIUSDMG && !(bombspot->flags4 & MF4_FORCERADIUSDMG))
continue;
if (!DamageSource && (thing == bombsource || thing == bombspot))
if (!(flags & RADF_HURTSOURCE) && (thing == bombsource || thing == bombspot))
{ // don't damage the source of the explosion
continue;
}
@ -4486,7 +4498,7 @@ void P_RadiusAttack (AActor *bombspot, AActor *bombsource, int bombdamage, int b
// them far too "active." BossBrains also use the old code
// because some user levels require they have a height of 16,
// which can make them near impossible to hit with the new code.
if (!bombdodamage || !((bombspot->flags5 | thing->flags5) & MF5_OLDRADIUSDMG))
if ((flags & RADF_NODAMAGE) || !((bombspot->flags5 | thing->flags5) & MF5_OLDRADIUSDMG))
{
// [RH] New code. The bounding box only covers the
// height of the thing and not the height of the map.
@ -4545,14 +4557,17 @@ void P_RadiusAttack (AActor *bombspot, AActor *bombsource, int bombdamage, int b
double thrust;
int damage = (int)points;
if (bombdodamage) P_DamageMobj (thing, bombspot, bombsource, damage, bombmod);
else if (thing->player == NULL && !noimpactdamage) thing->flags2 |= MF2_BLASTED;
if (!(flags & RADF_NODAMAGE))
P_DamageMobj (thing, bombspot, bombsource, damage, bombmod);
else if (thing->player == NULL && !(flags & RADF_NOIMPACTDAMAGE))
thing->flags2 |= MF2_BLASTED;
if (!(thing->flags & MF_ICECORPSE))
{
if (bombdodamage && !(bombspot->flags3 & MF3_BLOODLESSIMPACT)) P_TraceBleed (damage, thing, bombspot);
if (!(flags & RADF_NODAMAGE) && !(bombspot->flags3 & MF3_BLOODLESSIMPACT))
P_TraceBleed (damage, thing, bombspot);
if (!bombdodamage || !(bombspot->flags2 & MF2_NODMGTHRUST))
if (!(flags & RADF_NODAMAGE) || !(bombspot->flags2 & MF2_NODMGTHRUST))
{
if (bombsource == NULL || !(bombsource->flags2 & MF2_NODMGTHRUST))
{
@ -4573,7 +4588,7 @@ void P_RadiusAttack (AActor *bombspot, AActor *bombsource, int bombdamage, int b
angle_t ang = R_PointToAngle2 (bombspot->x, bombspot->y, thing->x, thing->y) >> ANGLETOFINESHIFT;
thing->velx += fixed_t (finecosine[ang] * thrust);
thing->vely += fixed_t (finesine[ang] * thrust);
if (bombdodamage)
if (!(flags & RADF_NODAMAGE))
thing->velz += (fixed_t)velz; // this really doesn't work well
}
}

View file

@ -37,6 +37,7 @@
#include "doomstat.h"
#include "v_video.h"
#include "c_cvars.h"
#include "c_dispatch.h"
#include "b_bot.h" //Added by MC:
#include "stats.h"
#include "a_hexenglobal.h"
@ -107,6 +108,7 @@ static FRandom pr_missiledamage ("MissileDamage");
FRandom pr_slam ("SkullSlam");
static FRandom pr_multiclasschoice ("MultiClassChoice");
static FRandom pr_rockettrail("RocketTrail");
static FRandom pr_uniquetid("UniqueTID");
// PUBLIC DATA DEFINITIONS -------------------------------------------------
@ -1158,6 +1160,7 @@ void P_ExplodeMissile (AActor *mo, line_t *line, AActor *target)
}
mo->velx = mo->vely = mo->velz = 0;
mo->effects = 0; // [RH]
mo->flags &= ~MF_SHOOTABLE;
FState *nextstate=NULL;
@ -1983,7 +1986,9 @@ explode:
}
if (mo->z > mo->floorz && !(mo->flags2 & MF2_ONMOBJ) &&
(!(mo->flags2 & MF2_FLY) || !(mo->flags & MF_NOGRAVITY)) && !mo->waterlevel)
!mo->IsNoClip2() &&
(!(mo->flags2 & MF2_FLY) || !(mo->flags & MF_NOGRAVITY)) &&
!mo->waterlevel)
{ // [RH] Friction when falling is available for larger aircontrols
if (player != NULL && level.airfriction != FRACUNIT)
{
@ -2226,7 +2231,10 @@ void P_ZMovement (AActor *mo, fixed_t oldfloorz)
}
if (mo->player && (mo->flags & MF_NOGRAVITY) && (mo->z > mo->floorz))
{
mo->z += finesine[(FINEANGLES/80*level.maptime)&FINEMASK]/8;
if (!mo->IsNoClip2())
{
mo->z += finesine[(FINEANGLES/80*level.maptime)&FINEMASK]/8;
}
mo->velz = FixedMul (mo->velz, FRICTION_FLY);
}
if (mo->waterlevel && !(mo->flags & MF_NOGRAVITY))
@ -2474,7 +2482,7 @@ static void PlayerLandedOnThing (AActor *mo, AActor *onmobj)
{
grunted = false;
// Why should this number vary by gravity?
if (mo->velz < (fixed_t)(800.f /*level.gravity * mo->Sector->gravity*/ * -983.04f) && mo->health > 0)
if (mo->health > 0 && mo->velz < -mo->player->mo->GruntSpeed)
{
S_Sound (mo, CHAN_VOICE, "*grunt", 1, ATTN_NORM);
grunted = true;
@ -2613,10 +2621,7 @@ AActor *AActor::TIDHash[128];
void AActor::ClearTIDHashes ()
{
int i;
for (i = 0; i < 128; i++)
TIDHash[i] = NULL;
memset(TIDHash, NULL, sizeof(TIDHash));
}
//
@ -2667,6 +2672,92 @@ void AActor::RemoveFromHash ()
tid = 0;
}
//==========================================================================
//
// P_IsTIDUsed
//
// Returns true if there is at least one actor with the specified TID
// (dead or alive).
//
//==========================================================================
bool P_IsTIDUsed(int tid)
{
AActor *probe = AActor::TIDHash[tid & 127];
while (probe != NULL)
{
if (probe->tid == tid)
{
return true;
}
probe = probe->inext;
}
return false;
}
//==========================================================================
//
// P_FindUniqueTID
//
// Returns an unused TID. If start_tid is 0, then a random TID will be
// chosen. Otherwise, it will perform a linear search starting from
// start_tid. If limit is non-0, then it will not check more than <limit>
// number of TIDs. Returns 0 if no suitable TID was found.
//
//==========================================================================
int P_FindUniqueTID(int start_tid, int limit)
{
int tid;
if (start_tid != 0)
{ // Do a linear search.
limit = start_tid + limit - 1;
if (limit < start_tid)
{ // If it overflowed, clamp to INT_MAX
limit = INT_MAX;
}
for (tid = start_tid; tid <= limit; ++tid)
{
if (tid != 0 && !P_IsTIDUsed(tid))
{
return tid;
}
}
// Nothing free found.
return 0;
}
// Do a random search. To try and be a bit more performant, this
// actually does several linear searches. In the case of *very*
// dense TID usage, this could potentially perform worse than doing
// a complete linear scan starting at 1. However, you would need
// to use an absolutely ridiculous number of actors before this
// becomes a real concern.
if (limit == 0)
{
limit = INT_MAX;
}
for (int i = 0; i < limit; i += 5)
{
// Use a positive starting TID.
tid = pr_uniquetid.GenRand32() & INT_MAX;
tid = P_FindUniqueTID(tid == 0 ? 1 : tid, 5);
if (tid != 0)
{
return tid;
}
}
// Nothing free found.
return 0;
}
CCMD(utid)
{
Printf("%d\n",
P_FindUniqueTID(argv.argc() > 1 ? atoi(argv[1]) : 0,
argv.argc() > 2 ? atoi(argv[2]) : 0));
}
//==========================================================================
//
// AActor :: GetMissileDamage
@ -3363,8 +3454,11 @@ void AActor::Tick ()
|| ((onmo->activationtype & THINGSPEC_MissileTrigger) && (flags & MF_MISSILE))
) && (level.maptime > onmo->lastbump)) // Leave the bumper enough time to go away
{
if (P_ActivateThingSpecial(onmo, this))
onmo->lastbump = level.maptime + TICRATE;
if (player == NULL || !(player->cheats & CF_PREDICTING))
{
if (P_ActivateThingSpecial(onmo, this))
onmo->lastbump = level.maptime + TICRATE;
}
}
if (velz != 0 && (BounceFlags & BOUNCE_Actors))
{
@ -3902,6 +3996,19 @@ void AActor::PostBeginPlay ()
PrevAngle = angle;
}
void AActor::MarkPrecacheSounds() const
{
SeeSound.MarkUsed();
AttackSound.MarkUsed();
PainSound.MarkUsed();
DeathSound.MarkUsed();
ActiveSound.MarkUsed();
UseSound.MarkUsed();
BounceSound.MarkUsed();
WallBounceSound.MarkUsed();
CrushPainSound.MarkUsed();
}
bool AActor::isFast()
{
if (flags5&MF5_ALWAYSFAST) return true;
@ -4734,13 +4841,16 @@ void P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, angle_t dir, int damage, AAc
// Moved out of the blood actor so that replacing blood is easier
if (gameinfo.gametype & GAME_DoomStrifeChex)
{
FState *state = th->FindState(NAME_Spray);
if (gameinfo.gametype == GAME_Strife)
{
if (damage > 13)
{
FState *state = th->FindState(NAME_Spray);
if (state != NULL) th->SetState (state);
if (state != NULL)
{
th->SetState (state);
goto statedone;
}
}
else damage += 2;
}
@ -4758,14 +4868,15 @@ void P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, angle_t dir, int damage, AAc
while (cls != RUNTIME_CLASS(AActor))
{
int checked_advance = advance;
if (cls->OwnsState(th->SpawnState))
{
for (; advance > 0; --advance)
for (; checked_advance > 0; --checked_advance)
{
// [RH] Do not set to a state we do not own.
if (!cls->OwnsState(th->SpawnState + advance))
if (cls->OwnsState(th->SpawnState + checked_advance))
{
th->SetState(th->SpawnState + advance);
th->SetState(th->SpawnState + checked_advance);
goto statedone;
}
}
@ -5295,7 +5406,7 @@ static fixed_t GetDefaultSpeed(PClassActor *type)
AActor *P_SpawnMissile (AActor *source, AActor *dest, PClassActor *type, AActor *owner)
{
return P_SpawnMissileXYZ (source->x, source->y, source->z + 32*FRACUNIT,
return P_SpawnMissileXYZ (source->x, source->y, source->z + 32*FRACUNIT + source->GetBobOffset(),
source, dest, type, true, owner);
}
@ -5417,7 +5528,7 @@ AActor *P_OldSpawnMissile(AActor *source, AActor *owner, AActor *dest, PClassAct
AActor *P_SpawnMissileAngle (AActor *source, PClassActor *type,
angle_t angle, fixed_t velz)
{
return P_SpawnMissileAngleZSpeed (source, source->z + 32*FRACUNIT,
return P_SpawnMissileAngleZSpeed (source, source->z + 32*FRACUNIT + source->GetBobOffset(),
type, angle, velz, GetDefaultSpeed (type));
}
@ -5460,7 +5571,7 @@ AActor *P_SpawnMissileZAimed (AActor *source, fixed_t z, AActor *dest, PClassAct
AActor *P_SpawnMissileAngleSpeed (AActor *source, PClassActor *type,
angle_t angle, fixed_t velz, fixed_t speed)
{
return P_SpawnMissileAngleZSpeed (source, source->z + 32*FRACUNIT,
return P_SpawnMissileAngleZSpeed (source, source->z + 32*FRACUNIT + source->GetBobOffset(),
type, angle, velz, speed);
}
@ -5985,25 +6096,25 @@ void PrintMiscActorInfo(AActor *query)
Printf("\n\tflags6: %x", query->flags6);
for (flagi = 0; flagi < 31; flagi++)
if (query->flags6 & 1<<flagi) Printf(" %s", FLAG_NAME(1<<flagi, flags6));
Printf("\nIts bounce style and factors are %x and f:%f, w:%f; its bounce flags are:\n\tflagsb: %x",
Printf("\nBounce style: %x\nBounce factors: f:%f, w:%f\nBounce flags: %x",
query->BounceFlags, FIXED2FLOAT(query->bouncefactor),
FIXED2FLOAT(query->wallbouncefactor), query->BounceFlags);
/*for (flagi = 0; flagi < 31; flagi++)
if (query->BounceFlags & 1<<flagi) Printf(" %s", flagnamesb[flagi]);*/
Printf("\nIts render style is %i:%s with alpha %f and the following render flags:\n\tflagsr: %x",
Printf("\nRender style = %i:%s, alpha %f\nRender flags: %x",
querystyle, (querystyle < STYLE_Count ? renderstyles[querystyle] : "Unknown"),
FIXED2FLOAT(query->alpha), query->renderflags);
/*for (flagi = 0; flagi < 31; flagi++)
if (query->renderflags & 1<<flagi) Printf(" %s", flagnamesr[flagi]);*/
Printf("\nIts thing special and arguments are %s(%i, %i, %i, %i, %i), and its specials are %i and %i.",
Printf("\nSpecial+args: %s(%i, %i, %i, %i, %i)\nspecial1: %i, special2: %i.",
(query->special ? LineSpecialsInfo[query->special]->name : "None"),
query->args[0], query->args[1], query->args[2], query->args[3],
query->args[4], query->special1, query->special2);
Printf("\nTID is %d", query->tid);
Printf("\nIts coordinates are x: %f, y: %f, z:%f, floor:%f, ceiling:%f.",
Printf("\nTID: %d", query->tid);
Printf("\nCoord= x: %f, y: %f, z:%f, floor:%f, ceiling:%f.",
FIXED2FLOAT(query->x), FIXED2FLOAT(query->y), FIXED2FLOAT(query->z),
FIXED2FLOAT(query->floorz), FIXED2FLOAT(query->ceilingz));
Printf("\nIts speed is %f and velocity is x:%f, y:%f, z:%f, combined:%f.\n",
Printf("\nSpeed= %f, velocity= x:%f, y:%f, z:%f, combined:%f.\n",
FIXED2FLOAT(query->Speed), FIXED2FLOAT(query->velx), FIXED2FLOAT(query->vely), FIXED2FLOAT(query->velz),
sqrt(pow(FIXED2FLOAT(query->velx), 2) + pow(FIXED2FLOAT(query->vely), 2) + pow(FIXED2FLOAT(query->velz), 2)));
}

View file

@ -909,7 +909,6 @@ int FStateDefinitions::FinishStates(PClassActor *actor, AActor *defaults)
{
FState *realstates = new FState[count];
int i;
int currange;
memcpy(realstates, &StateArray[0], count*sizeof(FState));
actor->OwnedStates = realstates;
@ -917,12 +916,15 @@ int FStateDefinitions::FinishStates(PClassActor *actor, AActor *defaults)
// adjust the state pointers
// In the case new states are added these must be adjusted, too!
FixStatePointers (actor, StateLabels);
FixStatePointers(actor, StateLabels);
for(i = currange = 0; i < count; i++)
// Fix state pointers that are gotos
ResolveGotoLabels(actor, defaults, StateLabels);
for (i = 0; i < count; i++)
{
// resolve labels and jumps
switch(realstates[i].DefineFlags)
switch (realstates[i].DefineFlags)
{
case SDF_STOP: // stop
realstates[i].NextState = NULL;
@ -946,10 +948,11 @@ int FStateDefinitions::FinishStates(PClassActor *actor, AActor *defaults)
}
}
}
// Fix state pointers that are gotos
ResolveGotoLabels(actor, defaults, StateLabels);
else
{
// Fix state pointers that are gotos
ResolveGotoLabels(actor, defaults, StateLabels);
}
return count;
}

View file

@ -137,6 +137,10 @@ bool P_MoveThing(AActor *source, fixed_t x, fixed_t y, fixed_t z, bool fog)
source->PrevX = x;
source->PrevY = y;
source->PrevZ = z;
if (source == players[consoleplayer].camera)
{
R_ResetViewInterpolation();
}
return true;
}
else

View file

@ -471,6 +471,29 @@ void PClassPlayerPawn::EnumColorSets(TArray<int> *out)
qsort(&(*out)[0], out->Size(), sizeof(int), intcmp);
}
//==========================================================================
//
//
//==========================================================================
bool PClassPlayerPawn::GetPainFlash(FName type, PalEntry *color) const
{
const PClassPlayerPawn *info = this;
while (info != NULL)
{
const PalEntry *flash = info->PainFlashes.CheckKey(type);
if (flash != NULL)
{
*color = *flash;
return true;
}
// Try parent class
info = dyn_cast<PClassPlayerPawn>(info->ParentClass);
}
return false;
}
//===========================================================================
//
// player_t :: SendPitchLimits
@ -523,6 +546,28 @@ void APlayerPawn::Serialize (FArchive &arc)
<< DamageFade
<< PlayerFlags
<< FlechetteType;
if (SaveVersion < 3829)
{
GruntSpeed = 12*FRACUNIT;
FallingScreamMinSpeed = 35*FRACUNIT;
FallingScreamMaxSpeed = 40*FRACUNIT;
}
else
{
arc << GruntSpeed << FallingScreamMinSpeed << FallingScreamMaxSpeed;
}
}
//===========================================================================
//
// APlayerPawn :: MarkPrecacheSounds
//
//===========================================================================
void APlayerPawn::MarkPrecacheSounds() const
{
Super::MarkPrecacheSounds();
S_MarkPlayerSounds(GetSoundClass());
}
//===========================================================================
@ -1018,7 +1063,7 @@ void APlayerPawn::FilterCoopRespawnInventory (APlayerPawn *oldplayer)
//
//===========================================================================
const char *APlayerPawn::GetSoundClass ()
const char *APlayerPawn::GetSoundClass() const
{
if (player != NULL &&
(player->mo == NULL || !(player->mo->flags4 &MF4_NOSKIN)) &&
@ -1679,7 +1724,11 @@ void P_CalcHeight (player_t *player)
// it causes bobbing jerkiness when the player moves from ice to non-ice,
// and vice-versa.
if ((player->mo->flags & MF_NOGRAVITY) && !onground)
if (player->cheats & CF_NOCLIP2)
{
player->bob = 0;
}
else if ((player->mo->flags & MF_NOGRAVITY) && !onground)
{
player->bob = FRACUNIT / 2;
}
@ -1804,7 +1853,7 @@ void P_MovePlayer (player_t *player)
mo->angle += cmd->ucmd.yaw << 16;
}
onground = (mo->z <= mo->floorz) || (mo->flags2 & MF2_ONMOBJ) || (mo->BounceFlags & BOUNCE_MBF);
onground = (mo->z <= mo->floorz) || (mo->flags2 & MF2_ONMOBJ) || (mo->BounceFlags & BOUNCE_MBF) || (player->cheats & CF_NOCLIP2);
// killough 10/98:
//
@ -2185,7 +2234,11 @@ void P_PlayerThink (player_t *player)
player->inventorytics--;
}
// No-clip cheat
if (player->cheats & CF_NOCLIP || (player->mo->GetDefault()->flags & MF_NOCLIP))
if ((player->cheats & (CF_NOCLIP | CF_NOCLIP2)) == CF_NOCLIP2)
{ // No noclip2 without noclip
player->cheats &= ~CF_NOCLIP2;
}
if (player->cheats & (CF_NOCLIP | CF_NOCLIP2) || (player->mo->GetDefault()->flags & MF_NOCLIP))
{
player->mo->flags |= MF_NOCLIP;
}
@ -2193,6 +2246,14 @@ void P_PlayerThink (player_t *player)
{
player->mo->flags &= ~MF_NOCLIP;
}
if (player->cheats & CF_NOCLIP2)
{
player->mo->flags |= MF_NOGRAVITY;
}
else if (!(player->mo->flags2 & MF2_FLY) && !(player->mo->GetDefault()->flags & MF_NOGRAVITY))
{
player->mo->flags &= ~MF_NOGRAVITY;
}
cmd = &player->cmd;
// Make unmodified copies for ACS's GetPlayerInput.
@ -2413,7 +2474,7 @@ void P_PlayerThink (player_t *player)
{
cmd->ucmd.upmove = ksgn (cmd->ucmd.upmove) * 0x300;
}
if (player->mo->waterlevel >= 2 || (player->mo->flags2 & MF2_FLY))
if (player->mo->waterlevel >= 2 || (player->mo->flags2 & MF2_FLY) || (player->cheats & CF_NOCLIP2))
{
player->mo->velz = cmd->ucmd.upmove << 9;
if (player->mo->waterlevel < 2 && !(player->mo->flags & MF_NOGRAVITY))
@ -2447,8 +2508,8 @@ void P_PlayerThink (player_t *player)
P_PlayerInSpecialSector (player);
}
P_PlayerOnSpecialFlat (player, P_GetThingFloorType (player->mo));
if (player->mo->velz <= -35*FRACUNIT &&
player->mo->velz >= -40*FRACUNIT && !player->morphTics &&
if (player->mo->velz <= -player->mo->FallingScreamMinSpeed &&
player->mo->velz >= -player->mo->FallingScreamMaxSpeed && !player->morphTics &&
player->mo->waterlevel == 0)
{
int id = S_FindSkinnedSound (player->mo, "*falling");
@ -2531,7 +2592,7 @@ void P_PlayerThink (player_t *player)
{
if (player->mo->waterlevel < 3 ||
(player->mo->flags2 & MF2_INVULNERABLE) ||
(player->cheats & CF_GODMODE))
(player->cheats & (CF_GODMODE | CF_NOCLIP2)))
{
player->mo->ResetAirSupply ();
}
@ -2763,6 +2824,14 @@ void player_t::Serialize (FArchive &arc)
{
cheats &= ~(1 << 17); // make sure old CF_REGENERATION bit is cleared
}
if (SaveVersion >= 3780)
{
arc << settings_controller;
}
else
{
settings_controller = (this - players == Net_Arbitrator);
}
if (isbot)
{

View file

@ -1185,7 +1185,7 @@ void R_Subsector (subsector_t *sub)
frontsector->GetTexture(sector_t::floor),
floorlightlevel + r_actualextralight, // killough 3/16/98
frontsector->GetAlpha(sector_t::floor),
!!(frontsector->GetFlags(sector_t::floor) & PLANEF_ADDITIVE),
!!(fakeFloor->flags & FF_ADDITIVETRANS),
frontsector->GetXOffset(position), // killough 3/7/98
frontsector->GetYOffset(position), // killough 3/7/98
frontsector->GetXScale(position),
@ -1250,7 +1250,7 @@ void R_Subsector (subsector_t *sub)
frontsector->GetTexture(sector_t::ceiling),
ceilinglightlevel + r_actualextralight, // killough 4/11/98
frontsector->GetAlpha(sector_t::ceiling),
!!(frontsector->GetFlags(sector_t::ceiling) & PLANEF_ADDITIVE),
!!(fakeFloor->flags & FF_ADDITIVETRANS),
frontsector->GetXOffset(position), // killough 3/7/98
frontsector->GetYOffset(position), // killough 3/7/98
frontsector->GetXScale(position),

View file

@ -403,14 +403,22 @@ void FRemapTable::AddColorRange(int start, int end, int _r1,int _g1, int _b1, in
//
//----------------------------------------------------------------------------
void FRemapTable::AddDesaturation(int start, int end, float r1,float g1, float b1, float r2, float g2, float b2)
void FRemapTable::AddDesaturation(int start, int end, double r1, double g1, double b1, double r2, double g2, double b2)
{
r1 = clamp(r1, 0.0f, 2.0f);
g1 = clamp(g1, 0.0f, 2.0f);
b1 = clamp(b1, 0.0f, 2.0f);
r2 = clamp(r2, 0.0f, 2.0f);
g2 = clamp(g2, 0.0f, 2.0f);
b2 = clamp(b2, 0.0f, 2.0f);
r1 = clamp(r1, 0.0, 2.0);
g1 = clamp(g1, 0.0, 2.0);
b1 = clamp(b1, 0.0, 2.0);
r2 = clamp(r2, 0.0, 2.0);
g2 = clamp(g2, 0.0, 2.0);
b2 = clamp(b2, 0.0, 2.0);
if (start > end)
{
swapvalues(start, end);
swapvalues(r1, r2);
swapvalues(g1, g2);
swapvalues(b1, b2);
}
r2 -= r1;
g2 -= g1;
@ -419,7 +427,7 @@ void FRemapTable::AddDesaturation(int start, int end, float r1,float g1, float b
g1 *= 255;
b1 *= 255;
for(int c = start; c < end; c++)
for(int c = start; c <= end; c++)
{
double intensity = (GPalette.BaseColors[c].r * 77 +
GPalette.BaseColors[c].g * 143 +
@ -443,7 +451,7 @@ void FRemapTable::AddDesaturation(int start, int end, float r1,float g1, float b
//
//----------------------------------------------------------------------------
void FRemapTable::AddToTranslation(const char * range)
void FRemapTable::AddToTranslation(const char *range)
{
int start,end;
bool desaturated = false;
@ -515,39 +523,39 @@ void FRemapTable::AddToTranslation(const char * range)
else if (sc.TokenType == '%')
{
// translation using RGB values
float r1,g1,b1,r2,g2,b2;
double r1,g1,b1,r2,g2,b2;
sc.MustGetToken('[');
sc.MustGetAnyToken();
if (sc.TokenType != TK_IntConst) sc.TokenMustBe(TK_FloatConst);
r1 = float(sc.Float);
r1 = sc.Float;
sc.MustGetToken(',');
sc.MustGetAnyToken();
if (sc.TokenType != TK_IntConst) sc.TokenMustBe(TK_FloatConst);
g1 = float(sc.Float);
g1 = sc.Float;
sc.MustGetToken(',');
sc.MustGetAnyToken();
if (sc.TokenType != TK_IntConst) sc.TokenMustBe(TK_FloatConst);
b1 = float(sc.Float);
b1 = sc.Float;
sc.MustGetToken(']');
sc.MustGetToken(':');
sc.MustGetToken('[');
sc.MustGetAnyToken();
if (sc.TokenType != TK_IntConst) sc.TokenMustBe(TK_FloatConst);
r2 = float(sc.Float);
r2 = sc.Float;
sc.MustGetToken(',');
sc.MustGetAnyToken();
if (sc.TokenType != TK_IntConst) sc.TokenMustBe(TK_FloatConst);
g2 = float(sc.Float);
g2 = sc.Float;
sc.MustGetToken(',');
sc.MustGetAnyToken();
if (sc.TokenType != TK_IntConst) sc.TokenMustBe(TK_FloatConst);
b2 = float(sc.Float);
b2 = sc.Float;
sc.MustGetToken(']');
AddDesaturation(start, end, r1, g1, b1, r2, g2, b2);

View file

@ -38,7 +38,7 @@ struct FRemapTable
void Serialize(FArchive &ar);
void AddIndexRange(int start, int end, int pal1, int pal2);
void AddColorRange(int start, int end, int r1,int g1, int b1, int r2, int g2, int b2);
void AddDesaturation(int start, int end, float r1,float g1, float b1, float r2, float g2, float b2);
void AddDesaturation(int start, int end, double r1, double g1, double b1, double r2, double g2, double b2);
void AddToTranslation(const char * range);
int StoreTranslation();

View file

@ -423,6 +423,10 @@ static void R_ExtendSpriteFrames(spritedef_t &spr, int frame)
// at all, so we can tack the new frames directly on to the end
// of the SpriteFrames array.
newstart = SpriteFrames.Reserve(frame - spr.numframes);
if (spr.numframes == 0)
{
spr.spriteframes = WORD(newstart);
}
}
else
{ // We need to allocate space for all the sprite's frames and copy
@ -439,7 +443,6 @@ static void R_ExtendSpriteFrames(spritedef_t &spr, int frame)
// Initialize all new frames to 0.
memset(&SpriteFrames[newstart], 0, sizeof(spriteframe_t)*(frame - spr.numframes));
spr.numframes = frame;
spr.spriteframes = newstart;
}
//==========================================================================

View file

@ -71,7 +71,7 @@ TDeletingArray<FVoxelDef *> VoxelDefs;
struct VoxelOptions
{
VoxelOptions()
: DroppedSpin(0), PlacedSpin(0), Scale(FRACUNIT), AngleOffset(0)
: DroppedSpin(0), PlacedSpin(0), Scale(FRACUNIT), AngleOffset(ANGLE_90)
{}
int DroppedSpin;
@ -332,7 +332,7 @@ FVoxelDef *R_LoadVoxelDef(int lumpnum, int spin)
voxdef->Voxel = vox;
voxdef->Scale = FRACUNIT;
voxdef->DroppedSpin = voxdef->PlacedSpin = spin;
voxdef->AngleOffset = 0;
voxdef->AngleOffset = ANGLE_90;
Voxels.Push(vox);
VoxelDefs.Push(voxdef);
@ -508,7 +508,7 @@ static void VOX_ReadOptions(FScanner &sc, VoxelOptions &opts)
{
sc.TokenMustBe(TK_FloatConst);
}
opts.AngleOffset = angle_t(sc.Float * ANGLE_180 / 180.0);
opts.AngleOffset = ANGLE_90 + angle_t(sc.Float * ANGLE_180 / 180.0);
}
else
{

View file

@ -38,8 +38,8 @@
#include "dthinker.h"
#define MAXWIDTH 2880
#define MAXHEIGHT 1800
#define MAXWIDTH 5760
#define MAXHEIGHT 3600
const WORD NO_INDEX = 0xffffu;
const DWORD NO_SIDE = 0xffffffffu;
@ -832,11 +832,11 @@ struct side_t
void SetTextureXScale(int which, fixed_t scale)
{
textures[which].xscale = scale <= 0? FRACUNIT : scale;
textures[which].xscale = scale == 0 ? FRACUNIT : scale;
}
void SetTextureXScale(fixed_t scale)
{
textures[top].xscale = textures[mid].xscale = textures[bottom].xscale = scale <= 0? FRACUNIT : scale;
textures[top].xscale = textures[mid].xscale = textures[bottom].xscale = scale == 0 ? FRACUNIT : scale;
}
fixed_t GetTextureXScale(int which) const
{
@ -850,11 +850,11 @@ struct side_t
void SetTextureYScale(int which, fixed_t scale)
{
textures[which].yscale = scale <= 0? FRACUNIT : scale;
textures[which].yscale = scale == 0 ? FRACUNIT : scale;
}
void SetTextureYScale(fixed_t scale)
{
textures[top].yscale = textures[mid].yscale = textures[bottom].yscale = scale <= 0? FRACUNIT : scale;
textures[top].yscale = textures[mid].yscale = textures[bottom].yscale = scale == 0 ? FRACUNIT : scale;
}
fixed_t GetTextureYScale(int which) const
{

View file

@ -79,6 +79,8 @@ void (*R_DrawSpan)(void);
void (*R_DrawSpanMasked)(void);
void (*R_DrawSpanTranslucent)(void);
void (*R_DrawSpanMaskedTranslucent)(void);
void (*R_DrawSpanAddClamp)(void);
void (*R_DrawSpanMaskedAddClamp)(void);
void (STACK_ARGS *rt_map4cols)(int,int,int);
//
@ -1324,6 +1326,152 @@ void R_DrawSpanMaskedTranslucentP_C (void)
}
}
void R_DrawSpanAddClampP_C (void)
{
dsfixed_t xfrac;
dsfixed_t yfrac;
dsfixed_t xstep;
dsfixed_t ystep;
BYTE* dest;
const BYTE* source = ds_source;
const BYTE* colormap = ds_colormap;
int count;
int spot;
DWORD *fg2rgb = dc_srcblend;
DWORD *bg2rgb = dc_destblend;
xfrac = ds_xfrac;
yfrac = ds_yfrac;
dest = ylookup[ds_y] + ds_x1 + dc_destorg;
count = ds_x2 - ds_x1 + 1;
xstep = ds_xstep;
ystep = ds_ystep;
if (ds_xbits == 6 && ds_ybits == 6)
{
// 64x64 is the most common case by far, so special case it.
do
{
spot = ((xfrac>>(32-6-6))&(63*64)) + (yfrac>>(32-6));
DWORD a = fg2rgb[colormap[source[spot]]] + bg2rgb[*dest];
DWORD b = a;
a |= 0x01f07c1f;
b &= 0x40100400;
a &= 0x3fffffff;
b = b - (b >> 5);
a |= b;
*dest++ = RGB32k[0][0][a & (a>>15)];
xfrac += xstep;
yfrac += ystep;
} while (--count);
}
else
{
BYTE yshift = 32 - ds_ybits;
BYTE xshift = yshift - ds_xbits;
int xmask = ((1 << ds_xbits) - 1) << ds_ybits;
do
{
spot = ((xfrac >> xshift) & xmask) + (yfrac >> yshift);
DWORD a = fg2rgb[colormap[source[spot]]] + bg2rgb[*dest];
DWORD b = a;
a |= 0x01f07c1f;
b &= 0x40100400;
a &= 0x3fffffff;
b = b - (b >> 5);
a |= b;
*dest++ = RGB32k[0][0][a & (a>>15)];
xfrac += xstep;
yfrac += ystep;
} while (--count);
}
}
void R_DrawSpanMaskedAddClampP_C (void)
{
dsfixed_t xfrac;
dsfixed_t yfrac;
dsfixed_t xstep;
dsfixed_t ystep;
BYTE* dest;
const BYTE* source = ds_source;
const BYTE* colormap = ds_colormap;
int count;
int spot;
DWORD *fg2rgb = dc_srcblend;
DWORD *bg2rgb = dc_destblend;
xfrac = ds_xfrac;
yfrac = ds_yfrac;
dest = ylookup[ds_y] + ds_x1 + dc_destorg;
count = ds_x2 - ds_x1 + 1;
xstep = ds_xstep;
ystep = ds_ystep;
if (ds_xbits == 6 && ds_ybits == 6)
{
// 64x64 is the most common case by far, so special case it.
do
{
BYTE texdata;
spot = ((xfrac>>(32-6-6))&(63*64)) + (yfrac>>(32-6));
texdata = source[spot];
if (texdata != 0)
{
DWORD a = fg2rgb[colormap[texdata]] + bg2rgb[*dest];
DWORD b = a;
a |= 0x01f07c1f;
b &= 0x40100400;
a &= 0x3fffffff;
b = b - (b >> 5);
a |= b;
*dest = RGB32k[0][0][a & (a>>15)];
}
dest++;
xfrac += xstep;
yfrac += ystep;
} while (--count);
}
else
{
BYTE yshift = 32 - ds_ybits;
BYTE xshift = yshift - ds_xbits;
int xmask = ((1 << ds_xbits) - 1) << ds_ybits;
do
{
BYTE texdata;
spot = ((xfrac >> xshift) & xmask) + (yfrac >> yshift);
texdata = source[spot];
if (texdata != 0)
{
DWORD a = fg2rgb[colormap[texdata]] + bg2rgb[*dest];
DWORD b = a;
a |= 0x01f07c1f;
b &= 0x40100400;
a &= 0x3fffffff;
b = b - (b >> 5);
a |= b;
*dest = RGB32k[0][0][a & (a>>15)];
}
dest++;
xfrac += xstep;
yfrac += ystep;
} while (--count);
}
}
// [RH] Just fill a span with a color
void R_FillSpan (void)
{
@ -2005,6 +2153,14 @@ void tmvline4_revsubclamp ()
const BYTE *R_GetColumn (FTexture *tex, int col)
{
int width;
// If the texture's width isn't a power of 2, then we need to make it a
// positive offset for proper clamping.
if (col < 0 && (width = tex->GetWidth()) != (1 << tex->WidthBits))
{
col = width + (col % width);
}
return tex->GetColumn (col, NULL);
}
@ -2040,6 +2196,8 @@ void R_InitColumnDrawers ()
#endif
R_DrawSpanTranslucent = R_DrawSpanTranslucentP_C;
R_DrawSpanMaskedTranslucent = R_DrawSpanMaskedTranslucentP_C;
R_DrawSpanAddClamp = R_DrawSpanAddClampP_C;
R_DrawSpanMaskedAddClamp = R_DrawSpanMaskedAddClampP_C;
}
// [RH] Choose column drawers in a single place

View file

@ -106,6 +106,12 @@ extern void (*R_DrawSpanTranslucent)(void);
// Span drawing for masked, translucent textures.
extern void (*R_DrawSpanMaskedTranslucent)(void);
// Span drawing for translucent, additive textures.
extern void (*R_DrawSpanAddClamp)(void);
// Span drawing for masked, translucent, additive textures.
extern void (*R_DrawSpanMaskedAddClamp)(void);
// [RH] Span blit into an interleaved intermediate buffer
extern void (*R_DrawColumnHoriz)(void);
void R_DrawMaskedColumnHoriz (const BYTE *column, const FTexture::Span *spans);

View file

@ -596,7 +596,6 @@ visplane_t *R_FindPlane (const secplane_t &height, FTextureID picnum, int lightl
else sky = 0; // not skyflatnum so it can't be a sky
skybox = NULL;
alpha = FRACUNIT;
additive = false;
}
// New visplane algorithm uses hash table -- killough
@ -1047,7 +1046,7 @@ void R_DrawHeightPlanes(fixed_t height)
viewy = pl->viewy;
viewangle = pl->viewangle;
MirrorFlags = pl->MirrorFlags;
R_DrawSinglePlane (pl, pl->sky & 0x7FFFFFFF, false, true);
R_DrawSinglePlane (pl, pl->sky & 0x7FFFFFFF, pl->Additive, true);
}
}
}
@ -1528,16 +1527,24 @@ void R_DrawNormalPlane (visplane_t *pl, fixed_t alpha, bool additive, bool maske
else
plane_shade = true;
// Additive not supported yet because the drawer function doesn't look like it can handle it.
if (spanfunc != R_FillSpan)
{
if (masked)
{
if (alpha < OPAQUE)
if (alpha < OPAQUE || additive)
{
spanfunc = R_DrawSpanMaskedTranslucent;
dc_srcblend = Col2RGB8[alpha>>10];
dc_destblend = Col2RGB8[(OPAQUE-alpha)>>10];
if (!additive)
{
spanfunc = R_DrawSpanMaskedTranslucent;
dc_srcblend = Col2RGB8[alpha>>10];
dc_destblend = Col2RGB8[(OPAQUE-alpha)>>10];
}
else
{
spanfunc = R_DrawSpanMaskedAddClamp;
dc_srcblend = Col2RGB8_LessPrecision[alpha>>10];
dc_destblend = Col2RGB8_LessPrecision[FRACUNIT>>10];
}
}
else
{
@ -1546,11 +1553,20 @@ void R_DrawNormalPlane (visplane_t *pl, fixed_t alpha, bool additive, bool maske
}
else
{
if (alpha < OPAQUE)
if (alpha < OPAQUE || additive)
{
spanfunc = R_DrawSpanTranslucent;
dc_srcblend = Col2RGB8[alpha>>10];
dc_destblend = Col2RGB8[(OPAQUE-alpha)>>10];
if (!additive)
{
spanfunc = R_DrawSpanTranslucent;
dc_srcblend = Col2RGB8[alpha>>10];
dc_destblend = Col2RGB8[(OPAQUE-alpha)>>10];
}
else
{
spanfunc = R_DrawSpanAddClamp;
dc_srcblend = Col2RGB8_LessPrecision[alpha>>10];
dc_destblend = Col2RGB8_LessPrecision[FRACUNIT>>10];
}
}
else
{

View file

@ -1965,7 +1965,7 @@ void R_NewWall (bool needlights)
}
if (midtexture->bWorldPanning)
{
rw_midtexturemid = MulScale16(rowoffset, yrepeat);
rw_midtexturemid += MulScale16(rowoffset, yrepeat);
}
else
{
@ -2769,6 +2769,7 @@ int WallMost (short *mostbuf, const secplane_t &plane)
static void PrepWallRoundFix(fixed_t *lwall, fixed_t walxrepeat)
{
// fix for rounding errors
walxrepeat = abs(walxrepeat);
fixed_t fix = (MirrorFlags & RF_XFLIP) ? walxrepeat-1 : 0;
int x;
@ -2803,7 +2804,7 @@ static void PrepWallRoundFix(fixed_t *lwall, fixed_t walxrepeat)
void PrepWall (fixed_t *swall, fixed_t *lwall, fixed_t walxrepeat)
{ // swall = scale, lwall = texturecolumn
double top, bot, i;
double xrepeat = walxrepeat;
double xrepeat = fabs((double)walxrepeat);
i = WallSX1 - centerx;
top = WallUoverZorg + WallUoverZstep * i;
@ -2812,7 +2813,14 @@ void PrepWall (fixed_t *swall, fixed_t *lwall, fixed_t walxrepeat)
for (int x = WallSX1; x < WallSX2; x++)
{
double frac = top / bot;
lwall[x] = xs_RoundToInt(frac * xrepeat);
if (walxrepeat < 0)
{
lwall[x] = xs_RoundToInt(xrepeat - frac * xrepeat);
}
else
{
lwall[x] = xs_RoundToInt(frac * xrepeat);
}
swall[x] = xs_RoundToInt(frac * WallDepthScale + WallDepthOrg);
top += WallUoverZstep;
bot += WallInvZstep;
@ -2823,7 +2831,7 @@ void PrepWall (fixed_t *swall, fixed_t *lwall, fixed_t walxrepeat)
void PrepLWall (fixed_t *lwall, fixed_t walxrepeat)
{ // lwall = texturecolumn
double top, bot, i;
double xrepeat = walxrepeat;
double xrepeat = fabs((double)walxrepeat);
double topstep;
i = WallSX1 - centerx;
@ -2835,7 +2843,14 @@ void PrepLWall (fixed_t *lwall, fixed_t walxrepeat)
for (int x = WallSX1; x < WallSX2; x++)
{
lwall[x] = xs_RoundToInt(top / bot);
if (walxrepeat < 0)
{
lwall[x] = xs_RoundToInt(xrepeat - top / bot);
}
else
{
lwall[x] = xs_RoundToInt(top / bot);
}
top += topstep;
bot += WallInvZstep;
}

View file

@ -514,13 +514,7 @@ void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor
// [RH] Interpolate the sprite's position to make it look smooth
fx = thing->PrevX + FixedMul (r_TicFrac, thing->x - thing->PrevX);
fy = thing->PrevY + FixedMul (r_TicFrac, thing->y - thing->PrevY);
fz = thing->PrevZ + FixedMul (r_TicFrac, thing->z - thing->PrevZ);
// [RH] Make floatbobbing a renderer-only effect.
if (thing->flags2 & MF2_FLOATBOB)
{
fz += finesine[(Scale(thing->FloatBobPhase + level.maptime, FINEANGLES, 64) + r_TicFrac * ((FINEANGLES/64) / 1000)) & FINEMASK] * 8;
}
fz = thing->PrevZ + FixedMul (r_TicFrac, thing->z - thing->PrevZ) + thing->GetBobOffset(r_TicFrac);
// transform the origin point
tr_x = fx - viewx;

View file

@ -100,6 +100,7 @@ public:
void AddSound (int player_sound_id, int sfx_id);
int LookupSound (int player_sound_id);
FPlayerSoundHashTable &operator= (const FPlayerSoundHashTable &other);
void MarkUsed();
protected:
struct Entry
@ -122,7 +123,7 @@ struct FAmbientSound
int periodmax; // max # of tics for random ambients
float volume; // relative volume of sound
float attenuation;
FString sound; // Logical name of sound to play
FSoundID sound; // Sound to play
};
TMap<int, FAmbientSound> Ambients;
@ -219,6 +220,7 @@ extern int sfx_empty;
// PUBLIC DATA DEFINITIONS -------------------------------------------------
TArray<sfxinfo_t> S_sfx (128);
TMap<int, FString> HexenMusic;
// PRIVATE DATA DEFINITIONS ------------------------------------------------
@ -830,6 +832,25 @@ int FPlayerSoundHashTable::LookupSound (int player_sound_id)
return entry != NULL ? entry->SfxID : 0;
}
//==========================================================================
//
// FPlayerSoundHashTable :: Mark
//
// Marks all sounds defined for this class/gender as used.
//
//==========================================================================
void FPlayerSoundHashTable::MarkUsed()
{
for (size_t i = 0; i < NUM_BUCKETS; ++i)
{
for (Entry *probe = Buckets[i]; probe != NULL; probe = probe->Next)
{
S_sfx[probe->SfxID].bUsed = true;
}
}
}
//==========================================================================
//
// S_ClearSoundData
@ -866,6 +887,7 @@ static void S_ClearSoundData()
DefPlayerClassName = "";
MusicAliases.Clear();
MidiDevices.Clear();
HexenMusic.Clear();
}
//==========================================================================
@ -984,10 +1006,10 @@ static void S_AddSNDINFO (int lump)
ambient->periodmax = 0;
ambient->volume = 0;
ambient->attenuation = 0;
ambient->sound = "";
ambient->sound = 0;
sc.MustGetString ();
ambient->sound = sc.String;
ambient->sound = FSoundID(S_FindSoundTentative(sc.String));
ambient->attenuation = 0;
sc.MustGetString ();
@ -1064,16 +1086,14 @@ static void S_AddSNDINFO (int lump)
case SI_Map: {
// Hexen-style $MAP command
level_info_t *info;
char temp[16];
int mapnum;
sc.MustGetNumber ();
mysnprintf (temp, countof(temp), "MAP%02d", sc.Number);
info = FindLevelInfo (temp);
sc.MustGetString ();
if (info->mapname[0] && (!(info->flags2 & LEVEL2_MUSICDEFINED)))
sc.MustGetNumber();
mapnum = sc.Number;
sc.MustGetString();
if (mapnum != 0)
{
info->Music = sc.String;
HexenMusic[mapnum] = sc.String;
}
}
break;
@ -1899,6 +1919,44 @@ bool S_ParseTimeTag(const char *tag, bool *as_samples, unsigned int *time)
return true;
}
//==========================================================================
//
// sfxinfo_t :: MarkUsed
//
// Marks this sound for precaching.
//
//==========================================================================
void sfxinfo_t::MarkUsed()
{
bUsed = true;
}
//==========================================================================
//
// S_MarkPlayerSounds
//
// Marks all sounds from a particular player class for precaching.
//
//==========================================================================
void S_MarkPlayerSounds (const char *playerclass)
{
int classidx = S_FindPlayerClass(playerclass);
if (classidx < 0)
{
classidx = DefPlayerClass;
}
for (int g = 0; g < 3; ++g)
{
int listidx = PlayerClassLookups[classidx].ListIndex[0];
if (listidx != 0xffff)
{
PlayerSounds[listidx].MarkUsed();
}
}
}
//==========================================================================
//
// CCMD soundlist
@ -2014,6 +2072,7 @@ class AAmbientSound : public AActor
public:
void Serialize (FArchive &arc);
void MarkPrecacheSounds () const;
void BeginPlay ();
void Tick ();
void Activate (AActor *activator);
@ -2040,6 +2099,22 @@ void AAmbientSound::Serialize (FArchive &arc)
arc << bActive << NextCheck;
}
//==========================================================================
//
// AmbientSound :: MarkPrecacheSounds
//
//==========================================================================
void AAmbientSound::MarkPrecacheSounds() const
{
Super::MarkPrecacheSounds();
FAmbientSound *ambient = Ambients.CheckKey(args[0]);
if (ambient != NULL)
{
ambient->sound.MarkUsed();
}
}
//==========================================================================
//
// AmbientSound :: Tick
@ -2067,7 +2142,7 @@ void AAmbientSound::Tick ()
loop = CHAN_LOOP;
}
if (ambient->sound.IsNotEmpty())
if (ambient->sound != 0)
{
// The second argument scales the ambient sound's volume.
// 0 and 100 are normal volume. The maximum volume level

View file

@ -760,7 +760,7 @@ static void AddSequence (int curseq, FName seqname, FName slot, int stopsound, c
Sequences[curseq] = (FSoundSequence *)M_Malloc (sizeof(FSoundSequence) + sizeof(DWORD)*ScriptTemp.Size());
Sequences[curseq]->SeqName = seqname;
Sequences[curseq]->Slot = slot;
Sequences[curseq]->StopSound = stopsound;
Sequences[curseq]->StopSound = FSoundID(stopsound);
memcpy (Sequences[curseq]->Script, &ScriptTemp[0], sizeof(DWORD)*ScriptTemp.Size());
Sequences[curseq]->Script[ScriptTemp.Size()] = MakeCommand(SS_CMD_END, 0);
}
@ -1311,6 +1311,32 @@ FName SN_GetSequenceSlot (int sequence, seqtype_t type)
return NAME_None;
}
//==========================================================================
//
// SN_MarkPrecacheSounds
//
// Marks all sounds played by this sequence for precaching.
//
//==========================================================================
void SN_MarkPrecacheSounds(int sequence, seqtype_t type)
{
if (TwiddleSeqNum(sequence, type))
{
FSoundSequence *seq = Sequences[sequence];
seq->StopSound.MarkUsed();
for (int i = 0; GetCommand(seq->Script[i]) != SS_CMD_END; ++i)
{
int cmd = GetCommand(seq->Script[i]);
if (cmd == SS_CMD_PLAY || cmd == SS_CMD_PLAYREPEAT || cmd == SS_CMD_PLAYLOOP)
{
FSoundID(GetData(seq->Script[i])).MarkUsed();
}
}
}
}
//==========================================================================
//
// SN_ChangeNodeData

View file

@ -71,10 +71,10 @@ void SN_StopAllSequences (void);
struct FSoundSequence
{
FName SeqName;
FName Slot;
int StopSound;
SDWORD Script[1]; // + more until end of sequence script
FName SeqName;
FName Slot;
FSoundID StopSound;
SDWORD Script[1]; // + more until end of sequence script
};
void S_ParseSndSeq (int levellump);
@ -98,6 +98,7 @@ void SN_DoStop (void *);
void SN_ChangeNodeData (int nodeNum, int seqOffset, int delayTics,
float volume, int currentSoundID);
FName SN_GetSequenceSlot (int sequence, seqtype_t type);
void SN_MarkPrecacheSounds (int sequence, seqtype_t type);
bool SN_IsMakingLoopingSound (sector_t *sector);
#endif //__S_SNDSEQ_H__

View file

@ -326,7 +326,6 @@ void S_InitData ()
LastLocalSndInfo = LastLocalSndSeq = "";
S_ParseSndInfo (false);
S_ParseSndSeq (-1);
S_ParseMusInfo();
}
//==========================================================================
@ -477,14 +476,15 @@ void S_PrecacheLevel ()
AActor *actor;
TThinkerIterator<AActor> iterator;
while ( (actor = iterator.Next ()) != NULL )
// Precache all sounds known to be used by the currently spawned actors.
while ( (actor = iterator.Next()) != NULL )
{
S_sfx[actor->SeeSound].bUsed = true;
S_sfx[actor->AttackSound].bUsed = true;
S_sfx[actor->PainSound].bUsed = true;
S_sfx[actor->DeathSound].bUsed = true;
S_sfx[actor->ActiveSound].bUsed = true;
S_sfx[actor->UseSound].bUsed = true;
actor->MarkPrecacheSounds();
}
// Precache all extra sounds requested by this map.
for (i = 0; i < level.info->PrecacheSounds.Size(); ++i)
{
level.info->PrecacheSounds[i].MarkUsed();
}
for (i = 1; i < S_sfx.Size(); ++i)
@ -1764,7 +1764,7 @@ void S_SetSoundPaused (int state)
S_ResumeSound(true);
if (GSnd != NULL)
{
GSnd->SetInactive(false);
GSnd->SetInactive(SoundRenderer::INACTIVE_Active);
}
if (!netgame
#ifdef _DEBUG
@ -1783,7 +1783,9 @@ void S_SetSoundPaused (int state)
S_PauseSound(false, true);
if (GSnd != NULL)
{
GSnd->SetInactive(true);
GSnd->SetInactive(gamestate == GS_LEVEL || gamestate == GS_TITLELEVEL ?
SoundRenderer::INACTIVE_Complete :
SoundRenderer::INACTIVE_Mute);
}
if (!netgame
#ifdef _DEBUG

View file

@ -65,6 +65,8 @@ struct sfxinfo_t
FRolloffInfo Rolloff;
float Attenuation; // Multiplies the attenuation passed to S_Sound.
void MarkUsed(); // Marks this sound as used.
};
// Rolloff types
@ -132,6 +134,10 @@ public:
{
return ID ? S_sfx[ID].name.GetChars() : NULL;
}
void MarkUsed() const
{
S_sfx[ID].MarkUsed();
}
private:
int ID;
protected:
@ -351,6 +357,7 @@ int S_AddSoundLump (const char *logicalname, int lump); // Add sound by lump ind
int S_AddPlayerSound (const char *playerclass, const int gender, int refid, const char *lumpname);
int S_AddPlayerSound (const char *playerclass, const int gender, int refid, int lumpnum, bool fromskin=false);
int S_AddPlayerSoundExisting (const char *playerclass, const int gender, int refid, int aliasto, bool fromskin=false);
void S_MarkPlayerSounds (const char *playerclass);
void S_ShrinkPlayerSoundLists ();
void S_UnloadSound (sfxinfo_t *sfx);
sfxinfo_t *S_LoadSound(sfxinfo_t *sfx);

View file

@ -177,6 +177,10 @@ void I_ClosestResolution (int *width, int *height, int bits)
}
}
void I_SetFPSLimit(int limit)
{
}
extern int NewWidth, NewHeight, NewBits, DisplayBits;
CUSTOM_CVAR (Bool, fullscreen, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)

View file

@ -59,6 +59,8 @@ void I_InitGraphics ();
void I_ShutdownGraphics ();
void I_CreateRenderer();
void I_SetFPSLimit(int limit);
extern IVideo *Video;
#endif // __HARDWARE_H__

View file

@ -672,6 +672,7 @@ bool FMODSoundRenderer::Init()
PrevEnvironment = DefaultEnvironments[0];
DSPClock.AsOne = 0;
ChannelGroupTargetUnit = NULL;
ChannelGroupTargetUnitOutput = NULL;
SfxReverbHooked = false;
SfxReverbPlaceholder = NULL;
OutputPlugin = 0;
@ -1155,6 +1156,15 @@ bool FMODSoundRenderer::Init()
{
ChannelGroupTargetUnit = NULL;
}
else
{
FMOD::DSP *dontcare;
result = ChannelGroupTargetUnit->getOutput(0, &dontcare, &ChannelGroupTargetUnitOutput);
if (result != FMOD_OK)
{
ChannelGroupTargetUnitOutput = NULL;
}
}
}
}
@ -1598,6 +1608,7 @@ SoundStream *FMODSoundRenderer::OpenStream(const char *filename_or_data, int fla
FMOD::Sound *stream;
FMOD_RESULT result;
bool url;
FString patches;
InitCreateSoundExInfo(&exinfo);
mode = FMOD_SOFTWARE | FMOD_2D | FMOD_CREATESTREAM;
@ -1614,7 +1625,20 @@ SoundStream *FMODSoundRenderer::OpenStream(const char *filename_or_data, int fla
exinfo.fileoffset = offset;
if ((*snd_midipatchset)[0] != '\0')
{
exinfo.dlsname = snd_midipatchset;
#ifdef _WIN32
// If the path does not contain any path separators, automatically
// prepend $PROGDIR to the path.
if (strcspn(snd_midipatchset, ":/\\") == strlen(snd_midipatchset))
{
patches << "$PROGDIR/" << snd_midipatchset;
patches = NicePath(patches);
}
else
#endif
{
patches = NicePath(snd_midipatchset);
}
exinfo.dlsname = patches;
}
url = (offset == 0 && length == 0 && strstr(filename_or_data, "://") > filename_or_data);
@ -2109,11 +2133,33 @@ void FMODSoundRenderer::SetSfxPaused(bool paused, int slot)
//
//==========================================================================
void FMODSoundRenderer::SetInactive(bool inactive)
void FMODSoundRenderer::SetInactive(SoundRenderer::EInactiveState inactive)
{
float mix;
bool active;
if (inactive == INACTIVE_Active)
{
mix = 1;
active = true;
}
else if (inactive == INACTIVE_Complete)
{
mix = 1;
active = false;
}
else // inactive == INACTIVE_Mute
{
mix = 0;
active = true;
}
if (ChannelGroupTargetUnitOutput != NULL)
{
ChannelGroupTargetUnitOutput->setMix(mix);
}
if (ChannelGroupTargetUnit != NULL)
{
ChannelGroupTargetUnit->setActive(!inactive);
ChannelGroupTargetUnit->setActive(active);
}
}

View file

@ -49,7 +49,7 @@ public:
void SetSfxPaused (bool paused, int slot);
// Pauses or resumes *every* channel, including environmental reverb.
void SetInactive (bool inactive);
void SetInactive (EInactiveState inactive);
// Updates the position of a sound channel.
void UpdateSoundParams3D (SoundListener *listener, FISoundChannel *chan, bool areasound, const FVector3 &pos, const FVector3 &vel);
@ -107,6 +107,7 @@ private:
FMOD::ChannelGroup *MusicGroup;
FMOD::DSP *WaterLP, *WaterReverb;
FMOD::DSPConnection *SfxConnection;
FMOD::DSPConnection *ChannelGroupTargetUnitOutput;
FMOD::DSP *ChannelGroupTargetUnit;
FMOD::DSP *SfxReverbPlaceholder;
bool SfxReverbHooked;

View file

@ -199,7 +199,7 @@ public:
}
// Pauses or resumes *every* channel, including environmental reverb.
void SetInactive(bool inactive)
void SetInactive(SoundRenderer::EInactiveState inactive)
{
}

View file

@ -126,7 +126,13 @@ public:
virtual void SetSfxPaused (bool paused, int slot) = 0;
// Pauses or resumes *every* channel, including environmental reverb.
virtual void SetInactive(bool inactive) = 0;
enum EInactiveState
{
INACTIVE_Active, // sound is active
INACTIVE_Complete, // sound is completely paused
INACTIVE_Mute // sound is only muted
};
virtual void SetInactive(EInactiveState inactive) = 0;
// Updates the volume, separation, and pitch of a sound channel.
virtual void UpdateSoundParams3D (SoundListener *listener, FISoundChannel *chan, bool areasound, const FVector3 &pos, const FVector3 &vel) = 0;

View file

@ -42,6 +42,7 @@
#include "m_swap.h"
#include "w_wad.h"
#include "v_text.h"
#include "cmdlib.h"
// MACROS ------------------------------------------------------------------
@ -471,7 +472,21 @@ int FluidSynthMIDIDevice::LoadPatchSets(const char *patches)
count = 0;
while (tok != NULL)
{
if (FLUID_FAILED != fluid_synth_sfload(FluidSynth, tok, count == 0))
FString path;
#ifdef _WIN32
// If the path does not contain any path separators, automatically
// prepend $PROGDIR to the path.
if (strcspn(tok, ":/\\") == strlen(tok))
{
path << "$PROGDIR/" << tok;
path = NicePath(path);
}
else
#endif
{
path = NicePath(tok);
}
if (FLUID_FAILED != fluid_synth_sfload(FluidSynth, path, count == 0))
{
DPrintf("Loaded patch set %s.\n", tok);
count++;

View file

@ -944,7 +944,13 @@ int MIDIStreamer::FillBuffer(int buffer_num, int max_events, DWORD max_time)
if (Restarting)
{
Restarting = false;
events = WriteStopNotes(events); // Stop all notes in case any were left hanging.
// Reset the tempo to the inital value.
events[0] = 0; // dwDeltaTime
events[1] = 0; // dwStreamID
events[2] = (MEVT_TEMPO << 24) | InitialTempo; // dwEvent
events += 3;
// Stop all notes in case any were left hanging.
events = WriteStopNotes(events);
DoRestart();
}
events = MakeEvents(events, max_event_p, max_time);
@ -1130,7 +1136,7 @@ void MIDIStreamer::Precache()
void MIDIStreamer::CreateSMF(TArray<BYTE> &file, int looplimit)
{
DWORD delay = 0;
BYTE running_status = 0;
BYTE running_status = 255;
// Always create songs aimed at GM devices.
CheckCaps(MOD_MIDIPORT);
@ -1163,6 +1169,7 @@ void MIDIStreamer::CreateSMF(TArray<BYTE> &file, int looplimit)
file.Push(BYTE(tempo >> 16));
file.Push(BYTE(tempo >> 8));
file.Push(BYTE(tempo));
running_status = 255;
}
else if (MEVT_EVENTTYPE(event[2]) == MEVT_LONGMSG)
{
@ -1176,6 +1183,7 @@ void MIDIStreamer::CreateSMF(TArray<BYTE> &file, int looplimit)
file.Push(MIDI_SYSEX);
WriteVarLen(file, len);
memcpy(&file[file.Reserve(len - 1)], bytes, len);
running_status = 255;
}
}
else if (MEVT_EVENTTYPE(event[2]) == 0)

View file

@ -608,10 +608,11 @@ int FMultiPatchTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rota
}
else
{
info.blendcolor[3] = b.a * FRACUNIT / 255;
info.blendcolor[0] = b.r * (FRACUNIT-info.blendcolor[3]);
info.blendcolor[1] = b.g * (FRACUNIT-info.blendcolor[3]);
info.blendcolor[2] = b.b * (FRACUNIT-info.blendcolor[3]);
fixed_t blendalpha = b.a * FRACUNIT / 255;
info.blendcolor[0] = b.r * blendalpha;
info.blendcolor[1] = b.g * blendalpha;
info.blendcolor[2] = b.b * blendalpha;
info.blendcolor[3] = FRACUNIT - blendalpha;
info.blend = BLEND_OVERLAY;
}
}

View file

@ -197,6 +197,7 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def)
if (type->NumOwnedStates == 1)
{
type->OwnedStates->Tics = -1;
type->OwnedStates->TicRange = 0;
type->OwnedStates->Misc1 = 0;
}
else
@ -224,6 +225,7 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def)
else
{
type->OwnedStates[i].Tics = -1;
type->OwnedStates[i].TicRange = 0;
type->OwnedStates[i].Misc1 = 0;
}
@ -274,6 +276,7 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def)
else
{
type->OwnedStates[i].Tics = -1;
type->OwnedStates[i].TicRange = 0;
type->OwnedStates[i].Misc1 = 0;
}
@ -308,12 +311,14 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def)
}
type->OwnedStates[i].NextState = &type->OwnedStates[type->NumOwnedStates-1];
type->OwnedStates[i].Tics = 5;
type->OwnedStates[i].TicRange = 0;
type->OwnedStates[i].Misc1 = 0;
type->OwnedStates[i].SetAction(FindGlobalActionFunction("A_FreezeDeath")->Function);
i = type->NumOwnedStates - 1;
type->OwnedStates[i].NextState = &type->OwnedStates[i];
type->OwnedStates[i].Tics = 1;
type->OwnedStates[i].TicRange = 0;
type->OwnedStates[i].Misc1 = 0;
type->OwnedStates[i].SetAction(FindGlobalActionFunction("A_FreezeDeathChunks")->Function);
bag.statedef.SetStateLabel("Ice", &type->OwnedStates[extra.IceDeathStart]);
@ -672,6 +677,7 @@ static void ParseSpriteFrames (PClassActor *info, TArray<FState> &states, FScann
}
state.Tics = rate;
state.TicRange = 0;
while (*token)
{

View file

@ -170,7 +170,7 @@ PClassActor *CreateNewActor(const FScriptPosition &sc, FName typeName, FName par
//
//==========================================================================
void SetReplacement(PClassActor *info, FName replaceName)
void SetReplacement(FScanner &sc, PClassActor *info, FName replaceName)
{
// Check for "replaces"
if (replaceName != NAME_None)
@ -180,7 +180,8 @@ void SetReplacement(PClassActor *info, FName replaceName)
if (replacee == NULL)
{
I_Error ("Replaced type '%s' not found in %s", replaceName.GetChars(), info->TypeName.GetChars());
sc.ScriptMessage("Replaced type '%s' not found for %s", replaceName.GetChars(), info->TypeName.GetChars());
return;
}
if (replacee != NULL)
{

View file

@ -211,7 +211,7 @@ PSymbolActionFunction *FindGlobalActionFunction(const char *name);
//==========================================================================
PClassActor *CreateNewActor(const FScriptPosition &sc, FName typeName, FName parentName, bool native);
void SetReplacement(PClassActor *info, FName replaceName);
void SetReplacement(FScanner &sc, PClassActor *info, FName replaceName);
void HandleActorFlag(FScanner &sc, Baggage &bag, const char *part1, const char *part2, int mod);
void FinishActor(const FScriptPosition &sc, PClassActor *info, Baggage &bag);

View file

@ -355,9 +355,9 @@ static void DoAttack (AActor *self, bool domelee, bool domissile,
else if (domissile && MissileType != NULL)
{
// This seemingly senseless code is needed for proper aiming.
self->z += MissileHeight - 32*FRACUNIT;
self->z += MissileHeight + self->GetBobOffset() - 32*FRACUNIT;
AActor *missile = P_SpawnMissileXYZ (self->x, self->y, self->z + 32*FRACUNIT, self, self->target, MissileType, false);
self->z -= MissileHeight - 32*FRACUNIT;
self->z -= MissileHeight + self->GetBobOffset() - 32*FRACUNIT;
if (missile)
{
@ -663,6 +663,42 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfHealthLower)
return numret;
}
//==========================================================================
//
// State jump function
//
//==========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetOutsideMeleeRange)
{
PARAM_ACTION_PROLOGUE;
PARAM_STATE(jump);
if (!self->CheckMeleeRange())
{
ACTION_JUMP(jump);
}
ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains!
return numret;
}
//==========================================================================
//
// State jump function
//
//==========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInsideMeleeRange)
{
PARAM_ACTION_PROLOGUE;
PARAM_STATE(jump);
if (self->CheckMeleeRange())
{
ACTION_JUMP(jump);
}
ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains!
return numret;
}
//==========================================================================
//
// State jump function
@ -799,12 +835,18 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfArmorType)
//
//==========================================================================
enum
{
XF_HURTSOURCE = 1,
XF_NOTMISSILE = 4,
};
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Explode)
{
PARAM_ACTION_PROLOGUE;
PARAM_INT_OPT (damage) { damage = -1; }
PARAM_INT_OPT (distance) { distance = -1; }
PARAM_BOOL_OPT (hurtSource) { hurtSource = true; }
PARAM_INT_OPT (flags) { flags = XF_HURTSOURCE; }
PARAM_BOOL_OPT (alert) { alert = false; }
PARAM_INT_OPT (fulldmgdistance) { fulldmgdistance = 0; }
PARAM_INT_OPT (nails) { nails = 0; }
@ -815,11 +857,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Explode)
{
damage = self->GetClass()->ExplosionDamage;
distance = self->GetClass()->ExplosionRadius;
if (distance < 0)
{
distance = damage;
}
hurtSource = !self->GetClass()->DontHurtShooter;
flags = !self->GetClass()->DontHurtShooter;
alert = false;
}
else
@ -842,7 +880,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Explode)
}
}
P_RadiusAttack (self, self->target, damage, distance, self->DamageType, hurtSource, true, fulldmgdistance);
P_RadiusAttack (self, self->target, damage, distance, self->DamageType, flags, fulldmgdistance);
P_CheckSplash(self, distance<<FRACBITS);
if (alert && self->target != NULL && self->target->player != NULL)
{
@ -852,43 +890,41 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Explode)
return 0;
}
enum
{
RTF_AFFECTSOURCE = 1,
RTF_NOIMPACTDAMAGE = 2,
};
//==========================================================================
//
// A_RadiusThrust
//
//==========================================================================
enum
{
RTF_AFFECTSOURCE = 1,
RTF_NOIMPACTDAMAGE = 2,
RTF_NOTMISSILE = 4,
};
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusThrust)
{
PARAM_ACTION_PROLOGUE;
PARAM_INT_OPT (force) { force = 128; }
PARAM_INT_OPT (distance) { distance = -1; }
PARAM_INT_OPT (thrustFlags) { thrustFlags = RTF_AFFECTSOURCE; }
PARAM_INT_OPT (flags) { flags = RTF_AFFECTSOURCE; }
PARAM_INT_OPT (fullthrustdistance) { fullthrustdistance = 0; }
bool affectSource = !!(thrustFlags & RTF_AFFECTSOURCE);
bool noimpactdamage = !!(thrustFlags & RTF_NOIMPACTDAMAGE);
bool sourcenothrust = false;
if (force <= 0) force = 128;
if (distance <= 0) distance = force;
// Temporarily negate MF2_NODMGTHRUST on the shooter, since it renders this function useless.
if (self->target != NULL && self->target->flags2 & MF2_NODMGTHRUST)
if (!(flags & RTF_NOTMISSILE) && self->target != NULL && self->target->flags2 & MF2_NODMGTHRUST)
{
sourcenothrust = true;
self->target->flags2 &= ~MF2_NODMGTHRUST;
}
int sourceflags2 = self->target != NULL ? self->target->flags2 : 0;
P_RadiusAttack (self, self->target, force, distance, self->DamageType, affectSource, false, fullthrustdistance, noimpactdamage);
P_RadiusAttack (self, self->target, force, distance, self->DamageType, flags | RADF_NODAMAGE, fullthrustdistance);
P_CheckSplash(self, distance << FRACBITS);
if (sourcenothrust)
@ -959,7 +995,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomMissile)
angle_t ang = (self->angle - ANGLE_90) >> ANGLETOFINESHIFT;
fixed_t x = spawnofs_xy * finecosine[ang];
fixed_t y = spawnofs_xy * finesine[ang];
fixed_t z = spawnheight - 32*FRACUNIT + (self->player? self->player->crouchoffset : 0);
fixed_t z = spawnheight + self->GetBobOffset() - 32*FRACUNIT + (self->player? self->player->crouchoffset : 0);
switch (aimmode)
{
@ -976,14 +1012,14 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomMissile)
break;
case 1:
missile = P_SpawnMissileXYZ(self->x+x, self->y+y, self->z+spawnheight, self, self->target, ti, false);
missile = P_SpawnMissileXYZ(self->x+x, self->y+y, self->z + self->GetBobOffset() + spawnheight, self, self->target, ti, false);
break;
case 2:
self->x += x;
self->y += y;
missile = P_SpawnMissileAngleZSpeed(self, self->z+spawnheight, ti, self->angle, 0, GetDefaultByType(ti)->Speed, self, false);
self->x -= x;
missile = P_SpawnMissileAngleZSpeed(self, self->z + self->GetBobOffset() + spawnheight, ti, self->angle, 0, GetDefaultByType(ti)->Speed, self, false);
self->x -= x;
self->y -= y;
flags |= CMF_ABSOLUTEPITCH;
@ -1210,9 +1246,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomComboAttack)
else if (ti)
{
// This seemingly senseless code is needed for proper aiming.
self->z += spawnheight - 32*FRACUNIT;
AActor *missile = P_SpawnMissileXYZ(self->x, self->y, self->z + 32*FRACUNIT, self, self->target, ti, false);
self->z -= spawnheight - 32*FRACUNIT;
self->z += spawnheight + self->GetBobOffset() - 32*FRACUNIT;
AActor *missile = P_SpawnMissileXYZ (self->x, self->y, self->z + 32*FRACUNIT, self, self->target, ti, false);
self->z -= spawnheight + self->GetBobOffset() - 32*FRACUNIT;
if (missile)
{
@ -1951,7 +1987,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnItem)
AActor *mo = Spawn(missile,
self->x + FixedMul(distance, finecosine[self->angle>>ANGLETOFINESHIFT]),
self->y + FixedMul(distance, finesine[self->angle>>ANGLETOFINESHIFT]),
self->z - self->floorclip + zheight, ALLOW_REPLACE);
self->z - self->floorclip + self->GetBobOffset() + zheight, ALLOW_REPLACE);
int flags = (transfer_translation ? SIXF_TRANSFERTRANSLATION : 0) + (useammo ? SIXF_SETMASTER : 0);
bool res = InitSpawnedItem(self, mo, flags);
@ -2024,7 +2060,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnItemEx)
xvel = newxvel;
}
AActor *mo = Spawn(missile, x, y, self->z - self->floorclip + zofs, ALLOW_REPLACE);
AActor * mo = Spawn(missile, x, y, self->z - self->floorclip + self->GetBobOffset() + zofs, ALLOW_REPLACE);
bool res = InitSpawnedItem(self, mo, flags);
ACTION_SET_RESULT(res); // for an inventory item's use state
if (mo)
@ -2073,7 +2109,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ThrowGrenade)
AActor *bo;
bo = Spawn(missile, self->x, self->y,
self->z - self->floorclip + zheight + 35*FRACUNIT + (self->player ? self->player->crouchoffset : 0),
self->z - self->floorclip + self->GetBobOffset() + zheight + 35*FRACUNIT + (self->player? self->player->crouchoffset : 0),
ALLOW_REPLACE);
if (bo)
{
@ -2435,7 +2471,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnDebris)
{
mo = Spawn(debris, self->x+((pr_spawndebris()-128)<<12),
self->y+((pr_spawndebris()-128)<<12),
self->z+(pr_spawndebris()*self->height/256), ALLOW_REPLACE);
self->z+(pr_spawndebris()*self->height/256+self->GetBobOffset()), ALLOW_REPLACE);
if (mo && transfer_translation)
{
mo->Translation = self->Translation;
@ -2760,7 +2796,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Burst)
mo = Spawn(chunk,
self->x + (((pr_burst()-128)*self->radius)>>7),
self->y + (((pr_burst()-128)*self->radius)>>7),
self->z + (pr_burst()*self->height/255), ALLOW_REPLACE);
self->z + (pr_burst()*self->height/255 + self->GetBobOffset()), ALLOW_REPLACE);
if (mo)
{
@ -4712,3 +4748,18 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusGive)
return 0;
}
//==========================================================================
//
// A_SetTics
//
//==========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetTics)
{
PARAM_ACTION_PROLOGUE;
PARAM_INT(tics_to_set);
self->tics = tics_to_set;
return 0;
}

View file

@ -276,6 +276,7 @@ static FFlagDef ActorFlags[]=
DEFINE_DUMMY_FLAG(NONETID), // netcode-based
DEFINE_DUMMY_FLAG(ALLOWCLIENTSPAWN), // netcode-based
DEFINE_DUMMY_FLAG(CLIENTSIDEONLY), // netcode-based
DEFINE_DUMMY_FLAG(SERVERSIDEONLY), // netcode-based
DEFINE_DUMMY_FLAG(EXPLODEONDEATH), // seems useless
};
@ -297,6 +298,7 @@ static FFlagDef InventoryFlags[] =
DEFINE_FLAG(IF, NOATTENPICKUPSOUND, AInventory, ItemFlags),
DEFINE_FLAG(IF, PERSISTENTPOWER, AInventory, ItemFlags),
DEFINE_FLAG(IF, RESTRICTABSOLUTELY, AInventory, ItemFlags),
DEFINE_FLAG(IF, NEVERRESPAWN, AInventory, ItemFlags),
DEFINE_DEPRECATED_FLAG(PICKUPFLASH),
DEFINE_DEPRECATED_FLAG(INTERHUBSTRIP),

View file

@ -1124,7 +1124,7 @@ static PClassActor *ParseActorHeader(FScanner &sc, Baggage *bag)
info->DoomEdNum = DoomEdNum > 0 ? DoomEdNum : -1;
info->SourceLumpName = Wads.GetLumpFullPath(sc.LumpNum);
SetReplacement(info, replaceName);
SetReplacement(sc, info, replaceName);
ResetBaggage (bag, info == RUNTIME_CLASS(AActor) ? NULL : static_cast<PClassActor *>(info->ParentClass));
bag->Info = info;

View file

@ -2280,6 +2280,26 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, jumpz, F, PlayerPawn)
defaults->JumpZ = z;
}
//==========================================================================
//
//==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(player, GruntSpeed, F, PlayerPawn)
{
PROP_FIXED_PARM(z, 0);
defaults->GruntSpeed = z;
}
//==========================================================================
//
//==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(player, FallingScreamSpeed, FF, PlayerPawn)
{
PROP_FIXED_PARM(minz, 0);
PROP_FIXED_PARM(maxz, 0);
defaults->FallingScreamMinSpeed = minz;
defaults->FallingScreamMaxSpeed = maxz;
}
//==========================================================================
//
//==========================================================================
@ -2454,7 +2474,8 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, damagescreencolor, Cfs, PlayerPawn)
PROP_STRING_PARM(type, 3);
color.a = BYTE(255 * clamp(a, 0.f, 1.f));
info->SetPainFlash(type, color);
assert(info->IsKindOf(RUNTIME_CLASS(PClassPlayerPawn)));
static_cast<PClassPlayerPawn *>(info)->PainFlashes.Insert(type, color);
}
}

View file

@ -56,6 +56,7 @@
#include "colormatcher.h"
#include "thingdef_exp.h"
#include "version.h"
#include "templates.h"
TDeletingArray<FStateTempCall *> StateTempCalls;
@ -223,12 +224,34 @@ do_stop:
sc.MustGetString();
statestring = sc.String;
sc.MustGetNumber();
state.Tics = clamp<int>(sc.Number, -1, 32767);
if (tcall == NULL)
{
tcall = new FStateTempCall;
}
if (sc.CheckString("RANDOM"))
{
int min, max;
sc.MustGetStringName("(");
sc.MustGetNumber();
min = clamp<int>(sc.Number, -1, SHRT_MAX);
sc.MustGetStringName(",");
sc.MustGetNumber();
max = clamp<int>(sc.Number, -1, SHRT_MAX);
sc.MustGetStringName(")");
if (min > max)
{
swapvalues(min, max);
}
state.Tics = min;
state.TicRange = max - min;
}
else
{
sc.MustGetNumber();
state.Tics = clamp<int>(sc.Number, -1, SHRT_MAX);
state.TicRange = 0;
}
while (sc.GetString() && !sc.Crossed)
{

View file

@ -120,15 +120,8 @@ void V_AddPlayerBlend (player_t *CPlayer, float blend[4], float maxinvalpha, int
BPART(gameinfo.pickupcolor)/255.f, cnt > 128 ? 0.5f : cnt / 255.f, blend);
}
PainFlashList * pfl = CPlayer->mo->GetClass()->PainFlashes;
PalEntry painFlash = CPlayer->mo->DamageFade;
if (pfl)
{
PalEntry * color = pfl->CheckKey(CPlayer->mo->DamageTypeReceived);
if (color) painFlash = *color;
}
CPlayer->mo->GetClass()->GetPainFlash(CPlayer->mo->DamageTypeReceived, &painFlash);
if (painFlash.a != 0)
{

View file

@ -837,10 +837,10 @@ void DCanvas::FillBorder (FTexture *img)
}
else
{
Clear (0, 0, Width, bordtop, 0, 0); // Top
Clear (0, bordtop, bordleft, Height - bordbottom, 0, 0); // Left
Clear (Width - bordright, bordtop, Width, Height - bordbottom, 0, 0); // Right
Clear (0, Height - bordbottom, Width, Height, 0, 0); // Bottom
Clear (0, 0, Width, bordtop, GPalette.BlackIndex, 0); // Top
Clear (0, bordtop, bordleft, Height - bordbottom, GPalette.BlackIndex, 0); // Left
Clear (Width - bordright, bordtop, Width, Height - bordbottom, GPalette.BlackIndex, 0); // Right
Clear (0, Height - bordbottom, Width, Height, GPalette.BlackIndex, 0); // Bottom
}
}

View file

@ -124,16 +124,26 @@ public:
FSingleLumpFont (const char *fontname, int lump);
protected:
void CheckFON1Chars (int lump, const BYTE *data, double *luminosity);
void CheckFON1Chars (double *luminosity);
void BuildTranslations2 ();
void FixupPalette (BYTE *identity, double *luminosity, const BYTE *palette,
bool rescale, PalEntry *out_palette);
void LoadTranslations ();
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);
enum
{
FONT1,
FONT2,
BMFFONT
} FontType;
BYTE PaletteData[768];
bool RescalePalette;
};
class FSinglePicFont : public FFont
@ -153,16 +163,22 @@ protected:
class FSpecialFont : public FFont
{
public:
FSpecialFont (const char *name, int first, int count, FTexture **lumplist, const bool *notranslate);
FSpecialFont (const char *name, int first, int count, FTexture **lumplist, const bool *notranslate, int lump);
void LoadTranslations();
protected:
bool notranslate[256];
};
// This is a font character that loads a texture and recolors it.
class FFontChar1 : public FTexture
{
public:
FFontChar1 (FTexture *sourcelump, const BYTE *sourceremap);
FFontChar1 (FTexture *sourcelump);
const BYTE *GetColumn (unsigned int column, const Span **spans_out);
const BYTE *GetPixels ();
void SetSourceRemap(const BYTE *sourceremap);
void Unload ();
~FFontChar1 ();
@ -178,11 +194,12 @@ protected:
class FFontChar2 : public FTexture
{
public:
FFontChar2 (int sourcelump, const BYTE *sourceremap, int sourcepos, int width, int height, int leftofs=0, int topofs=0);
FFontChar2 (int sourcelump, int sourcepos, int width, int height, int leftofs=0, int topofs=0);
~FFontChar2 ();
const BYTE *GetColumn (unsigned int column, const Span **spans_out);
const BYTE *GetPixels ();
void SetSourceRemap(const BYTE *sourceremap);
void Unload ();
protected:
@ -322,18 +339,17 @@ FArchive &SerializeFFontPtr (FArchive &arc, FFont* &font)
//
//==========================================================================
FFont::FFont (const char *name, const char *nametemplate, int first, int count, int start)
FFont::FFont (const char *name, const char *nametemplate, int first, int count, int start, int fdlump, int spacewidth)
{
int i;
FTextureID lump;
char buffer[12];
FTexture **charlumps;
BYTE usedcolors[256], identity[256];
double *luminosity;
int maxyoffs;
bool doomtemplate = gameinfo.gametype & GAME_DoomChex ? strncmp (nametemplate, "STCFN", 5) == 0 : false;
bool stcfn121 = false;
Lump = fdlump;
Chars = new CharData[count];
charlumps = new FTexture *[count];
PatchRemap = new BYTE[256];
@ -341,7 +357,6 @@ FFont::FFont (const char *name, const char *nametemplate, int first, int count,
LastChar = first + count - 1;
FontHeight = 0;
GlobalKerning = false;
memset (usedcolors, 0, 256);
Name = copystring (name);
Next = FirstFont;
FirstFont = this;
@ -392,18 +407,12 @@ FFont::FFont (const char *name, const char *nametemplate, int first, int count,
{
FontHeight = height;
}
RecordTextureColors (pic, usedcolors);
}
}
}
ActiveColors = SimpleTranslation (usedcolors, PatchRemap, identity, &luminosity);
for (i = 0; i < count; i++)
{
if (charlumps[i] != NULL)
{
Chars[i].Pic = new FFontChar1 (charlumps[i], PatchRemap);
Chars[i].Pic = new FFontChar1 (charlumps[i]);
Chars[i].XMove = Chars[i].Pic->GetScaledWidth();
}
else
@ -413,7 +422,11 @@ FFont::FFont (const char *name, const char *nametemplate, int first, int count,
}
}
if ('N'-first >= 0 && 'N'-first < count && Chars['N' - first].Pic != NULL)
if (spacewidth != -1)
{
SpaceWidth = spacewidth;
}
else if ('N'-first >= 0 && 'N'-first < count && Chars['N' - first].Pic != NULL)
{
SpaceWidth = (Chars['N' - first].XMove + 1) / 2;
}
@ -424,9 +437,8 @@ FFont::FFont (const char *name, const char *nametemplate, int first, int count,
FixXMoves();
BuildTranslations (luminosity, identity, &TranslationParms[0][0], ActiveColors, NULL);
LoadTranslations();
delete[] luminosity;
delete[] charlumps;
}
@ -803,6 +815,42 @@ int FFont::GetCharWidth (int code) const
return (code < 0) ? SpaceWidth : Chars[code - FirstChar].XMove;
}
//==========================================================================
//
// FFont :: LoadTranslations
//
//==========================================================================
void FFont::LoadTranslations()
{
unsigned int count = LastChar - FirstChar + 1;
BYTE usedcolors[256], identity[256];
double *luminosity;
memset (usedcolors, 0, 256);
for (unsigned int i = 0; i < count; i++)
{
FFontChar1 *pic = static_cast<FFontChar1 *>(Chars[i].Pic);
if(pic)
{
pic->SetSourceRemap(NULL); // Force the FFontChar1 to return the same pixels as the base texture
RecordTextureColors (pic, usedcolors);
}
}
ActiveColors = SimpleTranslation (usedcolors, PatchRemap, identity, &luminosity);
for (unsigned int i = 0; i < count; i++)
{
if(Chars[i].Pic)
static_cast<FFontChar1 *>(Chars[i].Pic)->SetSourceRemap(PatchRemap);
}
BuildTranslations (luminosity, identity, &TranslationParms[0][0], ActiveColors, NULL);
delete[] luminosity;
}
//==========================================================================
//
// FFont :: Preload
@ -854,8 +902,9 @@ void FFont::StaticPreloadFonts()
//
//==========================================================================
FFont::FFont ()
FFont::FFont (int lump)
{
Lump = lump;
Chars = NULL;
PatchRemap = NULL;
Name = NULL;
@ -869,7 +918,7 @@ FFont::FFont ()
//
//==========================================================================
FSingleLumpFont::FSingleLumpFont (const char *name, int lump)
FSingleLumpFont::FSingleLumpFont (const char *name, int lump) : FFont(lump)
{
assert(lump >= 0);
@ -927,6 +976,51 @@ void FSingleLumpFont::CreateFontFromPic (FTextureID picnum)
ActiveColors = 0;
}
//==========================================================================
//
// FSingleLumpFont :: LoadTranslations
//
//==========================================================================
void FSingleLumpFont::LoadTranslations()
{
double luminosity[256];
BYTE identity[256];
PalEntry local_palette[256];
bool useidentity = true;
bool usepalette = false;
const void* ranges;
unsigned int count = LastChar - FirstChar + 1;
switch(FontType)
{
case FONT1:
useidentity = false;
ranges = &TranslationParms[1][0];
CheckFON1Chars (luminosity);
break;
case BMFFONT:
case FONT2:
usepalette = true;
FixupPalette (identity, luminosity, PaletteData, RescalePalette, local_palette);
ranges = &TranslationParms[0][0];
break;
default:
break;
}
for(unsigned int i = 0;i < count;++i)
{
if(Chars[i].Pic)
static_cast<FFontChar2*>(Chars[i].Pic)->SetSourceRemap(PatchRemap);
}
BuildTranslations (luminosity, useidentity ? identity : NULL, ranges, ActiveColors, usepalette ? local_palette : NULL);
}
//==========================================================================
//
// FSingleLumpFont :: LoadFON1
@ -937,7 +1031,6 @@ void FSingleLumpFont::CreateFontFromPic (FTextureID picnum)
void FSingleLumpFont::LoadFON1 (int lump, const BYTE *data)
{
double luminosity[256];
int w, h;
Chars = new CharData[256];
@ -945,6 +1038,7 @@ void FSingleLumpFont::LoadFON1 (int lump, const BYTE *data)
w = data[4] + data[5]*256;
h = data[6] + data[7]*256;
FontType = FONT1;
FontHeight = h;
SpaceWidth = w;
FirstChar = 0;
@ -952,8 +1046,10 @@ void FSingleLumpFont::LoadFON1 (int lump, const BYTE *data)
GlobalKerning = 0;
PatchRemap = new BYTE[256];
CheckFON1Chars (lump, data, luminosity);
BuildTranslations (luminosity, NULL, &TranslationParms[1][0], ActiveColors, NULL);
for(unsigned int i = 0;i < 256;++i)
Chars[i].Pic = NULL;
LoadTranslations();
}
//==========================================================================
@ -969,17 +1065,17 @@ void FSingleLumpFont::LoadFON2 (int lump, const BYTE *data)
{
int count, i, totalwidth;
int *widths2;
BYTE identity[256];
double luminosity[256];
PalEntry local_palette[256];
WORD *widths;
const BYTE *palette;
const BYTE *data_p;
FontType = FONT2;
FontHeight = data[4] + data[5]*256;
FirstChar = data[6];
LastChar = data[7];
ActiveColors = data[10];
PatchRemap = NULL;
RescalePalette = data[9] == 0;
count = LastChar - FirstChar + 1;
Chars = new CharData[count];
@ -1029,7 +1125,7 @@ void FSingleLumpFont::LoadFON2 (int lump, const BYTE *data)
SpaceWidth = totalwidth * 2 / (3 * count);
}
FixupPalette (identity, luminosity, palette, data[9] == 0, local_palette);
memcpy(PaletteData, palette, (ActiveColors+1)*3);
data_p = palette + (ActiveColors+1)*3;
@ -1043,7 +1139,7 @@ void FSingleLumpFont::LoadFON2 (int lump, const BYTE *data)
}
else
{
Chars[i].Pic = new FFontChar2 (lump, NULL, int(data_p - data), widths2[i], FontHeight);
Chars[i].Pic = new FFontChar2 (lump, int(data_p - data), widths2[i], FontHeight);
do
{
SBYTE code = *data_p++;
@ -1066,7 +1162,7 @@ void FSingleLumpFont::LoadFON2 (int lump, const BYTE *data)
}
}
BuildTranslations (luminosity, identity, &TranslationParms[0][0], ActiveColors, local_palette);
LoadTranslations();
delete[] widths2;
}
@ -1087,15 +1183,14 @@ void FSingleLumpFont::LoadBMF(int lump, const BYTE *data)
int i, chari;
BYTE raw_palette[256*3];
PalEntry sort_palette[256];
PalEntry local_palette[256];
double luminosity[256];
BYTE identity[256];
FontType = BMFFONT;
FontHeight = data[5];
GlobalKerning = (SBYTE)data[8];
ActiveColors = data[16];
SpaceWidth = -1;
nwidth = -1;
RescalePalette = true;
infolen = data[17 + ActiveColors*3];
chardata = data + 18 + ActiveColors*3 + infolen;
@ -1160,7 +1255,7 @@ void FSingleLumpFont::LoadBMF(int lump, const BYTE *data)
PatchRemap[sort_palette[i].a] = i;
}
FixupPalette(identity, luminosity, raw_palette, true, local_palette);
memcpy(PaletteData, raw_palette, 768);
// 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])
@ -1180,7 +1275,7 @@ void FSingleLumpFont::LoadBMF(int lump, const BYTE *data)
{ // Empty character: skip it.
continue;
}
Chars[chardata[chari] - FirstChar].Pic = new FFontChar2(lump, PatchRemap, int(chardata + chari + 6 - data),
Chars[chardata[chari] - FirstChar].Pic = new FFontChar2(lump, int(chardata + chari + 6 - data),
chardata[chari+1], // width
chardata[chari+2], // height
-(SBYTE)chardata[chari+3], // x offset
@ -1202,7 +1297,7 @@ void FSingleLumpFont::LoadBMF(int lump, const BYTE *data)
}
FixXMoves();
BuildTranslations(luminosity, identity, &TranslationParms[0][0], ActiveColors, local_palette);
LoadTranslations();
}
//==========================================================================
@ -1232,8 +1327,11 @@ int STACK_ARGS FSingleLumpFont::BMFCompare(const void *a, const void *b)
//
//==========================================================================
void FSingleLumpFont::CheckFON1Chars (int lump, const BYTE *data, double *luminosity)
void FSingleLumpFont::CheckFON1Chars (double *luminosity)
{
FMemLump memLump = Wads.ReadLump(Lump);
const BYTE* data = (const BYTE*) memLump.GetMem();
BYTE used[256], reverse[256];
const BYTE *data_p;
int i, j;
@ -1245,8 +1343,11 @@ 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;
if(!Chars[i].Pic)
{
Chars[i].Pic = new FFontChar2 (Lump, int(data_p - data), SpaceWidth, FontHeight);
Chars[i].XMove = SpaceWidth;
}
// Advance to next char's data and count the used colors.
do
@ -1304,7 +1405,7 @@ void FSingleLumpFont::FixupPalette (BYTE *identity, double *luminosity, const BY
identity[0] = 0;
palette += 3; // Skip the transparent color
for (i = 1; i <= ActiveColors; ++i, palette += 3)
for (i = 1; i < ActiveColors; ++i, palette += 3)
{
int r = palette[0];
int g = palette[1];
@ -1331,7 +1432,7 @@ void FSingleLumpFont::FixupPalette (BYTE *identity, double *luminosity, const BY
{
diver = 1.0 / 255.0;
}
for (i = 1; i <= ActiveColors; ++i)
for (i = 1; i < ActiveColors; ++i)
{
luminosity[i] = (luminosity[i] - minlum) * diver;
}
@ -1347,7 +1448,8 @@ void FSingleLumpFont::FixupPalette (BYTE *identity, double *luminosity, const BY
//
//==========================================================================
FSinglePicFont::FSinglePicFont(const char *picname)
FSinglePicFont::FSinglePicFont(const char *picname) :
FFont(-1) // Since lump is only needed for priority information we don't need to worry about this here.
{
FTextureID picnum = TexMan.CheckForTexture (picname, FTexture::TEX_Any);
@ -1413,8 +1515,8 @@ int FSinglePicFont::GetCharWidth (int code) const
//
//==========================================================================
FFontChar1::FFontChar1 (FTexture *sourcelump, const BYTE *sourceremap)
: SourceRemap (sourceremap)
FFontChar1::FFontChar1 (FTexture *sourcelump)
: SourceRemap (NULL)
{
UseType = FTexture::TEX_FontChar;
BaseTexture = sourcelump;
@ -1453,9 +1555,16 @@ void FFontChar1::MakeTexture ()
Pixels = new BYTE[Width*Height];
const BYTE *pix = BaseTexture->GetPixels();
for (int x = 0; x < Width*Height; ++x)
if (!SourceRemap)
{
Pixels[x] = SourceRemap[pix[x]];
memcpy(Pixels, pix, Width*Height);
}
else
{
for (int x = 0; x < Width*Height; ++x)
{
Pixels[x] = SourceRemap[pix[x]];
}
}
}
@ -1476,6 +1585,18 @@ const BYTE *FFontChar1::GetColumn (unsigned int column, const Span **spans_out)
return Pixels + column*Height;
}
//==========================================================================
//
// FFontChar1 :: SetSourceRemap
//
//==========================================================================
void FFontChar1::SetSourceRemap(const BYTE *sourceremap)
{
Unload();
SourceRemap = sourceremap;
}
//==========================================================================
//
// FFontChar1 :: Unload
@ -1510,8 +1631,8 @@ FFontChar1::~FFontChar1 ()
//
//==========================================================================
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)
FFontChar2::FFontChar2 (int sourcelump, int sourcepos, int width, int height, int leftofs, int topofs)
: SourceLump (sourcelump), SourcePos (sourcepos), Pixels (0), Spans (0), SourceRemap(NULL)
{
UseType = TEX_FontChar;
Width = width;
@ -1594,6 +1715,18 @@ const BYTE *FFontChar2::GetColumn (unsigned int column, const Span **spans_out)
return Pixels + column*Height;
}
//==========================================================================
//
// FFontChar2 :: SetSourceRemap
//
//==========================================================================
void FFontChar2::SetSourceRemap(const BYTE *sourceremap)
{
Unload();
SourceRemap = sourceremap;
}
//==========================================================================
//
// FFontChar2 :: MakeTexture
@ -1730,16 +1863,15 @@ void FFontChar2::MakeTexture ()
//
//==========================================================================
FSpecialFont::FSpecialFont (const char *name, int first, int count, FTexture **lumplist, const bool *notranslate)
FSpecialFont::FSpecialFont (const char *name, int first, int count, FTexture **lumplist, const bool *notranslate, int lump) : FFont(lump)
{
int i, j;
int i;
FTexture **charlumps;
BYTE usedcolors[256], identity[256];
double *luminosity;
int maxyoffs;
int TotalColors;
FTexture *pic;
memcpy(this->notranslate, notranslate, 256*sizeof(bool));
Name = copystring(name);
Chars = new CharData[count];
charlumps = new FTexture*[count];
@ -1748,7 +1880,6 @@ FSpecialFont::FSpecialFont (const char *name, int first, int count, FTexture **l
LastChar = first + count - 1;
FontHeight = 0;
GlobalKerning = false;
memset (usedcolors, 0, 256);
Next = FirstFont;
FirstFont = this;
@ -1771,7 +1902,58 @@ FSpecialFont::FSpecialFont (const char *name, int first, int count, FTexture **l
{
FontHeight = height;
}
}
if (charlumps[i] != NULL)
{
Chars[i].Pic = new FFontChar1 (charlumps[i]);
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 != NULL)
{
SpaceWidth = (Chars['N' - first].XMove + 1) / 2;
}
else
{
SpaceWidth = 4;
}
FixXMoves();
LoadTranslations();
delete[] charlumps;
}
//==========================================================================
//
// FSpecialFont :: LoadTranslations
//
//==========================================================================
void FSpecialFont::LoadTranslations()
{
int count = LastChar - FirstChar + 1;
BYTE usedcolors[256], identity[256];
double *luminosity;
int TotalColors;
int i, j;
memset (usedcolors, 0, 256);
for (i = 0; i < count; i++)
{
FFontChar1 *pic = static_cast<FFontChar1 *>(Chars[i].Pic);
if(pic)
{
pic->SetSourceRemap(NULL); // Force the FFontChar1 to return the same pixels as the base texture
RecordTextureColors (pic, usedcolors);
}
}
@ -1802,30 +1984,10 @@ FSpecialFont::FSpecialFont (const char *name, int first, int count, FTexture **l
for (i = 0; i < count; i++)
{
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(Chars[i].Pic)
static_cast<FFontChar1 *>(Chars[i].Pic)->SetSourceRemap(PatchRemap);
}
// Special fonts normally don't have all characters so be careful here!
if ('N'-first >= 0 && 'N'-first < count && Chars['N' - first].Pic != NULL)
{
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
@ -1845,7 +2007,6 @@ FSpecialFont::FSpecialFont (const char *name, int first, int count, FTexture **l
ActiveColors = TotalColors;
delete[] luminosity;
delete[] charlumps;
}
//==========================================================================
@ -1899,6 +2060,7 @@ void V_InitCustomFonts()
int start;
int first;
int count;
int spacewidth;
char cursor = '_';
while ((llump = Wads.FindLump ("FONTDEFS", &lastlump)) != -1)
@ -1913,6 +2075,7 @@ void V_InitCustomFonts()
start = 33;
first = 33;
count = 223;
spacewidth = -1;
sc.MustGetStringName ("{");
while (!sc.CheckString ("}"))
@ -1951,6 +2114,13 @@ void V_InitCustomFonts()
sc.MustGetString();
cursor = sc.String[0];
}
else if (sc.Compare ("SPACEWIDTH"))
{
if (format == 2) goto wrong;
sc.MustGetNumber();
spacewidth = sc.Number;
format = 1;
}
else if (sc.Compare ("NOTRANSLATION"))
{
if (format == 1) goto wrong;
@ -1994,7 +2164,7 @@ void V_InitCustomFonts()
}
if (format == 1)
{
FFont *fnt = new FFont (namebuffer, templatebuf, first, count, start);
FFont *fnt = new FFont (namebuffer, templatebuf, first, count, start, llump, spacewidth);
fnt->SetCursor(cursor);
}
else if (format == 2)
@ -2017,7 +2187,7 @@ void V_InitCustomFonts()
}
if (count > 0)
{
FFont *fnt = new FSpecialFont (namebuffer, first, count, &lumplist[first], notranslate);
FFont *fnt = new FSpecialFont (namebuffer, first, count, &lumplist[first], notranslate, llump);
fnt->SetCursor(cursor);
}
}
@ -2396,19 +2566,19 @@ void V_InitFonts()
}
else if (Wads.CheckNumForName ("FONTA_S") >= 0)
{
SmallFont = new FFont ("SmallFont", "FONTA%02u", HU_FONTSTART, HU_FONTSIZE, 1);
SmallFont = new FFont ("SmallFont", "FONTA%02u", HU_FONTSTART, HU_FONTSIZE, 1, -1);
SmallFont->SetCursor('[');
}
else
{
SmallFont = new FFont ("SmallFont", "STCFN%.3d", HU_FONTSTART, HU_FONTSIZE, HU_FONTSTART);
SmallFont = new FFont ("SmallFont", "STCFN%.3d", HU_FONTSTART, HU_FONTSIZE, HU_FONTSTART, -1);
}
}
if (!(SmallFont2 = FFont::FindFont("SmallFont2"))) // Only used by Strife
{
if (Wads.CheckNumForName ("STBFN033", ns_graphics) >= 0)
{
SmallFont2 = new FFont ("SmallFont2", "STBFN%.3d", HU_FONTSTART, HU_FONTSIZE, HU_FONTSTART);
SmallFont2 = new FFont ("SmallFont2", "STBFN%.3d", HU_FONTSTART, HU_FONTSIZE, HU_FONTSTART, -1);
}
else
{
@ -2427,7 +2597,7 @@ void V_InitFonts()
}
else
{
BigFont = new FFont ("BigFont", "FONTB%02u", HU_FONTSTART, HU_FONTSIZE, 1);
BigFont = new FFont ("BigFont", "FONTB%02u", HU_FONTSTART, HU_FONTSIZE, 1, -1);
}
}
if (!(ConFont = FFont::FindFont("ConsoleFont")))
@ -2455,4 +2625,14 @@ void V_ClearFonts()
}
FFont::FirstFont = NULL;
SmallFont = SmallFont2 = BigFont = ConFont = IntermissionFont = NULL;
}
}
void V_RetranslateFonts()
{
FFont *font = FFont::FirstFont;
while(font)
{
font->LoadTranslations();
font = font->Next;
}
}

View file

@ -76,15 +76,17 @@ extern int NumTextColors;
class FFont
{
public:
FFont (const char *fontname, const char *nametemplate, int first, int count, int base);
FFont (const char *fontname, const char *nametemplate, int first, int count, int base, int fdlump, int spacewidth=-1);
virtual ~FFont ();
virtual FTexture *GetChar (int code, int *const width) const;
virtual int GetCharWidth (int code) const;
FRemapTable *GetColorTranslation (EColorRange range) const;
int GetLump() const { return Lump; }
int GetSpaceWidth () const { return SpaceWidth; }
int GetHeight () const { return FontHeight; }
int GetDefaultKerning () const { return GlobalKerning; }
virtual void LoadTranslations();
void Preload() const;
static FFont *FindFont (const char *fontname);
@ -99,7 +101,7 @@ public:
void SetCursor(char c) { Cursor = c; }
protected:
FFont ();
FFont (int lump);
void BuildTranslations (const double *luminosity, const BYTE *identity,
const void *ranges, int total_colors, const PalEntry *palette);
@ -122,6 +124,7 @@ protected:
TArray<FRemapTable> Ranges;
BYTE *PatchRemap;
int Lump;
char *Name;
FFont *Next;
@ -129,6 +132,7 @@ protected:
friend struct FontsDeleter;
friend void V_ClearFonts();
friend void V_RetranslateFonts();
friend FArchive &SerializeFFontPtr (FArchive &arc, FFont* &font);
};
@ -143,5 +147,6 @@ PalEntry V_LogColorFromColorRange (EColorRange range);
EColorRange V_ParseFontColor (const BYTE *&color_value, int normalcolor, int boldcolor);
FFont *V_GetFont(const char *);
void V_InitFontColors();
void V_RetranslateFonts();
#endif //__V_FONT_H__

View file

@ -159,8 +159,8 @@ void FPalette::SetPalette (const BYTE *colors)
// Find white and black from the original palette so that they can be
// used to make an educated guess of the translucency % for a BOOM
// translucency map.
WhiteIndex = BestColor ((DWORD *)BaseColors, 255, 255, 255);
BlackIndex = BestColor ((DWORD *)BaseColors, 0, 0, 0);
WhiteIndex = BestColor ((DWORD *)BaseColors, 255, 255, 255, 0, 255);
BlackIndex = BestColor ((DWORD *)BaseColors, 0, 0, 0, 0, 255);
}
// In ZDoom's new texture system, color 0 is used as the transparent color.

View file

@ -859,7 +859,7 @@ void DFrameBuffer::DrawRateStuff ()
chars = mysnprintf (fpsbuff, countof(fpsbuff), "%2u ms (%3u fps)", howlong, LastCount);
rate_x = Width - chars * 8;
Clear (rate_x, 0, Width, 8, 0, 0);
Clear (rate_x, 0, Width, 8, GPalette.BlackIndex, 0);
DrawText (ConFont, CR_WHITE, rate_x, 0, (char *)&fpsbuff[0], TAG_DONE);
DWORD thisSec = ms/1000;
@ -1324,10 +1324,7 @@ CCMD(clean)
bool V_DoModeSetup (int width, int height, int bits)
{
DFrameBuffer *buff = I_SetMode (width, height, screen);
int ratio;
int cwidth;
int cheight;
int cx1, cy1, cx2, cy2;
int cx1, cx2;
if (buff == NULL)
{
@ -1342,41 +1339,7 @@ bool V_DoModeSetup (int width, int height, int bits)
// if D3DFB is being used for the display.
FFont::StaticPreloadFonts();
ratio = CheckRatio (width, height);
if (ratio & 4)
{
cwidth = width;
cheight = height * BaseRatioSizes[ratio][3] / 48;
}
else
{
cwidth = width * BaseRatioSizes[ratio][3] / 48;
cheight = height;
}
// Use whichever pair of cwidth/cheight or width/height that produces less difference
// between CleanXfac and CleanYfac.
cx1 = MAX(cwidth / 320, 1);
cy1 = MAX(cheight / 200, 1);
cx2 = MAX(width / 320, 1);
cy2 = MAX(height / 200, 1);
if (abs(cx1 - cy1) <= abs(cx2 - cy2))
{ // e.g. 640x360 looks better with this.
CleanXfac = cx1;
CleanYfac = cy1;
}
else
{ // e.g. 720x480 looks better with this.
CleanXfac = cx2;
CleanYfac = cy2;
}
if (CleanXfac > 1 && CleanYfac > 1 && CleanXfac != CleanYfac)
{
if (CleanXfac < CleanYfac)
CleanYfac = CleanXfac;
else
CleanXfac = CleanYfac;
}
V_CalcCleanFacs(320, 200, width, height, &CleanXfac, &CleanYfac, &cx1, &cx2);
CleanWidth = width / CleanXfac;
CleanHeight = height / CleanYfac;
@ -1426,6 +1389,52 @@ bool V_DoModeSetup (int width, int height, int bits)
return true;
}
void V_CalcCleanFacs (int designwidth, int designheight, int realwidth, int realheight, int *cleanx, int *cleany, int *_cx1, int *_cx2)
{
int ratio;
int cwidth;
int cheight;
int cx1, cy1, cx2, cy2;
ratio = CheckRatio(realwidth, realheight);
if (ratio & 4)
{
cwidth = realwidth;
cheight = realheight * BaseRatioSizes[ratio][3] / 48;
}
else
{
cwidth = realwidth * BaseRatioSizes[ratio][3] / 48;
cheight = realheight;
}
// Use whichever pair of cwidth/cheight or width/height that produces less difference
// between CleanXfac and CleanYfac.
cx1 = MAX(cwidth / designwidth, 1);
cy1 = MAX(cheight / designheight, 1);
cx2 = MAX(realwidth / designwidth, 1);
cy2 = MAX(realheight / designheight, 1);
if (abs(cx1 - cy1) <= abs(cx2 - cy2))
{ // e.g. 640x360 looks better with this.
*cleanx = cx1;
*cleany = cy1;
}
else
{ // e.g. 720x480 looks better with this.
*cleanx = cx2;
*cleany = cy2;
}
if (*cleanx > 1 && *cleany > 1 && *cleanx != *cleany)
{
if (*cleanx < *cleany)
*cleany = *cleanx;
else
*cleanx = *cleany;
}
if (_cx1 != NULL) *_cx1 = cx1;
if (_cx2 != NULL) *_cx2 = cx2;
}
bool IVideo::SetResolution (int width, int height, int bits)
{
int oldwidth, oldheight;

View file

@ -46,6 +46,7 @@ extern int CleanWidth_1, CleanHeight_1, CleanXfac_1, CleanYfac_1;
extern int DisplayWidth, DisplayHeight, DisplayBits;
bool V_DoModeSetup (int width, int height, int bits);
void V_CalcCleanFacs (int designwidth, int designheight, int realwidth, int realheight, int *cleanx, int *cleany, int *cx1=NULL, int *cx2=NULL);
class FTexture;

View file

@ -116,7 +116,7 @@ static inline const char *MakeSaveSig()
#define BUGS_FORUM_URL "http://forum.zdoom.org/index.php?c=3"
#ifdef unix
#define GAME_DIR ".zdoom"
#define GAME_DIR ".config/zdoom"
#elif defined(__APPLE__)
#define GAME_DIR GAMENAME
#else

View file

@ -1588,30 +1588,36 @@ void WI_updateNetgameStats ()
void WI_drawNetgameStats ()
{
int i, x, y, height;
int maxnamewidth, maxscorewidth;
int i, x, y, ypadding, height, lineheight;
int maxnamewidth, maxscorewidth, maxiconheight;
int pwidth = IntermissionFont->GetCharWidth('%');
int icon_x, name_x, kills_x, bonus_x, secret_x;
int bonus_len, secret_len;
int missed_kills, missed_items, missed_secrets;
EColorRange color;
const char *bonus_label;
const char *text_bonus, *text_color, *text_secret, *text_kills;
// draw animated background
WI_drawBackground();
y = WI_drawLF();
HU_GetPlayerWidths(maxnamewidth, maxscorewidth);
HU_GetPlayerWidths(maxnamewidth, maxscorewidth, maxiconheight);
height = SmallFont->GetHeight() * CleanYfac;
lineheight = MAX(height, maxiconheight * CleanYfac);
ypadding = (lineheight - height + 1) / 2;
y += 16*CleanYfac;
bonus_label = (gameinfo.gametype & GAME_Raven) ? "BONUS" : "ITEMS";
icon_x = (SmallFont->StringWidth("COLOR") + 8) * CleanXfac;
text_bonus = GStrings((gameinfo.gametype & GAME_Raven) ? "SCORE_BONUS" : "SCORE_ITEMS");
text_color = GStrings("SCORE_COLOR");
text_secret = GStrings("SCORE_SECRET");
text_kills = GStrings("SCORE_KILLS");
icon_x = (SmallFont->StringWidth(text_color) + 8) * CleanXfac;
name_x = icon_x + maxscorewidth * CleanXfac;
kills_x = name_x + (maxnamewidth + SmallFont->StringWidth("XXXXX") + 8) * CleanXfac;
bonus_x = kills_x + ((bonus_len = SmallFont->StringWidth(bonus_label)) + 8) * CleanXfac;
secret_x = bonus_x + ((secret_len = SmallFont->StringWidth("SECRET")) + 8) * CleanXfac;
kills_x = name_x + (maxnamewidth + MAX(SmallFont->StringWidth("XXXXX"), SmallFont->StringWidth(text_kills)) + 8) * CleanXfac;
bonus_x = kills_x + ((bonus_len = SmallFont->StringWidth(text_bonus)) + 8) * CleanXfac;
secret_x = bonus_x + ((secret_len = SmallFont->StringWidth(text_secret)) + 8) * CleanXfac;
x = (SCREENWIDTH - secret_x) >> 1;
icon_x += x;
@ -1622,11 +1628,11 @@ void WI_drawNetgameStats ()
color = (gameinfo.gametype & GAME_Raven) ? CR_GREEN : CR_UNTRANSLATED;
screen->DrawText(SmallFont, color, x, y, "COLOR", DTA_CleanNoMove, true, TAG_DONE);
screen->DrawText(SmallFont, color, name_x, y, "NAME", DTA_CleanNoMove, true, TAG_DONE);
screen->DrawText(SmallFont, color, kills_x - SmallFont->StringWidth("KILLS")*CleanXfac, y, "KILLS", DTA_CleanNoMove, true, TAG_DONE);
screen->DrawText(SmallFont, color, bonus_x - bonus_len*CleanXfac, y, bonus_label, DTA_CleanNoMove, true, TAG_DONE);
screen->DrawText(SmallFont, color, secret_x - secret_len*CleanXfac, y, "SECRET", DTA_CleanNoMove, true, TAG_DONE);
screen->DrawText(SmallFont, color, x, y, text_color, DTA_CleanNoMove, true, TAG_DONE);
screen->DrawText(SmallFont, color, name_x, y, GStrings("SCORE_NAME"), DTA_CleanNoMove, true, TAG_DONE);
screen->DrawText(SmallFont, color, kills_x - SmallFont->StringWidth(text_kills)*CleanXfac, y, text_kills, DTA_CleanNoMove, true, TAG_DONE);
screen->DrawText(SmallFont, color, bonus_x - bonus_len*CleanXfac, y, text_bonus, DTA_CleanNoMove, true, TAG_DONE);
screen->DrawText(SmallFont, color, secret_x - secret_len*CleanXfac, y, text_secret, DTA_CleanNoMove, true, TAG_DONE);
y += height + 6 * CleanYfac;
missed_kills = wbs->maxkills;
@ -1642,32 +1648,32 @@ void WI_drawNetgameStats ()
continue;
player = &players[i];
HU_DrawColorBar(x, y, height, i);
HU_DrawColorBar(x, y, lineheight, i);
color = (EColorRange)HU_GetRowColor(player, i == consoleplayer);
if (player->mo->ScoreIcon.isValid())
{
FTexture *pic = TexMan[player->mo->ScoreIcon];
screen->DrawTexture(pic, icon_x, y, DTA_CleanNoMove, true, TAG_DONE);
}
screen->DrawText(SmallFont, color, name_x, y, player->userinfo.netname, DTA_CleanNoMove, true, TAG_DONE);
WI_drawPercent(SmallFont, kills_x, y, cnt_kills[i], wbs->maxkills, false, color);
screen->DrawText(SmallFont, color, name_x, y + ypadding, player->userinfo.netname, DTA_CleanNoMove, true, TAG_DONE);
WI_drawPercent(SmallFont, kills_x, y + ypadding, cnt_kills[i], wbs->maxkills, false, color);
missed_kills -= cnt_kills[i];
if (ng_state >= 4)
{
WI_drawPercent(SmallFont, bonus_x, y, cnt_items[i], wbs->maxitems, false, color);
WI_drawPercent(SmallFont, bonus_x, y + ypadding, cnt_items[i], wbs->maxitems, false, color);
missed_items -= cnt_items[i];
if (ng_state >= 6)
{
WI_drawPercent(SmallFont, secret_x, y, cnt_secret[i], wbs->maxsecret, false, color);
WI_drawPercent(SmallFont, secret_x, y + ypadding, cnt_secret[i], wbs->maxsecret, false, color);
missed_secrets -= cnt_secret[i];
}
}
y += height + CleanYfac;
y += lineheight + CleanYfac;
}
// Draw "MISSED" line
y += 5 * CleanYfac;
screen->DrawText(SmallFont, CR_DARKGRAY, name_x, y, "MISSED", DTA_CleanNoMove, true, TAG_DONE);
screen->DrawText(SmallFont, CR_DARKGRAY, name_x, y, GStrings("SCORE_MISSED"), DTA_CleanNoMove, true, TAG_DONE);
WI_drawPercent(SmallFont, kills_x, y, missed_kills, wbs->maxkills, false, CR_DARKGRAY);
if (ng_state >= 4)
{
@ -1681,7 +1687,7 @@ void WI_drawNetgameStats ()
// Draw "TOTAL" line
y += height + 5 * CleanYfac;
color = (gameinfo.gametype & GAME_Raven) ? CR_GREEN : CR_UNTRANSLATED;
screen->DrawText(SmallFont, color, name_x, y, "TOTAL", DTA_CleanNoMove, true, TAG_DONE);
screen->DrawText(SmallFont, color, name_x, y, GStrings("SCORE_TOTAL"), DTA_CleanNoMove, true, TAG_DONE);
WI_drawNum(SmallFont, kills_x, y, wbs->maxkills, 0, false, color);
if (ng_state >= 4)
{

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