by Fishytza » Fri May 03, 2013 11:20 am
Greetings, folks. Here's something trivial and completely irrelevant.
Spoiler: tl;dr
Sorcerer1 and 2's DECORATE conversion is not 100% accurate, me thinks.
For a long time I've been bugged by the odd fact that (in ZDoom) certain sounds [wiki=Classes:Sorcerer2]D'Sparil[/wiki] and [wiki=Classes:Sorcerer1]his serpent[/wiki] make play on the entire map while others do not. But my ancient memory tells me he did in fact play all sounds (except pain) on the entire map. Specifically dsparil/attack and dsparil/active (and */sight when called through A_Look) always play on the entire map while the other dsparil/* sounds don't.
Instead of testing whether my memory was to be trusted by trying to play Heretic in DOSBox, I've decided to look at Heretic's source code and previous ZDoom revisions.
In Heretic's source code's P_ENEMY.C we have this:
Code: Select all
//----------------------------------------------------------------------------
//
// D'Sparil Sound Routines
//
//----------------------------------------------------------------------------
void A_SorZap(mobj_t *actor) {S_StartSound(NULL, sfx_sorzap);}
void A_SorRise(mobj_t *actor) {S_StartSound(NULL, sfx_sorrise);}
void A_SorDSph(mobj_t *actor) {S_StartSound(NULL, sfx_sordsph);}
void A_SorDExp(mobj_t *actor) {S_StartSound(NULL, sfx_sordexp);}
void A_SorDBon(mobj_t *actor) {S_StartSound(NULL, sfx_sordbon);}
void A_SorSightSnd(mobj_t *actor) {S_StartSound(NULL, sfx_sorsit);}
My point with the above code is that, if I understand correctly,
S_StartSound(NULL, *insert sound here*) is kind of like ZDoom's
S_Sound (self, *insert channel here*, *insert sound here*, 1, ATTN_NONE).
While
S_StartSound(*insert actor here*, *insert sound here*) is kind of like ZDoom's
S_Sound (self/*insert actor here*, *insert channel here*, *insert sound here*, 1, ATTN_NORM) (I came to this conclusion by comparing Heretic's A_Look in P_ENEMY.C with ZDoom's)
Looking back at previous revisions, trying the find the point when all Heretic actors were converted to DECORATE, I stumbled upon r1077(from 2008; 5 years ago).
At the bottom of r1077's a_dsparil.cpp we have this:
Code: Select all
//----------------------------------------------------------------------------
//
// D'Sparil Sound Routines
//
//----------------------------------------------------------------------------
void A_SorZap (AActor *actor) {S_Sound (actor, CHAN_BODY, "dsparil/zap", 1, ATTN_NONE);}
void A_SorRise (AActor *actor) {S_Sound (actor, CHAN_BODY, "dsparil/rise", 1, ATTN_NONE);}
void A_SorDSph (AActor *actor) {S_Sound (actor, CHAN_BODY, "dsparil/scream", 1, ATTN_NONE);}
void A_SorDExp (AActor *actor) {S_Sound (actor, CHAN_BODY, "dsparil/explode", 1, ATTN_NONE);}
void A_SorDBon (AActor *actor) {S_Sound (actor, CHAN_BODY, "dsparil/bones", 1, ATTN_NONE);}
void A_SorSightSnd (AActor *actor) {S_Sound (actor, CHAN_BODY, "dsparil/sight", 1, ATTN_NONE);}
Note: This piece of code is absent in r1078 and all subsequent revisions. (I think)
All of these were converted into generic code pointers with each (respectively) looking like this:
Code: Select all
A_PlaySoundEx("dsparil/zap", "body")
A_PlaySoundEx("dsparil/rise", "Body")
A_PlaySoundEx("dsparil/scream", "Body")
A_PlaySoundEx("dsparil/explode", "Body")
A_PlaySoundEx("dsparil/bones", "Body")
A_PlaySoundEx("dsparil/sight", "Body")
The default parameters for A_PlaySoundEx are as follows (from zdoom.pk3's actor.txt):
Code: Select all
action native A_PlaySoundEx(sound whattoplay, coerce name slot, bool looping = false, int attenuation = 0);
The default attenuation is 0, is it? Hmm.
thingdef_codeptr.cpp: (In the present, of course)
Code: Select all
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PlaySoundEx)
{
ACTION_PARAM_START(4);
ACTION_PARAM_SOUND(soundid, 0);
ACTION_PARAM_NAME(channel, 1);
ACTION_PARAM_BOOL(looping, 2);
ACTION_PARAM_INT(attenuation_raw, 3);
float attenuation;
switch (attenuation_raw)
{
case -1: attenuation = ATTN_STATIC; break; // drop off rapidly
default:
case 0: attenuation = ATTN_NORM; break; // normal
case 1:
case 2: attenuation = ATTN_NONE; break; // full volume
}
if (channel < NAME_Auto || channel > NAME_SoundSlot7)
{
channel = NAME_Auto;
}
if (!looping)
{
S_Sound (self, int(channel) - NAME_Auto, soundid, 1, attenuation);
}
else
{
if (!S_IsActorPlayingSomething (self, int(channel) - NAME_Auto, soundid))
{
S_Sound (self, (int(channel) - NAME_Auto) | CHAN_LOOP, soundid, 1, attenuation);
}
}
}
So attenuation 0 means ATTN_NORM, but it should be ATTN_NONE, no?
My proposed fix would be either this:
Code: Select all
A_PlaySoundEx("dsparil/zap", "body", false, 1)
A_PlaySoundEx("dsparil/rise", "Body", false, 1)
A_PlaySoundEx("dsparil/scream", "Body", false, 1)
A_PlaySoundEx("dsparil/explode", "Body", false, 1)
A_PlaySoundEx("dsparil/bones", "Body", false, 1)
A_PlaySoundEx("dsparil/sight", "Body", false, 1)
or this:
Code: Select all
A_PlaySound("dsparil/zap", CHAN_BODY, 1.0, false, ATTN_NONE)
A_PlaySound("dsparil/rise", CHAN_BODY, 1.0, false, ATTN_NONE)
A_PlaySound("dsparil/scream", CHAN_BODY, 1.0, false, ATTN_NONE)
A_PlaySound("dsparil/explode", CHAN_BODY, 1.0, false, ATTN_NONE)
A_PlaySound("dsparil/bones", CHAN_BODY, 1.0, false, ATTN_NONE)
A_PlaySound("dsparil/sight", CHAN_BODY, 1.0, false, ATTN_NONE)
Greetings, folks. Here's something trivial and completely irrelevant. :P
[spoiler=tl;dr]Sorcerer1 and 2's DECORATE conversion is not 100% accurate, me thinks.[/spoiler]
For a long time I've been bugged by the odd fact that (in ZDoom) certain sounds [wiki=Classes:Sorcerer2]D'Sparil[/wiki] and [wiki=Classes:Sorcerer1]his serpent[/wiki] make play on the entire map while others do not. But my ancient memory tells me he did in fact play all sounds (except pain) on the entire map. Specifically dsparil/attack and dsparil/active (and */sight when called through A_Look) always play on the entire map while the other dsparil/* sounds don't.
Instead of testing whether my memory was to be trusted by trying to play Heretic in DOSBox, I've decided to look at Heretic's source code and previous ZDoom revisions.
In Heretic's source code's P_ENEMY.C we have this:
[code]//----------------------------------------------------------------------------
//
// D'Sparil Sound Routines
//
//----------------------------------------------------------------------------
void A_SorZap(mobj_t *actor) {S_StartSound(NULL, sfx_sorzap);}
void A_SorRise(mobj_t *actor) {S_StartSound(NULL, sfx_sorrise);}
void A_SorDSph(mobj_t *actor) {S_StartSound(NULL, sfx_sordsph);}
void A_SorDExp(mobj_t *actor) {S_StartSound(NULL, sfx_sordexp);}
void A_SorDBon(mobj_t *actor) {S_StartSound(NULL, sfx_sordbon);}
void A_SorSightSnd(mobj_t *actor) {S_StartSound(NULL, sfx_sorsit);}[/code]
My point with the above code is that, if I understand correctly, [b]S_StartSound(NULL, *insert sound here*)[/b] is kind of like ZDoom's [b]S_Sound (self, *insert channel here*, *insert sound here*, 1, ATTN_NONE)[/b].
While [b]S_StartSound(*insert actor here*, *insert sound here*)[/b] is kind of like ZDoom's [b]S_Sound (self/*insert actor here*, *insert channel here*, *insert sound here*, 1, ATTN_NORM)[/b] (I came to this conclusion by comparing Heretic's A_Look in P_ENEMY.C with ZDoom's)
Looking back at previous revisions, trying the find the point when all Heretic actors were converted to DECORATE, I stumbled upon r1077(from 2008; 5 years ago).
At the bottom of r1077's a_dsparil.cpp we have this:
[code]//----------------------------------------------------------------------------
//
// D'Sparil Sound Routines
//
//----------------------------------------------------------------------------
void A_SorZap (AActor *actor) {S_Sound (actor, CHAN_BODY, "dsparil/zap", 1, ATTN_NONE);}
void A_SorRise (AActor *actor) {S_Sound (actor, CHAN_BODY, "dsparil/rise", 1, ATTN_NONE);}
void A_SorDSph (AActor *actor) {S_Sound (actor, CHAN_BODY, "dsparil/scream", 1, ATTN_NONE);}
void A_SorDExp (AActor *actor) {S_Sound (actor, CHAN_BODY, "dsparil/explode", 1, ATTN_NONE);}
void A_SorDBon (AActor *actor) {S_Sound (actor, CHAN_BODY, "dsparil/bones", 1, ATTN_NONE);}
void A_SorSightSnd (AActor *actor) {S_Sound (actor, CHAN_BODY, "dsparil/sight", 1, ATTN_NONE);}[/code]
Note: This piece of code is absent in r1078 and all subsequent revisions. (I think)
All of these were converted into generic code pointers with each (respectively) looking like this:
[code]A_PlaySoundEx("dsparil/zap", "body")
A_PlaySoundEx("dsparil/rise", "Body")
A_PlaySoundEx("dsparil/scream", "Body")
A_PlaySoundEx("dsparil/explode", "Body")
A_PlaySoundEx("dsparil/bones", "Body")
A_PlaySoundEx("dsparil/sight", "Body")[/code]
The default parameters for A_PlaySoundEx are as follows (from zdoom.pk3's actor.txt):
[code]action native A_PlaySoundEx(sound whattoplay, coerce name slot, bool looping = false, int attenuation = 0);[/code]
The default attenuation is 0, is it? Hmm.
thingdef_codeptr.cpp: (In the present, of course)
[code]DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PlaySoundEx)
{
ACTION_PARAM_START(4);
ACTION_PARAM_SOUND(soundid, 0);
ACTION_PARAM_NAME(channel, 1);
ACTION_PARAM_BOOL(looping, 2);
ACTION_PARAM_INT(attenuation_raw, 3);
float attenuation;
switch (attenuation_raw)
{
case -1: attenuation = ATTN_STATIC; break; // drop off rapidly
default:
case 0: attenuation = ATTN_NORM; break; // normal
case 1:
case 2: attenuation = ATTN_NONE; break; // full volume
}
if (channel < NAME_Auto || channel > NAME_SoundSlot7)
{
channel = NAME_Auto;
}
if (!looping)
{
S_Sound (self, int(channel) - NAME_Auto, soundid, 1, attenuation);
}
else
{
if (!S_IsActorPlayingSomething (self, int(channel) - NAME_Auto, soundid))
{
S_Sound (self, (int(channel) - NAME_Auto) | CHAN_LOOP, soundid, 1, attenuation);
}
}
}[/code]
So attenuation 0 means ATTN_NORM, but it should be ATTN_NONE, no?
My proposed fix would be either this:
[code]A_PlaySoundEx("dsparil/zap", "body", false, 1)
A_PlaySoundEx("dsparil/rise", "Body", false, 1)
A_PlaySoundEx("dsparil/scream", "Body", false, 1)
A_PlaySoundEx("dsparil/explode", "Body", false, 1)
A_PlaySoundEx("dsparil/bones", "Body", false, 1)
A_PlaySoundEx("dsparil/sight", "Body", false, 1)[/code]
or this:
[code]A_PlaySound("dsparil/zap", CHAN_BODY, 1.0, false, ATTN_NONE)
A_PlaySound("dsparil/rise", CHAN_BODY, 1.0, false, ATTN_NONE)
A_PlaySound("dsparil/scream", CHAN_BODY, 1.0, false, ATTN_NONE)
A_PlaySound("dsparil/explode", CHAN_BODY, 1.0, false, ATTN_NONE)
A_PlaySound("dsparil/bones", CHAN_BODY, 1.0, false, ATTN_NONE)
A_PlaySound("dsparil/sight", CHAN_BODY, 1.0, false, ATTN_NONE)[/code]