Update to ZDoom r2047:

- Fixed: Decals could spread to walls which had a decal-less texture or
  were flagged not to have decals.
- Fixed: DBaseDecal/DImpactDecal::CloneSelf never checked the return value
  from their StickToWall call and left unplaced decals behind if that happened.
- Reintroduced Doom.exe's player_t::usedown variable so that respawning a
  player does not immediately activate switches. oldbuttons was not usable
  for this. This also required that CopyPlayer preserves this info.
- Fixed: When restarting the music there was a NULL pointer check missing
  so it crashed when the game was started wi
- Fixed: If the Use key is used to respawn the player it must be cleared
  so that it doesn't trigger any subsequent actions after respawning.
- Fixed: Resurrecting a monster did not restore flags5 and flags6.
- Fixed: Projectiles which killed a non-monster were unable to determine
  what precisely they hit because MF_CORPSE is only valid for monsters.
  A new flag, MF6_KILLED that gets set for all objects that die, was added
  for this case.
- Added a generic A_Weave function that exposes all possible options of
  A_BishopMissileWeave and A_CStaffMissileSlither. These 2 functions are
  no longer needed from DECORATE and therefore deprecated.
- The options menu no longer scales up so quickly, so it can fit wider text
  onscreen. In addition, it now uses the whole height available to it. Also,
  at lower resolutions, items on the compatibility options menu now cut off
  the beginning of the option label rather than the option setting, making
  this menu useable where previously it was not.
- Added a channel parameter to the sector overload of SN_StopSequence() so
  it can be properly paired with calls to SN_StartSequence().
- Fixed: P_CheckPlayerSprites() ignored the MF4_NOSKIN flag.  It now also sets
  the X scale, so switching skins while morphed does not produce weird
  stretching upon unmorphing.
- Fixed: Calling S_ChangeMusic() with the same song but a different looping
  flag now restarts the song so that the new looping setting can be applied.
  (This was easier than modifying every music handler to support modifying
  loop changes on the fly, which seems like overkill.)
- Fixed: savepatchsize was declared incorrectly in d_dehacked.cpp:DoInclude().
- Changed AFastProjectile::Effect() so that it sets the spawned trail to face
  same direction as the projectile.

git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@672 b0f79afe-0144-0410-b225-9a4edf0717df
This commit is contained in:
Christoph Oelckers 2009-12-25 12:10:12 +00:00
parent 8653592339
commit 7d5c48606b
35 changed files with 437 additions and 177 deletions

View file

@ -1,3 +1,67 @@
December 25, 2009 (Changes by Graf Zahl)
- Fixed: Decals could spread to walls which had a decal-less texture or
were flagged not to have decals.
- Fixed: DBaseDecal/DImpactDecal::CloneSelf never checked the return value
from their StickToWall call and left unplaced decals behind if that happened.
- Reintroduced Doom.exe's player_t::usedown variable so that respawning a
player does not immediately activate switches. oldbuttons was not usable
for this. This also required that CopyPlayer preserves this info.
- Fixed: When restarting the music there was a NULL pointer check missing
so it crashed when the game was started wi
- Fixed: If the Use key is used to respawn the player it must be cleared
so that it doesn't trigger any subsequent actions after respawning.
- Fixed: Resurrecting a monster did not restore flags5 and flags6.
- Fixed: Projectiles which killed a non-monster were unable to determine
what precisely they hit because MF_CORPSE is only valid for monsters.
A new flag, MF6_KILLED that gets set for all objects that die, was added
for this case.
- Added a generic A_Weave function that exposes all possible options of
A_BishopMissileWeave and A_CStaffMissileSlither. These 2 functions are
no longer needed from DECORATE and therefore deprecated.
December 24, 2009
- The options menu no longer scales up so quickly, so it can fit wider text
onscreen. In addition, it now uses the whole height available to it. Also,
at lower resolutions, items on the compatibility options menu now cut off
the beginning of the option label rather than the option setting, making
this menu useable where previously it was not.
- Added a channel parameter to the sector overload of SN_StopSequence() so
it can be properly paired with calls to SN_StartSequence().
- Fixed: P_CheckPlayerSprites() ignored the MF4_NOSKIN flag. It now also sets
the X scale, so switching skins while morphed does not produce weird
stretching upon unmorphing.
- Fixed: Calling S_ChangeMusic() with the same song but a different looping
flag now restarts the song so that the new looping setting can be applied.
(This was easier than modifying every music handler to support modifying
loop changes on the fly, which seems like overkill.)
- Fixed: savepatchsize was declared incorrectly in d_dehacked.cpp:DoInclude().
- Changed AFastProjectile::Effect() so that it sets the spawned trail to face
same direction as the projectile.
December 24, 2009 (Changes by Graf Zahl)
- fixed: The UDMF blockfloaters flag was misnamed. Changed to match the spec.
December 23, 2009 (Changes by Graf Zahl)
- made the initial weave index for A_BishopMissileWeave and A_CStaffMissileSlither
a configurable actor property.
- added a menu item for snd_channels.
December 20, 2009 (Changes by Graf Zahl)
- Fixed: The Dehacked parser could read past the end of the file if the last
element was improperly defined.
December 19, 2009
- Extended MF3_SKYEXPLODE to apply to horizon walls as well.
December 19, 2009 (Changes by Graf Zahl)
- Fixed: It was not possible to set the ammo type of a weapon explicitly to
'none'.
December 18, 2009
- A_FreezeDeath() now removes fuzz effects.
- In mus2midi.cpp, added range checking to MUS_SYSEVENT and MUS_CTRLCHANGE,
and masking for note-off keys, note-on velocities, and program changes.
December 18, 2009 (Changes by Graf Zahl) December 18, 2009 (Changes by Graf Zahl)
- added all known maps requiring inverted sprite sorting to compatibility.txt. - added all known maps requiring inverted sprite sorting to compatibility.txt.
- added compatibility option to invert sprite sorting. Apparently Doom.exe - added compatibility option to invert sprite sorting. Apparently Doom.exe

View file

@ -319,6 +319,7 @@ enum
MF6_LINEDONE = 0x00008000, // From MBF: Object has already run a line effect MF6_LINEDONE = 0x00008000, // From MBF: Object has already run a line effect
MF6_NOTRIGGER = 0x00010000, // actor cannot trigger any line actions MF6_NOTRIGGER = 0x00010000, // actor cannot trigger any line actions
MF6_SHATTERING = 0x00020000, // marks an ice corpse for forced shattering MF6_SHATTERING = 0x00020000, // marks an ice corpse for forced shattering
MF6_KILLED = 0x00040000, // Something that was killed (but not necessarily a corpse)
// --- mobj.renderflags --- // --- mobj.renderflags ---
@ -765,7 +766,6 @@ public:
DWORD flags6; // Shit! Where did all the flags go? DWORD flags6; // Shit! Where did all the flags go?
int special1; // Special info int special1; // Special info
int special2; // Special info int special2; // Special info
int weaveindex; // Separated from special2 because it's used by globally accessible functions.
int health; int health;
BYTE movedir; // 0-7 BYTE movedir; // 0-7
SBYTE visdir; SBYTE visdir;
@ -783,6 +783,8 @@ public:
TObjPtr<AActor> LastLookActor; // Actor last looked for (if TIDtoHate != 0) TObjPtr<AActor> LastLookActor; // Actor last looked for (if TIDtoHate != 0)
fixed_t SpawnPoint[3]; // For nightmare respawn fixed_t SpawnPoint[3]; // For nightmare respawn
WORD SpawnAngle; WORD SpawnAngle;
BYTE WeaveIndexXY; // Separated from special2 because it's used by globally accessible functions.
BYTE WeaveIndexZ;
int skillrespawncount; int skillrespawncount;
int TIDtoHate; // TID of things to hate (0 if none) int TIDtoHate; // TID of things to hate (0 if none)
FNameNoInit Species; // For monster families FNameNoInit Species; // For monster families

View file

