* Updated to ZDoom r3350:

- Fixed compilation with FMOD 4.38+. The removal of hardware voices and EAX was a fairly major change, so I'm making no provisions for using older FMOD DLLs when compiled with the 4.38 API. However, sound positioning is still broken like in 4.28, so you are recommended to continue building with 4.26. Also, the Freeverb-based DSP unit is no longer present in FMOD, so the underwater effect is currently unavailable when using 4.38 until I can figure out how to make it work with the SFX Reverb unit instead. (And on that topic, the Freeverb DSP was officially only for stereo outputs, so I really shouldn't have been using it in the first place.)
- Since I would like to eventually figure out the sound positioning issues with the FMODs, the following have been added:
  # snd_drawoutput now labels its outputs with the speakers they represent.
  # DCanvas::DrawTextA was added as an alias for DrawText, since the Windows headers #define DrawText to a Unicode/non-Unicode variant.
  # The loopsound console command was added to spawn an actor at the player's location and have it loop a sound infinitely.
  Hopefully I can figure it out. FMOD's 3D example works, so I assume the problem lies with my code, though I don't really know where to begin looking for the problem.
- Fixed: Line type 49 was wrong for all games. Fixed by adding a new Ceiling_CrushAndRaiseDist special.
- Fixed: If an episode skips the skill menu, it should also skip the confirm skill menu   if the default skill requests confirmation.
- Fixed: Episodes with NoSkillMenu defined had their own idea of default skill that differed   from episodes with skill menus (and completely ignored whichever skill is explicitly defined   as the default skill).
- Remove all restrictions on what you can do with tags as line special arguments in xlat. Something like 「(tag & 5) + (tag & 2) / 2」 is now a valid argument for a standard line translation.
- Added modulus to FParseContext/xlat.
- Fixed: Division of tag arguments for xlat was in the wrong order.
- Added more tag operators for xlat: * / & | ^
- Improve tag support for xlat: Any combination of arguments can now be tags, and you can add (or subtract) a constant to them. If you do wish to add a constant, tag must come first. e.g. tag+3 is good, but 3+tag will not work. (As a bonus, the parser is simpler, too.)
- Fixed: Totally freezing a player did not ignore crouch toggling.

git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@1283 b0f79afe-0144-0410-b225-9a4edf0717df
This commit is contained in:
gez 2012-02-20 12:02:36 +00:00
parent e90377ae9a
commit e6e6f45a91
27 changed files with 609 additions and 338 deletions

View file

@ -146,6 +146,7 @@ DEFINE_SPECIAL(Sector_Set3DFloor, 160, -1, -1, 5)
DEFINE_SPECIAL(Sector_SetContents, 161, -1, -1, 3) DEFINE_SPECIAL(Sector_SetContents, 161, -1, -1, 3)
// [RH] Begin new specials for ZDoom // [RH] Begin new specials for ZDoom
DEFINE_SPECIAL(Ceiling_CrushAndRaiseDist, 168, 3, 5, 5)
DEFINE_SPECIAL(Generic_Crusher2, 169, 5, 5, 5) DEFINE_SPECIAL(Generic_Crusher2, 169, 5, 5, 5)
DEFINE_SPECIAL(Sector_SetCeilingScale2, 170, 3, 3, 3) DEFINE_SPECIAL(Sector_SetCeilingScale2, 170, 3, 3, 3)
DEFINE_SPECIAL(Sector_SetFloorScale2, 171, 3, 3, 3) DEFINE_SPECIAL(Sector_SetFloorScale2, 171, 3, 3, 3)

View file

@ -2353,7 +2353,8 @@ void Net_DoCommand (int type, BYTE **stream, int player)
case DEM_CROUCH: case DEM_CROUCH:
if (gamestate == GS_LEVEL && players[player].mo != NULL && if (gamestate == GS_LEVEL && players[player].mo != NULL &&
players[player].health > 0 && !(players[player].oldbuttons & BT_JUMP)) players[player].health > 0 && !(players[player].oldbuttons & BT_JUMP) &&
!P_IsPlayerTotallyFrozen(&players[player]))
{ {
players[player].crouching = players[player].crouchdir < 0 ? 1 : -1; players[player].crouching = players[player].crouchdir < 0 ? 1 : -1;
} }

View file

@ -426,6 +426,8 @@ void P_CheckPlayerSprites();
#define CROUCHSPEED (FRACUNIT/12) #define CROUCHSPEED (FRACUNIT/12)
bool P_IsPlayerTotallyFrozen(const player_t *player);
// [GRB] Custom player classes // [GRB] Custom player classes
enum enum
{ {

View file

@ -671,6 +671,7 @@ void M_ActivateMenu(DMenu *menu);
void M_ClearMenus (); void M_ClearMenus ();
void M_ParseMenuDefs(); void M_ParseMenuDefs();
void M_StartupSkillMenu(FGameStartup *gs); void M_StartupSkillMenu(FGameStartup *gs);
int M_GetDefaultSkill();
void M_StartControlPanel (bool makeSound); void M_StartControlPanel (bool makeSound);
void M_SetMenu(FName menu, int param = -1); void M_SetMenu(FName menu, int param = -1);
void M_NotifyNewSave (const char *file, const char *title, bool okForQuicksave); void M_NotifyNewSave (const char *file, const char *title, bool okForQuicksave);

View file

@ -1235,7 +1235,7 @@ void M_CreateMenus()
//============================================================================= //=============================================================================
// //
// THe skill menu must be refeshed each time it starts up // The skill menu must be refeshed each time it starts up
// //
//============================================================================= //=============================================================================
extern int restart; extern int restart;
@ -1320,8 +1320,8 @@ void M_StartupSkillMenu(FGameStartup *gs)
FSkillInfo &skill = AllSkills[i]; FSkillInfo &skill = AllSkills[i];
FListMenuItem *li; FListMenuItem *li;
// Using a different name for skills that must be confirmed makes handling this easier. // Using a different name for skills that must be confirmed makes handling this easier.
FName action = skill.MustConfirm? NAME_StartgameConfirm : NAME_Startgame; FName action = (skill.MustConfirm && !AllEpisodes[gs->Episode].mNoSkill) ?
NAME_StartgameConfirm : NAME_Startgame;
FString *pItemText = NULL; FString *pItemText = NULL;
if (gs->PlayerClass != NULL) if (gs->PlayerClass != NULL)
{ {
@ -1345,7 +1345,7 @@ void M_StartupSkillMenu(FGameStartup *gs)
} }
if (AllEpisodes[gs->Episode].mNoSkill || AllSkills.Size() == 1) if (AllEpisodes[gs->Episode].mNoSkill || AllSkills.Size() == 1)
{ {
ld->mAutoselect = firstitem + MIN(2u, AllSkills.Size()-1); ld->mAutoselect = firstitem + M_GetDefaultSkill();
} }
else else
{ {
@ -1388,7 +1388,8 @@ fail:
FSkillInfo &skill = AllSkills[i]; FSkillInfo &skill = AllSkills[i];
FOptionMenuItem *li; FOptionMenuItem *li;
// Using a different name for skills that must be confirmed makes handling this easier. // Using a different name for skills that must be confirmed makes handling this easier.
const char *action = skill.MustConfirm? "StartgameConfirm" : "Startgame"; const char *action = (skill.MustConfirm && !AllEpisodes[gs->Episode].mNoSkill) ?
"StartgameConfirm" : "Startgame";
FString *pItemText = NULL; FString *pItemText = NULL;
if (gs->PlayerClass != NULL) if (gs->PlayerClass != NULL)
@ -1400,12 +1401,23 @@ fail:
if (!done) if (!done)
{ {
done = true; done = true;
od->mSelectedItem = M_GetDefaultSkill();
}
}
}
//=============================================================================
//
// Returns the default skill level.
//
//=============================================================================
int M_GetDefaultSkill()
{
int defskill = DefaultSkill; int defskill = DefaultSkill;
if ((unsigned int)defskill >= AllSkills.Size()) if ((unsigned int)defskill >= AllSkills.Size())
{ {
defskill = (AllSkills.Size() - 1) / 2; defskill = (AllSkills.Size() - 1) / 2;
} }
od->mSelectedItem = defskill; return defskill;
}
}
} }

View file

