Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for spellcast command's -x flag for all spells #293

Open
wants to merge 19 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
13421bd
SpellsLvl01: add support for -x spellcast flag
meszaros-lajos-gyorgy Oct 13, 2023
0d1ad32
SpellsLvl02: extract conditions that check spellcasts' -x flag into v…
meszaros-lajos-gyorgy Oct 13, 2023
1721114
SpellsLvl03: add support for -x spellcast flag
meszaros-lajos-gyorgy Oct 13, 2023
b54b528
Spells: Prevent loop sounds of spells with spellcast -x flag
meszaros-lajos-gyorgy Oct 13, 2023
81a1934
SpellsLvl04: Add support for -x spellcast flag
meszaros-lajos-gyorgy Oct 13, 2023
8de7c0c
SpellsLvl01: Wrap more sound related functions with checks for spellc…
meszaros-lajos-gyorgy Oct 13, 2023
cfa4083
SpellsLvl02: Wrap more sound related functions with checks for spellc…
meszaros-lajos-gyorgy Oct 13, 2023
a63450d
SpellsLvl03: Wrap more sound related functions with checks for spellc…
meszaros-lajos-gyorgy Oct 13, 2023
d12d6d0
SpellsLvl05: Wrap more sound related functions with checks for spellc…
meszaros-lajos-gyorgy Oct 14, 2023
9953856
SpellsLvl06: Wrap sound related functions with checks for spellcast -…
meszaros-lajos-gyorgy Oct 14, 2023
af9cf90
SpellsLvl07: Wrap sound related functions with checks for spellcast -…
meszaros-lajos-gyorgy Oct 14, 2023
bf23d43
SpellsLvl01: Remove extra space after if keyword
meszaros-lajos-gyorgy Oct 14, 2023
11dca3a
SpellsLvl08: Wrap sound related functions with checks for spellcast -…
meszaros-lajos-gyorgy Oct 14, 2023
70fa40d
SpellsLvl09: Wrap sound related functions with checks for spellcast -…
meszaros-lajos-gyorgy Oct 14, 2023
9256ffb
SpellsLvl10: Wrap sound related functions with checks for spellcast -…
meszaros-lajos-gyorgy Oct 14, 2023
07e16a5
Spells: Simplify emitsSound conditions
meszaros-lajos-gyorgy Oct 15, 2023
31551cf
Spell: Extract emitsSound's logic into a method
meszaros-lajos-gyorgy Oct 15, 2023
2736b66
spells: Restore whitespace
meszaros-lajos-gyorgy Oct 15, 2023
cef5377
spells: Restore whitespace
meszaros-lajos-gyorgy Oct 15, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 59 additions & 22 deletions src/game/magic/spells/SpellsLvl01.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,38 +56,48 @@ void MagicSightSpell::Launch() {
m_hasDuration = m_launchDuration >= 0;
m_duration = m_hasDuration ? m_launchDuration : 0;

ARX_SOUND_PlaySFX(g_snd.SPELL_VISION_START, &m_caster_pos);
bool emitsSound = !(m_flags & SPELLCAST_FLAG_NOSOUND);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this bit flag magic could be moved to a macro or function instead. makes it easier to understand

bool emitsSound = GET_EMITS_SOUND(m_flags);

also removes code repetition

Copy link
Contributor

@bsxf-47 bsxf-47 Oct 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a member function would look much cleaner than a macro. I lean towards keeping the flag checks as they are, they are fairly clear.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is a double negation in there (NO and !) so they are much harder to read than "getEmitsSound"

a macro would mean no extra call to a function for such a simple operation

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I'm concerned, macros are just preprocessor crutches. I wouldn't worry about efficiency as the function would probably get inlined, and this is not a hot codepath anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also lean towards a method in the Spell class as opposed to adding a macro because macros are leaning the codebase back towards C and low level constructs while a method could be migrated more easily to a more modern language if needed.


if(emitsSound) {
ARX_SOUND_PlaySFX(g_snd.SPELL_VISION_START, &m_caster_pos);
}

if(m_caster == EntityHandle_Player) {
player.m_improve = true;
m_snd_loop = ARX_SOUND_PlaySFX_loop(g_snd.SPELL_VISION_LOOP, &m_caster_pos, 1.f);
if(emitsSound) {
m_snd_loop = ARX_SOUND_PlaySFX_loop(g_snd.SPELL_VISION_LOOP, &m_caster_pos, 1.f);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could all or some of these ARX_SOUND calls get a conditional variant where you pass the bool in? yes of course its more efficient to put the if() around each call instead of doing a method call just to jump back immediately, but i dont think this would affect anything.

just easier than to have 500 if(emitsSound) clauses in each spell file.

alternatively, create a macro

#define conditional_call(condition, func) if(condition){func;}
conditional_call(emitsSound, ARX_SOUND_PlaySFX_loop(g_snd.SPELL_VISION_LOOP, &m_caster_pos, 1.f))

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand correctly, you'd pass a bool to a function just to tell it if it should do anything or not? That doesn't sound good.
It looks like the flag is set at the start of a spell and not anywhere else, so why not check the bit value once and use a member variable for that? Maybe see if you can use Spell base class to simplify what you want to do.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternatively, ARX_SOUND_PlaySFX_loop() could be wrapped in a member function, say playSoundLoop() that checks for the member variable away from the main code, if reducing clutter is the goal.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that playSoundLoop would do exactly what i proposed first with a function. the conditional macro thing would not add any extra function calls but make it a oneliner that is much easier to read. the files are long enough as they are

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't imagine reading that code a year later without having to inspect that macro and spending time on it. This doesn't feel like self-documenting code.

}
}
}