@ -2205,8 +2205,8 @@ static int PatchStrings (int dummy)
static int DoInclude (int dummy) static int DoInclude (int dummy)
{ {
char *data; char *data;
int savedversion, savepversion; int savedversion, savepversion, savepatchsize;
char *savepatchfile, *savepatchpt, *savepatchname, savepatchsize; char *savepatchfile, *savepatchpt, *savepatchname;
if (including) if (including)
{ {

View file

@ -276,6 +276,7 @@ public:
bool centering; bool centering;
BYTE turnticks; BYTE turnticks;
bool attackdown; bool attackdown;
bool usedown;
DWORD oldbuttons; DWORD oldbuttons;
int health; // only used between levels, mo->health int health; // only used between levels, mo->health
// is used during levels // is used during levels

View file

@ -1316,7 +1316,7 @@ void G_PlayerReborn (int player)
p->skill = b_skill; //Added by MC: p->skill = b_skill; //Added by MC:
p->oldbuttons = ~0, p->attackdown = true; // don't do anything immediately p->oldbuttons = ~0, p->attackdown = true; p->usedown = true; // don't do anything immediately
p->original_oldbuttons = ~0; p->original_oldbuttons = ~0;
p->playerstate = PST_LIVE; p->playerstate = PST_LIVE;

View file

@ -72,27 +72,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BishopAttack2)
DEFINE_ACTION_FUNCTION(AActor, A_BishopMissileWeave) DEFINE_ACTION_FUNCTION(AActor, A_BishopMissileWeave)
{ {
fixed_t newX, newY; A_Weave(self, 2, 2, 2*FRACUNIT, FRACUNIT);
int weaveXY, weaveZ;
int angle;
// for compatibility this needs to set the value itself if it was never done by the projectile itself
if (self->weaveindex == -1) self->weaveindex = 16;
// since these values are now user configurable we have to do a proper range check to avoid array overflows.
weaveXY = (self->weaveindex >> 16) & 63;
weaveZ = (self->weaveindex & 63);
angle = (self->angle + ANG90) >> ANGLETOFINESHIFT;
newX = self->x - FixedMul (finecosine[angle], FloatBobOffsets[weaveXY]<<1);
newY = self->y - FixedMul (finesine[angle], FloatBobOffsets[weaveXY]<<1);
weaveXY = (weaveXY + 2) & 63;
newX += FixedMul (finecosine[angle], FloatBobOffsets[weaveXY]<<1);
newY += FixedMul (finesine[angle], FloatBobOffsets[weaveXY]<<1);
P_TryMove (self, newX, newY, true);
self->z -= FloatBobOffsets[weaveZ];
weaveZ = (weaveZ + 2) & 63;
self->z += FloatBobOffsets[weaveZ];
self->weaveindex = weaveZ + (weaveXY<<16);
} }
//============================================================================ //============================================================================

View file

@ -135,12 +135,12 @@ DEFINE_ACTION_FUNCTION(AActor, A_CStaffAttack)
mo = P_SpawnPlayerMissile (self, RUNTIME_CLASS(ACStaffMissile), self->angle-(ANG45/15)); mo = P_SpawnPlayerMissile (self, RUNTIME_CLASS(ACStaffMissile), self->angle-(ANG45/15));
if (mo) if (mo)
{ {
mo->weaveindex = 32; mo->WeaveIndexXY = 32;
} }
mo = P_SpawnPlayerMissile (self, RUNTIME_CLASS(ACStaffMissile), self->angle+(ANG45/15)); mo = P_SpawnPlayerMissile (self, RUNTIME_CLASS(ACStaffMissile), self->angle+(ANG45/15));
if (mo) if (mo)
{ {
mo->weaveindex = 0; mo->WeaveIndexXY = 0;
} }
S_Sound (self, CHAN_WEAPON, "ClericCStaffFire", 1, ATTN_NORM); S_Sound (self, CHAN_WEAPON, "ClericCStaffFire", 1, ATTN_NORM);
} }
@ -153,22 +153,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CStaffAttack)
DEFINE_ACTION_FUNCTION(AActor, A_CStaffMissileSlither) DEFINE_ACTION_FUNCTION(AActor, A_CStaffMissileSlither)
{ {
fixed_t newX, newY; A_Weave(self, 3, 0, FRACUNIT, 0);
int weaveXY;
int angle;
if (self->weaveindex == -1) self->weaveindex = 0;
// since these values are now user configurable we have to do a proper range check to avoid array overflows.
weaveXY = self->weaveindex & 63;
angle = (self->angle+ANG90)>>ANGLETOFINESHIFT;
newX = self->x-FixedMul(finecosine[angle], FloatBobOffsets[weaveXY]);
newY = self->y-FixedMul(finesine[angle], FloatBobOffsets[weaveXY]);
weaveXY = (weaveXY+3)&63;
newX += FixedMul(finecosine[angle], FloatBobOffsets[weaveXY]);
newY += FixedMul(finesine[angle], FloatBobOffsets[weaveXY]);
P_TryMove (self, newX, newY, true);
self->weaveindex = weaveXY;
} }
//============================================================================ //============================================================================

View file

@ -348,6 +348,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BellReset2)
{ {
self->flags |= MF_SHOOTABLE; self->flags |= MF_SHOOTABLE;
self->flags &= ~MF_CORPSE; self->flags &= ~MF_CORPSE;
self->flags6 &= ~MF6_KILLED;
self->health = 5; self->health = 5;
} }

View file

@ -298,6 +298,13 @@ FTextureID DBaseDecal::StickToWall (side_t *wall, fixed_t x, fixed_t y, F3DFloor
else return FNullTextureID(); else return FNullTextureID();
CalcFracPos (wall, x, y); CalcFracPos (wall, x, y);
FTexture *texture = TexMan[tex];
if (texture == NULL || texture->bNoDecals)
{
return FNullTextureID();
}
return tex; return tex;
} }
@ -546,11 +553,18 @@ DBaseDecal *DBaseDecal::CloneSelf (const FDecalTemplate *tpl, fixed_t ix, fixed_
DBaseDecal *decal = new DBaseDecal(iz); DBaseDecal *decal = new DBaseDecal(iz);
if (decal != NULL) if (decal != NULL)
{ {
decal->StickToWall (wall, ix, iy, ffloor); if (decal->StickToWall (wall, ix, iy, ffloor).isValid())
tpl->ApplyToDecal (decal, wall); {
decal->AlphaColor = AlphaColor; tpl->ApplyToDecal (decal, wall);
decal->RenderFlags = (decal->RenderFlags & RF_DECALMASK) | decal->AlphaColor = AlphaColor;
(this->RenderFlags & ~RF_DECALMASK); decal->RenderFlags = (decal->RenderFlags & RF_DECALMASK) |
(this->RenderFlags & ~RF_DECALMASK);
}
else
{
decal->Destroy();
return NULL;
}
} }
return decal; return decal;
} }
@ -652,16 +666,12 @@ DImpactDecal *DImpactDecal::StaticCreate (const FDecalTemplate *tpl, fixed_t x,
} }
DImpactDecal::CheckMax(); DImpactDecal::CheckMax();
decal = new DImpactDecal (z); decal = new DImpactDecal (z);
if (decal == NULL)
FTextureID stickypic = decal->StickToWall (wall, x, y, ffloor);
FTexture *tex = TexMan[stickypic];
if (tex != NULL && tex->bNoDecals)
{ {
return NULL; return NULL;
} }
if (decal == NULL) if (!decal->StickToWall (wall, x, y, ffloor).isValid())
{ {
return NULL; return NULL;
} }
@ -685,15 +695,27 @@ DImpactDecal *DImpactDecal::StaticCreate (const FDecalTemplate *tpl, fixed_t x,
DBaseDecal *DImpactDecal::CloneSelf (const FDecalTemplate *tpl, fixed_t ix, fixed_t iy, fixed_t iz, side_t *wall, F3DFloor * ffloor) const DBaseDecal *DImpactDecal::CloneSelf (const FDecalTemplate *tpl, fixed_t ix, fixed_t iy, fixed_t iz, side_t *wall, F3DFloor * ffloor) const
{ {
if (wall->Flags & WALLF_NOAUTODECALS)
{
return NULL;
}
DImpactDecal::CheckMax(); DImpactDecal::CheckMax();
DImpactDecal *decal = new DImpactDecal(iz); DImpactDecal *decal = new DImpactDecal(iz);
if (decal != NULL) if (decal != NULL)
{ {
decal->StickToWall (wall, ix, iy, ffloor); if (decal->StickToWall (wall, ix, iy, ffloor).isValid())
tpl->ApplyToDecal (decal, wall); {
decal->AlphaColor = AlphaColor; tpl->ApplyToDecal (decal, wall);
decal->RenderFlags = (decal->RenderFlags & RF_DECALMASK) | decal->AlphaColor = AlphaColor;
(this->RenderFlags & ~RF_DECALMASK); decal->RenderFlags = (decal->RenderFlags & RF_DECALMASK) |
(this->RenderFlags & ~RF_DECALMASK);
}
else
{
decal->Destroy();
return NULL;
}
} }
return decal; return decal;
} }

View file

@ -125,7 +125,14 @@ void AFastProjectile::Effect()
} }
const PClass *trail = PClass::FindClass(name); const PClass *trail = PClass::FindClass(name);
Spawn (trail, x, y, hitz, ALLOW_REPLACE); if (trail != NULL)
{
AActor *act = Spawn (trail, x, y, hitz, ALLOW_REPLACE);
if (act != NULL)
{
act->angle = this->angle;
}
}
} }
} }
} }

View file