@ -133,6 +133,7 @@ void DCeiling::Tick ()
switch (m_Type) switch (m_Type)
{ {
case ceilCrushAndRaise: case ceilCrushAndRaise:
case ceilCrushAndRaiseDist:
m_Direction = -1; m_Direction = -1;
m_Speed = m_Speed1; m_Speed = m_Speed1;
if (!SN_IsMakingLoopingSound (m_Sector)) if (!SN_IsMakingLoopingSound (m_Sector))
@ -164,6 +165,7 @@ void DCeiling::Tick ()
switch (m_Type) switch (m_Type)
{ {
case ceilCrushAndRaise: case ceilCrushAndRaise:
case ceilCrushAndRaiseDist:
case ceilCrushRaiseAndStay: case ceilCrushRaiseAndStay:
m_Speed = m_Speed2; m_Speed = m_Speed2;
m_Direction = 1; m_Direction = 1;
@ -193,6 +195,7 @@ void DCeiling::Tick ()
switch (m_Type) switch (m_Type)
{ {
case ceilCrushAndRaise: case ceilCrushAndRaise:
case ceilCrushAndRaiseDist:
case ceilLowerAndCrush: case ceilLowerAndCrush:
case ceilLowerAndCrushDist: case ceilLowerAndCrushDist:
if (m_Speed1 == FRACUNIT && m_Speed2 == FRACUNIT) if (m_Speed1 == FRACUNIT && m_Speed2 == FRACUNIT)
@ -254,6 +257,7 @@ DCeiling *DCeiling::Create(sector_t *sec, DCeiling::ECeiling type, line_t *line,
switch (type) switch (type)
{ {
case ceilCrushAndRaise: case ceilCrushAndRaise:
case ceilCrushAndRaiseDist:
case ceilCrushRaiseAndStay: case ceilCrushRaiseAndStay:
ceiling->m_TopHeight = sec->ceilingplane.d; ceiling->m_TopHeight = sec->ceilingplane.d;
case ceilLowerAndCrush: case ceilLowerAndCrush:
@ -263,7 +267,7 @@ DCeiling *DCeiling::Create(sector_t *sec, DCeiling::ECeiling type, line_t *line,
{ {
targheight += 8*FRACUNIT; targheight += 8*FRACUNIT;
} }
else if (type == ceilLowerAndCrushDist) else if (type == ceilLowerAndCrushDist || type == ceilCrushAndRaiseDist)
{ {
targheight += height; targheight += height;
} }
@ -505,7 +509,7 @@ bool EV_DoCeiling (DCeiling::ECeiling type, line_t *line,
// Reactivate in-stasis ceilings...for certain types. // Reactivate in-stasis ceilings...for certain types.
// This restarts a crusher after it has been stopped // This restarts a crusher after it has been stopped
if (type == DCeiling::ceilCrushAndRaise) if (type == DCeiling::ceilCrushAndRaise || type == DCeiling::ceilCrushAndRaiseDist)
{ {
P_ActivateInStasisCeiling (tag); P_ActivateInStasisCeiling (tag);
} }

View file

@ -616,6 +616,12 @@ FUNC(LS_Ceiling_CrushAndRaiseA)
return EV_DoCeiling (DCeiling::ceilCrushAndRaise, ln, arg0, SPEED(arg1), SPEED(arg2), 0, arg3, 0, 0, CRUSHTYPE(arg4)); return EV_DoCeiling (DCeiling::ceilCrushAndRaise, ln, arg0, SPEED(arg1), SPEED(arg2), 0, arg3, 0, 0, CRUSHTYPE(arg4));
} }
FUNC(LS_Ceiling_CrushAndRaiseDist)
// Ceiling_CrushAndRaiseDist (tag, dist, speed, damage, crushtype)
{
return EV_DoCeiling (DCeiling::ceilCrushAndRaiseDist, ln, arg0, SPEED(arg2), SPEED(arg2), arg1*FRACUNIT, arg3, 0, 0, CRUSHTYPE(arg4));
}
FUNC(LS_Ceiling_CrushAndRaiseSilentA) FUNC(LS_Ceiling_CrushAndRaiseSilentA)
// Ceiling_CrushAndRaiseSilentA (tag, dnspeed, upspeed, damage, crushtype) // Ceiling_CrushAndRaiseSilentA (tag, dnspeed, upspeed, damage, crushtype)
{ {
@ -3248,13 +3254,13 @@ lnSpecFunc LineSpecials[256] =
/* 159 */ LS_NOP, // Sector_SetPlaneReflection in GZDoom /* 159 */ LS_NOP, // Sector_SetPlaneReflection in GZDoom
/* 160 */ LS_NOP, // Sector_Set3DFloor in GZDoom and Vavoom /* 160 */ LS_NOP, // Sector_Set3DFloor in GZDoom and Vavoom
/* 161 */ LS_NOP, // Sector_SetContents in GZDoom and Vavoom /* 161 */ LS_NOP, // Sector_SetContents in GZDoom and Vavoom
/* 162 */ LS_NOP, /* 162 */ LS_NOP, // Reserved Doom64 branch
/* 163 */ LS_NOP, /* 163 */ LS_NOP, // Reserved Doom64 branch
/* 164 */ LS_NOP, /* 164 */ LS_NOP, // Reserved Doom64 branch
/* 165 */ LS_NOP, /* 165 */ LS_NOP, // Reserved Doom64 branch
/* 166 */ LS_NOP, /* 166 */ LS_NOP, // Reserved Doom64 branch
/* 167 */ LS_NOP, /* 167 */ LS_NOP, // Reserved Doom64 branch
/* 168 */ LS_NOP, /* 168 */ LS_Ceiling_CrushAndRaiseDist,
/* 169 */ LS_Generic_Crusher2, /* 169 */ LS_Generic_Crusher2,
/* 170 */ LS_Sector_SetCeilingScale2, /* 170 */ LS_Sector_SetCeilingScale2,
/* 171 */ LS_Sector_SetFloorScale2, /* 171 */ LS_Sector_SetFloorScale2,

View file

@ -603,6 +603,7 @@ public:
ceilLowerInstant, ceilLowerInstant,
ceilRaiseInstant, ceilRaiseInstant,
ceilCrushAndRaise, ceilCrushAndRaise,
ceilCrushAndRaiseDist,
ceilLowerAndCrush, ceilLowerAndCrush,
ceilLowerAndCrushDist, ceilLowerAndCrushDist,
ceilCrushRaiseAndStay, ceilCrushRaiseAndStay,

View file

@ -2126,9 +2126,7 @@ void P_PlayerThink (player_t *player)
player->mo->flags &= ~MF_JUSTATTACKED; player->mo->flags &= ~MF_JUSTATTACKED;
} }
bool totallyfrozen = (player->cheats & CF_TOTALLYFROZEN || gamestate == GS_TITLELEVEL || bool totallyfrozen = P_IsPlayerTotallyFrozen(player);
(( level.flags2 & LEVEL2_FROZEN ) && ( player == NULL || !( player->cheats & CF_TIMEFREEZE )))
);
// [RH] Being totally frozen zeros out most input parameters. // [RH] Being totally frozen zeros out most input parameters.
if (totallyfrozen) if (totallyfrozen)
@ -2723,3 +2721,10 @@ void P_EnumPlayerColorSets(FName classname, TArray<int> *out)
} }
} }
bool P_IsPlayerTotallyFrozen(const player_t *player)
{
return
gamestate == GS_TITLELEVEL ||
player->cheats & CF_TOTALLYFROZEN ||
((level.flags2 & LEVEL2_FROZEN) && !(player->cheats & CF_TIMEFREEZE));
}

View file

@ -118,11 +118,6 @@ void P_TranslateLineDef (line_t *ld, maplinedef_t *mld)
if (linetrans != NULL && linetrans->special != 0) if (linetrans != NULL && linetrans->special != 0)
{ {
ld->special = linetrans->special; ld->special = linetrans->special;
ld->args[0] = linetrans->args[0];
ld->args[1] = linetrans->args[1];
ld->args[2] = linetrans->args[2];
ld->args[3] = linetrans->args[3];
ld->args[4] = linetrans->args[4];
ld->flags = flags | ((linetrans->flags & 0x1f) << 9); ld->flags = flags | ((linetrans->flags & 0x1f) << 9);
if (linetrans->flags & 0x20) ld->flags |= ML_FIRSTSIDEONLY; if (linetrans->flags & 0x20) ld->flags |= ML_FIRSTSIDEONLY;
@ -134,30 +129,37 @@ void P_TranslateLineDef (line_t *ld, maplinedef_t *mld)
{ {
ld->activation = SPAC_UseThrough; ld->activation = SPAC_UseThrough;
} }
switch (linetrans->flags & LINETRANS_TAGMASK) // Set special arguments.
FXlatExprState state;
state.tag = tag;
state.linetype = special;
for (int t = 0; t < LINETRANS_MAXARGS; ++t)
{ {
case LINETRANS_HAS2TAGS: // First two arguments are tags int arg = linetrans->args[t];
ld->args[1] = tag; int argop = (linetrans->flags >> (LINETRANS_TAGSHIFT + t*TAGOP_NUMBITS)) & TAGOP_MASK;
case LINETRANS_HASTAGAT1: // First argument is a tag
ld->args[0] = tag;
break;
case LINETRANS_HASTAGAT2: // Second argument is a tag switch (argop)
ld->args[1] = tag; {
case ARGOP_Const:
ld->args[t] = arg;
break; break;
case ARGOP_Tag:
case LINETRANS_HASTAGAT3: // Third argument is a tag ld->args[t] = tag;
ld->args[2] = tag;
break; break;
case ARGOP_Expr:
case LINETRANS_HASTAGAT4: // Fourth argument is a tag {
ld->args[3] = tag; int *xnode = &XlatExpressions[arg];
state.bIsConstant = true;
XlatExprEval[*xnode](&ld->args[t], xnode, &state);
}
break; break;
default:
case LINETRANS_HASTAGAT5: // Fifth argument is a tag assert(0);
ld->args[4] = tag; ld->args[t] = 0;
break; break;
} }
}
if ((ld->flags & ML_SECRET) && ld->activation & (SPAC_Use|SPAC_UseThrough)) if ((ld->flags & ML_SECRET) && ld->activation & (SPAC_Use|SPAC_UseThrough))
{ {
ld->flags &= ~ML_MONSTERSCANACTIVATE; ld->flags &= ~ML_MONSTERSCANACTIVATE;
@ -359,3 +361,132 @@ int P_TranslateSectorSpecial (int special)
return special | mask; return special | mask;
} }
static const int *Expr_Const(int *dest, const int *xnode, FXlatExprState *state)
{
*dest = xnode[-1];
return xnode - 2;
}
static const int *Expr_Tag(int *dest, const int *xnode, FXlatExprState *state)
{
*dest = state->tag;
state->bIsConstant = false;
return xnode - 1;
}
static const int *Expr_Add(int *dest, const int *xnode, FXlatExprState *state)
{
int op1, op2;
xnode = XlatExprEval[xnode[-1]](&op2, xnode-1, state);
xnode = XlatExprEval[xnode[0]](&op1, xnode, state);
*dest = op1 + op2;
return xnode;
}
static const int *Expr_Sub(int *dest, const int *xnode, FXlatExprState *state)
{
int op1, op2;
xnode = XlatExprEval[xnode[-1]](&op2, xnode-1, state);
xnode = XlatExprEval[xnode[0]](&op1, xnode, state);
*dest = op1 - op2;
return xnode;
}
static const int *Expr_Mul(int *dest, const int *xnode, FXlatExprState *state)
{
int op1, op2;
xnode = XlatExprEval[xnode[-1]](&op2, xnode-1, state);
xnode = XlatExprEval[xnode[0]](&op1, xnode, state);
*dest = op1 * op2;
return xnode;
}
static void Div0Check(int &op1, int &op2, const FXlatExprState *state)
{
if (op2 == 0)
{
Printf("Xlat: Division by 0 for line type %d\n", state->linetype);
// Set some safe values
op1 = 0;
op2 = 1;
}
}
static const int *Expr_Div(int *dest, const int *xnode, FXlatExprState *state)
{
int op1, op2;
xnode = XlatExprEval[xnode[-1]](&op2, xnode-1, state);
xnode = XlatExprEval[xnode[0]](&op1, xnode, state);
Div0Check(op1, op2, state);
*dest = op1 / op2;
return xnode;
}
static const int *Expr_Mod(int *dest, const int *xnode, FXlatExprState *state)
{
int op1, op2;
xnode = XlatExprEval[xnode[-1]](&op2, xnode-1, state);
xnode = XlatExprEval[xnode[0]](&op1, xnode, state);
Div0Check(op1, op2, state);
*dest = op1 % op2;
return xnode;
}
static const int *Expr_And(int *dest, const int *xnode, FXlatExprState *state)
{
int op1, op2;
xnode = XlatExprEval[xnode[-1]](&op2, xnode-1, state);
xnode = XlatExprEval[xnode[0]](&op1, xnode, state);
*dest = op1 & op2;
return xnode;
}
static const int *Expr_Or(int *dest, const int *xnode, FXlatExprState *state)
{
int op1, op2;
xnode = XlatExprEval[xnode[-1]](&op2, xnode-1, state);
xnode = XlatExprEval[xnode[0]](&op1, xnode, state);
*dest = op1 | op2;
return xnode;
}
static const int *Expr_Xor(int *dest, const int *xnode, FXlatExprState *state)
{
int op1, op2;
xnode = XlatExprEval[xnode[-1]](&op2, xnode-1, state);
xnode = XlatExprEval[xnode[0]](&op1, xnode, state);
*dest = op1 ^ op2;
return xnode;
}
static const int *Expr_Neg(int *dest, const int *xnode, FXlatExprState *state)
{
int op;
xnode = XlatExprEval[xnode[-1]](&op, xnode-1, state);
*dest = -op;
return xnode;
}
const int* (*XlatExprEval[XEXP_COUNT])(int *dest, const int *xnode, FXlatExprState *state) =
{
Expr_Const,
Expr_Tag,
Expr_Add,
Expr_Sub,
Expr_Mul,
Expr_Div,
Expr_Mod,
Expr_And,
Expr_Or,
Expr_Xor,
Expr_Neg
};

View file

@ -267,6 +267,7 @@ loop:
case '-': return TokenTrans[MINUS]; case '-': return TokenTrans[MINUS];
case '+': return TokenTrans[PLUS]; case '+': return TokenTrans[PLUS];
case '*': return TokenTrans[MULTIPLY]; case '*': return TokenTrans[MULTIPLY];
case '%': return TokenTrans[MODULUS];
case '(': return TokenTrans[LPAREN]; case '(': return TokenTrans[LPAREN];
case ')': return TokenTrans[RPAREN]; case ')': return TokenTrans[RPAREN];
case ',': return TokenTrans[COMMA]; case ',': return TokenTrans[COMMA];

View file

@ -47,6 +47,7 @@ enum
PLUS , PLUS ,
MULTIPLY , MULTIPLY ,
DIVIDE , DIVIDE ,
MODULUS ,
NUM , NUM ,
FLOATVAL , FLOATVAL ,
LPAREN , LPAREN ,
@ -78,6 +79,7 @@ enum
prefix##PLUS, \ prefix##PLUS, \
prefix##MULTIPLY, \ prefix##MULTIPLY, \
prefix##DIVIDE, \ prefix##DIVIDE, \
prefix##MODULUS, \
prefix##NUM, \ prefix##NUM, \
prefix##FLOATVAL, \ prefix##FLOATVAL, \
prefix##LPAREN, \ prefix##LPAREN, \

View file

@ -671,7 +671,7 @@ void drawquad(float x0, float y0, float x1, float y1, float x2, float y2, float
void printnum(int x, int y, int num) void printnum(int x, int y, int num)
{ {
char foo[16]; mysnprintf (foo, countof(foo), "%d", num); char foo[16]; mysnprintf (foo, countof(foo), "%d", num);
RenderTarget->DrawText (SmallFont, CR_WHITE, x, y, foo); RenderTarget->DrawText (SmallFont, CR_WHITE, x, y, foo, TAG_DONE);
} }
void drawpolymosttest() void drawpolymosttest()

View file

@ -2591,7 +2591,44 @@ CCMD (playsound)
{ {
if (argv.argc() > 1) if (argv.argc() > 1)
{ {
S_Sound (CHAN_AUTO | CHAN_UI, argv[1], 1.f, ATTN_NONE); FSoundID id = argv[1];
if (id == 0)
{
Printf("'%s' is not a sound\n", argv[1]);
}
else
{
S_Sound (CHAN_AUTO | CHAN_UI, id, 1.f, ATTN_NONE);
}
}
}
//==========================================================================
//
// CCMD loopsound
//
//==========================================================================
CCMD (loopsound)
{
if (players[consoleplayer].mo != NULL && !netgame && argv.argc() > 1)
{
FSoundID id = argv[1];
if (id == 0)
{
Printf("'%s' is not a sound\n", argv[1]);
}
else
{
AActor *icon = Spawn("SpeakerIcon", players[consoleplayer].mo->x,
players[consoleplayer].mo->y,
players[consoleplayer].mo->z + 32*FRACUNIT,
ALLOW_REPLACE);
if (icon != NULL)
{
S_Sound(icon, CHAN_BODY | CHAN_LOOP, id, 1.f, ATTN_IDLE);
}
}
} }
} }

View file

@ -63,6 +63,10 @@ extern HWND Window;
#include "cmdlib.h" #include "cmdlib.h"
#include "s_sound.h" #include "s_sound.h"
#if FMOD_VERSION > 0x42899 && FMOD_VERSION < 0x43800
#error You are trying to compile with an unsupported version of FMOD.
#endif
// MACROS ------------------------------------------------------------------ // MACROS ------------------------------------------------------------------
// killough 2/21/98: optionally use varying pitched sounds // killough 2/21/98: optionally use varying pitched sounds
@ -173,12 +177,12 @@ static const FEnumList OutputNames[] =
{ "ESD", FMOD_OUTPUTTYPE_ESD }, { "ESD", FMOD_OUTPUTTYPE_ESD },
#if FMOD_VERSION >= 0x43400 #if FMOD_VERSION >= 0x43400
{ "PulseAudio", FMOD_OUTPUTTYPE_PULSEAUDIO }, { "PulseAudio", FMOD_OUTPUTTYPE_PULSEAUDIO },
{ "Pulse", FMOD_OUTPUTTYPE_PULSEAUDIO },
#endif #endif
{ "SDL", 666 }, { "SDL", 666 },
// Mac // Mac
#if FMOD_VERSION < 0x43000 #if FMOD_VERSION < 0x43000
// Sound Manager support was removed sometime in the 4.29 line.
{ "Sound Manager", FMOD_OUTPUTTYPE_SOUNDMANAGER }, { "Sound Manager", FMOD_OUTPUTTYPE_SOUNDMANAGER },
#endif #endif
{ "Core Audio", FMOD_OUTPUTTYPE_COREAUDIO }, { "Core Audio", FMOD_OUTPUTTYPE_COREAUDIO },
@ -238,6 +242,9 @@ static const char *OpenStateNames[] =
"Streaming" "Streaming"
}; };
const FMODSoundRenderer::spk FMODSoundRenderer::SpeakerNames4[4] = { "L", "R", "BL", "BR" };
const FMODSoundRenderer::spk FMODSoundRenderer::SpeakerNamesMore[8] = { "L", "R", "C", "LFE", "BL", "BR", "SL", "SR" };
// CODE -------------------------------------------------------------------- // CODE --------------------------------------------------------------------
//========================================================================== //==========================================================================
@ -348,7 +355,7 @@ public:
Channel->setSpeakerMix(1, 1, 1, 1, 1, 1, 1, 1); Channel->setSpeakerMix(1, 1, 1, 1, 1, 1, 1, 1);
Channel->setVolume(volume); Channel->setVolume(volume);
// Ensure reverb is disabled. // Ensure reverb is disabled.
FMOD_REVERB_CHANNELPROPERTIES reverb = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; FMOD_REVERB_CHANNELPROPERTIES reverb = { 0, };
if (FMOD_OK == Channel->getReverbProperties(&reverb)) if (FMOD_OK == Channel->getReverbProperties(&reverb))
{ {
reverb.Room = -10000; reverb.Room = -10000;
@ -704,7 +711,11 @@ bool FMODSoundRenderer::Init()
} }
const char *wrongver = NULL; const char *wrongver = NULL;
#if FMOD_VERSION >= 0x43800
if (version < 0x43800)
#else
if (version < 0x42000) if (version < 0x42000)
#endif
{ {
wrongver = "an old"; wrongver = "an old";
} }
@ -842,7 +853,14 @@ bool FMODSoundRenderer::Init()
result = Sys->setDriver(driver); result = Sys->setDriver(driver);
} }
result = Sys->getDriver(&driver); result = Sys->getDriver(&driver);
#if FMOD_VERSION >= 0x43700
// We were built with an FMOD that only returns the control panel frequency
result = Sys->getDriverCaps(driver, &Driver_Caps, &Driver_MinFrequency, &speakermode);
Driver_MaxFrequency = Driver_MinFrequency;
#else
// We were built with an FMOD that returns a frequency range
result = Sys->getDriverCaps(driver, &Driver_Caps, &Driver_MinFrequency, &Driver_MaxFrequency, &speakermode); result = Sys->getDriverCaps(driver, &Driver_Caps, &Driver_MinFrequency, &Driver_MaxFrequency, &speakermode);
#endif
if (result != FMOD_OK) if (result != FMOD_OK)
{ {
Printf(TEXTCOLOR_BLUE"Could not ascertain driver capabilities. Some things may be weird. (Error %d)\n", result); Printf(TEXTCOLOR_BLUE"Could not ascertain driver capabilities. Some things may be weird. (Error %d)\n", result);
@ -871,7 +889,9 @@ bool FMODSoundRenderer::Init()
format = eval >= 0 ? FMOD_SOUND_FORMAT(eval) : FMOD_SOUND_FORMAT_PCM16; format = eval >= 0 ? FMOD_SOUND_FORMAT(eval) : FMOD_SOUND_FORMAT_PCM16;
eval = Enum_NumForName(ResamplerNames, snd_resampler); eval = Enum_NumForName(ResamplerNames, snd_resampler);
resampler = eval >= 0 ? FMOD_DSP_RESAMPLER(eval) : FMOD_DSP_RESAMPLER_LINEAR; resampler = eval >= 0 ? FMOD_DSP_RESAMPLER(eval) : FMOD_DSP_RESAMPLER_LINEAR;
samplerate = clamp<int>(snd_samplerate, Driver_MinFrequency, Driver_MaxFrequency); // These represented the frequency limits for hardware channels, which we never used anyway.
// samplerate = clamp<int>(snd_samplerate, Driver_MinFrequency, Driver_MaxFrequency);
samplerate = snd_samplerate;
if (samplerate == 0 || snd_samplerate == 0) if (samplerate == 0 || snd_samplerate == 0)
{ // Creative's ASIO drivers report the only supported frequency as 0! { // Creative's ASIO drivers report the only supported frequency as 0!
if (FMOD_OK != Sys->getSoftwareFormat(&samplerate, NULL, NULL, NULL, NULL, NULL)) if (FMOD_OK != Sys->getSoftwareFormat(&samplerate, NULL, NULL, NULL, NULL, NULL))
@ -922,7 +942,12 @@ bool FMODSoundRenderer::Init()
initflags = FMOD_INIT_NORMAL; initflags = FMOD_INIT_NORMAL;
if (snd_hrtf) if (snd_hrtf)
{ {
// These flags are the same thing, just with different names.
#ifdef FMOD_INIT_SOFTWARE_HRTF
initflags |= FMOD_INIT_SOFTWARE_HRTF; initflags |= FMOD_INIT_SOFTWARE_HRTF;
#else
initflags |= FMOD_INIT_HRTF_LOWPASS;
#endif
} }
if (snd_profile) if (snd_profile)
{ {
@ -1007,6 +1032,7 @@ bool FMODSoundRenderer::Init()
} }
// Create DSP units for underwater effect // Create DSP units for underwater effect
#if FMOD_VERSION < 0x43701
result = Sys->createDSPByType(FMOD_DSP_TYPE_LOWPASS, &WaterLP); result = Sys->createDSPByType(FMOD_DSP_TYPE_LOWPASS, &WaterLP);
if (result != FMOD_OK) if (result != FMOD_OK)
{ {
@ -1020,6 +1046,9 @@ bool FMODSoundRenderer::Init()
Printf(TEXTCOLOR_BLUE" Could not create underwater reverb unit. (Error %d)\n", result); Printf(TEXTCOLOR_BLUE" Could not create underwater reverb unit. (Error %d)\n", result);
} }
} }
#else
result = FMOD_ERR_UNSUPPORTED;
#endif
// Connect underwater DSP unit between PausableSFX and SFX groups, while // Connect underwater DSP unit between PausableSFX and SFX groups, while
// retaining the connection established by SfxGroup->addGroup(). // retaining the connection established by SfxGroup->addGroup().
@ -1066,6 +1095,7 @@ bool FMODSoundRenderer::Init()
WaterLP->setActive(false); WaterLP->setActive(false);
WaterLP->setParameter(FMOD_DSP_LOWPASS_CUTOFF, snd_waterlp); WaterLP->setParameter(FMOD_DSP_LOWPASS_CUTOFF, snd_waterlp);
WaterLP->setParameter(FMOD_DSP_LOWPASS_RESONANCE, 2); WaterLP->setParameter(FMOD_DSP_LOWPASS_RESONANCE, 2);
#if FMOD_VERSION < 0x43701
if (WaterReverb != NULL) if (WaterReverb != NULL)
{ {
FMOD::DSPConnection *dry; FMOD::DSPConnection *dry;
@ -1090,6 +1120,7 @@ bool FMODSoundRenderer::Init()
} }
} }
else else
#endif
{ {
result = sfx_head->addInput(WaterLP, NULL); result = sfx_head->addInput(WaterLP, NULL);
} }
@ -1209,7 +1240,6 @@ void FMODSoundRenderer::PrintStatus()
int driver; int driver;
int samplerate; int samplerate;
int numoutputchannels; int numoutputchannels;
int num2d, num3d, total;
unsigned int bufferlength; unsigned int bufferlength;
int numbuffers; int numbuffers;
@ -1233,12 +1263,6 @@ void FMODSoundRenderer::PrintStatus()
Printf ("Driver: "TEXTCOLOR_GREEN"%d"TEXTCOLOR_NORMAL" ("TEXTCOLOR_ORANGE"%s"TEXTCOLOR_NORMAL")\n", driver, name); Printf ("Driver: "TEXTCOLOR_GREEN"%d"TEXTCOLOR_NORMAL" ("TEXTCOLOR_ORANGE"%s"TEXTCOLOR_NORMAL")\n", driver, name);
DumpDriverCaps(Driver_Caps, Driver_MinFrequency, Driver_MaxFrequency); DumpDriverCaps(Driver_Caps, Driver_MinFrequency, Driver_MaxFrequency);
} }
if (FMOD_OK == Sys->getHardwareChannels(&num2d, &num3d, &total))
{
Printf (TEXTCOLOR_YELLOW "Hardware 2D channels: "TEXTCOLOR_GREEN"%d\n", num2d);
Printf (TEXTCOLOR_YELLOW "Hardware 3D channels: "TEXTCOLOR_GREEN"%d\n", num3d);
Printf (TEXTCOLOR_YELLOW "Total hardware channels: "TEXTCOLOR_GREEN"%d\n", total);
}
if (FMOD_OK == Sys->getSoftwareFormat(&samplerate, &format, &numoutputchannels, NULL, &resampler, NULL)) if (FMOD_OK == Sys->getSoftwareFormat(&samplerate, &format, &numoutputchannels, NULL, &resampler, NULL))
{ {
Printf (TEXTCOLOR_LIGHTBLUE "Software mixer sample rate: "TEXTCOLOR_GREEN"%d\n", samplerate); Printf (TEXTCOLOR_LIGHTBLUE "Software mixer sample rate: "TEXTCOLOR_GREEN"%d\n", samplerate);
@ -1276,15 +1300,6 @@ void FMODSoundRenderer::DumpDriverCaps(FMOD_CAPS caps, int minfrequency, int max
{ {
Printf("\n"); Printf("\n");
} }
if (caps & FMOD_CAPS_REVERB_EAX2) Printf(TEXTCOLOR_OLIVE " EAX2");
if (caps & FMOD_CAPS_REVERB_EAX3) Printf(TEXTCOLOR_OLIVE " EAX3");
if (caps & FMOD_CAPS_REVERB_EAX4) Printf(TEXTCOLOR_OLIVE " EAX4");
if (caps & FMOD_CAPS_REVERB_EAX5) Printf(TEXTCOLOR_OLIVE " EAX5");
if (caps & FMOD_CAPS_REVERB_I3DL2) Printf(TEXTCOLOR_OLIVE " I3DL2");
if (caps & (FMOD_CAPS_REVERB_EAX2 | FMOD_CAPS_REVERB_EAX3 | FMOD_CAPS_REVERB_EAX4 | FMOD_CAPS_REVERB_EAX5 | FMOD_CAPS_REVERB_I3DL2))
{
Printf("\n");
}
if (caps & FMOD_CAPS_REVERB_LIMITED) Printf("TEXTCOLOR_OLIVE Limited reverb\n"); if (caps & FMOD_CAPS_REVERB_LIMITED) Printf("TEXTCOLOR_OLIVE Limited reverb\n");
} }
@ -1689,7 +1704,7 @@ FISoundChannel *FMODSoundRenderer::StartSound(SoundHandle sfx, float vol, int pi
} }
if (flags & SNDF_NOREVERB) if (flags & SNDF_NOREVERB)
{ {
FMOD_REVERB_CHANNELPROPERTIES reverb = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; FMOD_REVERB_CHANNELPROPERTIES reverb = { 0, };
if (FMOD_OK == chan->getReverbProperties(&reverb)) if (FMOD_OK == chan->getReverbProperties(&reverb))
{ {
reverb.Room = -10000; reverb.Room = -10000;
@ -1809,7 +1824,7 @@ FISoundChannel *FMODSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener *
} }
if (flags & SNDF_NOREVERB) if (flags & SNDF_NOREVERB)
{ {
FMOD_REVERB_CHANNELPROPERTIES reverb = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; FMOD_REVERB_CHANNELPROPERTIES reverb = { 0, };
if (FMOD_OK == chan->getReverbProperties(&reverb)) if (FMOD_OK == chan->getReverbProperties(&reverb))
{ {
reverb.Room = -10000; reverb.Room = -10000;
@ -2180,7 +2195,7 @@ void FMODSoundRenderer::UpdateListener(SoundListener *listener)
{ {
DPrintf ("Reverb Environment %s\n", env->Name); DPrintf ("Reverb Environment %s\n", env->Name);
const_cast<ReverbContainer*>(env)->Modified = false; const_cast<ReverbContainer*>(env)->Modified = false;
Sys->setReverbProperties((FMOD_REVERB_PROPERTIES *)(&env->Properties)); SetSystemReverbProperties(&env->Properties);
PrevEnvironment = env; PrevEnvironment = env;
if (!SfxReverbHooked) if (!SfxReverbHooked)
@ -2567,23 +2582,60 @@ void FMODSoundRenderer::DrawWaveDebug(int mode)
const int window_height = 100; const int window_height = 100;
int window_size; int window_size;
int numoutchans; int numoutchans;
int y; int y, yy;
const spk *labels;
int labelcount;
if (FMOD_OK != Sys->getSoftwareFormat(NULL, NULL, &numoutchans, NULL, NULL, NULL)) if (FMOD_OK != Sys->getSoftwareFormat(NULL, NULL, &numoutchans, NULL, NULL, NULL))
{ {
return; return;
} }
// Decide on which set of labels to use.
labels = (numoutchans == 4) ? SpeakerNames4 : SpeakerNamesMore;
labelcount = MIN<int>(numoutchans, countof(SpeakerNamesMore));
// Scale all the channel windows so one group fits completely on one row, with // Scale all the channel windows so one group fits completely on one row, with
// 16 pixels of padding between each window. // 16 pixels of padding between each window.
window_size = (screen->GetWidth() - 16) / numoutchans - 16; window_size = (screen->GetWidth() - 16) / numoutchans - 16;
float *wavearray = (float*)alloca(MAX(SPECTRUM_SIZE,window_size)*sizeof(float)); float *wavearray = (float*)alloca(MAX(SPECTRUM_SIZE,window_size)*sizeof(float));
y = 16; y = 16;
y = DrawChannelGroupOutput(SfxGroup, wavearray, window_size, window_height, y, mode);
y = DrawChannelGroupOutput(MusicGroup, wavearray, window_size, window_height, y, mode >> 2); yy = DrawChannelGroupOutput(SfxGroup, wavearray, window_size, window_height, y, mode);
y = DrawSystemOutput(wavearray, window_size, window_height, y, mode >> 4); if (y != yy)
{
DrawSpeakerLabels(labels, yy-14, window_size, labelcount);
}
y = DrawChannelGroupOutput(MusicGroup, wavearray, window_size, window_height, yy, mode >> 2);
if (y != yy)
{
DrawSpeakerLabels(labels, y-14, window_size, labelcount);
}
yy = DrawSystemOutput(wavearray, window_size, window_height, y, mode >> 4);
if (y != yy)
{
DrawSpeakerLabels(labels, yy-14, window_size, labelcount);
}
}
//==========================================================================
//
// FMODSoundRenderer :: DrawSpeakerLabels
//
//==========================================================================
void FMODSoundRenderer::DrawSpeakerLabels(const spk *labels, int y, int width, int count)
{
if (labels == NULL)
{
return;
}
for (int i = 0, x = 16; i < count; ++i)
{
screen->DrawText(SmallFont, CR_LIGHTBLUE, x, y, labels[i], TAG_DONE);
x += width + 16;
}
} }
//========================================================================== //==========================================================================
@ -2716,7 +2768,7 @@ void FMODSoundRenderer::DrawWave(float *wavearray, int x, int y, int width, int
// Draw a box around the oscilloscope. // Draw a box around the oscilloscope.
screen->DrawLine(x - 1, y - 1, x + width, y - 1, -1, MAKEARGB(160, 0, 40, 200)); screen->DrawLine(x - 1, y - 1, x + width, y - 1, -1, MAKEARGB(160, 0, 40, 200));
screen->DrawLine(x + width + 1, y - 1, x + width, y + height, -1, MAKEARGB(160, 0, 40, 200)); screen->DrawLine(x + width, y - 1, x + width, y + height, -1, MAKEARGB(160, 0, 40, 200));
screen->DrawLine(x + width, y + height, x - 1, y + height, -1, MAKEARGB(160, 0, 40, 200)); screen->DrawLine(x + width, y + height, x - 1, y + height, -1, MAKEARGB(160, 0, 40, 200));
screen->DrawLine(x - 1, y + height, x - 1, y - 1, -1, MAKEARGB(160, 0, 40, 200)); screen->DrawLine(x - 1, y + height, x - 1, y - 1, -1, MAKEARGB(160, 0, 40, 200));
@ -2823,7 +2875,7 @@ void FMODSoundRenderer::DrawSpectrum(float *spectrumarray, int x, int y, int wid
// Draw a border and dark background for the spectrum. // Draw a border and dark background for the spectrum.
screen->DrawLine(x - 1, y - 1, x + width, y - 1, -1, MAKEARGB(160, 0, 40, 200)); screen->DrawLine(x - 1, y - 1, x + width, y - 1, -1, MAKEARGB(160, 0, 40, 200));
screen->DrawLine(x + width + 1, y - 1, x + width, y + height, -1, MAKEARGB(160, 0, 40, 200)); screen->DrawLine(x + width, y - 1, x + width, y + height, -1, MAKEARGB(160, 0, 40, 200));
screen->DrawLine(x + width, y + height, x - 1, y + height, -1, MAKEARGB(160, 0, 40, 200)); screen->DrawLine(x + width, y + height, x - 1, y + height, -1, MAKEARGB(160, 0, 40, 200));
screen->DrawLine(x - 1, y + height, x - 1, y - 1, -1, MAKEARGB(160, 0, 40, 200)); screen->DrawLine(x - 1, y + height, x - 1, y - 1, -1, MAKEARGB(160, 0, 40, 200));
screen->Dim(MAKERGB(0,0,0), 0.3f, x, y, width, height); screen->Dim(MAKERGB(0,0,0), 0.3f, x, y, width, height);
@ -2912,7 +2964,8 @@ short *FMODSoundRenderer::DecodeSample(int outlen, const void *coded, int sizeby
void FMODSoundRenderer::InitCreateSoundExInfo(FMOD_CREATESOUNDEXINFO *exinfo) const void FMODSoundRenderer::InitCreateSoundExInfo(FMOD_CREATESOUNDEXINFO *exinfo) const
{ {
#if FMOD_VERSION >= 0x42600 memset(exinfo, 0, sizeof(*exinfo));
#if FMOD_VERSION >= 0x42600 && FMOD_VERSION < 0x43800
if (ActiveFMODVersion < 0x42600) if (ActiveFMODVersion < 0x42600)
{ {
// This parameter was added for 4.26.00, and trying to pass it to older // This parameter was added for 4.26.00, and trying to pass it to older
@ -2924,5 +2977,47 @@ void FMODSoundRenderer::InitCreateSoundExInfo(FMOD_CREATESOUNDEXINFO *exinfo) co
{ {
exinfo->cbsize = sizeof(*exinfo); exinfo->cbsize = sizeof(*exinfo);
} }
memset((BYTE *)exinfo + sizeof(exinfo->cbsize), 0, exinfo->cbsize - sizeof(exinfo->cbsize));
} }
//==========================================================================
//
// FMODSoundRenderer :: SetSystemReverbProperties
//
// Set the global reverb properties.
//
//==========================================================================
FMOD_RESULT FMODSoundRenderer::SetSystemReverbProperties(const REVERB_PROPERTIES *props)
{
#if FMOD_VERSION < 0x43800
return Sys->setReverbProperties((const FMOD_REVERB_PROPERTIES *)props);
#else
// The reverb format changed when hardware mixing support was dropped, because
// all EAX-only properties were removed from the structure.
FMOD_REVERB_PROPERTIES fr;
fr.Instance = props->Instance;
fr.Environment = props->Environment;
fr.EnvDiffusion = props->EnvDiffusion;
fr.Room = props->Room;
fr.RoomHF = props->RoomHF;
fr.RoomLF = props->RoomLF;
fr.DecayTime = props->DecayTime;
fr.DecayHFRatio = props->DecayHFRatio;
fr.DecayLFRatio = props->DecayLFRatio;
fr.Reflections = props->Reflections;
fr.ReflectionsDelay = props->ReflectionsDelay;
fr.Reverb = props->Reverb;
fr.ReverbDelay = props->ReverbDelay;
fr.ModulationTime = props->ModulationTime;
fr.ModulationDepth = props->ModulationDepth;
fr.HFReference = props->HFReference;
fr.LFReference = props->LFReference;
fr.Diffusion = props->Diffusion;
fr.Density = props->Density;
fr.Flags = props->Flags;
return Sys->setReverbProperties(&fr);
#endif
}

View file

@ -81,6 +81,7 @@ private:
bool ReconnectSFXReverbUnit(); bool ReconnectSFXReverbUnit();
void InitCreateSoundExInfo(FMOD_CREATESOUNDEXINFO *exinfo) const; void InitCreateSoundExInfo(FMOD_CREATESOUNDEXINFO *exinfo) const;
FMOD_RESULT SetSystemReverbProperties(const REVERB_PROPERTIES *props);
bool Init (); bool Init ();
void Shutdown (); void Shutdown ();
@ -97,6 +98,10 @@ private:
int DrawSystemSpectrum(float *wavearray, int width, int height, int y, bool skip); int DrawSystemSpectrum(float *wavearray, int width, int height, int y, bool skip);
void DrawSpectrum(float *spectrumarray, int x, int y, int width, int height); void DrawSpectrum(float *spectrumarray, int x, int y, int width, int height);
typedef char spk[4];
static const spk SpeakerNames4[4], SpeakerNamesMore[8];
void DrawSpeakerLabels(const spk *labels, int y, int width, int count);
FMOD::System *Sys; FMOD::System *Sys;
FMOD::ChannelGroup *SfxGroup, *PausableSfx; FMOD::ChannelGroup *SfxGroup, *PausableSfx;
FMOD::ChannelGroup *MusicGroup; FMOD::ChannelGroup *MusicGroup;

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 "3340" #define ZD_SVN_REVISION_STRING "3350"
#define ZD_SVN_REVISION_NUMBER 3340 #define ZD_SVN_REVISION_NUMBER 3350

View file

@ -78,11 +78,11 @@ void STACK_ARGS DCanvas::DrawChar (FFont *font, int normalcolor, int x, int y, B
// //
// Write a string using the given font // Write a string using the given font
// //
void STACK_ARGS DCanvas::DrawText (FFont *font, int normalcolor, int x, int y, const char *string, ...) void DCanvas::DrawTextV(FFont *font, int normalcolor, int x, int y, const char *string, uint32 tag1, va_list taglist)
{ {
va_list tags;
DWORD tag;
INTBOOL boolval; INTBOOL boolval;
va_list tags;
uint32 tag;
int maxstrlen = INT_MAX; int maxstrlen = INT_MAX;
int w, maxwidth; int w, maxwidth;
@ -117,8 +117,12 @@ void STACK_ARGS DCanvas::DrawText (FFont *font, int normalcolor, int x, int y, c
maxwidth = Width; maxwidth = Width;
scalex = scaley = 1; scalex = scaley = 1;
va_start (tags, string); #ifndef NO_VA_COPY
tag = va_arg (tags, DWORD); va_copy(tags, taglist);
#else
tags = taglist;
#endif
tag = tag1;
while (tag != TAG_DONE) while (tag != TAG_DONE)
{ {
@ -203,7 +207,7 @@ void STACK_ARGS DCanvas::DrawText (FFont *font, int normalcolor, int x, int y, c
height = va_arg (tags, int); height = va_arg (tags, int);
break; break;
} }
tag = va_arg (tags, DWORD); tag = va_arg (tags, uint32);
} }
height *= scaley; height *= scaley;
@ -233,8 +237,12 @@ void STACK_ARGS DCanvas::DrawText (FFont *font, int normalcolor, int x, int y, c
if (NULL != (pic = font->GetChar (c, &w))) if (NULL != (pic = font->GetChar (c, &w)))
{ {
va_list taglist; #ifndef NO_VA_COPY
va_start (taglist, string); va_copy(tags, taglist);
#else
tags = taglist;
#endif
tag = tag1;
if (forcedwidth) if (forcedwidth)
{ {
w = forcedwidth; w = forcedwidth;
@ -242,20 +250,35 @@ void STACK_ARGS DCanvas::DrawText (FFont *font, int normalcolor, int x, int y, c
DTA_Translation, range, DTA_Translation, range,
DTA_DestWidth, forcedwidth, DTA_DestWidth, forcedwidth,
DTA_DestHeight, height, DTA_DestHeight, height,
TAG_MORE, &taglist); TAG_MORE, &tags);
} }
else else
{ {
DrawTexture (pic, cx, cy, DrawTexture (pic, cx, cy,
DTA_Translation, range, DTA_Translation, range,
TAG_MORE, &taglist); TAG_MORE, &tags);
} }
va_end (taglist); va_end (tags);
} }
cx += (w + kerning) * scalex; cx += (w + kerning) * scalex;
} }
} }
void STACK_ARGS DCanvas::DrawText (FFont *font, int normalcolor, int x, int y, const char *string, uint32 tag, ...)
{
va_list tags;
va_start(tags, tag);
DrawTextV(font, normalcolor, x, y, string, tag, tags);
}
// A synonym so that this can still be used in files that #include Windows headers
void STACK_ARGS DCanvas::DrawTextA (FFont *font, int normalcolor, int x, int y, const char *string, uint32 tag, ...)
{
va_list tags;
va_start(tags, tag);
DrawTextV(font, normalcolor, x, y, string, tag, tags);
}
// //
// Find string width using this font // Find string width using this font
// //

View file

@ -214,7 +214,11 @@ public:
void VirtualToRealCoordsInt(int &x, int &y, int &w, int &h, int vwidth, int vheight, bool vbottom=false, bool handleaspect=true) const; void VirtualToRealCoordsInt(int &x, int &y, int &w, int &h, int vwidth, int vheight, bool vbottom=false, bool handleaspect=true) const;
// 2D Text drawing // 2D Text drawing
void STACK_ARGS DrawText (FFont *font, int normalcolor, int x, int y, const char *string, ...); void STACK_ARGS DrawText (FFont *font, int normalcolor, int x, int y, const char *string, uint32 tag, ...);
#ifndef DrawText // See WinUser.h for the definition of DrawText as a macro
void STACK_ARGS DrawTextA (FFont *font, int normalcolor, int x, int y, const char *string, uint32 tag, ...);
#endif
void DrawTextV (FFont *font, int normalcolor, int x, int y, const char *string, uint32 tag, va_list tags);
void STACK_ARGS DrawChar (FFont *font, int normalcolor, int x, int y, BYTE character, ...); void STACK_ARGS DrawChar (FFont *font, int normalcolor, int x, int y, BYTE character, ...);
struct DrawParms struct DrawParms

View file

@ -57,6 +57,7 @@ DEFINE_TOKEN_TRANS(XLAT_)
static FString LastTranslator; static FString LastTranslator;
TAutoGrowArray<FLineTrans> SimpleLineTranslations; TAutoGrowArray<FLineTrans> SimpleLineTranslations;
TArray<int> XlatExpressions;
FBoomTranslator Boomish[MAX_BOOMISH]; FBoomTranslator Boomish[MAX_BOOMISH];
int NumBoomish; int NumBoomish;
TAutoGrowArray<FSectorTrans> SectorTranslations; TAutoGrowArray<FSectorTrans> SectorTranslations;
@ -67,9 +68,16 @@ FLineFlagTrans LineFlagTranslations[16];
struct SpecialArgs struct SpecialArgs
{ {
int addflags; int addflags;
int argcount;
int args[5]; int args[5];
}; };
struct SpecialArg
{
int arg;
ELineTransArgOp argop;
};
struct ListFilter struct ListFilter
{ {
WORD filter; WORD filter;
@ -101,6 +109,7 @@ struct XlatParseContext : public FParseContext
XlatParseContext(void *parser, ParseFunc parse, int *tt) XlatParseContext(void *parser, ParseFunc parse, int *tt)
: FParseContext(parser, parse, tt) : FParseContext(parser, parse, tt)
{ {
DefiningLineType = -1;
} }
//========================================================================== //==========================================================================
@ -145,6 +154,8 @@ struct XlatParseContext : public FParseContext
} }
return false; return false;
} }
int DefiningLineType;
}; };
#include "xlat_parser.c" #include "xlat_parser.c"
@ -159,6 +170,7 @@ struct XlatParseContext : public FParseContext
void P_ClearTranslator() void P_ClearTranslator()
{ {
SimpleLineTranslations.Clear(); SimpleLineTranslations.Clear();
XlatExpressions.Clear();
NumBoomish = 0; NumBoomish = 0;
SectorTranslations.Clear(); SectorTranslations.Clear();
SectorMasks.Clear(); SectorMasks.Clear();

View file

@ -4,16 +4,37 @@
#include "doomtype.h" #include "doomtype.h"
#include "tarray.h" #include "tarray.h"
enum ELineTransArgOp
{
ARGOP_Const,
ARGOP_Tag,
ARGOP_Expr,
TAGOP_NUMBITS = 2,
TAGOP_MASK = (1 << TAGOP_NUMBITS) - 1
};
enum enum
{ {
LINETRANS_HASTAGAT1 = (1<<6), // (tag, x, x, x, x) LINETRANS_MAXARGS = 5,
LINETRANS_HASTAGAT2 = (2<<6), // (x, tag, x, x, x) LINETRANS_TAGSHIFT = 30 - LINETRANS_MAXARGS * TAGOP_NUMBITS,
LINETRANS_HASTAGAT3 = (3<<6), // (x, x, tag, x, x) };
LINETRANS_HASTAGAT4 = (4<<6), // (x, x, x, tag, x)
LINETRANS_HASTAGAT5 = (5<<6), // (x, x, x, x, tag)
LINETRANS_HAS2TAGS = (7<<6), // (tag, tag, x, x, x) enum
LINETRANS_TAGMASK = (7<<6) {
XEXP_Const,
XEXP_Tag,
XEXP_Add,
XEXP_Sub,
XEXP_Mul,
XEXP_Div,
XEXP_Mod,
XEXP_And,
XEXP_Or,
XEXP_Xor,
XEXP_Neg,
XEXP_COUNT
}; };
struct FLineTrans struct FLineTrans
@ -86,12 +107,21 @@ struct FLineFlagTrans
bool ismask; bool ismask;
}; };
struct FXlatExprState
{
int linetype;
int tag;
bool bIsConstant;
};
extern TAutoGrowArray<FLineTrans> SimpleLineTranslations; extern TAutoGrowArray<FLineTrans> SimpleLineTranslations;
extern TArray<int> XlatExpressions;
extern FBoomTranslator Boomish[MAX_BOOMISH]; extern FBoomTranslator Boomish[MAX_BOOMISH];
extern int NumBoomish; extern int NumBoomish;
extern TAutoGrowArray<FSectorTrans> SectorTranslations; extern TAutoGrowArray<FSectorTrans> SectorTranslations;
extern TArray<FSectorMask> SectorMasks; extern TArray<FSectorMask> SectorMasks;
extern FLineFlagTrans LineFlagTranslations[16]; extern FLineFlagTrans LineFlagTranslations[16];
extern const int* (*XlatExprEval[XEXP_COUNT])(int *dest, const int *xnode, FXlatExprState *state);
#endif #endif

View file

@ -27,7 +27,7 @@ external_declaration ::= NOP.
%left XOR. %left XOR.
%left AND. %left AND.
%left MINUS PLUS. %left MINUS PLUS.
%left MULTIPLY DIVIDE. %left MULTIPLY DIVIDE MODULUS.
%left NEG. %left NEG.
%type exp {int} %type exp {int}
@ -35,7 +35,8 @@ exp(A) ::= NUM(B). { A = B.val; }
exp(A) ::= exp(B) PLUS exp(C). { A = B + C; } exp(A) ::= exp(B) PLUS exp(C). { A = B + C; }
exp(A) ::= exp(B) MINUS exp(C). { A = B - C; } exp(A) ::= exp(B) MINUS exp(C). { A = B - C; }
exp(A) ::= exp(B) MULTIPLY exp(C). { A = B * C; } exp(A) ::= exp(B) MULTIPLY exp(C). { A = B * C; }
exp(A) ::= exp(B) DIVIDE exp(C). { if (C != 0) A = B / C; else context->PrintError("Division by Zero"); } exp(A) ::= exp(B) DIVIDE exp(C). { if (C != 0) A = B / C; else context->PrintError("Division by zero"); }
exp(A) ::= exp(B) MODULUS exp(C). { if (C != 0) A = B % C; else context->PrintError("Division by zero"); }
exp(A) ::= exp(B) OR exp(C). { A = B | C; } exp(A) ::= exp(B) OR exp(C). { A = B | C; }
exp(A) ::= exp(B) AND exp(C). { A = B & C; } exp(A) ::= exp(B) AND exp(C). { A = B & C; }
exp(A) ::= exp(B) XOR exp(C). { A = B ^ C; } exp(A) ::= exp(B) XOR exp(C). { A = B ^ C; }
@ -88,15 +89,105 @@ single_enum ::= SYM(A) EQUALS exp(B).
// //
//========================================================================== //==========================================================================
linetype_declaration ::= exp(linetype) EQUALS exp(flags) COMMA exp(special) LPAREN special_args(arg) RPAREN. %type linetype_exp {int}
linetype_exp(Z) ::= exp(A).
{
Z = static_cast<XlatParseContext *>(context)->DefiningLineType = A;
}
linetype_declaration ::= linetype_exp(linetype) EQUALS exp(flags) COMMA exp(special) LPAREN special_args(arg) RPAREN.
{ {
SimpleLineTranslations.SetVal(linetype, SimpleLineTranslations.SetVal(linetype,
FLineTrans(special&0xffff, flags+arg.addflags, arg.args[0], arg.args[1], arg.args[2], arg.args[3], arg.args[4])); FLineTrans(special&0xffff, flags+arg.addflags, arg.args[0], arg.args[1], arg.args[2], arg.args[3], arg.args[4]));
static_cast<XlatParseContext *>(context)->DefiningLineType = -1;
} }
linetype_declaration ::= exp EQUALS exp COMMA SYM(S) LPAREN special_args RPAREN. linetype_declaration ::= linetype_exp EQUALS exp COMMA SYM(S) LPAREN special_args RPAREN.
{ {
Printf ("%s, line %d: %s is undefined\n", context->SourceFile, context->SourceLine, S.sym); Printf ("%s, line %d: %s is undefined\n", context->SourceFile, context->SourceLine, S.sym);
static_cast<XlatParseContext *>(context)->DefiningLineType = -1;
}
%type exp_with_tag {int}
exp_with_tag(A) ::= NUM(B). { XlatExpressions.Push(B.val); A = XlatExpressions.Push(XEXP_Const); }
exp_with_tag(A) ::= TAG. { A = XlatExpressions.Push(XEXP_Tag); }
exp_with_tag(A) ::= exp_with_tag PLUS exp_with_tag. { A = XlatExpressions.Push(XEXP_Add); }
exp_with_tag(A) ::= exp_with_tag MINUS exp_with_tag. { A = XlatExpressions.Push(XEXP_Sub); }
exp_with_tag(A) ::= exp_with_tag MULTIPLY exp_with_tag. { A = XlatExpressions.Push(XEXP_Mul); }
exp_with_tag(A) ::= exp_with_tag DIVIDE exp_with_tag. { A = XlatExpressions.Push(XEXP_Div); }
exp_with_tag(A) ::= exp_with_tag MODULUS exp_with_tag. { A = XlatExpressions.Push(XEXP_Mod); }
exp_with_tag(A) ::= exp_with_tag OR exp_with_tag. { A = XlatExpressions.Push(XEXP_Or); }
exp_with_tag(A) ::= exp_with_tag AND exp_with_tag. { A = XlatExpressions.Push(XEXP_And); }
exp_with_tag(A) ::= exp_with_tag XOR exp_with_tag. { A = XlatExpressions.Push(XEXP_Xor); }
exp_with_tag(A) ::= MINUS exp_with_tag. [NEG] { A = XlatExpressions.Push(XEXP_Neg); }
exp_with_tag(A) ::= LPAREN exp_with_tag(B) RPAREN. { A = B; }
%type special_arg {SpecialArg}
special_arg(Z) ::= exp_with_tag(A).
{
if (XlatExpressions[A] == XEXP_Tag)
{ // Store tags directly
Z.arg = 0;
Z.argop = ARGOP_Tag;
XlatExpressions.Delete(A);
}
else
{ // Try and evaluate it. If it's a constant, store it and erase the
// expression. Otherwise, store the index to the expression. We make
// no attempt to simplify non-constant expressions.
FXlatExprState state;
int val;
const int *endpt;
int *xnode;
state.linetype = static_cast<XlatParseContext *>(context)->DefiningLineType;
state.tag = 0;
state.bIsConstant = true;
xnode = &XlatExpressions[A];
endpt = XlatExprEval[*xnode](&val, xnode, &state);
if (state.bIsConstant)
{
Z.arg = val;
Z.argop = ARGOP_Const;
endpt++;
assert(endpt >= &XlatExpressions[0]);
XlatExpressions.Resize((unsigned)(endpt - &XlatExpressions[0]));
}
else
{
Z.arg = A;
Z.argop = ARGOP_Expr;
}
}
}
%type multi_special_arg {SpecialArgs}
multi_special_arg(Z) ::= special_arg(A).
{
Z.addflags = A.argop << LINETRANS_TAGSHIFT;
Z.argcount = 1;
Z.args[0] = A.arg;
Z.args[1] = 0;
Z.args[2] = 0;
Z.args[3] = 0;
Z.args[4] = 0;
}
multi_special_arg(Z) ::= multi_special_arg(A) COMMA special_arg(B).
{
Z = A;
if (Z.argcount < LINETRANS_MAXARGS)
{
Z.addflags |= B.argop << (LINETRANS_TAGSHIFT + Z.argcount * TAGOP_NUMBITS);
Z.args[Z.argcount] = B.arg;
Z.argcount++;
}
else if (Z.argcount++ == LINETRANS_MAXARGS)
{
context->PrintError("Line special has too many arguments\n");
}
} }
%type special_args {SpecialArgs} %type special_args {SpecialArgs}
@ -104,223 +195,16 @@ linetype_declaration ::= exp EQUALS exp COMMA SYM(S) LPAREN special_args RPAREN.
special_args(Z) ::= . /* empty */ special_args(Z) ::= . /* empty */
{ {
Z.addflags = 0; Z.addflags = 0;
Z.argcount = 0;
Z.args[0] = 0; Z.args[0] = 0;
Z.args[1] = 0; Z.args[1] = 0;
Z.args[2] = 0; Z.args[2] = 0;
Z.args[3] = 0; Z.args[3] = 0;
Z.args[4] = 0; Z.args[4] = 0;
} }
special_args(Z) ::= TAG. special_args(Z) ::= multi_special_arg(A).
{ {
Z.addflags = LINETRANS_HASTAGAT1; Z = A;
Z.args[0] = 0;
Z.args[1] = 0;
Z.args[2] = 0;
Z.args[3] = 0;
Z.args[4] = 0;
}
special_args(Z) ::= TAG COMMA exp(B).
{
Z.addflags = LINETRANS_HASTAGAT1;
Z.args[0] = 0;
Z.args[1] = B;
Z.args[2] = 0;
Z.args[3] = 0;
Z.args[4] = 0;
}
special_args(Z) ::= TAG COMMA exp(B) COMMA exp(C).
{
Z.addflags = LINETRANS_HASTAGAT1;
Z.args[0] = 0;
Z.args[1] = B;
Z.args[2] = C;
Z.args[3] = 0;
Z.args[4] = 0;
}
special_args(Z) ::= TAG COMMA exp(B) COMMA exp(C) COMMA exp(D).
{
Z.addflags = LINETRANS_HASTAGAT1;
Z.args[0] = 0;
Z.args[1] = B;
Z.args[2] = C;
Z.args[3] = D;
Z.args[4] = 0;
}
special_args(Z) ::= TAG COMMA exp(B) COMMA exp(C) COMMA exp(D) COMMA exp(E).
{
Z.addflags = LINETRANS_HASTAGAT1;
Z.args[0] = 0;
Z.args[1] = B;
Z.args[2] = C;
Z.args[3] = D;
Z.args[4] = E;
}
special_args(Z) ::= TAG COMMA TAG.
{
Z.addflags = LINETRANS_HAS2TAGS;
Z.args[0] = Z.args[1] = 0;
Z.args[2] = 0;
Z.args[3] = 0;
Z.args[4] = 0;
}
special_args(Z) ::= TAG COMMA TAG COMMA exp(C).
{
Z.addflags = LINETRANS_HAS2TAGS;
Z.args[0] = Z.args[1] = 0;
Z.args[2] = C;
Z.args[3] = 0;
Z.args[4] = 0;
}
special_args(Z) ::= TAG COMMA TAG COMMA exp(C) COMMA exp(D).
{
Z.addflags = LINETRANS_HAS2TAGS;
Z.args[0] = Z.args[1] = 0;
Z.args[2] = C;
Z.args[3] = D;
Z.args[4] = 0;
}
special_args(Z) ::= TAG COMMA TAG COMMA exp(C) COMMA exp(D) COMMA exp(E).
{
Z.addflags = LINETRANS_HAS2TAGS;
Z.args[0] = Z.args[1] = 0;
Z.args[2] = C;
Z.args[3] = D;
Z.args[4] = E;
}
special_args(Z) ::= exp(A).
{
Z.addflags = 0;
Z.args[0] = A;
Z.args[1] = 0;
Z.args[2] = 0;
Z.args[3] = 0;
Z.args[4] = 0;
}
special_args(Z) ::= exp(A) COMMA exp(B).
{
Z.addflags = 0;
Z.args[0] = A;
Z.args[1] = B;
Z.args[2] = 0;
Z.args[3] = 0;
Z.args[4] = 0;
}
special_args(Z) ::= exp(A) COMMA exp(B) COMMA exp(C).
{
Z.addflags = 0;
Z.args[0] = A;
Z.args[1] = B;
Z.args[2] = C;
Z.args[3] = 0;
Z.args[4] = 0;
}
special_args(Z) ::= exp(A) COMMA exp(B) COMMA exp(C) COMMA exp(D).
{
Z.addflags = 0;
Z.args[0] = A;
Z.args[1] = B;
Z.args[2] = C;
Z.args[3] = D;
Z.args[4] = 0;
}
special_args(Z) ::= exp(A) COMMA exp(B) COMMA exp(C) COMMA exp(D) COMMA exp(E).
{
Z.addflags = 0;
Z.args[0] = A;
Z.args[1] = B;
Z.args[2] = C;
Z.args[3] = D;
Z.args[4] = E;
}
special_args(Z) ::= exp(A) COMMA TAG.
{
Z.addflags = LINETRANS_HASTAGAT2;
Z.args[0] = A;
Z.args[1] = 0;
Z.args[2] = 0;
Z.args[3] = 0;
Z.args[4] = 0;
}
special_args(Z) ::= exp(A) COMMA TAG COMMA exp(C).
{
Z.addflags = LINETRANS_HASTAGAT2;
Z.args[0] = A;
Z.args[1] = 0;
Z.args[2] = C;
Z.args[3] = 0;
Z.args[4] = 0;
}
special_args(Z) ::= exp(A) COMMA TAG COMMA exp(C) COMMA exp(D).
{
Z.addflags = LINETRANS_HASTAGAT2;
Z.args[0] = A;
Z.args[1] = 0;
Z.args[2] = C;
Z.args[3] = D;
Z.args[4] = 0;
}
special_args(Z) ::= exp(A) COMMA TAG COMMA exp(C) COMMA exp(D) COMMA exp(E).
{
Z.addflags = LINETRANS_HASTAGAT2;
Z.args[0] = A;
Z.args[1] = 0;
Z.args[2] = C;
Z.args[3] = D;
Z.args[4] = E;
}
special_args(Z) ::= exp(A) COMMA exp(B) COMMA TAG.
{
Z.addflags = LINETRANS_HASTAGAT3;
Z.args[0] = A;
Z.args[1] = B;
Z.args[2] = 0;
Z.args[3] = 0;
Z.args[4] = 0;
}
special_args(Z) ::= exp(A) COMMA exp(B) COMMA TAG COMMA exp(D).
{
Z.addflags = LINETRANS_HASTAGAT3;
Z.args[0] = A;
Z.args[1] = B;
Z.args[2] = 0;
Z.args[3] = D;
Z.args[4] = 0;
}
special_args(Z) ::= exp(A) COMMA exp(B) COMMA TAG COMMA exp(D) COMMA exp(E).
{
Z.addflags = LINETRANS_HASTAGAT3;
Z.args[0] = A;
Z.args[1] = B;
Z.args[2] = 0;
Z.args[3] = D;
Z.args[4] = E;
}
special_args(Z) ::= exp(A) COMMA exp(B) COMMA exp(C) COMMA TAG.
{
Z.addflags = LINETRANS_HASTAGAT4;
Z.args[0] = A;
Z.args[1] = B;
Z.args[2] = C;
Z.args[3] = 0;
Z.args[4] = 0;
}
special_args(Z) ::= exp(A) COMMA exp(B) COMMA exp(C) COMMA TAG COMMA exp(E).
{
Z.addflags = LINETRANS_HASTAGAT4;
Z.args[0] = A;
Z.args[1] = B;
Z.args[2] = C;
Z.args[3] = 0;
Z.args[4] = E;
}
special_args(Z) ::= exp(A) COMMA exp(B) COMMA exp(C) COMMA exp(D) COMMA TAG.
{
Z.addflags = LINETRANS_HASTAGAT5;
Z.args[0] = A;
Z.args[1] = B;
Z.args[2] = C;
Z.args[3] = D;
Z.args[4] = 0;
} }
//========================================================================== //==========================================================================
@ -463,7 +347,7 @@ list_val(A) ::= exp(B) COLON exp(C).
maxlinespecial_def ::= MAXLINESPECIAL EQUALS exp(mx) SEMICOLON. maxlinespecial_def ::= MAXLINESPECIAL EQUALS exp(mx) SEMICOLON.
{ {
// Just kill all specials higher than the max. // Just kill all specials higher than the max.
// If the translator wants to redefine some later, just let it.s // If the translator wants to redefine some later, just let it.
SimpleLineTranslations.Resize(mx+1); SimpleLineTranslations.Resize(mx+1);
} }

View file

@ -68,7 +68,7 @@ ACTOR MapSpotGravity : MapSpot 9013
-NOGRAVITY -NOGRAVITY
} }
// Point Pushers --------------------------------------------------- // Point Pushers -----------------------------------------------------------
ACTOR PointPusher 5001 ACTOR PointPusher 5001
{ {
@ -110,7 +110,7 @@ ACTOR Gibs : RealGibs 24
ClearFlags ClearFlags
} }
// Needed for loading Build maps --------------------------------------- // Needed for loading Build maps -------------------------------------------
ACTOR CustomSprite 9988 native ACTOR CustomSprite 9988 native
{ {
@ -124,7 +124,7 @@ ACTOR CustomSprite 9988 native
} }
} }
// SwitchableDecoration: Activate and Deactivate change state --------------- // SwitchableDecoration: Activate and Deactivate change state --------------
ACTOR SwitchableDecoration native ACTOR SwitchableDecoration native
{ {
@ -135,7 +135,7 @@ ACTOR SwitchingDecoration : SwitchableDecoration native
{ {
} }
// Random spawner ----------------------------------------------------------- // Random spawner ----------------------------------------------------------
ACTOR RandomSpawner native ACTOR RandomSpawner native
{ {
@ -145,14 +145,14 @@ ACTOR RandomSpawner native
+THRUACTORS +THRUACTORS
} }
// Fast projectiles ----------------------------------------------------------- // Fast projectiles --------------------------------------------------------
ACTOR FastProjectile native ACTOR FastProjectile native
{ {
Projectile Projectile
} }
// Sector flag setter ----------------------------------------------------------- // Sector flag setter ------------------------------------------------------
ACTOR SectorFlagSetter 9041 native ACTOR SectorFlagSetter 9041 native
{ {
@ -161,3 +161,16 @@ ACTOR SectorFlagSetter 9041 native
+DONTSPLASH +DONTSPLASH
RenderStyle None RenderStyle None
} }
// Marker for sounds -------------------------------------------------------
ACTOR SpeakerIcon : Unknown
{
States
{
Spawn:
SPKR A -1 BRIGHT
Stop
}
Scale 0.125
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 525 B

View file

@ -48,7 +48,7 @@ include "xlat/defines.i"
46 = SHOOT|REP|MONST, Door_Open (tag, D_SLOW) 46 = SHOOT|REP|MONST, Door_Open (tag, D_SLOW)
47 = SHOOT, Plat_RaiseAndStayTx0 (tag, P_SLOW/2) 47 = SHOOT, Plat_RaiseAndStayTx0 (tag, P_SLOW/2)
48 = 0, Scroll_Texture_Left (SCROLL_UNIT) 48 = 0, Scroll_Texture_Left (SCROLL_UNIT)
49 = USE, Ceiling_CrushAndRaiseA (tag, C_SLOW, C_SLOW, 10) 49 = USE, Ceiling_CrushAndRaiseDist (tag, 8, C_SLOW, 10)
50 = USE, Door_Close (tag, D_SLOW) 50 = USE, Door_Close (tag, D_SLOW)
51 = USE, Exit_Secret (0) 51 = USE, Exit_Secret (0)
52 = WALK, Exit_Normal (0) 52 = WALK, Exit_Normal (0)

View file

@ -4,6 +4,7 @@ include "xlat/base.txt"
8 = WALK, Stairs_BuildUpDoom (tag, F_SLOW, 8) 8 = WALK, Stairs_BuildUpDoom (tag, F_SLOW, 8)
10 = WALK, Plat_DownWaitUpStayLip (tag, P_FAST, PLATWAIT, 0) 10 = WALK, Plat_DownWaitUpStayLip (tag, P_FAST, PLATWAIT, 0)
36 = WALK, Floor_LowerToHighest (tag, F_FAST, 136, 1) 36 = WALK, Floor_LowerToHighest (tag, F_FAST, 136, 1)
49 = USE, Ceiling_LowerAndCrush (tag, C_SLOW, 0, 2)
88 = WALK|REP, Plat_DownWaitUpStayLip (tag, P_FAST, PLATWAIT, 0) 88 = WALK|REP, Plat_DownWaitUpStayLip (tag, P_FAST, PLATWAIT, 0)
99 = 0, Scroll_Texture_Right (SCROLL_UNIT) 99 = 0, Scroll_Texture_Right (SCROLL_UNIT)
100 = WALK|REP, Door_Raise (tag, D_SLOW*3, VDOORWAIT) 100 = WALK|REP, Door_Raise (tag, D_SLOW*3, VDOORWAIT)

View file

@ -244,7 +244,7 @@ RetailOnly = 121
189 = USE, ACS_LockedExecute (0, 0, 189, tag, 13) 189 = USE, ACS_LockedExecute (0, 0, 189, tag, 13)
41 = USE, Ceiling_LowerToFloor (tag, C_SLOW) 41 = USE, Ceiling_LowerToFloor (tag, C_SLOW)
71 = USE, Floor_LowerToHighest (tag, F_FAST, 128) 71 = USE, Floor_LowerToHighest (tag, F_FAST, 128)
49 = USE, Ceiling_CrushAndRaiseA (tag, C_SLOW, C_SLOW, 10) 49 = USE, Ceiling_CrushAndRaiseDist (tag, 8, C_SLOW, 0, 2)
50 = USE, Door_Close (tag, D_SLOW) 50 = USE, Door_Close (tag, D_SLOW)
51 = USE, Teleport_EndGame (0) 51 = USE, Teleport_EndGame (0)
55 = USE, Floor_RaiseAndCrush (tag, F_SLOW, 10, 2) 55 = USE, Floor_RaiseAndCrush (tag, F_SLOW, 10, 2)