Very cool. Now I need some 2KW Fresnels to do it properly .-)Griff wrote:if you can't afford 3d software but you have a digital camera and a torch:
http://www.zarria.net/nrmphoto/nrmphoto.html
Progress
Moderators: winston, another_commander
Cool... now all i need is to find the nearest space ship hull plating ...Griff wrote:if you can't afford 3d software but you have a digital camera and a torch:
http://www.zarria.net/nrmphoto/nrmphoto.html
no, really, very nice....
Bounty Scanner
Number 935
Number 935
- DaddyHoggy
- Intergalactic Spam Assassin
- Posts: 8515
- Joined: Tue Dec 05, 2006 9:43 pm
- Location: Newbury, UK
- Contact:
Nice one Griff - that's a cracking little tutorial that you've found there!
Oolite Life is now revealed hereSelezen wrote:Apparently I was having a DaddyHoggy moment.
- JensAyton
- Grand Admiral Emeritus
- Posts: 6657
- Joined: Sat Apr 02, 2005 2:43 pm
- Location: Sweden
- Contact:
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.
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.
E-mail: [email protected]
- JensAyton
- Grand Admiral Emeritus
- Posts: 6657
- Joined: Sat Apr 02, 2005 2:43 pm
- Location: Sweden
- Contact:
*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.
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.
E-mail: [email protected]
- Commander McLane
- ---- E L I T E ----
- Posts: 9520
- Joined: Thu Dec 14, 2006 9:08 am
- Location: a Hacker Outpost in a moderately remote area
- Contact:
- JensAyton
- Grand Admiral Emeritus
- Posts: 6657
- Joined: Sat Apr 02, 2005 2:43 pm
- Location: Sweden
- Contact:
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.
I actually wrote about half of this change several months ago, and having bits of incomplete code lying around is messy.
E-mail: [email protected]
- Commander McLane
- ---- E L I T E ----
- Posts: 9520
- Joined: Thu Dec 14, 2006 9:08 am
- Location: a Hacker Outpost in a moderately remote area
- Contact:
- JensAyton
- Grand Admiral Emeritus
- Posts: 6657
- Joined: Sat Apr 02, 2005 2:43 pm
- Location: Sweden
- Contact:
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.
E-mail: [email protected]
- Commander McLane
- ---- E L I T E ----
- Posts: 9520
- Joined: Thu Dec 14, 2006 9:08 am
- Location: a Hacker Outpost in a moderately remote area
- Contact:
- JensAyton
- Grand Admiral Emeritus
- Posts: 6657
- Joined: Sat Apr 02, 2005 2:43 pm
- Location: Sweden
- Contact:
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:
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.
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
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.
E-mail: [email protected]
- DaddyHoggy
- Intergalactic Spam Assassin
- Posts: 8515
- Joined: Tue Dec 05, 2006 9:43 pm
- Location: Newbury, UK
- Contact:
I have no idea what that means but it sounds great - the AI-using scripters will be all a twitter now!
Oolite Life is now revealed hereSelezen wrote:Apparently I was having a DaddyHoggy moment.
- Commander McLane
- ---- E L I T E ----
- Posts: 9520
- Joined: Thu Dec 14, 2006 9:08 am
- Location: a Hacker Outpost in a moderately remote area
- Contact:
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")?Ahruman wrote:Implemented new AI method, scanForNearestShipMatchingPredicate:. ...Code: Select all
"scanForNearestShipMatchingPredicate: this.complicatedPredicate()" // Call a function in the ship script
So, should I from the next release on prefer scanForNearestShipMatchingPredicate: over the sendScriptMessage: approach which is already viable?
- JensAyton
- Grand Admiral Emeritus
- Posts: 6657
- Joined: Sat Apr 02, 2005 2:43 pm
- Location: Sweden
- Contact:
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.)
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.)
E-mail: [email protected]
- JensAyton
- Grand Admiral Emeritus
- Posts: 6657
- Joined: Sat Apr 02, 2005 2:43 pm
- Location: Sweden
- Contact:
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.
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.
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();
}
E-mail: [email protected]