@ -2120,6 +2120,26 @@ static void M_PlayerSetupTicker (void)
} }
} }
static void M_DrawPlayerSlider (int x, int y, int cur)
{
const int range = 255;
x = (x - 160) * CleanXfac + screen->GetWidth() / 2;
y = (y - 100) * CleanYfac + screen->GetHeight() / 2;
screen->DrawText (ConFont, CR_WHITE, x, y,
"\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12",
DTA_CellX, 8 * CleanXfac,
DTA_CellY, 8 * CleanYfac,
TAG_DONE);
screen->DrawText (ConFont, CR_ORANGE, x + (5 + (int)((cur * 78) / range)) * CleanXfac, y,
"\x13",
DTA_CellX, 8 * CleanXfac,
DTA_CellY, 8 * CleanYfac,
TAG_DONE);
}
static void M_PlayerSetupDrawer () static void M_PlayerSetupDrawer ()
{ {
int x, xo, yo; int x, xo, yo;
@ -2251,9 +2271,9 @@ static void M_PlayerSetupDrawer ()
x = SmallFont->StringWidth ("Green") + 8 + PSetupDef.x; x = SmallFont->StringWidth ("Green") + 8 + PSetupDef.x;
color = players[consoleplayer].userinfo.color; color = players[consoleplayer].userinfo.color;
M_DrawSlider (x, PSetupDef.y + LINEHEIGHT*2+yo, 0.0f, 255.0f, float(RPART(color)), -1); M_DrawPlayerSlider (x, PSetupDef.y + LINEHEIGHT*2+yo, RPART(color));
M_DrawSlider (x, PSetupDef.y + LINEHEIGHT*3+yo, 0.0f, 255.0f, float(GPART(color)), -1); M_DrawPlayerSlider (x, PSetupDef.y + LINEHEIGHT*3+yo, GPART(color));
M_DrawSlider (x, PSetupDef.y + LINEHEIGHT*4+yo, 0.0f, 255.0f, float(BPART(color)), -1); M_DrawPlayerSlider (x, PSetupDef.y + LINEHEIGHT*4+yo, BPART(color));
// [GRB] Draw class setting // [GRB] Draw class setting
int pclass = players[consoleplayer].userinfo.PlayerClass; int pclass = players[consoleplayer].userinfo.PlayerClass;
@ -3443,7 +3463,13 @@ void M_Drawer ()
screen->DrawText(SmallFont, CR_UNTRANSLATED, 160, y + fontheight + 1, GStrings["TXT_NO"], DTA_Clean, true, TAG_DONE); screen->DrawText(SmallFont, CR_UNTRANSLATED, 160, y + fontheight + 1, GStrings["TXT_NO"], DTA_Clean, true, TAG_DONE);
if (skullAnimCounter < 6) if (skullAnimCounter < 6)
{ {
M_DrawConText(CR_RED, 150, y + (fontheight + 1) * messageSelection, "\xd"); screen->DrawText(ConFont, CR_RED,
(150 - 160) * CleanXfac + screen->GetWidth() / 2,
(y + (fontheight + 1) * messageSelection - 100) * CleanYfac + screen->GetHeight() / 2,
"\xd",
DTA_CellX, 8 * CleanXfac,
DTA_CellY, 8 * CleanYfac,
TAG_DONE);
} }
} }
} }

View file

@ -84,9 +84,6 @@ void M_DeactivateMenuInput ();
void M_NotifyNewSave (const char *file, const char *title, bool okForQuicksave); void M_NotifyNewSave (const char *file, const char *title, bool okForQuicksave);
// Draw a slider. Set fracdigits negative to not display the current value numerically.
void M_DrawSlider (int x, int y, double min, double max, double cur, int fracdigits=1);
// //
// MENU TYPEDEFS // MENU TYPEDEFS
// //

View file

