[+] Added ability not to overlap the unit voice if unit currently plays a voice.
[-] More check for valid orders
This commit is contained in:
parent
74e33dda51
commit
b291dacfb5
8 changed files with 113 additions and 45 deletions
src
action
ai
include
sound
unit
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Add table
Reference in a new issue