From b291dacfb5d89e13d849c048005b39d222183334 Mon Sep 17 00:00:00 2001 From: cybermind <iddqd_mail@mail.ru> Date: Tue, 29 May 2012 19:28:27 +0600 Subject: [PATCH] [+] Added ability not to overlap the unit voice if unit currently plays a voice. [-] More check for valid orders --- src/action/actions.cpp | 11 ++++++++-- src/action/command.cpp | 2 +- src/ai/ai.cpp | 34 ++++++++++++++++--------------- src/ai/ai_force.cpp | 2 +- src/include/sound_server.h | 12 ++++++++++- src/sound/sound.cpp | 17 +++++++++++++--- src/sound/sound_server.cpp | 41 +++++++++++++++++++++++++++++++++++--- src/unit/unit.cpp | 39 +++++++++++++++++++----------------- 8 files changed, 113 insertions(+), 45 deletions(-) diff --git a/src/action/actions.cpp b/src/action/actions.cpp index 93565cf24..477c4ff34 100644 --- a/src/action/actions.cpp +++ b/src/action/actions.cpp @@ -348,8 +348,15 @@ static void HandleUnitAction(CUnit &unit) return; } - delete unit.Orders[0]; - unit.Orders.erase(unit.Orders.begin()); + do { + delete unit.Orders[0]; + unit.Orders.erase(unit.Orders.begin()); + } while (unit.Orders[0]->IsValid() == false && unit.Orders.size() > 1); + + if (unit.Orders[0]->IsValid() == false && unit.Orders.size() == 1) { + delete unit.Orders[0]; + unit.Orders[0] = COrder::NewActionStill(); + } unit.State = 0; unit.Wait = 0; diff --git a/src/action/command.cpp b/src/action/command.cpp index d3afac0ed..c665e9e1d 100644 --- a/src/action/command.cpp +++ b/src/action/command.cpp @@ -311,7 +311,7 @@ void CommandAttack(CUnit &unit, const Vec2i &pos, CUnit *target, int flush) return; } } - if (target) { + if (target && target->IsAlive()) { *order = COrder::NewActionAttack(unit, *target); } else { *order = COrder::NewActionAttack(unit, pos); diff --git a/src/ai/ai.cpp b/src/ai/ai.cpp index 8f7e34186..ff0c02390 100644 --- a/src/ai/ai.cpp +++ b/src/ai/ai.cpp @@ -697,28 +697,30 @@ void AiHelpMe(const CUnit *attacker, CUnit &defender) // if brother is idle or attack no-agressive target and // can attack our attacker then ask for help // FIXME ad support for help from Coward type units - if (aiunit.IsAgressive() && CanTarget(aiunit.Type, attacker->Type)) { - bool shouldAttack = aiunit.IsIdle(); + if (aiunit.IsAgressive() && CanTarget(aiunit.Type, attacker->Type) + && aiunit.CurrentOrder()->GetGoal() != attacker) { + bool shouldAttack = aiunit.IsIdle(); - if (aiunit.CurrentAction() == UnitActionAttack) { - const COrder_Attack &orderAttack = *static_cast<COrder_Attack *>(aiunit.CurrentOrder()); - const CUnit *oldGoal = orderAttack.GetGoal(); + if (aiunit.CurrentAction() == UnitActionAttack) { + const COrder_Attack &orderAttack = *static_cast<COrder_Attack *>(aiunit.CurrentOrder()); + const CUnit *oldGoal = orderAttack.GetGoal(); - if (oldGoal == NULL || oldGoal->IsAgressive() == false - || ThreatCalculate(defender, *attacker) < ThreatCalculate(defender, *oldGoal)) { - shouldAttack = true; + if (oldGoal == NULL || oldGoal->IsAgressive() == false + || (ThreatCalculate(defender, *attacker) < ThreatCalculate(defender, *oldGoal) + && aiunit.MapDistanceTo(defender) <= aiunit.Stats->Variables[ATTACKRANGE_INDEX].Max)) { + shouldAttack = true; + } } - } - if (shouldAttack) { - CommandAttack(aiunit, attacker->tilePos, const_cast<CUnit *>(attacker), FlushCommands); - COrder *savedOrder = COrder::NewActionAttack(aiunit, attacker->tilePos); + if (shouldAttack) { + CommandAttack(aiunit, attacker->tilePos, const_cast<CUnit *>(attacker), FlushCommands); + COrder *savedOrder = COrder::NewActionAttack(aiunit, attacker->tilePos); - if (aiunit.StoreOrder(savedOrder) == false) { - delete savedOrder; - savedOrder = NULL; + if (aiunit.StoreOrder(savedOrder) == false) { + delete savedOrder; + savedOrder = NULL; + } } - } } } if (!aiForce.Defending && aiForce.State > 0) { diff --git a/src/ai/ai_force.cpp b/src/ai/ai_force.cpp index c0827b9cd..7aeb4056e 100644 --- a/src/ai/ai_force.cpp +++ b/src/ai/ai_force.cpp @@ -286,7 +286,7 @@ void AiForce::Attack(const Vec2i &pos) // Remember the original force position so we can return there after attack if (this->Role == AiForceRoleDefend || (this->Role == AiForceRoleAttack && this->State == AiForceAttackingState_Waiting)) { - this->HomePos = this->Units[0]->tilePos; + this->HomePos = this->Units[this->Units.size()-1]->tilePos; } this->Attacking = true; } diff --git a/src/include/sound_server.h b/src/include/sound_server.h index b8d32aa91..0a164d7a1 100644 --- a/src/include/sound_server.h +++ b/src/include/sound_server.h @@ -33,6 +33,12 @@ //@{ +/*---------------------------------------------------------------------------- +-- Includes +----------------------------------------------------------------------------*/ + +#include "sound.h" + /*---------------------------------------------------------------------------- -- Definitons ----------------------------------------------------------------------------*/ @@ -93,10 +99,14 @@ extern void StopChannel(int channel); /// Stop all channels extern void StopAllChannels(); +/// Check if this unit plays some sound +extern bool UnitSoundIsPlaying(Origin *origin); +/// Check, if this sample is already playing +extern bool SampleIsPlaying(CSample *sample); /// Load a sample extern CSample *LoadSample(const std::string &name); /// Play a sample -extern int PlaySample(CSample *sample); +extern int PlaySample(CSample *sample, Origin *origin = NULL); /// Play a sound file extern int PlaySoundFile(const std::string &name); diff --git a/src/sound/sound.cpp b/src/sound/sound.cpp index 657eda4cc..7807ea458 100644 --- a/src/sound/sound.cpp +++ b/src/sound/sound.cpp @@ -106,7 +106,7 @@ static CSample *ChooseSample(CSound *sound, bool selection, Origin &source) CSample *result = NULL; if (!sound || !SoundEnabled()) { - return NULL; + return NULL; } if (sound->Number == TWO_GROUPS) { @@ -276,7 +276,11 @@ void PlayUnitSound(const CUnit &unit, UnitVoiceGroup voice) bool selection = (voice == VoiceSelected || voice == VoiceBuilding); Origin source = {&unit, unit.Slot}; - int channel = PlaySample(ChooseSample(sound, selection, source)); + if (UnitSoundIsPlaying(&source)) { + return; + } + + int channel = PlaySample(ChooseSample(sound, selection, source), &source); if (channel == -1) { return; } @@ -295,6 +299,7 @@ void PlayUnitSound(const CUnit &unit, UnitVoiceGroup voice) void PlayUnitSound(const CUnit &unit, CSound *sound) { Origin source = {&unit, unit.Slot}; + int channel = PlaySample(ChooseSample(sound, false, source)); if (channel == -1) { return; @@ -336,7 +341,13 @@ void PlayGameSound(CSound *sound, unsigned char volume) { Origin source = {NULL, 0}; - int channel = PlaySample(ChooseSample(sound, false, source)); + CSample *sample = ChooseSample(sound, false, source); + + if (SampleIsPlaying(sample)) { + return; + } + + int channel = PlaySample(sample); if (channel == -1) { return; } diff --git a/src/sound/sound_server.cpp b/src/sound/sound_server.cpp index 4a7eb9b78..caba693b5 100644 --- a/src/sound/sound_server.cpp +++ b/src/sound/sound_server.cpp @@ -64,6 +64,7 @@ static bool EffectsEnabled = true; /// Channels for sound effects and unit speach struct SoundChannel { CSample *Sample; /// sample to play + Origin *Unit; /// pointer to unit, who plays the sound, if any unsigned char Volume; /// Volume of this channel signed char Stereo; /// stereo location of sound (-128 left, 0 center, 127 right) @@ -346,6 +347,30 @@ static void FillAudio(void *, Uint8 *stream, int len) -- Effects ----------------------------------------------------------------------------*/ +/** +** Check if this sound is already playing +*/ +bool SampleIsPlaying(CSample *sample) +{ + for (int i = 0; i < MaxChannels; ++i) { + if (Channels[i].Sample == sample && Channels[i].Playing) { + return true; + } + } + return false; +} + +bool UnitSoundIsPlaying(Origin *origin) +{ + for (int i = 0; i < MaxChannels; ++i) { + if (origin && Channels[i].Unit && origin->Id && Channels[i].Unit->Id + && origin->Id == Channels[i].Unit->Id && Channels[i].Playing) { + return true; + } + } + return false; +} + /** ** A channel is finished playing */ @@ -355,6 +380,10 @@ static void ChannelFinished(int channel) Channels[channel].FinishedCallback(channel); } + if (Channels[channel].Unit) { + delete Channels[channel].Unit; + Channels[channel].Unit = NULL; + } Channels[channel].Playing = false; Channels[channel].Point = NextFreeChannel; NextFreeChannel = channel; @@ -363,7 +392,7 @@ static void ChannelFinished(int channel) /** ** Put a sound request in the next free channel. */ -static int FillChannel(CSample *sample, unsigned char volume, char stereo) +static int FillChannel(CSample *sample, unsigned char volume, char stereo, Origin *origin) { Assert(NextFreeChannel < MaxChannels); @@ -376,6 +405,12 @@ static int FillChannel(CSample *sample, unsigned char volume, char stereo) Channels[NextFreeChannel].Sample = sample; Channels[NextFreeChannel].Stereo = stereo; Channels[NextFreeChannel].FinishedCallback = NULL; + if (origin && origin->Base) { + Origin *source = new Origin; + source->Base = origin->Base; + source->Id = origin->Id; + Channels[NextFreeChannel].Unit = source; + } NextFreeChannel = next_free; @@ -547,14 +582,14 @@ CSample *LoadSample(const std::string &name) ** ** @return Channel number, -1 for error */ -int PlaySample(CSample *sample) +int PlaySample(CSample *sample, Origin *origin) { int channel = -1; SDL_LockAudio(); if (SoundEnabled() && EffectsEnabled && sample && NextFreeChannel != MaxChannels) { - channel = FillChannel(sample, EffectsVolume, 0); + channel = FillChannel(sample, EffectsVolume, 0, origin); } SDL_UnlockAudio(); diff --git a/src/unit/unit.cpp b/src/unit/unit.cpp index dae4efb56..5adac60dd 100644 --- a/src/unit/unit.cpp +++ b/src/unit/unit.cpp @@ -404,7 +404,7 @@ bool CUnit::StoreOrder(COrder *order) { Assert(order); - if (order && order->Finished == true) { + if (order && order->Finished == true && order->IsValid() == false) { return false; } if (this->SavedOrder != NULL) { @@ -3023,27 +3023,30 @@ void HitUnit(CUnit *attacker, CUnit &target, int damage) } // Calculate the best target we could attack - best = oldgoal ? oldgoal : (goal ? goal : attacker); - if (best && best != attacker) { - if (goal && ((goal->IsAgressive() && best->IsAgressive() == false) - || (ThreatCalculate(target, *goal) < ThreatCalculate(target, *best)))) { + if (!best || (goal && ((goal->IsAgressive() && best->IsAgressive() == false) + || (ThreatCalculate(target, *goal) < ThreatCalculate(target, *best))))) { best = goal; - } - if (!RevealAttacker && (best->IsAgressive() == false || ThreatCalculate(target, *attacker) < ThreatCalculate(target, *best))) { + } + if (CanTarget(target.Type, attacker->Type) && (!best || (attacker && goal != attacker + && ((attacker->IsAgressive() && best->IsAgressive() == false) + || (ThreatCalculate(target, *attacker) < ThreatCalculate(target, *best)))))) { best = attacker; + } + if (best) { + if (target.MapDistanceTo(*best) <= target.Stats->Variables[ATTACKRANGE_INDEX].Max) { + CommandAttack(target, best->tilePos, best, FlushCommands); + } else { + CommandAttack(target, best->tilePos, NoUnitP, FlushCommands); + } + // Set threshold value only for agressive units + if (best->IsAgressive()) { + target.Threshold = threshold; + } + if (target.StoreOrder(savedOrder) == false) { + delete savedOrder; + savedOrder = NULL; } } - CommandAttack(target, best->tilePos, NoUnitP, FlushCommands); - - // Set threshold value only for agressive units - if (best->IsAgressive()) { - target.Threshold = threshold; - } - if (target.StoreOrder(savedOrder) == false) { - delete savedOrder; - savedOrder = NULL; - } - return; } /*