@ -87,15 +87,17 @@
#include "m_menu.h" #include "m_menu.h"
extern FButtonStatus MenuButtons[NUM_MKEYS]; extern FButtonStatus MenuButtons[NUM_MKEYS];
void StartGLMenu (void);
EXTERN_CVAR(Int, vid_renderer)
EXTERN_CVAR(Bool, nomonsterinterpolation) EXTERN_CVAR(Bool, nomonsterinterpolation)
EXTERN_CVAR(Int, showendoom) EXTERN_CVAR(Int, showendoom)
EXTERN_CVAR(Bool, hud_althud) EXTERN_CVAR(Bool, hud_althud)
EXTERN_CVAR(Int, compatmode) EXTERN_CVAR(Int, compatmode)
EXTERN_CVAR (Bool, vid_vsync) EXTERN_CVAR (Bool, vid_vsync)
EXTERN_CVAR(Bool, displaynametags) EXTERN_CVAR(Bool, displaynametags)
EXTERN_CVAR (Int, snd_channels)
void StartGLMenu (void);
EXTERN_CVAR(Int, vid_renderer)
static value_t Renderers[] = { static value_t Renderers[] = {
{ 0.0, "Software" }, { 0.0, "Software" },
{ 1.0, "OpenGL" }, { 1.0, "OpenGL" },
@ -104,7 +106,6 @@ EXTERN_CVAR (Float, vid_brightness)
EXTERN_CVAR (Float, vid_contrast) EXTERN_CVAR (Float, vid_contrast)
extern bool gl_disabled; extern bool gl_disabled;
// //
// defaulted values // defaulted values
// //
@ -1266,6 +1267,7 @@ static menuitem_t SoundItems[] =
{ discrete, "Underwater reverb", {&snd_waterreverb}, {2.0}, {0.0}, {0.0}, {OnOff} }, { discrete, "Underwater reverb", {&snd_waterreverb}, {2.0}, {0.0}, {0.0}, {OnOff} },
{ slider, "Underwater cutoff", {&snd_waterlp}, {0.0}, {2000.0},{50.0}, {NULL} }, { slider, "Underwater cutoff", {&snd_waterlp}, {0.0}, {2000.0},{50.0}, {NULL} },
{ discrete, "Randomize pitches", {&snd_pitched}, {2.0}, {0.0}, {0.0}, {OnOff} }, { discrete, "Randomize pitches", {&snd_pitched}, {2.0}, {0.0}, {0.0}, {OnOff} },
{ slider, "Sound channels", {&snd_channels}, {8.0}, {256.0}, {8.0}, {NULL} },
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} }, { redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
{ more, "Restart sound", {NULL}, {0.0}, {0.0}, {0.0}, {(value_t *)MakeSoundChanges} }, { more, "Restart sound", {NULL}, {0.0}, {0.0}, {0.0}, {(value_t *)MakeSoundChanges} },
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} }, { redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
@ -1513,11 +1515,9 @@ void M_DrawConText (int color, int x, int y, const char *str)
{ {
int len = (int)strlen(str); int len = (int)strlen(str);
x = (x - 160) * CleanXfac + screen->GetWidth() / 2;
y = (y - 100) * CleanYfac + screen->GetHeight() / 2;
screen->DrawText (ConFont, color, x, y, str, screen->DrawText (ConFont, color, x, y, str,
DTA_CellX, 8 * CleanXfac, DTA_CellX, 8 * CleanXfac_1,
DTA_CellY, 8 * CleanYfac, DTA_CellY, 8 * CleanYfac_1,
TAG_DONE); TAG_DONE);
} }
@ -1577,7 +1577,8 @@ bool M_StartOptionsMenu (void)
return true; return true;
} }
void M_DrawSlider (int x, int y, double min, double max, double cur,int fracdigits) // Draw a slider. Set fracdigits negative to not display the current value numerically.
static void M_DrawSlider (int x, int y, double min, double max, double cur,int fracdigits)
{ {
double range; double range;
@ -1591,7 +1592,7 @@ void M_DrawSlider (int x, int y, double min, double max, double cur,int fracdigi
{ {
char textbuf[16]; char textbuf[16];
mysnprintf(textbuf, countof(textbuf), "%.*f", fracdigits, cur); mysnprintf(textbuf, countof(textbuf), "%.*f", fracdigits, cur);
screen->DrawText(SmallFont, CR_DARKGRAY, x + 12*8 + 4, y, textbuf, DTA_Clean, true, TAG_DONE); screen->DrawText(SmallFont, CR_DARKGRAY, x + (12*8 + 4) * CleanXfac_1, y, textbuf, DTA_CleanNoMove_1, true, TAG_DONE);
} }
} }
@ -1662,6 +1663,7 @@ void M_OptDrawer ()
DWORD overlay; DWORD overlay;
int labelofs; int labelofs;
int indent; int indent;
int cursorspace;
if (!CurrentMenu->DontDim) if (!CurrentMenu->DontDim)
{ {
@ -1682,9 +1684,9 @@ void M_OptDrawer ()
if (BigFont && CurrentMenu->texttitle) if (BigFont && CurrentMenu->texttitle)
{ {
screen->DrawText (BigFont, gameinfo.gametype & GAME_DoomChex ? CR_RED : CR_UNTRANSLATED, screen->DrawText (BigFont, gameinfo.gametype & GAME_DoomChex ? CR_RED : CR_UNTRANSLATED,
160-BigFont->StringWidth (CurrentMenu->texttitle)/2, 10, (screen->GetWidth() - BigFont->StringWidth(CurrentMenu->texttitle) * CleanXfac_1) / 2, 10*CleanYfac_1,
CurrentMenu->texttitle, DTA_Clean, true, TAG_DONE); CurrentMenu->texttitle, DTA_CleanNoMove_1, true, TAG_DONE);
y = 15 + BigFont->GetHeight (); y = 15 + BigFont->GetHeight();
} }
else else
{ {
@ -1693,7 +1695,7 @@ void M_OptDrawer ()
} }
if (gameinfo.gametype & GAME_Raven) if (gameinfo.gametype & GAME_Raven)
{ {
labelofs = 2; labelofs = 2 * CleanXfac_1;
y -= 2; y -= 2;
fontheight = 9; fontheight = 9;
} }
@ -1702,9 +1704,13 @@ void M_OptDrawer ()
labelofs = 0; labelofs = 0;
fontheight = 8; fontheight = 8;
} }
ytop = y + CurrentMenu->scrolltop * 8; cursorspace = 14 * CleanXfac_1;
y *= CleanYfac_1;
fontheight *= CleanYfac_1;
ytop = y + CurrentMenu->scrolltop * 8 * CleanYfac_1;
int lastrow = screen->GetHeight() - SmallFont->GetHeight() * CleanYfac_1;
for (i = 0; i < CurrentMenu->numitems && y <= 200 - SmallFont->GetHeight(); i++, y += fontheight) for (i = 0; i < CurrentMenu->numitems && y <= lastrow; i++, y += fontheight)
{ {
if (i == CurrentMenu->scrolltop) if (i == CurrentMenu->scrolltop)
{ {
@ -1715,15 +1721,30 @@ void M_OptDrawer ()
overlay = 0; overlay = 0;
if (item->type == discrete && item->c.discretecenter == 1) if (item->type == discrete && item->c.discretecenter == 1)
{ {
indent = 160; indent = screen->GetWidth() / 2;
} }
else if (item->type == joymore) else if (item->type == joymore)
{ {
indent = 4; indent = 4 * CleanXfac_1;
} }
else else
{ {
indent = CurrentMenu->indent; indent = CurrentMenu->indent;
if (indent > 280)
{ // kludge for the compatibility options with their extremely long labels
if (indent + 40 <= CleanWidth_1)
{
indent = (screen->GetWidth() - ((indent + 40) * CleanXfac_1)) / 2 + indent * CleanXfac_1;
}
else
{
indent = screen->GetWidth() - 40 * CleanXfac_1;
}
}
else
{
indent = (indent - 160) * CleanXfac_1 + screen->GetWidth() / 2;
}
} }
if (item->type != screenres) if (item->type != screenres)
@ -1746,7 +1767,7 @@ void M_OptDrawer ()
label = somestring; label = somestring;
} }
} }
width = SmallFont->StringWidth(label); width = SmallFont->StringWidth(label) * CleanXfac_1;
switch (item->type) switch (item->type)
{ {
case more: case more:
@ -1756,34 +1777,34 @@ void M_OptDrawer ()
break; break;
case joymore: case joymore:
x = 20; x = 20 * CleanXfac_1;
color = MoreColor; color = MoreColor;
break; break;
case numberedmore: case numberedmore:
case rsafemore: case rsafemore:
case rightmore: case rightmore:
x = indent + 14; x = indent + cursorspace;
color = item->type != rightmore ? CR_GREEN : MoreColor; color = item->type != rightmore ? CR_GREEN : MoreColor;
break; break;
case redtext: case redtext:
x = 160 - width / 2; x = screen->GetWidth() / 2 - width / 2;
color = LabelColor; color = LabelColor;
break; break;
case whitetext: case whitetext:
x = 160 - width / 2; x = screen->GetWidth() / 2 - width / 2;
color = CR_GOLD;//ValueColor; color = CR_GOLD;//ValueColor;
break; break;
case listelement: case listelement:
x = indent + 14; x = indent + cursorspace;
color = LabelColor; color = LabelColor;
break; break;
case colorpicker: case colorpicker:
x = indent + 14; x = indent + cursorspace;
color = MoreColor; color = MoreColor;
break; break;
@ -1800,7 +1821,7 @@ void M_OptDrawer ()
? CR_YELLOW : LabelColor; ? CR_YELLOW : LabelColor;
break; break;
} }
screen->DrawText (SmallFont, color, x, y, label, DTA_Clean, true, DTA_ColorOverlay, overlay, TAG_DONE); screen->DrawText (SmallFont, color, x, y, label, DTA_CleanNoMove_1, true, DTA_ColorOverlay, overlay, TAG_DONE);
switch (item->type) switch (item->type)
{ {
@ -1810,8 +1831,8 @@ void M_OptDrawer ()
char tbuf[16]; char tbuf[16];
mysnprintf (tbuf, countof(tbuf), "%d.", item->b.position); mysnprintf (tbuf, countof(tbuf), "%d.", item->b.position);
x = indent - SmallFont->StringWidth (tbuf); x = indent - SmallFont->StringWidth (tbuf) * CleanXfac_1;
screen->DrawText (SmallFont, CR_GREY, x, y, tbuf, DTA_Clean, true, TAG_DONE); screen->DrawText (SmallFont, CR_GREY, x, y, tbuf, DTA_CleanNoMove_1, true, TAG_DONE);
} }
break; break;
@ -1827,14 +1848,14 @@ void M_OptDrawer ()
if (v == vals) if (v == vals)
{ {
screen->DrawText (SmallFont, ValueColor, indent + 14, y, "Unknown", screen->DrawText (SmallFont, ValueColor, indent + cursorspace, y, "Unknown",
DTA_Clean, true, TAG_DONE); DTA_CleanNoMove_1, true, TAG_DONE);
} }
else else
{ {
screen->DrawText (SmallFont, item->type == cdiscrete ? v : ValueColor, screen->DrawText (SmallFont, item->type == cdiscrete ? v : ValueColor,
indent + 14, y, item->e.values[v].name, indent + cursorspace, y, item->e.values[v].name,
DTA_Clean, true, TAG_DONE); DTA_CleanNoMove_1, true, TAG_DONE);
} }
} }
@ -1884,15 +1905,15 @@ void M_OptDrawer ()
if (v == vals) if (v == vals)
{ {
screen->DrawText (SmallFont, ValueColor, indent + 14, y, "Unknown", screen->DrawText (SmallFont, ValueColor, indent + cursorspace, y, "Unknown",
DTA_Clean, true, DTA_ColorOverlay, overlay, TAG_DONE); DTA_CleanNoMove_1, true, DTA_ColorOverlay, overlay, TAG_DONE);
} }
else else
{ {
screen->DrawText (SmallFont, item->type == cdiscrete ? v : ValueColor, screen->DrawText (SmallFont, item->type == cdiscrete ? v : ValueColor,
indent + 14, y, indent + cursorspace, y,
item->type != discretes ? item->e.values[v].name : item->e.valuestrings[v].name.GetChars(), item->type != discretes ? item->e.values[v].name : item->e.valuestrings[v].name.GetChars(),
DTA_Clean, true, DTA_ColorOverlay, overlay, TAG_DONE); DTA_CleanNoMove_1, true, DTA_ColorOverlay, overlay, TAG_DONE);
} }
} }
@ -1904,18 +1925,18 @@ void M_OptDrawer ()
value = item->a.cvar->GetGenericRep (CVAR_String); value = item->a.cvar->GetGenericRep (CVAR_String);
v = M_FindCurVal(value.String, item->e.enumvalues, (int)item->b.numvalues); v = M_FindCurVal(value.String, item->e.enumvalues, (int)item->b.numvalues);
screen->DrawText(SmallFont, ValueColor, indent + 14, y, v, DTA_Clean, true, TAG_DONE); screen->DrawText(SmallFont, ValueColor, indent + cursorspace, y, v, DTA_CleanNoMove_1, true, TAG_DONE);
} }
break; break;
case nochoice: case nochoice:
screen->DrawText (SmallFont, CR_GOLD, indent + 14, y, screen->DrawText (SmallFont, CR_GOLD, indent + cursorspace, y,
(item->e.values[(int)item->b.min]).name, DTA_Clean, true, TAG_DONE); (item->e.values[(int)item->b.min]).name, DTA_CleanNoMove_1, true, TAG_DONE);
break; break;
case joy_sens: case joy_sens:
value.Float = SELECTED_JOYSTICK->GetSensitivity(); value.Float = SELECTED_JOYSTICK->GetSensitivity();
M_DrawSlider (indent + 14, y + labelofs, item->b.min, item->c.max, value.Float, 1); M_DrawSlider (indent + cursorspace, y + labelofs, item->b.min, item->c.max, value.Float, 1);
break; break;
case joy_slider: case joy_slider:
@ -1928,29 +1949,29 @@ void M_OptDrawer ()
assert(item->e.joyslidernum == 1); assert(item->e.joyslidernum == 1);
value.Float = SELECTED_JOYSTICK->GetAxisDeadZone(item->a.joyselection); value.Float = SELECTED_JOYSTICK->GetAxisDeadZone(item->a.joyselection);
} }
M_DrawSlider (indent + 14, y + labelofs, item->b.min, item->c.max, fabs(value.Float), 3); M_DrawSlider (indent + cursorspace, y + labelofs, item->b.min, item->c.max, fabs(value.Float), 3);
break; break;
case joy_inverter: case joy_inverter:
assert(item->e.joyslidernum == 0); assert(item->e.joyslidernum == 0);
value.Float = SELECTED_JOYSTICK->GetAxisScale(item->a.joyselection); value.Float = SELECTED_JOYSTICK->GetAxisScale(item->a.joyselection);
screen->DrawText(SmallFont, ValueColor, indent + 14, y, screen->DrawText(SmallFont, ValueColor, indent + cursorspace, y,
(value.Float < 0) ? "Yes" : "No", (value.Float < 0) ? "Yes" : "No",
DTA_Clean, true, TAG_DONE); DTA_CleanNoMove_1, true, TAG_DONE);
break; break;
case slider: case slider:
value = item->a.cvar->GetGenericRep (CVAR_Float); value = item->a.cvar->GetGenericRep (CVAR_Float);
M_DrawSlider (indent + 14, y + labelofs, item->b.min, item->c.max, value.Float, 1); M_DrawSlider (indent + cursorspace, y + labelofs, item->b.min, item->c.max, value.Float, 1);
break; break;
case absslider: case absslider:
value = item->a.cvar->GetGenericRep (CVAR_Float); value = item->a.cvar->GetGenericRep (CVAR_Float);
M_DrawSlider (indent + 14, y + labelofs, item->b.min, item->c.max, fabs(value.Float), 1); M_DrawSlider (indent + cursorspace, y + labelofs, item->b.min, item->c.max, fabs(value.Float), 1);
break; break;
case intslider: case intslider:
M_DrawSlider (indent + 14, y + labelofs, item->b.min, item->c.max, item->a.fval, 0); M_DrawSlider (indent + cursorspace, y + labelofs, item->b.min, item->c.max, item->a.fval, 0);
break; break;
case control: case control:
@ -1960,12 +1981,12 @@ void M_OptDrawer ()
C_NameKeys (description, item->b.key1, item->c.key2); C_NameKeys (description, item->b.key1, item->c.key2);
if (description[0]) if (description[0])
{ {
M_DrawConText(CR_WHITE, indent + 14, y-1+labelofs, description); M_DrawConText(CR_WHITE, indent + cursorspace, y-1+labelofs, description);
} }
else else
{ {
screen->DrawText(SmallFont, CR_BLACK, indent + 14, y + labelofs, "---", screen->DrawText(SmallFont, CR_BLACK, indent + cursorspace, y + labelofs, "---",
DTA_Clean, true, TAG_DONE); DTA_CleanNoMove_1, true, TAG_DONE);
} }
} }
break; break;
@ -1973,9 +1994,9 @@ void M_OptDrawer ()
case colorpicker: case colorpicker:
{ {
int box_x, box_y; int box_x, box_y;
box_x = (indent - 35 - 160) * CleanXfac + screen->GetWidth()/2; box_x = indent - 35 * CleanXfac_1;
box_y = (y - ((gameinfo.gametype & GAME_Raven) ? 99 : 100)) * CleanYfac + screen->GetHeight()/2; box_y = (gameinfo.gametype & GAME_Raven) ? y - CleanYfac_1 : y;
screen->Clear (box_x, box_y, box_x + 32*CleanXfac, box_y + (fontheight-1)*CleanYfac, screen->Clear (box_x, box_y, box_x + 32*CleanXfac_1, box_y + fontheight-CleanYfac_1,
item->a.colorcvar->GetIndex(), 0); item->a.colorcvar->GetIndex(), 0);
} }
break; break;
@ -1984,12 +2005,12 @@ void M_OptDrawer ()
{ {
int box_x, box_y; int box_x, box_y;
int x1, p; int x1, p;
const int w = fontheight*CleanXfac; const int w = fontheight;
const int h = fontheight*CleanYfac; const int h = fontheight;
box_y = (y - 98) * CleanYfac + screen->GetHeight()/2; box_y = y - 2 * CleanYfac_1;
p = 0; p = 0;
box_x = (indent - 32 - 160) * CleanXfac + screen->GetWidth()/2; box_x = indent - 32 * CleanXfac_1;
for (x1 = 0, p = int(item->b.min * 16); x1 < 16; ++p, ++x1) for (x1 = 0, p = int(item->b.min * 16); x1 < 16; ++p, ++x1)
{ {
screen->Clear (box_x, box_y, box_x + w, box_y + h, p, 0); screen->Clear (box_x, box_y, box_x + w, box_y + h, p, 0);
@ -2044,7 +2065,7 @@ void M_OptDrawer ()
} }
screen->DrawText (SmallFont, ValueColor, screen->DrawText (SmallFont, ValueColor,
indent + 14, y, str, DTA_Clean, true, TAG_DONE); indent + cursorspace, y, str, DTA_CleanNoMove_1, true, TAG_DONE);
} }
break; break;
@ -2056,12 +2077,13 @@ void M_OptDrawer ()
i == CurrentItem && i == CurrentItem &&
(skullAnimCounter < 6 || menuactive == MENU_WaitKey)) (skullAnimCounter < 6 || menuactive == MENU_WaitKey))
{ {
M_DrawConText(CR_RED, indent + 3, y-1+labelofs, "\xd"); M_DrawConText(CR_RED, indent + 3 * CleanXfac_1, y-CleanYfac_1+labelofs, "\xd");
} }
} }
else else
{ {
char *str = NULL; char *str = NULL;
int colwidth = screen->GetWidth() / 3;
for (x = 0; x < 3; x++) for (x = 0; x < 3; x++)
{ {
@ -2078,13 +2100,13 @@ void M_OptDrawer ()
else else
color = CR_BRICK; //LabelColor; color = CR_BRICK; //LabelColor;
screen->DrawText (SmallFont, color, 104 * x + 20, y, str, DTA_Clean, true, TAG_DONE); screen->DrawText (SmallFont, color, colwidth * x + 20 * CleanXfac_1, y, str, DTA_CleanNoMove_1, true, TAG_DONE);
} }
} }
if (i == CurrentItem && ((item->a.selmode != -1 && (skullAnimCounter < 6 || menuactive == MENU_WaitKey)) || testingmode)) if (i == CurrentItem && ((item->a.selmode != -1 && (skullAnimCounter < 6 || menuactive == MENU_WaitKey)) || testingmode))
{ {
M_DrawConText(CR_RED, item->a.selmode * 104 + 8, y-1 + labelofs, "\xd"); M_DrawConText(CR_RED, item->a.selmode * colwidth + 8 * CleanXfac_1, y - CleanYfac_1 + labelofs, "\xd");
} }
} }
} }
@ -2095,11 +2117,11 @@ void M_OptDrawer ()
if (CanScrollUp) if (CanScrollUp)
{ {
M_DrawConText(CR_ORANGE, 3, ytop + labelofs, "\x1a"); M_DrawConText(CR_ORANGE, 3 * CleanXfac_1, ytop + labelofs, "\x1a");
} }
if (CanScrollDown) if (CanScrollDown)
{ {
M_DrawConText(CR_ORANGE, 3, y - 8 + labelofs, "\x1b"); M_DrawConText(CR_ORANGE, 3 * CleanXfac_1, y - 8*CleanYfac_1 + labelofs, "\x1b");
} }
if (flagsvar) if (flagsvar)
@ -2122,8 +2144,8 @@ void M_OptDrawer ()
} }
} }
screen->DrawText (SmallFont, ValueColor, screen->DrawText (SmallFont, ValueColor,
160 - (SmallFont->StringWidth (flagsblah) >> 1), 0, flagsblah, (screen->GetWidth() - SmallFont->StringWidth (flagsblah) * CleanXfac_1) / 2, 0, flagsblah,
DTA_Clean, true, TAG_DONE); DTA_CleanNoMove_1, true, TAG_DONE);
} }
} }
@ -2276,31 +2298,33 @@ void M_OptButtonHandler(EMenuKey key, bool repeat)
} }
if (CurrentItem < 0) if (CurrentItem < 0)
{ {
int maxitems, rowheight; int ytop, maxitems, rowheight;
// Figure out how many lines of text fit on the menu // Figure out how many lines of text fit on the menu
if (CurrentMenu->y != 0) if (CurrentMenu->y != 0)
{ {
maxitems = CurrentMenu->y; ytop = CurrentMenu->y;
} }
else if (BigFont && CurrentMenu->texttitle) else if (BigFont && CurrentMenu->texttitle)
{ {
maxitems = 15 + BigFont->GetHeight (); ytop = 15 + BigFont->GetHeight ();
} }
else else
{ {
maxitems = 15; ytop = 15;
} }
if (!(gameinfo.gametype & GAME_DoomChex)) if (!(gameinfo.gametype & GAME_DoomChex))
{ {
maxitems -= 2; ytop -= 2;
rowheight = 9; rowheight = 9;
} }
else else
{ {
rowheight = 8; rowheight = 8;
} }
maxitems = (200 - SmallFont->GetHeight () - maxitems) / rowheight + 1; ytop *= CleanYfac_1;
rowheight *= CleanYfac_1;
maxitems = (screen->GetHeight() - SmallFont->GetHeight() - ytop) / rowheight + 1;
CurrentMenu->scrollpos = MAX (0,CurrentMenu->numitems - maxitems + CurrentMenu->scrolltop); CurrentMenu->scrollpos = MAX (0,CurrentMenu->numitems - maxitems + CurrentMenu->scrolltop);
CurrentItem = CurrentMenu->numitems - 1; CurrentItem = CurrentMenu->numitems - 1;
@ -3008,16 +3032,16 @@ static void ColorPickerDrawer ()
DWORD oldColor = DWORD(*ColorPickerItems[0].a.colorcvar) | 0xFF000000; DWORD oldColor = DWORD(*ColorPickerItems[0].a.colorcvar) | 0xFF000000;
int x = screen->GetWidth()*2/3; int x = screen->GetWidth()*2/3;
int y = (15 + BigFont->GetHeight() + SmallFont->GetHeight()*5 - 90) * CleanYfac + screen->GetHeight()/2; int y = (15 + BigFont->GetHeight() + SmallFont->GetHeight()*5 - 10) * CleanYfac_1;
screen->Clear (x, y, x + 48*CleanXfac, y + 48*CleanYfac, -1, oldColor); screen->Clear (x, y, x + 48*CleanXfac_1, y + 48*CleanYfac_1, -1, oldColor);
screen->Clear (x + 48*CleanXfac, y, x + 48*2*CleanXfac, y + 48*CleanYfac, -1, newColor); screen->Clear (x + 48*CleanXfac_1, y, x + 48*2*CleanXfac_1, y + 48*CleanYfac_1, -1, newColor);
y += 49*CleanYfac; y += 49*CleanYfac_1;
screen->DrawText (SmallFont, CR_GRAY, x+(24-SmallFont->StringWidth("Old")/2)*CleanXfac, y, screen->DrawText (SmallFont, CR_GRAY, x+(24-SmallFont->StringWidth("Old")/2)*CleanXfac_1, y,
"Old", DTA_CleanNoMove, true, TAG_DONE); "Old", DTA_CleanNoMove_1, true, TAG_DONE);
screen->DrawText (SmallFont, CR_WHITE, x+(48+24-SmallFont->StringWidth("New")/2)*CleanXfac, y, screen->DrawText (SmallFont, CR_WHITE, x+(48+24-SmallFont->StringWidth("New")/2)*CleanXfac_1, y,
"New", DTA_CleanNoMove, true, TAG_DONE); "New", DTA_CleanNoMove_1, true, TAG_DONE);
} }
static void SetColorPickerSliders () static void SetColorPickerSliders ()
@ -3118,11 +3142,12 @@ static void DrawJoystickConfigMenuHeader()
{ {
FString joyname = SELECTED_JOYSTICK->GetName(); FString joyname = SELECTED_JOYSTICK->GetName();
screen->DrawText(BigFont, gameinfo.gametype & GAME_DoomChex ? CR_RED : CR_UNTRANSLATED, screen->DrawText(BigFont, gameinfo.gametype & GAME_DoomChex ? CR_RED : CR_UNTRANSLATED,
160-BigFont->StringWidth(CurrentMenu->texttitle)/2, 5, (screen->GetWidth() - BigFont->StringWidth(CurrentMenu->texttitle) * CleanXfac_1) / 2,
CurrentMenu->texttitle, DTA_Clean, true, TAG_DONE); 5 * CleanYfac_1,
CurrentMenu->texttitle, DTA_CleanNoMove_1, true, TAG_DONE);
screen->DrawText(SmallFont, gameinfo.gametype & GAME_DoomChex ? CR_RED : CR_UNTRANSLATED, screen->DrawText(SmallFont, gameinfo.gametype & GAME_DoomChex ? CR_RED : CR_UNTRANSLATED,
160-SmallFont->StringWidth(joyname)/2, 8 + BigFont->GetHeight(), (screen->GetWidth() - SmallFont->StringWidth(joyname) * CleanXfac_1) / 2, (8 + BigFont->GetHeight()) * CleanYfac_1,
joyname, DTA_Clean, true, TAG_DONE); joyname, DTA_CleanNoMove_1, true, TAG_DONE);
} }
static void UpdateJoystickConfigMenu(IJoystickConfig *joy) static void UpdateJoystickConfigMenu(IJoystickConfig *joy)

