Page 21 of 138
Posted: Sun Dec 07, 2008 6:41 pm
by Svengali
Very cool. Now I need some 2KW Fresnels to do it properly .-)
Posted: Sun Dec 07, 2008 8:05 pm
by Frame
Cool... now all i need is to find the nearest space ship hull plating
...
no, really, very nice....
Posted: Sun Dec 07, 2008 10:33 pm
by DaddyHoggy
Nice one Griff - that's a cracking little tutorial that you've found there!
Posted: Sat Dec 13, 2008 1:00 am
by JensAyton
I just noticed that the OXP verifier is broken in 1.72; it skips most
shipdata.plist checks. This is fixed for 1.73.
For Mac users, various “secret” settings are now exposed through the
Secrets preference pane. (If you already have Secrets installed, you may need to click “Update Secrets” for Oolite to appear in the application list.) I intend to document these tweaks and how to edit them on all platforms on EliteWiki.
Posted: Wed Dec 17, 2008 12:47 am
by JensAyton
*spins the wheel of unexpected new features*
And this week’s grand prize is… data-driven crosshairs. This means that crosshair shapes are now loaded from
a config file. But that’s not all! They can also be overridden by any HUD plist by adding a
crosshairs dictionary. But that’s not all! The size, thickness and colour of crosshairs can also be overridden by any HUD plist with the keys
crosshair_scale (default: 32),
crosshair_width (default: 1.5) and
crosshair_color (default: greenColor) respectively. But that’s not all! Oh wait, yes it is. Except for the minor detail that crosshair width is now proportional to window size, just like everything else.
The format of the
crosshairs.plist entry is simple: each entry is an array, whose elements are arrays of six numbers, each such array representing a line segment. The first three numbers are alpha, x and y for one end of the line segment, the other three numbers are alpha, x and y for (surprise!) the other end.
Posted: Wed Dec 17, 2008 8:31 am
by Commander McLane
Posted: Wed Dec 17, 2008 9:38 am
by JensAyton
Hey, customizable crosshairs have been requested. At least twice.
I actually wrote about half of this change several months ago, and having bits of incomplete code lying around is messy.
Posted: Wed Dec 17, 2008 10:29 am
by Commander McLane
I'm not complaining.
Just wanted to give a small reminder, as far as other open requests are concerned (and you will have noticed, I even shamelessly added a completely new one to the mix (the last link)
).
Posted: Wed Dec 17, 2008 11:36 pm
by JensAyton
As for the specific things you linked to… fulfilling new scripting requests is currently a low priority. In fact, my priorities right now are:
- Graphics fixes, specifically fixing a reworking of mesh drawing code that I started on a couple of weeks ago and getting the lighting and shadow model to work properly with shaders. This could also lead to a pretty nifty upgrade to the lighting rig, but no guarantees.
- Urgent scripting fixes, specifically stuff that is currently done with the legacy scripting engine and has no JS equivalent. I’ll be starting a new thread for this.
- Bug fixes.
- Competition for new higher-resolution icon – I’ve been putting this off for about a year(!), should get that started at some point…
- Stable release in late spring/early summer.
- Work on a completely unrelated iPhone app in summer.
Stuff like the data-driven crosshairs just happens between priorities when I don’t feel up to working on the priority stuff and the alternative would be to play games or have a life.
Posted: Thu Dec 18, 2008 7:12 am
by Commander McLane
I
do think, however, that you
should try this one out at some point.
Posted: Wed Jan 07, 2009 11:38 pm
by JensAyton
Implemented new AI method,
scanForNearestShipMatchingPredicate:. This method’s parameter is a JavaScript expression, which should evaluate to a boolean. In the context of the expression,
ship means the ship being evaluated, and
this means the script object associated with the same ship as the AI. Some examples:
Code: Select all
"scanForNearestShipMatchingPredicate: ship.isWeapon" // Simple case
"scanForNearestShipMatchingPredicate: this.complicatedPredicate()" // Call a function in the ship script
"scanForNearestShipMatchingPredicate: function () { if (ship.isPolice) return false; return !ship.isPlayer; } ()" // anonymous function allows multiple statements
I was somewhat leery of mixing JavaScript code into AI code, and was considering using a function name to be called instead. However, this would only work when the ship has a known script, making it impossible to use the new method in generic AIs.
Technical note: for efficiency, the generated function’s
scope is the global object. This has the effect that you must qualify references to the ship script’s properties with
this.. The benefit of this is that the compiled function can be reused without taking different ship scripts into account.
Due to details of AI parsing, calling a function in the ship script is likely to be more efficient than complex inline expressions. In particular, every AI (or legacy script) command has overhead proportional to the number of spaces in it.
Posted: Thu Jan 08, 2009 12:29 am
by DaddyHoggy
I have no idea what that means but it sounds great - the AI-using scripters will be all a twitter now!
Posted: Thu Jan 08, 2009 6:32 am
by Commander McLane
Ahruman wrote:Implemented new AI method,
scanForNearestShipMatchingPredicate:. ...
Code: Select all
"scanForNearestShipMatchingPredicate: this.complicatedPredicate()" // Call a function in the ship script
Practically, is there a difference between this and a simple "sendScriptMessage: this.complicatedPredicate"; and then have the ship script perform the search and end with a reactToAIMessage("TARGET_FOUND")?
So, should I from the next release on prefer
scanForNearestShipMatchingPredicate: over the
sendScriptMessage: approach which is already viable?
Posted: Thu Jan 08, 2009 9:39 am
by JensAyton
The AI search mechanism is somewhat more efficient, since it only calls the predicated for ships within scanner range rather than all entities in the system. It also expresses intention more clearly, which makes it easier to understand what you’re doing. Lastly, you forgot about NOTHING_FOUND. :-)
But the most important difference is that, for the simple cases, this doesn’t depend on the ship script, so the AI remains independent. Obviously the this.complicatedPredicate() form abandons that advantage.
Overall, I wouldn’t say it provides an overwhelming reason to rewrite working code.
(On a nitpicky note, it would be wrong for this.complicatedPredicate() to send AI messages; “predicate” indicates a function which returns a boolean and has no side effects.)
Posted: Fri Jan 30, 2009 1:55 pm
by JensAyton
Added delay parameter to
playerStartedJumpCountdown event, as discussed elsewhere. Here is an example of use. Note the necessity of accounting for non-integer delays. (Delays less than one are also possible, and should work fine – the timer will be cancelled before it gets called.)
Also note that witchspace countdowns can end four ways: through cancellation, through failure (mass locked, out of fue l), by the player dying, or by entering witchspace. A general
playerJumpCountdownStopped event to catch this and any new cases would probably be a good idea.
Code: Select all
this.hyperspaceCountdownTimer = null;
this.hythis.hyperspaceCountdownTimer = null;
this.hyperspaceCountdownSecondsRemaining = 0;
this.hyperspaceCountdownTimerFunc = function ()
{
log("Hyperspace in " + this.hyperspaceCountdownSecondsRemaining + " seconds.");
this.hyperspaceCountdownSecondsRemaining--;
}
this.stopHyperspaceCountdownTimer = function ()
{
if (this.hyperspaceCountdownTimer)
{
this.hyperspaceCountdownTimer.stop();
this.hyperspaceCountdownTimer = null;
}
}
// Called when player initiates witchspace countdown.
this.playerStartedJumpCountdown = function (type, delay)
{
// Get number of whole seconds until jump.
this.hyperspaceCountdownSecondsRemaining = Math.floor(delay);
// Get fractional part of delay, if any.
var initialDelay = delay - this.hyperspaceCountdownSecondsRemaining;
if (initialDelay == 0)
{
// If no fractional time, call countdown function immediately
// and use timer for subsequent seconds.
this.hyperspaceCountdownTimerFunc();
initialDelay = 1.0;
this.hyperspaceCountdownSecondsRemaining--;
}
// Call timer function every 1.0 seconds after initialDelay.
this.hyperspaceCountdownTimer =
new Timer(this, this.hyperspaceCountdownTimerFunc, initialDelay, 1.0);
}
this.playerCancelledJumpCountdown = function ()
{
this.stopHyperspaceCountdownTimer();
}
this.playerJumpFailed = function (reason)
{
this.stopHyperspaceCountdownTimer();
}
this.shipWillEnterWitchspace = function (type)
{
this.stopHyperspaceCountdownTimer();
}
this.shipDied = function (type)
{
this.stopHyperspaceCountdownTimer();
}
Backwards compatibility note: if you use this script in a pre-1.73 version of Oolite,
delay will be
undefined. This is true in general: if your function accepts more arguments than the caller passes, the extra ones will be
undefined. The backwards-compatible way of dealing this would be to start
playerStartedJumpCountdown() with
if (delay == undefined) delay = 15; – although I don’t particularly recommend aiming for backwards-compatibility with earlier test releases.