ffutures wrote: ↑Sun Mar 26, 2017 10:13 pmDo the beeps speed up as it gets closer? That would be a lovely bit of ambience.
In this update, they do:
oolite.oxp.hoqllnq.missile_beep-1.2.oxz
The previous version would check for incoming missiles once a second, and if one was found, play a 0.5 second beep.
To make the beep speed depend on missile distance, I had to change "everything":
* Rather than detecting just any incoming missile, I now have to find the nearest one.
* Calculate a beep-interval based on the distance to the nearest incoming missile.
* Register a FCB to turn the beep on/off when the beep-interval has expired.
It now plays 1 beep per second when the missile is at the edge of the scanner range, 10 bps when distance is zero. Maybe these numbers need some tweaking. The 'duty cycle' is always 50%, i.e. the duration of the beeps is half the period.
Edit to add:
And here is version 1.3 -->
oolite.oxp.hoqllnq.missile_beep-1.3.oxz
Functionality is the same as V1.2, but I made some code changes. Hopefully improvements...
* Lower the timer interval to 0.5 sec. while missiles are present, so that the change in beeping speed is smoother. (Put it back to 1 sec. when no more incoming missiles are around.)
* Added shipAttackedWithMissile() event handler that calls the timer hook when an incoming missile is fired, so beeping starts immediately instead of at the next timer interval.
This is the entire thing:
Code: Select all
// This is the world script for Missile Beep OXP
"use strict";
this.name = "Missile Beep";
this.description = "Missile Beep World Script";
this.version = "1.3";
this.author = "hoqllnq";
this.copyright = "2017 hoqllnq";
this.licence = "CC-BY-NC-SA 3.0";
this._timer = null; // To periodically check for incoming missiles
this._fcb = null; // To time the beeps
this._sound_source = null; // To play the beeps
this._beep_time = 0; // How long beep (or silence) has been playing
this._beep_interval = 0; // How long beep (or silence) should last
this._beep_on = false; // Currently beeping?
this._debug = false; // Logging
// Initialize the timer and the sound source
this.startUp = function()
{
if (!this._timer)
{
this._timer = new Timer(this, this._timer_hook.bind(this),1,1);
}
if (!this._sound_source)
{
this._sound_source = new SoundSource();
this._sound_source.loop = false;
this._sound_source.sound = "[missile_beep]";
}
if (this._debug)
log(this.name,"Started");
}
// A missile was fired at us, it could be the nearest one,
// don't wait for timer to fire, call timer hook now to check
this.shipAttackedWithMissile = function(missile,whom)
{
if (this._debug)
log(this.name,"Missile fired");
this._timer_hook();
}
// Periodic check for presence and distance of incoming missiles
this._timer_hook = function()
{
var things;
var dist;
if (player && player.ship)
{ // Find all missiles in scanner range
things = system.entitiesWithScanClass("CLASS_MISSILE",player.ship,25600);
// See if any of them are targeted at us
for (var i = 0;i < things.length;i++)
{
if (things[i].target == player.ship)
{ // Yes.
// This is the nearest one, since the list is ordered by distance
dist = things[i].position.distanceTo(player.ship.position);
if (this._debug)
log(this.name,"Missile at " + dist);
// Beep duration based on distance
this._beep_interval = 0.05 + dist / 51200.0;
// If we weren't beeping yet, start now
if(!isValidFrameCallback(this._fcb))
{
this._fcb = addFrameCallback(this._fcb_hook.bind(this));
this._timer.interval = 0.5;
}
return;
}
}
}
// No incoming missiles
// If we were beeping, stop now.
if (isValidFrameCallback(this._fcb))
{
if (this._debug)
log(this.name,"No more incoming missiles");
removeFrameCallback(this._fcb);
this._timer.interval = 1.0;
}
if (this._sound_source.isPlaying)
this._sound_source.stop();
this._beep_time = 0;
this._beep_on = false;
}
// Frame callback to turn beep on/off
// This does the timing for the beeping speed
this._fcb_hook = function(delta)
{
this._beep_time += delta;
// Time for next beep/silence?
if (this._beep_time < this._beep_interval)
return; // No.
// Reset time
this._beep_time -= this._beep_interval;
// Toggle beep
if (this._beep_on)
{
if (this._sound_source.isPlaying)
this._sound_source.stop();
this._beep_on = false;
}
else
{
if (this._debug)
log(this.name,"Beep!");
if (!this._sound_source.isPlaying)
this._sound_source.play();
this._beep_on = true;
}
}
I'm happy with how it works. Testing / playing around with it, I found it quite useful. When you fire at another ship, get the 'incoming missile' warning, but no beeping, you know you've already shot the missile, no need for ECM. Conversely, when multiple ships fire multiple missiles, and you hit your ECM, and the beeping continues, then you know it's time to ECM some more and make evasive manoeuvres. Unless there are problems (or really good ideas), I will leave it like this. It fulfils its original purpose, which was continuous alert for incoming missiles, and with the variable beeping speed (thanks cmdr. ffutures!) it does it even nicer than I originally envisioned.