View file

@ -112,7 +112,7 @@ void DCeiling::Tick ()
m_Sector->SetTexture(sector_t::ceiling, m_Texture); m_Sector->SetTexture(sector_t::ceiling, m_Texture);
// fall through // fall through
default: default:
SN_StopSequence (m_Sector); SN_StopSequence (m_Sector, CHAN_CEILING);
Destroy (); Destroy ();
break; break;
} }
@ -145,7 +145,7 @@ void DCeiling::Tick ()
m_Sector->SetTexture(sector_t::ceiling, m_Texture); m_Sector->SetTexture(sector_t::ceiling, m_Texture);
// fall through // fall through
default: default:
SN_StopSequence (m_Sector); SN_StopSequence (m_Sector, CHAN_CEILING);
Destroy (); Destroy ();
break; break;
} }
@ -500,7 +500,7 @@ bool EV_CeilingCrushStop (int tag)
{ {
if (scan->m_Tag == tag && scan->m_Direction != 0) if (scan->m_Tag == tag && scan->m_Direction != 0)
{ {
SN_StopSequence (scan->m_Sector); SN_StopSequence (scan->m_Sector, CHAN_CEILING);
scan->m_OldDirection = scan->m_Direction; scan->m_OldDirection = scan->m_Direction;
scan->m_Direction = 0; // in-stasis; scan->m_Direction = 0; // in-stasis;
rtn = true; rtn = true;

View file

@ -133,7 +133,7 @@ void DDoor::Tick ()
if (res == pastdest) if (res == pastdest)
{ {
SN_StopSequence (m_Sector); SN_StopSequence (m_Sector, CHAN_CEILING);
switch (m_Type) switch (m_Type)
{ {
case doorRaise: case doorRaise:
@ -179,7 +179,7 @@ void DDoor::Tick ()
if (res == pastdest) if (res == pastdest)
{ {
SN_StopSequence (m_Sector); SN_StopSequence (m_Sector, CHAN_CEILING);
switch (m_Type) switch (m_Type)
{ {
case doorRaise: case doorRaise:

View file

@ -54,6 +54,7 @@ void P_NewChaseDir (AActor *actor);
AInventory *P_DropItem (AActor *source, const PClass *type, int special, int chance); AInventory *P_DropItem (AActor *source, const PClass *type, int special, int chance);
void P_TossItem (AActor *item); void P_TossItem (AActor *item);
bool P_LookForPlayers (AActor *actor, INTBOOL allaround, FLookExParams *params); bool P_LookForPlayers (AActor *actor, INTBOOL allaround, FLookExParams *params);
void A_Weave(AActor *self, int xyspeed, int zspeed, fixed_t xydist, fixed_t zdist);
DECLARE_ACTION(A_Look) DECLARE_ACTION(A_Look)
DECLARE_ACTION(A_Wander) DECLARE_ACTION(A_Wander)

View file

@ -126,7 +126,7 @@ void DFloor::Tick ()
if (res == pastdest) if (res == pastdest)
{ {
SN_StopSequence (m_Sector); SN_StopSequence (m_Sector, CHAN_FLOOR);
if (m_Type == buildStair) if (m_Type == buildStair)
m_Type = waitStair; m_Type = waitStair;
@ -530,7 +530,7 @@ bool EV_FloorCrushStop (int tag)
if (sec->floordata && sec->floordata->IsKindOf (RUNTIME_CLASS(DFloor)) && if (sec->floordata && sec->floordata->IsKindOf (RUNTIME_CLASS(DFloor)) &&
barrier_cast<DFloor *>(sec->floordata)->m_Type == DFloor::floorRaiseAndCrush) barrier_cast<DFloor *>(sec->floordata)->m_Type == DFloor::floorRaiseAndCrush)
{ {
SN_StopSequence (sec); SN_StopSequence (sec, CHAN_FLOOR);
sec->floordata->Destroy (); sec->floordata->Destroy ();
sec->floordata = NULL; sec->floordata = NULL;
} }
@ -959,7 +959,7 @@ void DElevator::Tick ()
if (res == pastdest) // if destination height acheived if (res == pastdest) // if destination height acheived
{ {
// make floor stop sound // make floor stop sound
SN_StopSequence (m_Sector); SN_StopSequence (m_Sector, CHAN_FLOOR);
m_Sector->floordata = NULL; //jff 2/22/98 m_Sector->floordata = NULL; //jff 2/22/98
m_Sector->ceilingdata = NULL; //jff 2/22/98 m_Sector->ceilingdata = NULL; //jff 2/22/98

View file

@ -396,6 +396,8 @@ void AActor::Die (AActor *source, AActor *inflictor)
// be revived by an Arch-Vile. Batman Doom needs this. // be revived by an Arch-Vile. Batman Doom needs this.
flags |= MF_CORPSE; flags |= MF_CORPSE;
} }
flags6 |= MF6_KILLED;
// [RH] Allow the death height to be overridden using metadata. // [RH] Allow the death height to be overridden using metadata.
fixed_t metaheight = 0; fixed_t metaheight = 0;
if (DamageType == NAME_Fire) if (DamageType == NAME_Fire)

View file

@ -312,13 +312,34 @@ void AActor::Serialize (FArchive &arc)
{ {
arc << DamageFactor; arc << DamageFactor;
} }
if (SaveVersion >= 2036) if (SaveVersion > 2036)
{ {
arc << weaveindex; arc << WeaveIndexXY << WeaveIndexZ;
} }
else else
{ {
weaveindex = special2; int index;
if (SaveVersion < 2036)
{
index = special2;
}
else
{
arc << index;
}
// A_BishopMissileWeave and A_CStaffMissileSlither stored the weaveXY
// value in different parts of the index.
if (this->IsKindOf(PClass::FindClass("BishopFX")))
{
WeaveIndexXY = index >> 16;
WeaveIndexZ = index;
}
else
{
WeaveIndexXY = index;
WeaveIndexZ = 0;
}
} }
// Skip past uservar array in old savegames // Skip past uservar array in old savegames

View file

@ -98,7 +98,7 @@ void DPillar::Tick ()
if (r == pastdest && s == pastdest) if (r == pastdest && s == pastdest)
{ {
SN_StopSequence (m_Sector); SN_StopSequence (m_Sector, CHAN_FLOOR);
Destroy (); Destroy ();
} }
else else

View file

@ -82,7 +82,7 @@ void DPlat::Tick ()
} }
else if (res == pastdest) else if (res == pastdest)
{ {
SN_StopSequence (m_Sector); SN_StopSequence (m_Sector, CHAN_FLOOR);
if (m_Type != platToggle) if (m_Type != platToggle)
{ {
m_Count = m_Wait; m_Count = m_Wait;
@ -121,7 +121,7 @@ void DPlat::Tick ()
if (res == pastdest) if (res == pastdest)
{ {
SN_StopSequence (m_Sector); SN_StopSequence (m_Sector, CHAN_FLOOR);
// if not an instant toggle, start waiting // if not an instant toggle, start waiting
if (m_Type != platToggle) //jff 3/14/98 toggle up down if (m_Type != platToggle) //jff 3/14/98 toggle up down
{ // is silent, instant, no waiting { // is silent, instant, no waiting

View file

@ -244,6 +244,8 @@ static void CopyPlayer (player_t *dst, player_t *src, const char *name)
// needs to come from the save for bots. // needs to come from the save for bots.
userinfo_t uibackup = dst->userinfo; userinfo_t uibackup = dst->userinfo;
int chasecam = dst->cheats & CF_CHASECAM; // Remember the chasecam setting int chasecam = dst->cheats & CF_CHASECAM; // Remember the chasecam setting
bool attackdown = dst->attackdown;
bool usedown = dst->usedown;
*dst = *src; *dst = *src;
dst->cheats |= chasecam; dst->cheats |= chasecam;
@ -270,6 +272,9 @@ static void CopyPlayer (player_t *dst, player_t *src, const char *name)
{ {
dst->mo->player = dst; dst->mo->player = dst;
} }
// These 2 variables may not be overwritten.
dst->attackdown = attackdown;
dst->usedown = usedown;
} }
static void SpawnExtraPlayers () static void SpawnExtraPlayers ()

View file

@ -466,6 +466,8 @@ bool P_Thing_Raise(AActor *thing)
thing->flags2 = info->flags2; thing->flags2 = info->flags2;
thing->flags3 = info->flags3; thing->flags3 = info->flags3;
thing->flags4 = info->flags4; thing->flags4 = info->flags4;
thing->flags5 = info->flags5;
thing->flags6 = info->flags6;
thing->health = info->health; thing->health = info->health;
thing->target = NULL; thing->target = NULL;
thing->lastenemy = NULL; thing->lastenemy = NULL;

View file

@ -222,6 +222,7 @@ player_t::player_t()
centering(0), centering(0),
turnticks(0), turnticks(0),
attackdown(0), attackdown(0),
usedown(0),
oldbuttons(0), oldbuttons(0),
health(0), health(0),
inventorytics(0), inventorytics(0),
@ -1399,10 +1400,12 @@ void P_CheckPlayerSprites()
{ {
int crouchspriteno; int crouchspriteno;
fixed_t defscaleY = mo->GetDefault()->scaleY; fixed_t defscaleY = mo->GetDefault()->scaleY;
fixed_t defscaleX = mo->GetDefault()->scaleX;
if (player->userinfo.skin != 0) if (player->userinfo.skin != 0 && !(player->mo->flags4 & MF4_NOSKIN))
{ {
defscaleY = skins[player->userinfo.skin].ScaleY; defscaleY = skins[player->userinfo.skin].ScaleY;
defscaleX = skins[player->userinfo.skin].ScaleX;
} }
// Set the crouch sprite // Set the crouch sprite
@ -1413,8 +1416,9 @@ void P_CheckPlayerSprites()
{ {
crouchspriteno = mo->crouchsprite; crouchspriteno = mo->crouchsprite;
} }
else if (mo->sprite == skins[player->userinfo.skin].sprite || else if (!(player->mo->flags4 & MF4_NOSKIN) &&
mo->sprite == skins[player->userinfo.skin].crouchsprite) (mo->sprite == skins[player->userinfo.skin].sprite ||
mo->sprite == skins[player->userinfo.skin].crouchsprite))
{ {
crouchspriteno = skins[player->userinfo.skin].crouchsprite; crouchspriteno = skins[player->userinfo.skin].crouchsprite;
} }
@ -1446,6 +1450,7 @@ void P_CheckPlayerSprites()
} }
mo->scaleY = defscaleY; mo->scaleY = defscaleY;
} }
mo->scaleX = defscaleX;
} }
} }
} }
@ -2283,10 +2288,15 @@ void P_PlayerThink (player_t *player)
} }
} }
// check for use // check for use
if ((cmd->ucmd.buttons & BT_USE) && !(player->oldbuttons & BT_USE)) if ((cmd->ucmd.buttons & BT_USE) && !player->usedown)
{ {
player->usedown = true;
P_UseLines (player); P_UseLines (player);
} }
else
{
player->usedown = false;
}
// Morph counter // Morph counter
if (player->morphTics) if (player->morphTics)
{ {

View file

@ -849,7 +849,7 @@ DSeqNode *SN_StartSequence (sector_t *sector, int chan, int sequence, seqtype_t
{ {
if (!nostop) if (!nostop)
{ {
SN_StopSequence (sector); SN_StopSequence (sector, chan);
} }
if (TwiddleSeqNum (sequence, type)) if (TwiddleSeqNum (sequence, type))
{ {
@ -963,9 +963,23 @@ void SN_StopSequence (AActor *actor)
SN_DoStop (actor); SN_DoStop (actor);
} }
void SN_StopSequence (sector_t *sector) void SN_StopSequence (sector_t *sector, int chan)
{ {
SN_DoStop (sector); DSeqNode *node;
for (node = DSeqNode::FirstSequence(); node; )
{
DSeqNode *next = node->NextSequence();
if (node->Source() == sector)
{
assert(node->IsKindOf(RUNTIME_CLASS(DSeqSectorNode)));
if ((static_cast<DSeqSectorNode *>(node)->Channel & 7) == chan)
{
node->StopAndDestroy ();
}
}
node = next;
}
} }
void SN_StopSequence (FPolyObj *poly) void SN_StopSequence (FPolyObj *poly)

View file

@ -86,7 +86,7 @@ DSeqNode *SN_StartSequence (sector_t *sec, int chan, FName seqname, int modenum)
DSeqNode *SN_StartSequence (FPolyObj *poly, int sequence, seqtype_t type, int modenum, bool nostop=false); DSeqNode *SN_StartSequence (FPolyObj *poly, int sequence, seqtype_t type, int modenum, bool nostop=false);
DSeqNode *SN_StartSequence (FPolyObj *poly, const char *name, int modenum); DSeqNode *SN_StartSequence (FPolyObj *poly, const char *name, int modenum);
void SN_StopSequence (AActor *mobj); void SN_StopSequence (AActor *mobj);
void SN_StopSequence (sector_t *sector); void SN_StopSequence (sector_t *sector, int chan);
void SN_StopSequence (FPolyObj *poly); void SN_StopSequence (FPolyObj *poly);
void SN_UpdateActiveSequences (void); void SN_UpdateActiveSequences (void);
ptrdiff_t SN_GetSequenceOffset (int sequence, SDWORD *sequencePtr); ptrdiff_t SN_GetSequenceOffset (int sequence, SDWORD *sequencePtr);

View file

@ -2306,7 +2306,10 @@ bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force)
} }
} }
if (!mus_playing.name.IsEmpty() && stricmp (mus_playing.name, musicname) == 0) if (!mus_playing.name.IsEmpty() &&
mus_playing.handle != NULL &&
stricmp (mus_playing.name, musicname) == 0 &&
mus_playing.handle->m_Looping == looping)
{ {
if (order != mus_playing.baseorder) if (order != mus_playing.baseorder)
{ {

View file

@ -3,5 +3,5 @@
// This file was automatically generated by the // This file was automatically generated by the
// updaterevision tool. Do not edit by hand. // updaterevision tool. Do not edit by hand.
#define ZD_SVN_REVISION_STRING "2037" #define ZD_SVN_REVISION_STRING "2047"
#define ZD_SVN_REVISION_NUMBER 2037 #define ZD_SVN_REVISION_NUMBER 2047

View file

@ -3019,6 +3019,58 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Quake)
P_StartQuake(self, 0, intensity, duration, damrad, tremrad, sound); P_StartQuake(self, 0, intensity, duration, damrad, tremrad, sound);
} }
//===========================================================================
//
// A_Weave
//
//===========================================================================
void A_Weave(AActor *self, int xyspeed, int zspeed, fixed_t xydist, fixed_t zdist)
{
fixed_t newX, newY;
int weaveXY, weaveZ;
int angle;
fixed_t dist;
weaveXY = self->WeaveIndexXY & 63;
weaveZ = self->WeaveIndexZ & 63;
angle = (self->angle + ANG90) >> ANGLETOFINESHIFT;
if (xydist != 0 && xyspeed != 0)
{
dist = FixedMul(FloatBobOffsets[weaveXY], xydist);
newX = self->x - FixedMul (finecosine[angle], dist);
newY = self->y - FixedMul (finesine[angle], dist);
weaveXY = (weaveXY + xyspeed) & 63;
dist = FixedMul(FloatBobOffsets[weaveXY], xydist);
newX += FixedMul (finecosine[angle], dist);
newY += FixedMul (finesine[angle], dist);
P_TryMove (self, newX, newY, true);
self->WeaveIndexXY = weaveXY;
}
if (zdist != 0 && zspeed != 0)
{
self->z -= FixedMul(FloatBobOffsets[weaveZ], zdist);
weaveZ = (weaveZ + zspeed) & 63;
self->z += FixedMul(FloatBobOffsets[weaveZ], zdist);
self->WeaveIndexZ = weaveZ;
}
}
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Weave)
{
ACTION_PARAM_START(4);
ACTION_PARAM_INT(xspeed, 0);
ACTION_PARAM_INT(yspeed, 1);
ACTION_PARAM_FIXED(xdist, 2);
ACTION_PARAM_FIXED(ydist, 3);
A_Weave(self, xspeed, yspeed, xdist, ydist);
}
//=========================================================================== //===========================================================================
// //
// A_LineEffect // A_LineEffect

View file

@ -905,10 +905,19 @@ DEFINE_PROPERTY(bouncecount, I, Actor)
//========================================================================== //==========================================================================
// //
//========================================================================== //==========================================================================
DEFINE_PROPERTY(weaveindex, I, Actor) DEFINE_PROPERTY(weaveindexXY, I, Actor)
{ {
PROP_INT_PARM(id, 0); PROP_INT_PARM(id, 0);
defaults->weaveindex = id; defaults->WeaveIndexXY = id;
}
//==========================================================================
//
//==========================================================================
DEFINE_PROPERTY(weaveindexZ, I, Actor)
{
PROP_INT_PARM(id, 0);
defaults->WeaveIndexZ = id;
} }
//========================================================================== //==========================================================================

View file

@ -59,6 +59,9 @@ int CleanXfac, CleanYfac;
// [RH] Effective screen sizes that the above scale values give you // [RH] Effective screen sizes that the above scale values give you
int CleanWidth, CleanHeight; int CleanWidth, CleanHeight;
// Above minus 1 (or 1, if they are already 1)
int CleanXfac_1, CleanYfac_1, CleanWidth_1, CleanHeight_1;
CVAR (Bool, hud_scale, false, CVAR_ARCHIVE); CVAR (Bool, hud_scale, false, CVAR_ARCHIVE);
// For routines that take RGB colors, cache the previous lookup in case there // For routines that take RGB colors, cache the previous lookup in case there
@ -425,6 +428,15 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, double x, double y, DWORD tag
} }
break; break;
case DTA_CleanNoMove_1:
boolval = va_arg(tags, INTBOOL);
if (boolval)
{
parms->destwidth = parms->texwidth * CleanXfac_1;
parms->destheight = parms->texheight * CleanYfac_1;
}
break;
case DTA_320x200: case DTA_320x200:
boolval = va_arg(tags, INTBOOL); boolval = va_arg(tags, INTBOOL);
if (boolval) if (boolval)

View file

@ -156,13 +156,23 @@ void STACK_ARGS DCanvas::DrawText (FFont *font, int normalcolor, int x, int y, c
ptrval = va_arg (tags, void*); ptrval = va_arg (tags, void*);
break; break;
case DTA_CleanNoMove_1:
boolval = va_arg (tags, INTBOOL);
if (boolval)
{
scalex = CleanXfac_1;
scaley = CleanYfac_1;
maxwidth = Width - (Width % scalex);
}
break;
case DTA_CleanNoMove: case DTA_CleanNoMove:
boolval = va_arg (tags, INTBOOL); boolval = va_arg (tags, INTBOOL);
if (boolval) if (boolval)
{ {
scalex = CleanXfac; scalex = CleanXfac;
scaley = CleanYfac; scaley = CleanYfac;
maxwidth = Width - (Width % CleanYfac); maxwidth = Width - (Width % scalex);
} }
break; break;

View file

@ -1398,6 +1398,11 @@ bool V_DoModeSetup (int width, int height, int bits)
assert(CleanWidth >= 320); assert(CleanWidth >= 320);
assert(CleanHeight >= 200); assert(CleanHeight >= 200);
CleanXfac_1 = MAX(CleanXfac - 1, 1);
CleanYfac_1 = MAX(CleanYfac - 1, 1);
CleanWidth_1 = width / CleanXfac_1;
CleanHeight_1 = height / CleanYfac_1;
DisplayWidth = width; DisplayWidth = width;
DisplayHeight = height; DisplayHeight = height;
DisplayBits = bits; DisplayBits = bits;

View file

@ -42,6 +42,7 @@
#include "c_cvars.h" #include "c_cvars.h"
extern int CleanWidth, CleanHeight, CleanXfac, CleanYfac; extern int CleanWidth, CleanHeight, CleanXfac, CleanYfac;
extern int CleanWidth_1, CleanHeight_1, CleanXfac_1, CleanYfac_1;
extern int DisplayWidth, DisplayHeight, DisplayBits; extern int DisplayWidth, DisplayHeight, DisplayBits;
bool V_DoModeSetup (int width, int height, int bits); bool V_DoModeSetup (int width, int height, int bits);
@ -79,6 +80,7 @@ enum
DTA_320x200, // bool: scale texture size and position to fit on a virtual 320x200 screen DTA_320x200, // bool: scale texture size and position to fit on a virtual 320x200 screen
DTA_Bottom320x200, // bool: same as DTA_320x200 but centers virtual screen on bottom for 1280x1024 targets DTA_Bottom320x200, // bool: same as DTA_320x200 but centers virtual screen on bottom for 1280x1024 targets
DTA_CleanNoMove, // bool: like DTA_Clean but does not reposition output position DTA_CleanNoMove, // bool: like DTA_Clean but does not reposition output position
DTA_CleanNoMove_1, // bool: like DTA_CleanNoMove, but uses Clean[XY]fac_1 instead
DTA_FlipX, // bool: flip image horizontally //FIXME: Does not work with DTA_Window(Left|Right) DTA_FlipX, // bool: flip image horizontally //FIXME: Does not work with DTA_Window(Left|Right)
DTA_ShadowColor, // color of shadow DTA_ShadowColor, // color of shadow
DTA_ShadowAlpha, // alpha of shadow DTA_ShadowAlpha, // alpha of shadow

View file

@ -19,7 +19,8 @@ ACTOR Actor native //: Thinker
Gravity 1 Gravity 1
DamageFactor 1.0 DamageFactor 1.0
PushFactor 0.25 PushFactor 0.25
WeaveIndex -1 WeaveIndexXY 0
WeaveIndexZ 16
// Variables for the expression evaluator // Variables for the expression evaluator
// NOTE: fixed_t and angle_t are only used here to ensure proper conversion // NOTE: fixed_t and angle_t are only used here to ensure proper conversion
@ -221,6 +222,7 @@ ACTOR Actor native //: Thinker
action native A_PlayerSkinCheck(state label); action native A_PlayerSkinCheck(state label);
action native A_BasicAttack(int meleedamage, sound meleesound, class<actor> missiletype, float missileheight); action native A_BasicAttack(int meleedamage, sound meleesound, class<actor> missiletype, float missileheight);
action native A_ThrowGrenade(class<Actor> itemtype, float zheight = 0, float xyvel = 0, float zvel = 0, bool useammo = true); action native A_ThrowGrenade(class<Actor> itemtype, float zheight = 0, float xyvel = 0, float zvel = 0, bool useammo = true);
action native A_Weave(int xspeed, int yspeed, float xdist, float ydist);
action native A_Recoil(float xyvel); action native A_Recoil(float xyvel);
action native A_JumpIfInTargetInventory(class<Inventory> itemtype, int amount, state label); action native A_JumpIfInTargetInventory(class<Inventory> itemtype, int amount, state label);