[+] Added ability not to overlap the unit voice if unit currently plays a voice.

[-] More check for valid orders
This commit is contained in:
cybermind 2012-05-29 19:28:27 +06:00
parent 74e33dda51
commit b291dacfb5
8 changed files with 113 additions and 45 deletions

View file

@ -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;

View file

@ -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);

View file

@ -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) {

View file

@ -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;
}

View file

@ -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);

View file

@ -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;
}

View file

@ -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();

View file

@ -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;
}
/*