Basic positional support for built-in sounds
- needs soundset to be in mono - no support yet for scripting soundsource positions
This commit is contained in:
parent
6df270e3b1
commit
907a3e6441
@ -795,6 +795,7 @@ typedef enum
|
||||
|
||||
- (OOWeaponType) weaponForFacing:(OOWeaponFacing)facing;
|
||||
- (OOWeaponType) currentWeapon;
|
||||
- (Vector) currentLaserOffset;
|
||||
|
||||
- (void) rotateCargo;
|
||||
|
||||
|
@ -4453,7 +4453,14 @@ static GLfloat sBaseMass = 0.0;
|
||||
|
||||
if ([ms isEqual:@"INCOMING_MISSILE"])
|
||||
{
|
||||
[self playIncomingMissile];
|
||||
if ([self primaryAggressor] != nil)
|
||||
{
|
||||
[self playIncomingMissile:HPVectorToVector([[self primaryAggressor] position])];
|
||||
}
|
||||
else
|
||||
{
|
||||
[self playIncomingMissile:kZeroVector];
|
||||
}
|
||||
[UNIVERSE addMessage:DESC(@"incoming-missile") forCount:4.5];
|
||||
}
|
||||
|
||||
@ -4547,7 +4554,7 @@ static GLfloat sBaseMass = 0.0;
|
||||
{
|
||||
firedMissile = [self launchMine:missile];
|
||||
if (!replacingMissile) [self removeFromPylon:activeMissile];
|
||||
if (firedMissile != nil) [self playMineLaunched];
|
||||
if (firedMissile != nil) [self playMineLaunched:[self missileLaunchPosition]];
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -4558,7 +4565,7 @@ static GLfloat sBaseMass = 0.0;
|
||||
if (firedMissile != nil)
|
||||
{
|
||||
if (!replacingMissile) [self removeFromPylon:activeMissile];
|
||||
[self playMissileLaunched];
|
||||
[self playMissileLaunched:[self missileLaunchPosition]];
|
||||
}
|
||||
}
|
||||
|
||||
@ -4772,6 +4779,12 @@ static GLfloat sBaseMass = 0.0;
|
||||
}
|
||||
|
||||
|
||||
- (Vector) currentLaserOffset
|
||||
{
|
||||
return [self laserPortOffset:currentWeaponFacing];
|
||||
}
|
||||
|
||||
|
||||
- (BOOL) fireMainWeapon
|
||||
{
|
||||
int weapon_to_be_fired = [self currentWeapon];
|
||||
@ -4783,7 +4796,7 @@ static GLfloat sBaseMass = 0.0;
|
||||
|
||||
if (weapon_temp / PLAYER_MAX_WEAPON_TEMP >= WEAPON_COOLING_CUTOUT)
|
||||
{
|
||||
[self playWeaponOverheated];
|
||||
[self playWeaponOverheated:[self currentLaserOffset]];
|
||||
[UNIVERSE addMessage:DESC(@"weapon-overheat") forCount:3.0];
|
||||
return NO;
|
||||
}
|
||||
@ -4943,7 +4956,7 @@ static GLfloat sBaseMass = 0.0;
|
||||
- (void) takeEnergyDamage:(double)amount from:(Entity *)ent becauseOf:(Entity *)other
|
||||
{
|
||||
HPVector rel_pos;
|
||||
double d_forward;
|
||||
double d_forward, d_right, d_up;
|
||||
BOOL internal_damage = NO; // base chance
|
||||
|
||||
OOLog(@"player.ship.damage", @"Player took damage from %@ becauseOf %@", ent, other);
|
||||
@ -4971,8 +4984,11 @@ static GLfloat sBaseMass = 0.0;
|
||||
if ([ent isShip]) [(ShipEntity *)ent doScriptEvent:OOJSID("shipAttackedOther") withArgument:self];
|
||||
|
||||
d_forward = dot_product(HPVectorToVector(rel_pos), v_forward);
|
||||
|
||||
[self playShieldHit];
|
||||
d_right = dot_product(HPVectorToVector(rel_pos), v_right);
|
||||
d_up = dot_product(HPVectorToVector(rel_pos), v_up);
|
||||
Vector relative = make_vector(d_right,d_up,d_forward);
|
||||
|
||||
[self playShieldHit:relative];
|
||||
|
||||
// firing on an innocent ship is an offence
|
||||
if ([other isShip])
|
||||
@ -5013,7 +5029,7 @@ static GLfloat sBaseMass = 0.0;
|
||||
{
|
||||
internal_damage = ((ranrot_rand() & PLAYER_INTERNAL_DAMAGE_FACTOR) < amount); // base chance of damage to systems
|
||||
energy -= amount;
|
||||
[self playDirectHit];
|
||||
[self playDirectHit:relative];
|
||||
ship_temperature += (amount / [self heatInsulation]);
|
||||
}
|
||||
[self noteTakingDamage:amount from:other type:damageType];
|
||||
@ -5038,7 +5054,7 @@ static GLfloat sBaseMass = 0.0;
|
||||
- (void) takeScrapeDamage:(double) amount from:(Entity *) ent
|
||||
{
|
||||
HPVector rel_pos;
|
||||
double d_forward;
|
||||
double d_forward, d_right, d_up;
|
||||
BOOL internal_damage = NO; // base chance
|
||||
|
||||
if ([self status] == STATUS_DEAD) return;
|
||||
@ -5055,8 +5071,11 @@ static GLfloat sBaseMass = 0.0;
|
||||
rel_pos = HPvector_subtract(rel_pos, position);
|
||||
// rel_pos is now small
|
||||
d_forward = dot_product(HPVectorToVector(rel_pos), v_forward);
|
||||
|
||||
[self playScrapeDamage];
|
||||
d_right = dot_product(HPVectorToVector(rel_pos), v_right);
|
||||
d_up = dot_product(HPVectorToVector(rel_pos), v_up);
|
||||
Vector relative = make_vector(d_right,d_up,d_forward);
|
||||
|
||||
[self playScrapeDamage:relative];
|
||||
if (d_forward >= 0)
|
||||
{
|
||||
forward_shield -= amount;
|
||||
|
@ -916,7 +916,7 @@ static NSTimeInterval time_last_frame;
|
||||
{
|
||||
if ([self fireMainWeapon])
|
||||
{
|
||||
[self playLaserHit:[self shipHitByLaser] != nil];
|
||||
[self playLaserHit:([self shipHitByLaser] != nil) offset:[self currentLaserOffset]];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,6 @@ MA 02110-1301, USA.
|
||||
|
||||
#import "PlayerEntity.h"
|
||||
|
||||
|
||||
@interface PlayerEntity (Sound)
|
||||
|
||||
- (void) setUpSound;
|
||||
@ -107,7 +106,7 @@ MA 02110-1301, USA.
|
||||
// Warning sounds
|
||||
- (void) playHostileWarning;
|
||||
- (void) playAlertConditionRed;
|
||||
- (void) playIncomingMissile;
|
||||
- (void) playIncomingMissile:(Vector)missileVector;
|
||||
- (void) playEnergyLow;
|
||||
- (void) playDockingDenied;
|
||||
- (void) playWitchjumpFailure;
|
||||
@ -118,15 +117,15 @@ MA 02110-1301, USA.
|
||||
- (void) playFuelLeak;
|
||||
|
||||
// Damage sounds
|
||||
- (void) playShieldHit;
|
||||
- (void) playDirectHit;
|
||||
- (void) playScrapeDamage;
|
||||
- (void) playShieldHit:(Vector)attackVector;
|
||||
- (void) playDirectHit:(Vector)attackVector;
|
||||
- (void) playScrapeDamage:(Vector)attackVector;
|
||||
|
||||
// Weapon sounds
|
||||
- (void) playLaserHit:(BOOL)hit;
|
||||
- (void) playWeaponOverheated;
|
||||
- (void) playMissileLaunched;
|
||||
- (void) playMineLaunched;
|
||||
- (void) playLaserHit:(BOOL)hit offset:(Vector)weaponOffset;
|
||||
- (void) playWeaponOverheated:(Vector)weaponOffset;
|
||||
- (void) playMissileLaunched:(Vector)weaponOffset;
|
||||
- (void) playMineLaunched:(Vector)weaponOffset;
|
||||
|
||||
// Miscellaneous sounds
|
||||
- (void) playEscapePodScooped;
|
||||
|
@ -27,6 +27,7 @@ MA 02110-1301, USA.
|
||||
#import "ResourceManager.h"
|
||||
#import "Universe.h"
|
||||
#import "OOSoundSourcePool.h"
|
||||
#import "OOMaths.h"
|
||||
|
||||
|
||||
// Sizes of sound source pools
|
||||
@ -51,6 +52,14 @@ static OOSoundSource *sBreakPatternSource;
|
||||
static OOSoundSourcePool *sBuySellSourcePool;
|
||||
static OOSoundSource *sAfterburnerSources[2];
|
||||
|
||||
const Vector kInterfaceBeepPosition = { 0.0f, -0.2f, 0.5f };
|
||||
const Vector kInterfaceWarningPosition = { 0.0f, -0.2f, 0.4f };
|
||||
const Vector kBreakPatternPosition = { 0.0f, 0.0f, 1.0f };
|
||||
const Vector kEcmPosition = { 0.2f, 0.6f, -0.1f };
|
||||
const Vector kWitchspacePosition = { 0.0f, -0.3f, -0.3f };
|
||||
// maybe these should actually track engine positions
|
||||
const Vector kAfterburner1Position = { -0.1f, 0.0f, -1.0f };
|
||||
const Vector kAfterburner2Position = { 0.1f, 0.0f, -1.0f };
|
||||
|
||||
@implementation PlayerEntity (Sound)
|
||||
|
||||
@ -59,9 +68,16 @@ static OOSoundSource *sAfterburnerSources[2];
|
||||
[self destroySound];
|
||||
|
||||
sInterfaceBeepSource = [[OOSoundSource alloc] init];
|
||||
[sInterfaceBeepSource setPosition:kInterfaceBeepPosition];
|
||||
|
||||
sBreakPatternSource = [[OOSoundSource alloc] init];
|
||||
[sBreakPatternSource setPosition:kBreakPatternPosition];
|
||||
|
||||
sEcmSource = [[OOSoundSource alloc] init];
|
||||
[sEcmSource setPosition:kEcmPosition];
|
||||
|
||||
sHyperspaceSoundSource = [[OOSoundSource alloc] init];
|
||||
[sHyperspaceSoundSource setPosition:kWitchspacePosition];
|
||||
|
||||
sBuySellSourcePool = [[OOSoundSourcePool alloc] initWithCount:kBuySellSourcePoolSize minRepeatTime:0.0];
|
||||
sWarningSoundPool = [[OOSoundSourcePool alloc] initWithCount:kWarningPoolSize minRepeatTime:0.0];
|
||||
@ -72,7 +88,9 @@ static OOSoundSource *sAfterburnerSources[2];
|
||||
// Two sources with the same sound are used to simulate looping.
|
||||
OOSound *afterburnerSound = [ResourceManager ooSoundNamed:@"afterburner1.ogg" inFolder:@"Sounds"];
|
||||
sAfterburnerSources[0] = [[OOSoundSource alloc] initWithSound:afterburnerSound];
|
||||
[sAfterburnerSources[0] setPosition:kAfterburner1Position];
|
||||
sAfterburnerSources[1] = [[OOSoundSource alloc] initWithSound:afterburnerSound];
|
||||
[sAfterburnerSources[1] setPosition:kAfterburner2Position];
|
||||
}
|
||||
|
||||
|
||||
@ -340,6 +358,8 @@ static OOSoundSource *sAfterburnerSources[2];
|
||||
{
|
||||
if(![sInterfaceBeepSource isPlaying])
|
||||
{
|
||||
/* TODO: this should use the scoop position, not the standard
|
||||
* interface beep position */
|
||||
[self playInterfaceBeep:@"[scoop]"];
|
||||
scoopSoundPlayTime = 0.5;
|
||||
}
|
||||
@ -484,134 +504,134 @@ static OOSoundSource *sAfterburnerSources[2];
|
||||
|
||||
- (void) playHostileWarning
|
||||
{
|
||||
[sWarningSoundPool playSoundWithKey:@"[hostile-warning]" priority:1];
|
||||
[sWarningSoundPool playSoundWithKey:@"[hostile-warning]" priority:1 position:kInterfaceWarningPosition];
|
||||
}
|
||||
|
||||
|
||||
- (void) playAlertConditionRed
|
||||
{
|
||||
[sWarningSoundPool playSoundWithKey:@"[alert-condition-red]" priority:2];
|
||||
[sWarningSoundPool playSoundWithKey:@"[alert-condition-red]" priority:2 position:kInterfaceWarningPosition];
|
||||
}
|
||||
|
||||
|
||||
- (void) playIncomingMissile
|
||||
- (void) playIncomingMissile:(Vector)missileVector
|
||||
{
|
||||
[sWarningSoundPool playSoundWithKey:@"[incoming-missile]" priority:3];
|
||||
[sWarningSoundPool playSoundWithKey:@"[incoming-missile]" priority:3 position:missileVector];
|
||||
}
|
||||
|
||||
|
||||
- (void) playEnergyLow
|
||||
{
|
||||
[sWarningSoundPool playSoundWithKey:@"[energy-low]" priority:0.5];
|
||||
[sWarningSoundPool playSoundWithKey:@"[energy-low]" priority:0.5 position:kInterfaceWarningPosition];
|
||||
}
|
||||
|
||||
|
||||
- (void) playDockingDenied
|
||||
{
|
||||
[sWarningSoundPool playSoundWithKey:@"[autopilot-denied]" priority:1];
|
||||
[sWarningSoundPool playSoundWithKey:@"[autopilot-denied]" priority:1 position:kInterfaceWarningPosition];
|
||||
}
|
||||
|
||||
|
||||
- (void) playWitchjumpFailure
|
||||
{
|
||||
[sWarningSoundPool playSoundWithKey:@"[witchdrive-failure]" priority:1.5];
|
||||
[sWarningSoundPool playSoundWithKey:@"[witchdrive-failure]" priority:1.5 position:kWitchspacePosition];
|
||||
}
|
||||
|
||||
|
||||
- (void) playWitchjumpMisjump
|
||||
{
|
||||
[sWarningSoundPool playSoundWithKey:@"[witchdrive-malfunction]" priority:1.5];
|
||||
[sWarningSoundPool playSoundWithKey:@"[witchdrive-malfunction]" priority:1.5 position:kWitchspacePosition];
|
||||
}
|
||||
|
||||
|
||||
- (void) playWitchjumpBlocked
|
||||
{
|
||||
[sWarningSoundPool playSoundWithKey:@"[witch-blocked-by-@]" priority:1.3];
|
||||
[sWarningSoundPool playSoundWithKey:@"[witch-blocked-by-@]" priority:1.3 position:kWitchspacePosition];
|
||||
}
|
||||
|
||||
|
||||
- (void) playWitchjumpDistanceTooGreat
|
||||
{
|
||||
[sWarningSoundPool playSoundWithKey:@"[witch-too-far]" priority:1.3];
|
||||
[sWarningSoundPool playSoundWithKey:@"[witch-too-far]" priority:1.3 position:kWitchspacePosition];
|
||||
}
|
||||
|
||||
|
||||
- (void) playWitchjumpInsufficientFuel
|
||||
{
|
||||
[sWarningSoundPool playSoundWithKey:@"[witch-no-fuel]" priority:1.3];
|
||||
[sWarningSoundPool playSoundWithKey:@"[witch-no-fuel]" priority:1.3 position:kWitchspacePosition];
|
||||
}
|
||||
|
||||
|
||||
- (void) playFuelLeak
|
||||
{
|
||||
[sWarningSoundPool playSoundWithKey:@"[fuel-leak]" priority:0.5];
|
||||
[sWarningSoundPool playSoundWithKey:@"[fuel-leak]" priority:0.5 position:kWitchspacePosition];
|
||||
}
|
||||
|
||||
|
||||
- (void) playShieldHit
|
||||
- (void) playShieldHit:(Vector)attackVector
|
||||
{
|
||||
[sDamageSoundPool playSoundWithKey:@"[player-hit-by-weapon]"];
|
||||
[sDamageSoundPool playSoundWithKey:@"[player-hit-by-weapon]" position:attackVector];
|
||||
}
|
||||
|
||||
|
||||
- (void) playDirectHit
|
||||
- (void) playDirectHit:(Vector)attackVector
|
||||
{
|
||||
[sDamageSoundPool playSoundWithKey:@"[player-direct-hit]"];
|
||||
[sDamageSoundPool playSoundWithKey:@"[player-direct-hit]" position:attackVector];
|
||||
}
|
||||
|
||||
|
||||
- (void) playScrapeDamage
|
||||
- (void) playScrapeDamage:(Vector)attackVector
|
||||
{
|
||||
[sDamageSoundPool playSoundWithKey:@"[player-scrape-damage]"];
|
||||
[sDamageSoundPool playSoundWithKey:@"[player-scrape-damage]" position:attackVector];
|
||||
}
|
||||
|
||||
|
||||
- (void) playLaserHit:(BOOL)hit
|
||||
- (void) playLaserHit:(BOOL)hit offset:(Vector)weaponOffset
|
||||
{
|
||||
if (hit)
|
||||
{
|
||||
[sWeaponSoundPool playSoundWithKey:@"[player-laser-hit]" priority:1 expiryTime:0.05];
|
||||
[sWeaponSoundPool playSoundWithKey:@"[player-laser-hit]" priority:1.0 expiryTime:0.05 overlap:YES position:weaponOffset];
|
||||
}
|
||||
else
|
||||
{
|
||||
[sWeaponSoundPool playSoundWithKey:@"[player-laser-miss]" priority:1 expiryTime:0.05];
|
||||
[sWeaponSoundPool playSoundWithKey:@"[player-laser-miss]" priority:1.0 expiryTime:0.05 overlap:YES position:weaponOffset];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (void) playWeaponOverheated
|
||||
- (void) playWeaponOverheated:(Vector)weaponOffset
|
||||
{
|
||||
[sWeaponSoundPool playSoundWithKey:@"[weapon-overheat]" overlap:NO];
|
||||
[sWeaponSoundPool playSoundWithKey:@"[weapon-overheat]" overlap:NO position:weaponOffset];
|
||||
}
|
||||
|
||||
|
||||
- (void) playMissileLaunched
|
||||
- (void) playMissileLaunched:(Vector)weaponOffset
|
||||
{
|
||||
[sWeaponSoundPool playSoundWithKey:@"[missile-launched]"];
|
||||
[sWeaponSoundPool playSoundWithKey:@"[missile-launched]" position:weaponOffset];
|
||||
}
|
||||
|
||||
|
||||
- (void) playMineLaunched
|
||||
- (void) playMineLaunched:(Vector)weaponOffset
|
||||
{
|
||||
[sWeaponSoundPool playSoundWithKey:@"[mine-launched]"];
|
||||
[sWeaponSoundPool playSoundWithKey:@"[mine-launched]" position:weaponOffset];
|
||||
}
|
||||
|
||||
|
||||
- (void) playEscapePodScooped
|
||||
{
|
||||
[sMiscSoundPool playSoundWithKey:@"[escape-pod-scooped]"];
|
||||
[sMiscSoundPool playSoundWithKey:@"[escape-pod-scooped]" position:kInterfaceBeepPosition];
|
||||
}
|
||||
|
||||
|
||||
- (void) playAegisCloseToPlanet
|
||||
{
|
||||
[sMiscSoundPool playSoundWithKey:@"[aegis-planet]"];
|
||||
[sMiscSoundPool playSoundWithKey:@"[aegis-planet]" position:kInterfaceBeepPosition];
|
||||
}
|
||||
|
||||
|
||||
- (void) playAegisCloseToStation
|
||||
{
|
||||
[sMiscSoundPool playSoundWithKey:@"[aegis-station]"];
|
||||
[sMiscSoundPool playSoundWithKey:@"[aegis-station]" position:kInterfaceBeepPosition];
|
||||
}
|
||||
|
||||
|
||||
|
@ -997,11 +997,13 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q
|
||||
- (BOOL) fireDirectLaserShot:(double)range;
|
||||
- (BOOL) fireDirectLaserDefensiveShot;
|
||||
- (BOOL) fireDirectLaserShotAt:(Entity *)my_target;
|
||||
- (Vector) laserPortOffset:(OOWeaponFacing)direction;
|
||||
- (BOOL) fireLaserShotInDirection:(OOWeaponFacing)direction;
|
||||
- (void) adjustMissedShots:(int)delta;
|
||||
- (int) missedShots;
|
||||
- (BOOL) firePlasmaShotAtOffset:(double)offset speed:(double)speed color:(OOColor *)color;
|
||||
- (void) considerFiringMissile:(double)delta_t;
|
||||
- (Vector) missileLaunchPosition;
|
||||
- (ShipEntity *) fireMissile;
|
||||
- (ShipEntity *) fireMissileWithIdentifier:(NSString *) identifier andTarget:(Entity *) target;
|
||||
- (BOOL) isMissileFlagSet;
|
||||
|
@ -10764,15 +10764,9 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q
|
||||
}
|
||||
|
||||
|
||||
- (BOOL) fireLaserShotInDirection:(OOWeaponFacing)direction
|
||||
- (Vector) laserPortOffset:(OOWeaponFacing)direction
|
||||
{
|
||||
double range_limit2 = weaponRange * weaponRange;
|
||||
GLfloat hit_at_range;
|
||||
Vector vel = vector_multiply_scalar(v_forward, flightSpeed);
|
||||
Vector laserPortOffset = kZeroVector;
|
||||
|
||||
last_shot_time = [UNIVERSE getTime];
|
||||
|
||||
Vector laserPortOffset = kZeroVector;
|
||||
switch (direction)
|
||||
{
|
||||
case WEAPON_FACING_FORWARD:
|
||||
@ -10792,7 +10786,19 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q
|
||||
laserPortOffset = starboardWeaponOffset;
|
||||
break;
|
||||
}
|
||||
|
||||
return laserPortOffset;
|
||||
}
|
||||
|
||||
|
||||
- (BOOL) fireLaserShotInDirection:(OOWeaponFacing)direction
|
||||
{
|
||||
double range_limit2 = weaponRange * weaponRange;
|
||||
GLfloat hit_at_range;
|
||||
Vector vel = vector_multiply_scalar(v_forward, flightSpeed);
|
||||
Vector laserPortOffset = [self laserPortOffset:direction];
|
||||
|
||||
last_shot_time = [UNIVERSE getTime];
|
||||
|
||||
ShipEntity *victim = [UNIVERSE firstShipHitByLaserFromShip:self inDirection:direction offset:laserPortOffset gettingRangeFound:&hit_at_range];
|
||||
[self setShipHitByLaser:victim];
|
||||
|
||||
@ -11044,6 +11050,28 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q
|
||||
}
|
||||
|
||||
|
||||
- (Vector) missileLaunchPosition
|
||||
{
|
||||
Vector start;
|
||||
// default launching position
|
||||
start.x = 0.0f; // in the middle
|
||||
start.y = boundingBox.min.y - 4.0f; // 4m below bounding box
|
||||
start.z = boundingBox.max.z + 1.0f; // 1m ahead of bounding box
|
||||
|
||||
// custom launching position
|
||||
start = [shipinfoDictionary oo_vectorForKey:@"missile_launch_position" defaultValue:start];
|
||||
|
||||
if (start.x == 0.0f && start.y == 0.0f && start.z <= 0.0f) // The kZeroVector as start is illegal also.
|
||||
{
|
||||
OOLog(@"ship.missileLaunch.invalidPosition", @"***** ERROR: The missile_launch_position defines a position %@ behind the %@. In future versions such missiles may explode on launch because they have to travel through the ship.", VectorDescription(start), self);
|
||||
start.x = 0.0f;
|
||||
start.y = boundingBox.min.y - 4.0f;
|
||||
start.z = boundingBox.max.z + 1.0f;
|
||||
}
|
||||
return start;
|
||||
}
|
||||
|
||||
|
||||
- (ShipEntity *) fireMissile
|
||||
{
|
||||
return [self fireMissileWithIdentifier:nil andTarget:[self primaryTarget]];
|
||||
@ -11062,21 +11090,7 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q
|
||||
|
||||
if ([UNIVERSE getTime] < missile_launch_time) return nil;
|
||||
|
||||
// default launching position
|
||||
start.x = 0.0f; // in the middle
|
||||
start.y = boundingBox.min.y - 4.0f; // 4m below bounding box
|
||||
start.z = boundingBox.max.z + 1.0f; // 1m ahead of bounding box
|
||||
|
||||
// custom launching position
|
||||
start = [shipinfoDictionary oo_vectorForKey:@"missile_launch_position" defaultValue:start];
|
||||
|
||||
if (start.x == 0.0f && start.y == 0.0f && start.z <= 0.0f) // The kZeroVector as start is illegal also.
|
||||
{
|
||||
OOLog(@"ship.missileLaunch.invalidPosition", @"***** ERROR: The missile_launch_position defines a position %@ behind the %@. In future versions such missiles may explode on launch because they have to travel through the ship.", VectorDescription(start), self);
|
||||
start.x = 0.0f;
|
||||
start.y = boundingBox.min.y - 4.0f;
|
||||
start.z = boundingBox.max.z + 1.0f;
|
||||
}
|
||||
start = [self missileLaunchPosition];
|
||||
|
||||
double throw_speed = 250.0f;
|
||||
|
||||
|
@ -32,6 +32,7 @@ SOFTWARE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "OOOpenALController.h"
|
||||
#import "OOMaths.h"
|
||||
|
||||
@class OOSound;
|
||||
|
||||
@ -57,6 +58,8 @@ SOFTWARE.
|
||||
- (OOSoundChannel *) next;
|
||||
- (void) setNext:(OOSoundChannel *)next;
|
||||
|
||||
// set sound position relative to listener
|
||||
- (void) setPosition:(Vector) vector;
|
||||
- (BOOL) playSound:(OOSound *)sound looped:(BOOL)loop;
|
||||
- (void)stop;
|
||||
|
||||
|
@ -28,6 +28,7 @@ SOFTWARE.
|
||||
#import "OOALSoundChannel.h"
|
||||
#import "OOALSound.h"
|
||||
#import "OOLogging.h"
|
||||
#import "OOMaths.h"
|
||||
|
||||
@interface OOSoundChannel (Private)
|
||||
|
||||
@ -52,6 +53,9 @@ SOFTWARE.
|
||||
[self release];
|
||||
self = nil;
|
||||
}
|
||||
// sources are all relative to listener, defaulting to zero vector
|
||||
OOAL(alSourcei(_source, AL_SOURCE_RELATIVE, AL_TRUE));
|
||||
OOAL(alSource3f(_source, AL_POSITION, 0.0f, 0.0f, 0.0f));
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@ -139,6 +143,12 @@ SOFTWARE.
|
||||
}
|
||||
|
||||
|
||||
- (void) setPosition:(Vector) vector
|
||||
{
|
||||
OOAL(alSource3f(_source, AL_POSITION, vector.x, vector.y, vector.z));
|
||||
}
|
||||
|
||||
|
||||
- (BOOL) playSound:(OOSound *)sound looped:(BOOL)loop
|
||||
{
|
||||
if (sound == nil) return NO;
|
||||
|
@ -64,6 +64,7 @@ static id sSingleton = nil;
|
||||
{
|
||||
OOLog(kOOLogSoundInitError,@"Error %d creating sound context",error);
|
||||
}
|
||||
OOAL(alDistanceModel(AL_NONE));
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
@ -44,6 +44,8 @@ OUT OF OR
|
||||
BOOL _loop;
|
||||
uint8_t _repeatCount,
|
||||
_remainingCount;
|
||||
Vector _position;
|
||||
BOOL _positional;
|
||||
}
|
||||
|
||||
+ (instancetype) sourceWithSound:(OOSound *)inSound;
|
||||
@ -69,9 +71,10 @@ OUT OF OR
|
||||
- (void) playSound:(OOSound *)inSound repeatCount:(uint8_t)inCount;
|
||||
- (void) playOrRepeatSound:(OOSound *)inSound;
|
||||
|
||||
// Positional audio attributes are ignored in this implementation
|
||||
// Positional audio attributes are used in this implementation
|
||||
- (void) setPositional:(BOOL)inPositional;
|
||||
- (void) setPosition:(Vector)inPosition;
|
||||
// *Advanced* positional audio attributes are ignored in this implementation
|
||||
- (void) setVelocity:(Vector)inVelocity;
|
||||
- (void) setOrientation:(Vector)inOrientation;
|
||||
- (void) setConeAngle:(float)inAngle;
|
||||
|
@ -27,7 +27,7 @@ SOFTWARE.
|
||||
|
||||
#import "OOSoundInternal.h"
|
||||
#import "OOLogging.h"
|
||||
|
||||
#import "OOMaths.h"
|
||||
|
||||
static NSMutableSet *sPlayingSoundSources;
|
||||
|
||||
@ -45,6 +45,9 @@ static NSMutableSet *sPlayingSoundSources;
|
||||
self = [self init];
|
||||
if (!self) return nil;
|
||||
|
||||
_positional = NO;
|
||||
_position = kZeroVector;
|
||||
|
||||
[self setSound:inSound];
|
||||
|
||||
return self;
|
||||
@ -133,6 +136,7 @@ static NSMutableSet *sPlayingSoundSources;
|
||||
{
|
||||
_remainingCount = [self repeatCount];
|
||||
[_channel setDelegate:self];
|
||||
[_channel setPosition:_position];
|
||||
[_channel playSound:[self sound] looped:[self loop]];
|
||||
[self retain];
|
||||
}
|
||||
@ -211,16 +215,32 @@ static NSMutableSet *sPlayingSoundSources;
|
||||
|
||||
- (void) setPositional:(BOOL)inPositional
|
||||
{
|
||||
|
||||
if (inPositional)
|
||||
{
|
||||
_positional = YES;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* OpenAL doesn't easily do non-positional sounds beyond the
|
||||
* stereo/mono distinction, but setting the position to the
|
||||
* zero vector is probably close enough */
|
||||
_positional = NO;
|
||||
[self setPosition:kZeroVector];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (void) setPosition:(Vector)inPosition
|
||||
{
|
||||
|
||||
_position = inPosition;
|
||||
if (_channel)
|
||||
{
|
||||
[_channel setPosition:_position];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Following not yet implemented */
|
||||
- (void) setVelocity:(Vector)inVelocity
|
||||
{
|
||||
|
||||
|
@ -35,7 +35,7 @@ SOFTWARE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "OOTypes.h"
|
||||
|
||||
#import "OOMaths.h"
|
||||
|
||||
@interface OOSoundSourcePool: NSObject
|
||||
{
|
||||
@ -52,6 +52,12 @@ SOFTWARE.
|
||||
+ (instancetype) poolWithCount:(uint8_t)count minRepeatTime:(OOTimeDelta)minRepeat;
|
||||
- (id) initWithCount:(uint8_t)count minRepeatTime:(OOTimeDelta)minRepeat;
|
||||
|
||||
- (void) playSoundWithKey:(NSString *)key
|
||||
priority:(float)priority
|
||||
expiryTime:(OOTimeDelta)expiryTime
|
||||
overlap:(BOOL)overlap
|
||||
position:(Vector)position;
|
||||
|
||||
- (void) playSoundWithKey:(NSString *)key
|
||||
priority:(float)priority
|
||||
expiryTime:(OOTimeDelta)expiryTime;
|
||||
@ -59,9 +65,17 @@ SOFTWARE.
|
||||
- (void) playSoundWithKey:(NSString *)key
|
||||
priority:(float)priority; // expiryTime:0.1 +/- 0.5
|
||||
|
||||
- (void) playSoundWithKey:(NSString *)key
|
||||
priority:(float)priority
|
||||
position:(Vector)position; // expiryTime:0.1 +/- 0.5
|
||||
|
||||
- (void) playSoundWithKey:(NSString *)key
|
||||
position:(Vector)position; // expiryTime:0.1 +/- 0.5
|
||||
|
||||
- (void) playSoundWithKey:(NSString *)key; // priority: 1.0, expiryTime:0.1 +/- 0.5
|
||||
|
||||
- (void) playSoundWithKey:(NSString *)key overlap:(BOOL)overlap; // if overlap == NO it waits for key to finish before playing key again
|
||||
- (void) playSoundWithKey:(NSString *)key overlap:(BOOL)overlap position:(Vector)position;
|
||||
|
||||
|
||||
@end
|
||||
|
@ -103,6 +103,7 @@ typedef struct OOSoundSourcePoolElement
|
||||
priority:(float)priority
|
||||
expiryTime:(OOTimeDelta)expiryTime
|
||||
overlap:(BOOL)overlap
|
||||
position:(Vector)position
|
||||
{
|
||||
uint8_t slot;
|
||||
OOTimeAbsolute now, absExpiryTime;
|
||||
@ -137,6 +138,7 @@ typedef struct OOSoundSourcePoolElement
|
||||
if (!overlap) _reserved = slot;
|
||||
|
||||
// Play and store metadata
|
||||
[element->source setPosition:position];
|
||||
[element->source playSound:sound];
|
||||
element->expiryTime = absExpiryTime;
|
||||
element->priority = priority;
|
||||
@ -159,7 +161,20 @@ typedef struct OOSoundSourcePoolElement
|
||||
[self playSoundWithKey:key
|
||||
priority:priority
|
||||
expiryTime:expiryTime
|
||||
overlap:YES];
|
||||
overlap:YES
|
||||
position:kZeroVector];
|
||||
}
|
||||
|
||||
|
||||
- (void) playSoundWithKey:(NSString *)key
|
||||
priority:(float)priority
|
||||
position:(Vector)position
|
||||
{
|
||||
[self playSoundWithKey:key
|
||||
priority:priority
|
||||
expiryTime:0.5 + randf() * 0.1
|
||||
overlap:YES
|
||||
position:position];
|
||||
}
|
||||
|
||||
|
||||
@ -178,14 +193,32 @@ typedef struct OOSoundSourcePoolElement
|
||||
}
|
||||
|
||||
|
||||
- (void) playSoundWithKey:(NSString *)key position:(Vector)position
|
||||
{
|
||||
[self playSoundWithKey:key priority:1.0 position:position];
|
||||
}
|
||||
|
||||
|
||||
- (void) playSoundWithKey:(NSString *)key overlap:(BOOL)overlap
|
||||
{
|
||||
[self playSoundWithKey:key
|
||||
priority:1.0
|
||||
expiryTime:0.5
|
||||
overlap:overlap];
|
||||
overlap:overlap
|
||||
position:kZeroVector];
|
||||
}
|
||||
|
||||
|
||||
- (void) playSoundWithKey:(NSString *)key overlap:(BOOL)overlap position:(Vector)position
|
||||
{
|
||||
[self playSoundWithKey:key
|
||||
priority:1.0
|
||||
expiryTime:0.5
|
||||
overlap:overlap
|
||||
position:position];
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
@ -29,6 +29,7 @@ MA 02110-1301, USA.
|
||||
#import "ResourceManager.h"
|
||||
#import "OOSound.h"
|
||||
#import "OOStringParsing.h"
|
||||
#import "OOMaths.h"
|
||||
|
||||
|
||||
static void InitTrumbleSounds(void);
|
||||
@ -987,7 +988,12 @@ static void InitTrumbleSounds(void)
|
||||
static void PlayTrumbleIdle(void)
|
||||
{
|
||||
// Only play idle sound if no trumble is making noise.
|
||||
if (![sTrumbleSoundSource isPlaying]) [sTrumbleSoundSource playSound:sTrumbleIdleSound];
|
||||
if (![sTrumbleSoundSource isPlaying])
|
||||
{
|
||||
// trumble sound from random direction - where's it gone now?
|
||||
[sTrumbleSoundSource setPosition:OORandomUnitVector()];
|
||||
[sTrumbleSoundSource playSound:sTrumbleIdleSound];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -996,6 +1002,8 @@ static void PlayTrumbleSqueal(void)
|
||||
// Play squeal sound if no trumble is currently squealing, but trumping idle sound.
|
||||
if (![sTrumbleSoundSource isPlaying] || [sTrumbleSoundSource sound] == sTrumbleIdleSound)
|
||||
{
|
||||
// trumble sound from random direction - where's it gone now?
|
||||
[sTrumbleSoundSource setPosition:OORandomUnitVector()];
|
||||
[sTrumbleSoundSource playSound:sTrumbleSqealSound];
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user