void MagicSightSpell::End() {

bool emitsSound = !(m_flags & SPELLCAST_FLAG_NOSOUND);

if(m_caster == EntityHandle_Player) {
player.m_improve = false;
}

ARX_SOUND_Stop(m_snd_loop);
m_snd_loop = audio::SourcedSample();

Entity * caster = entities.get(m_caster);
if(caster) {
ARX_SOUND_PlaySFX(g_snd.SPELL_VISION_START, &caster->pos);
if(emitsSound) {
ARX_SOUND_Stop(m_snd_loop);
m_snd_loop = audio::SourcedSample();

Entity * caster = entities.get(m_caster);
if(caster) {
ARX_SOUND_PlaySFX(g_snd.SPELL_VISION_START, &caster->pos);
}
}
}

void MagicSightSpell::Update() {

if(m_caster == EntityHandle_Player) {
bool emitsSound = !(m_flags & SPELLCAST_FLAG_NOSOUND);
if(emitsSound && m_caster == EntityHandle_Player) {
Vec3f pos = ARX_PLAYER_FrontPos();
ARX_SOUND_RefreshPosition(m_snd_loop, pos);
}
}

static void LaunchMagicMissileExplosion(const Vec3f & _ePos, bool mrCheat) {
static void LaunchMagicMissileExplosion(const Vec3f & _ePos, bool mrCheat, bool emitsSound) {

std::unique_ptr<ParticleSystem> particles = std::make_unique<ParticleSystem>();
if(mrCheat) {
Expand All @@ -112,7 +122,9 @@ static void LaunchMagicMissileExplosion(const Vec3f & _ePos, bool mrCheat) {
light->duration = 1500ms;
}

ARX_SOUND_PlaySFX(g_snd.SPELL_MM_HIT, &_ePos);
if(emitsSound) {
ARX_SOUND_PlaySFX(g_snd.SPELL_MM_HIT, &_ePos);
}

}

Expand Down Expand Up @@ -223,9 +235,13 @@ void MagicMissileSpell::Launch() {
missile.SetDuration(lTime);
}

ARX_SOUND_PlaySFX(g_snd.SPELL_MM_CREATE, &startPos);
ARX_SOUND_PlaySFX(g_snd.SPELL_MM_LAUNCH, &startPos);
snd_loop = ARX_SOUND_PlaySFX_loop(g_snd.SPELL_MM_LOOP, &startPos, 1.f);
bool emitsSound = !(m_flags & SPELLCAST_FLAG_NOSOUND);

if(emitsSound) {
ARX_SOUND_PlaySFX(g_snd.SPELL_MM_CREATE, &startPos);
ARX_SOUND_PlaySFX(g_snd.SPELL_MM_LAUNCH, &startPos);
snd_loop = ARX_SOUND_PlaySFX_loop(g_snd.SPELL_MM_LOOP, &startPos, 1.f);
}

m_duration = lMax + 1s;
}
Expand All @@ -238,12 +254,18 @@ void MagicMissileSpell::End() {

m_missiles.clear();

ARX_SOUND_Stop(snd_loop);
snd_loop = audio::SourcedSample();
bool emitsSound = !(m_flags & SPELLCAST_FLAG_NOSOUND);

if(emitsSound) {
ARX_SOUND_Stop(snd_loop);
snd_loop = audio::SourcedSample();
}
}

void MagicMissileSpell::Update() {

bool emitsSound = !(m_flags & SPELLCAST_FLAG_NOSOUND);

for(CMagicMissile & missile : util::dereference(m_missiles)) {

if(missile.bExplo) {
Expand All @@ -255,7 +277,7 @@ void MagicMissileSpell::Update() {
Entity * caster = entities.get(m_caster);
if(CheckAnythingInSphere(sphere, caster, CAS_NO_SAME_GROUP)) {

LaunchMagicMissileExplosion(missile.eCurPos, m_mrCheat);
LaunchMagicMissileExplosion(missile.eCurPos, m_mrCheat, emitsSound);
if(caster) {
spawnAudibleSound(missile.eCurPos, *caster);
}
Expand Down Expand Up @@ -287,7 +309,10 @@ void MagicMissileSpell::Update() {
}

averageMissilePos /= float(m_missiles.size());
ARX_SOUND_RefreshPosition(snd_loop, averageMissilePos);

if(emitsSound) {
ARX_SOUND_RefreshPosition(snd_loop, averageMissilePos);
}

arx_assert(m_lights.size() == m_missiles.size());

Expand Down Expand Up @@ -396,10 +421,14 @@ void IgnitSpell::Launch() {

void IgnitSpell::End() {

bool emitsSound = !(m_flags & SPELLCAST_FLAG_NOSOUND);

for(T_LINKLIGHTTOFX & entry : m_lights) {
EERIE_LIGHT * light = &g_staticLights[entry.m_targetLight];
light->m_ignitionStatus = true;
ARX_SOUND_PlaySFX(g_snd.SPELL_IGNITE, &light->pos);
if(emitsSound) {
ARX_SOUND_PlaySFX(g_snd.SPELL_IGNITE, &light->pos);
}
lightHandleDestroy(entry.m_effectLight);
}

Expand Down Expand Up @@ -499,10 +528,14 @@ void DouseSpell::Launch() {

void DouseSpell::End() {

bool emitsSound = !(m_flags & SPELLCAST_FLAG_NOSOUND);

for(size_t index : m_lights) {
EERIE_LIGHT * light = &g_staticLights[index];
light->m_ignitionStatus = false;
ARX_SOUND_PlaySFX(g_snd.SPELL_DOUSE, &light->pos);
if(emitsSound) {
ARX_SOUND_PlaySFX(g_snd.SPELL_DOUSE, &light->pos);
}
}

}
Expand All @@ -513,7 +546,11 @@ void DouseSpell::Update() {

void ActivatePortalSpell::Launch() {

ARX_SOUND_PlayInterface(g_snd.SPELL_ACTIVATE_PORTAL);
bool emitsSound = !(m_flags & SPELLCAST_FLAG_NOSOUND);

if(emitsSound) {
ARX_SOUND_PlayInterface(g_snd.SPELL_ACTIVATE_PORTAL);
}

m_duration = 20ms;
m_hasDuration = true;
Expand Down
83 changes: 61 additions & 22 deletions src/game/magic/spells/SpellsLvl02.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ bool HealSpell::CanLaunch() {

void HealSpell::Launch() {

if(!(m_flags & SPELLCAST_FLAG_NOSOUND)) {
bool emitsSound = !(m_flags & SPELLCAST_FLAG_NOSOUND);

if(emitsSound) {
ARX_SOUND_PlaySFX(g_snd.SPELL_HEALING, &m_caster_pos);
}

Expand Down Expand Up @@ -148,7 +150,9 @@ void DetectTrapSpell::Launch() {

if(m_caster == EntityHandle_Player) {
m_target = m_caster;
if(!(m_flags & SPELLCAST_FLAG_NOSOUND)) {
bool emitsSound = !(m_flags & SPELLCAST_FLAG_NOSOUND);

if(emitsSound) {
ARX_SOUND_PlayInterface(g_snd.SPELL_DETECT_TRAP);
m_snd_loop = ARX_SOUND_PlaySFX_loop(g_snd.SPELL_DETECT_TRAP_LOOP, &m_caster_pos, 1.f);
}
Expand All @@ -163,15 +167,19 @@ void DetectTrapSpell::Launch() {

void DetectTrapSpell::End() {

ARX_SOUND_Stop(m_snd_loop);
m_snd_loop = audio::SourcedSample();
bool emitsSound = !(m_flags & SPELLCAST_FLAG_NOSOUND);

if(emitsSound) {
ARX_SOUND_Stop(m_snd_loop);
m_snd_loop = audio::SourcedSample();
}

m_targets.clear();
}

void DetectTrapSpell::Update() {

if(m_caster == EntityHandle_Player) {
bool emitsSound = !(m_flags & SPELLCAST_FLAG_NOSOUND);
if(emitsSound && m_caster == EntityHandle_Player) {
Vec3f pos = ARX_PLAYER_FrontPos();
ARX_SOUND_RefreshPosition(m_snd_loop, pos);
}
Expand All @@ -189,12 +197,13 @@ void ArmorSpell::Launch()
m_target = m_caster;
}

if(!(m_flags & SPELLCAST_FLAG_NOSOUND)) {
bool emitsSound = !(m_flags & SPELLCAST_FLAG_NOSOUND);

if(emitsSound) {
ARX_SOUND_PlaySFX(g_snd.SPELL_ARMOR_START, &entities[m_target]->pos);
m_snd_loop = ARX_SOUND_PlaySFX_loop(g_snd.SPELL_ARMOR_LOOP, &entities[m_target]->pos, 1.f);
}

m_snd_loop = ARX_SOUND_PlaySFX_loop(g_snd.SPELL_ARMOR_LOOP, &entities[m_target]->pos, 1.f);

if(m_caster == EntityHandle_Player) {
m_duration = 0;
m_hasDuration = false;
Expand All @@ -217,12 +226,18 @@ void ArmorSpell::Launch()

void ArmorSpell::End() {

ARX_SOUND_Stop(m_snd_loop);
m_snd_loop = audio::SourcedSample();
bool emitsSound = !(m_flags & SPELLCAST_FLAG_NOSOUND);

if(emitsSound) {
ARX_SOUND_Stop(m_snd_loop);
m_snd_loop = audio::SourcedSample();
}

Entity * target = entities.get(m_target);
if(target) {
ARX_SOUND_PlaySFX(g_snd.SPELL_ARMOR_END, &target->pos);
if(emitsSound) {
ARX_SOUND_PlaySFX(g_snd.SPELL_ARMOR_END, &target->pos);
}
ARX_HALO_SetToNative(target);
}

Expand All @@ -238,7 +253,11 @@ void ArmorSpell::Update() {
io->halo.radius = 45.f;
}

ARX_SOUND_RefreshPosition(m_snd_loop, entities[m_target]->pos);
bool emitsSound = !(m_flags & SPELLCAST_FLAG_NOSOUND);

if(emitsSound) {
ARX_SOUND_RefreshPosition(m_snd_loop, entities[m_target]->pos);
}
}

Vec3f ArmorSpell::getPosition() const {
Expand All @@ -258,7 +277,9 @@ void LowerArmorSpell::Launch() {
spells.endByCaster(m_caster, SPELL_FIRE_PROTECTION);
spells.endByCaster(m_caster, SPELL_COLD_PROTECTION);

if(!(m_flags & SPELLCAST_FLAG_NOSOUND)) {
bool emitsSound = !(m_flags & SPELLCAST_FLAG_NOSOUND);

if(emitsSound) {
ARX_SOUND_PlaySFX(g_snd.SPELL_LOWER_ARMOR, &entities[m_target]->pos);
}

Expand Down Expand Up @@ -290,7 +311,11 @@ void LowerArmorSpell::Launch() {

void LowerArmorSpell::End() {

ARX_SOUND_PlaySFX(g_snd.SPELL_LOWER_ARMOR_END);
bool emitsSound = !(m_flags & SPELLCAST_FLAG_NOSOUND);

if(emitsSound) {
ARX_SOUND_PlaySFX(g_snd.SPELL_LOWER_ARMOR_END);
}

if(m_haloCreated) {
Entity * io = entities.get(m_target);
Expand All @@ -316,7 +341,11 @@ void LowerArmorSpell::Update() {
}
}

ARX_SOUND_RefreshPosition(m_snd_loop, entities[m_target]->pos);
bool emitsSound = !(m_flags & SPELLCAST_FLAG_NOSOUND);

if(emitsSound) {
ARX_SOUND_RefreshPosition(m_snd_loop, entities[m_target]->pos);
}
}

Vec3f LowerArmorSpell::getPosition() const {
Expand All @@ -325,12 +354,13 @@ Vec3f LowerArmorSpell::getPosition() const {

void HarmSpell::Launch() {

if(!(m_flags & SPELLCAST_FLAG_NOSOUND)) {
bool emitsSound = !(m_flags & SPELLCAST_FLAG_NOSOUND);

if(emitsSound) {
ARX_SOUND_PlaySFX(g_snd.SPELL_HARM, &m_caster_pos);
m_snd_loop = ARX_SOUND_PlaySFX_loop(g_snd.SPELL_MAGICAL_SHIELD_LOOP, &m_caster_pos, 1.f);
}

m_snd_loop = ARX_SOUND_PlaySFX_loop(g_snd.SPELL_MAGICAL_SHIELD_LOOP, &m_caster_pos, 1.f);

spells.endByCaster(m_caster, SPELL_LIFE_DRAIN);
spells.endByCaster(m_caster, SPELL_MANA_DRAIN);

Expand Down Expand Up @@ -366,8 +396,12 @@ void HarmSpell::End() {

m_cabal.end();

ARX_SOUND_Stop(m_snd_loop);
m_snd_loop = audio::SourcedSample();
bool emitsSound = !(m_flags & SPELLCAST_FLAG_NOSOUND);

if(emitsSound) {
ARX_SOUND_Stop(m_snd_loop);
m_snd_loop = audio::SourcedSample();
}
}

void HarmSpell::Update() {
Expand All @@ -388,5 +422,10 @@ void HarmSpell::Update() {
casterPos = entities[m_caster]->pos;
}
Vec3f cabalPos = m_cabal.update(casterPos);
ARX_SOUND_RefreshPosition(m_snd_loop, cabalPos);

bool emitsSound = !(m_flags & SPELLCAST_FLAG_NOSOUND);

if(emitsSound) {
ARX_SOUND_RefreshPosition(m_snd_loop, cabalPos);
}
}
Loading