Start system populator framework.

Adds buoys, nothing else
This commit is contained in:
cim 2013-07-01 13:46:13 +01:00
parent 701a750822
commit 68cbeed17b
12 changed files with 638 additions and 81 deletions

View File

@ -283,6 +283,7 @@ OOLITE_SCRIPTING_FILES = \
OOJSPlanet.m \
OOJSPlayer.m \
OOJSPlayerShip.m \
OOJSPopulatorDefinition.m \
OOJSQuaternion.m \
OOJSScript.m \
OOJSShip.m \

View File

@ -460,6 +460,7 @@
universe.findSystems.badDistance = $error;
universe.populate = no; // “Populating a system with…” message when generating a star system
universe.populate.error = yes;
universe.populate.witchspace = inherit;
universe.setup.badStation = $scriptError; // Message generated if the main station turns out not to be a station (for instance, this could happen if a non-station ship had the role coriolis).
universe.maxEntitiesDump = no; // Dumps all entities when universe is full (Can be quite verbose)

View File

@ -1,11 +1,18 @@
(
/* General */
"oolite-populator.js",
/* Interfaces */
"oolite-contracts-cargo.js",
"oolite-contracts-helpers.js",
"oolite-contracts-parcels.js",
"oolite-contracts-passengers.js",
/* Missions */
"oolite-constrictor-hunt-mission.js",
"oolite-cloaking-device-mission.js",
"oolite-nova-mission.js",
"oolite-thargoid-plans-mission.js",
"oolite-trumbles-mission.js",
"oolite-contracts-cargo.js",
"oolite-contracts-helpers.js",
"oolite-contracts-parcels.js",
"oolite-contracts-passengers.js"
"oolite-trumbles-mission.js"
)

View File

@ -0,0 +1,93 @@
/*
oolite-populator.js
Built-in system populator settings
Oolite
Copyright © 2004-2013 Giles C Williams and contributors
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
*/
/*jslint white: true, undef: true, eqeqeq: true, bitwise: true, regexp: true, newcap: true, immed: true */
/*global missionVariables, player*/
"use strict";
this.name = "oolite-populator";
this.author = "cim";
this.copyright = "© 2008-2013 the Oolite team.";
this.version = "1.79";
/* TO-DO:
* Buoys need to be given spin (0.15 pitch, 0.1 roll)
*/
this.systemWillPopulate = function() {
log(this.name,"System populator");
/* Priority range 0-100 used by Oolite default populator */
/* Add navigation buoys */
// for the compass to work properly, the buoys need to be added first,
// in this order.
system.setPopulator("oolite-nav-buoy",
{
priority: 1,
location: "COORDINATES",
coordinates: system.mainStation.position.add(system.mainStation.vectorForward.multiply(10E3)),
callback: function(pos) {
var nb = system.addShips("buoy",1,pos,0)[0];
nb.scanClass = "CLASS_BUOY";
},
deterministic: true
});
system.setPopulator("oolite-witch-buoy",
{
priority: 2,
location: "COORDINATES",
coordinates: [0,0,0],
callback: function(pos) {
var wb = system.addShips("buoy-witchpoint",1,pos,0)[0];
wb.scanClass = "CLASS_BUOY";
},
deterministic: true
});
}
this.interstellarSpaceWillPopulate = function() {
log(this.name,"Interstellar populator");
system.setPopulator("oolite-interstellar-thargoids",
{
priority: 10,
location: "WITCHPOINT",
groupCount: 2+Math.floor(Math.random()*4),
callback: function(pos) {
system.addShips("thargoid",1,pos,0);
}
});
}

View File

@ -69,6 +69,8 @@ OOINLINE Vector2D MakeVector2D(OOScalar vx, OOScalar vy) INLINE_CONST_FUNC;
Vector OORandomUnitVector(void);
Vector OOVectorRandomSpatial(OOScalar maxLength); // Random vector uniformly distributed in radius-maxLength sphere. (Longer vectors are more common.)
Vector OOVectorRandomRadial(OOScalar maxLength); // Random vector with uniform distribution of direction and radius in radius-maxLength sphere. (Causes clustering at centre.)
Vector OORandomPositionInCylinder(Vector centre1, OOScalar exclusion1, Vector centre2, OOScalar exclusion2, OOScalar radius);
Vector OORandomPositionInShell(Vector centre, OOScalar inner, OOScalar outer);
#endif
/* Multiply vector by scalar (in place) */

View File

@ -104,4 +104,29 @@ Vector OORandomPositionInBoundingBox(BoundingBox bb)
result.z = bb.min.z + randf() * (bb.max.z - bb.min.z);
return result;
}
Vector OORandomPositionInCylinder(Vector centre1, OOScalar exclusion1, Vector centre2, OOScalar exclusion2, OOScalar radius)
{
OOScalar exc12 = exclusion1*exclusion1;
OOScalar exc22 = exclusion2*exclusion2;
Vector result;
do
{
result = vector_add(OOVectorInterpolate(centre1,centre2,randf()),OOVectorRandomSpatial(radius));
}
while(distance2(result,centre1)<exc12 || distance2(result,centre2)<exc22);
return result;
}
Vector OORandomPositionInShell(Vector centre, OOScalar inner, OOScalar outer)
{
Vector result;
OOScalar inner2 = inner*inner;
do
{
result = vector_add(centre,OOVectorRandomSpatial(outer));
} while(distance2(result,centre)<inner2);
return result;
}
#endif

View File

@ -0,0 +1,46 @@
/*
OOJSPopulatorDefinition.h
Oolite
Copyright (C) 2004-2013 Giles C Williams and contributors
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
*/
#import "OOJSScript.h"
#include <jsapi.h>
#import "OOVector.h"
@interface OOJSPopulatorDefinition: OOWeakRefObject
{
@private
jsval _callback;
JSObject *_callbackThis;
OOJSScript *_owningScript;
}
- (jsval)callback;
- (void)setCallback:(jsval)callback;
- (JSObject *)callbackThis;
- (void)setCallbackThis:(JSObject *)callbackthis;
- (void)runCallback:(Vector)location;
@end

View File

@ -0,0 +1,128 @@
/*
OOJSPopulatorDefinition.m
Oolite
Copyright (C) 2004-2013 Giles C Williams and contributors
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
*/
#import "OOJSPopulatorDefinition.h"
#import "OOJavaScriptEngine.h"
#import "OOVector.h"
#import "OOJSVector.h"
@implementation OOJSPopulatorDefinition
- (id) init {
_callback = JSVAL_VOID;
_callbackThis = NULL;
_owningScript = [[OOJSScript currentlyRunningScript] weakRetain];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(deleteJSPointers)
name:kOOJavaScriptEngineWillResetNotification
object:[OOJavaScriptEngine sharedEngine]];
return self;
}
- (void) deleteJSPointers
{
JSContext *context = OOJSAcquireContext();
_callback = JSVAL_VOID;
_callbackThis = NULL;
JS_RemoveValueRoot(context, &_callback);
JS_RemoveObjectRoot(context, &_callbackThis);
OOJSRelinquishContext(context);
[[NSNotificationCenter defaultCenter] removeObserver:self
name:kOOJavaScriptEngineWillResetNotification
object:[OOJavaScriptEngine sharedEngine]];
}
- (void) dealloc
{
[_owningScript release];
[self deleteJSPointers];
[super dealloc];
}
- (jsval)callback
{
return _callback;
}
- (void)setCallback:(jsval)callback
{
JSContext *context = OOJSAcquireContext();
JS_RemoveValueRoot(context, &_callback);
_callback = callback;
OOJSAddGCValueRoot(context, &_callback, "OOJSPopulatorDefinition callback function");
OOJSRelinquishContext(context);
}
- (JSObject *)callbackThis
{
return _callbackThis;
}
- (void)setCallbackThis:(JSObject *)callbackThis
{
JSContext *context = OOJSAcquireContext();
JS_RemoveObjectRoot(context, &_callbackThis);
_callbackThis = callbackThis;
OOJSAddGCObjectRoot(context, &_callbackThis, "OOJSPopulatorDefinition callback this");
OOJSRelinquishContext(context);
}
- (void)runCallback:(Vector)location
{
OOJavaScriptEngine *engine = [OOJavaScriptEngine sharedEngine];
JSContext *context = OOJSAcquireContext();
jsval loc, rval = JSVAL_VOID;
VectorToJSValue(context, location, &loc);
OOJSScript *owner = [_owningScript retain]; // local copy needed
[OOJSScript pushScript:owner];
[engine callJSFunction:_callback
forObject:_callbackThis
argc:1
argv:&loc
result:&rval];
[OOJSScript popScript:owner];
[owner release];
OOJSRelinquishContext(context);
}
@end

View File

@ -38,3 +38,4 @@ MA 02110-1301, USA.
#define OOJSID(str) ({ static jsid idCache = JSID_VOID; if (EXPECT_NOT(idCache == JSID_VOID)) OOJSInitJSIDCachePRIVATE(""str, &idCache); idCache; })
#endif
void OOJSInitJSIDCachePRIVATE(const char *name, jsid *idCache);

View File

@ -39,7 +39,7 @@
#import "OOConstToJSString.h"
#import "OOEntityFilterPredicate.h"
#import "OOFilteringEnumerator.h"
#import "OOJSPopulatorDefinition.h"
static JSObject *sSystemPrototype;
@ -74,6 +74,7 @@ static JSBool SystemAddGroup(JSContext *context, uintN argc, jsval *vp);
static JSBool SystemAddShipsToRoute(JSContext *context, uintN argc, jsval *vp);
static JSBool SystemAddGroupToRoute(JSContext *context, uintN argc, jsval *vp);
static JSBool SystemAddVisualEffect(JSContext *context, uintN argc, jsval *vp);
static JSBool SystemSetPopulator(JSContext *context, uintN argc, jsval *vp);
static JSBool SystemLegacyAddShips(JSContext *context, uintN argc, jsval *vp);
static JSBool SystemLegacyAddSystemShips(JSContext *context, uintN argc, jsval *vp);
@ -123,6 +124,7 @@ enum
kSystem_name, // name, string, read/write
kSystem_planets, // planets in system, array of Planet, read-only
kSystem_population, // population, integer, read/write
kSystem_populatorSettings, // populator settings, dictionary, read-only
kSystem_productivity, // productivity, integer, read/write
kSystem_pseudoRandom100, // constant-per-system pseudorandom number in [0..100), integer, read-only
kSystem_pseudoRandom256, // constant-per-system pseudorandom number in [0..256), integer, read-only
@ -180,6 +182,7 @@ static JSFunctionSpec sSystemMethods[] =
{ "filteredEntities", SystemFilteredEntities, 2 },
// scrambledPseudoRandomNumber is implemented in oolite-global-prefix.js
{ "sendAllShipsAway", SystemSendAllShipsAway, 1 },
{ "setPopulator", SystemSetPopulator, 2 },
{ "shipsWithPrimaryRole", SystemShipsWithPrimaryRole, 1 },
{ "shipsWithRole", SystemShipsWithRole, 1 },
@ -287,6 +290,10 @@ static JSBool SystemGetProperty(JSContext *context, JSObject *this, jsid propID,
case kSystem_breakPattern:
*value = OOJSValueFromBOOL([UNIVERSE witchspaceBreakPattern]);
return YES;
case kSystem_populatorSettings:
*value = OOJSValueFromNativeObject(context, [UNIVERSE populatorSettings]);
return YES;
}
if (!handled)
@ -1182,6 +1189,64 @@ static JSBool SystemAddVisualEffect(JSContext *context, uintN argc, jsval *vp)
OOJS_NATIVE_EXIT
}
static JSBool SystemSetPopulator(JSContext *context, uintN argc, jsval *vp)
{
OOJS_NATIVE_ENTER(context)
NSString *key;
NSMutableDictionary *settings;
JSObject *params = NULL;
if (argc < 2)
{
OOJSReportBadArguments(context, @"System", @"setPopulator", MIN(argc, 0U), &OOJS_ARGV[0], nil, @"string (key), object (settings)");
return NO;
}
key = OOStringFromJSValue(context, OOJS_ARGV[0]);
if (key == nil)
{
OOJSReportBadArguments(context, @"System", @"setPopulator", MIN(argc, 0U), &OOJS_ARGV[0], nil, @"key, settings");
return NO;
}
if (!JS_ValueToObject(context, OOJS_ARGV[1], &params))
{
OOJSReportBadArguments(context, @"System", @"setPopulator", MIN(argc, 1U), OOJS_ARGV, NULL, @"key, settings");
return NO;
}
jsval callback = JSVAL_NULL;
if (JS_GetProperty(context, params, "callback", &callback) == JS_FALSE || JSVAL_IS_VOID(callback))
{
OOJSReportBadArguments(context, @"System", @"setPopulator", MIN(argc, 1U), OOJS_ARGV, NULL, @"settings must have a 'callback' property.");
return NO;
}
OOJSPopulatorDefinition *populator = [[OOJSPopulatorDefinition alloc] init];
[populator setCallback:callback];
settings = OOJSNativeObjectFromJSObject(context, JSVAL_TO_OBJECT(OOJS_ARGV[1]));
[settings setObject:populator forKey:@"callbackObj"];
jsval coords = JSVAL_NULL;
if (JS_GetProperty(context, params, "coordinates", &coords) != JS_FALSE && !JSVAL_IS_VOID(coords))
{
Vector coordinates = kZeroVector;
if (JSValueToVector(context, coords, &coordinates))
{
// convert vector in NS-storable form
[settings setObject:[NSArray arrayWithObjects:[NSNumber numberWithFloat:coordinates.x],[NSNumber numberWithFloat:coordinates.y],[NSNumber numberWithFloat:coordinates.z],nil] forKey:@"coordinates"];
}
}
[populator release];
[UNIVERSE setPopulatorSetting:key to:settings];
OOJS_RETURN_VOID;
OOJS_NATIVE_EXIT
}
// *** Helper functions ***
// Shared implementation of addShips() and addGroup().

View File

@ -257,6 +257,8 @@ enum
OOSunEntity *cachedSun;
NSMutableArray *allPlanets;
NSMutableDictionary *populatorSettings;
NSArray *closeSystems;
BOOL strict;
@ -339,6 +341,11 @@ enum
- (void) setUpWitchspace;
- (void) setUpWitchspaceBetweenSystem:(Random_Seed)s1 andSystem:(Random_Seed)s2;
- (void) setUpSpace;
- (void) populateNormalSpace;
- (void) clearSystemPopulator;
- (void) populateSystemFromDictionariesWithSun:(OOSunEntity *)sun andPlanet:(OOPlanetEntity *)planet;
- (NSDictionary *) populatorSettings;
- (void) setPopulatorSetting:(NSString *)key to:(NSDictionary *)setting;
- (void) setLighting;
- (void) forceLightSwitch;
- (void) setMainLightPosition: (Vector) sunPos;
@ -742,6 +749,7 @@ OOINLINE Universe *OOGetUniverse(void)
#define DESC_PLURAL(key,count) (OOLookUpPluralDescriptionPRIV(key "", count))
// Not for direct use.
NSComparisonResult populatorPrioritySort(id a, id b, void *context);
NSString *OOLookUpDescriptionPRIV(NSString *key);
NSString *OOLookUpPluralDescriptionPRIV(NSString *key, NSInteger count);

View File

@ -83,6 +83,7 @@ MA 02110-1301, USA.
#import "OOScriptTimer.h"
#import "OOJSScript.h"
#import "OOJSFrameCallbacks.h"
#import "OOJSPopulatorDefinition.h"
#if OO_LOCALIZATION_TOOLS
#import "OOConvertSystemDescriptions.h"
@ -106,9 +107,11 @@ enum
#define STANDARD_STATION_ROLL 0.4
#define WOLFPACK_SHIPS_DISTANCE 0.1
#define FIXED_ASTEROID_FIELDS 0
// currently twice scanner radius
#define LANE_WIDTH 51200.0
static NSString * const kOOLogUniversePopulate = @"universe.populate";
static NSString * const kOOLogUniversePopulateError = @"universe.populate.error";
static NSString * const kOOLogUniversePopulateWitchspace = @"universe.populate.witchspace";
extern NSString * const kOOLogEntityVerificationError;
static NSString * const kOOLogEntityVerificationRebuild = @"entity.linkedList.verify.rebuild";
@ -179,6 +182,7 @@ static OOComparisonResult comparePrice(id dict1, id dict2, void * context);
- (void) resetSystemDataCache;
- (void) populateSpaceFromActiveWormholes;
- (Vector) locationByCode:(NSString *)code withSun:(OOSunEntity *)sun andPlanet:(OOPlanetEntity *)planet;
- (void) populateSpaceFromHyperPoint:(Vector)h1_pos toPlanetPosition:(Vector)p1_pos andSunPosition:(Vector)s1_pos;
- (NSUInteger) scatterAsteroidsAt:(Vector)spawnPos withVelocity:(Vector)spawnVel includingRockHermit:(BOOL)spawnHermit asCinders:(BOOL)asCinders;
- (NSUInteger) scatterAsteroidsAt:(Vector)spawnPos withVelocity:(Vector)spawnVel includingRockHermit:(BOOL)spawnHermit asCinders:(BOOL)asCinders clusterSize:(NSUInteger)clusterSize;
@ -370,6 +374,7 @@ GLfloat docked_light_specular[4] = { DOCKED_ILLUM_LEVEL, DOCKED_ILLUM_LEVEL, DOC
[[GameController sharedController] logProgress:DESC(@"running-scripts")];
[player completeSetUp];
[self populateNormalSpace];
#if OO_LOCALIZATION_TOOLS
[self runLocalizationTools];
@ -410,6 +415,7 @@ GLfloat docked_light_specular[4] = { DOCKED_ILLUM_LEVEL, DOCKED_ILLUM_LEVEL, DOC
[autoAIMap release];
[screenBackgrounds release];
[gameView release];
[populatorSettings release];
[localPlanetInfoOverrides release];
[activeWormholes release];
@ -597,6 +603,7 @@ GLfloat docked_light_specular[4] = { DOCKED_ILLUM_LEVEL, DOCKED_ILLUM_LEVEL, DOC
[self setSystemTo: dest];
[self setUpSpace];
[self populateNormalSpace];
[player setBounty:([player legalStatus]/2) withReason:kOOLegalStatusReasonNewSystem];
if ([player random_factor] < 8) [player erodeReputation]; // every 32 systems or so, dro
}
@ -669,6 +676,7 @@ GLfloat docked_light_specular[4] = { DOCKED_ILLUM_LEVEL, DOCKED_ILLUM_LEVEL, DOC
if (!dockedStation || !interstel)
{
[self setUpSpace]; // launching from station that jumped from interstellar space to normal space.
[self populateNormalSpace];
if (dockedStation)
{
if ([dockedStation maxFlightSpeed] > 0) // we are a carrier: exit near the WitchspaceExitPosition
@ -729,6 +737,7 @@ GLfloat docked_light_specular[4] = { DOCKED_ILLUM_LEVEL, DOCKED_ILLUM_LEVEL, DOC
}
[self setUpSpace];
[self populateNormalSpace];
[player leaveWitchspace];
[player release]; // released here
@ -825,6 +834,14 @@ GLfloat docked_light_specular[4] = { DOCKED_ILLUM_LEVEL, DOCKED_ILLUM_LEVEL, DOC
OOLog(kOOLogUniversePopulateWitchspace, @"Populating witchspace ...");
OOLogIndentIf(kOOLogUniversePopulateWitchspace);
[self clearSystemPopulator];
NSString *populator = [systeminfo oo_stringForKey:@"populator" defaultValue:@"interstellarSpaceWillPopulate"];
JSContext *context = OOJSAcquireContext();
[PLAYER doWorldScriptEvent:OOJSIDFromString(populator) inContext:context withArguments:NULL count:0 timeLimit:kOOJSLongTimeLimit];
OOJSRelinquishContext(context);
[self populateSystemFromDictionariesWithSun:nil andPlanet:nil];
/*
// actual thargoids and tharglets next...
int n_thargs = 2 + (Ranrot() & 3);
if (n_thargs < 1)
@ -866,7 +883,7 @@ GLfloat docked_light_specular[4] = { DOCKED_ILLUM_LEVEL, DOCKED_ILLUM_LEVEL, DOC
[thargoid release];
}
}
*/
// systeminfo might have a 'script_actions' resource we want to activate now...
NSArray *script_actions = [systeminfo oo_arrayForKey:@"script_actions"];
if (script_actions != nil)
@ -913,11 +930,13 @@ GLfloat docked_light_specular[4] = { DOCKED_ILLUM_LEVEL, DOCKED_ILLUM_LEVEL, DOC
return [a_planet autorelease];
}
/* At any time other than game start, any call to this must be followed
* by [self populateNormalSpace]. However, at game start, they need to be
* separated to allow Javascript startUp routines to be run in-between */
- (void) setUpSpace
{
Entity *thing;
ShipEntity *nav_buoy;
// ShipEntity *nav_buoy;
StationEntity *a_station;
OOSunEntity *a_sun;
OOPlanetEntity *a_planet;
@ -994,7 +1013,7 @@ GLfloat docked_light_specular[4] = { DOCKED_ILLUM_LEVEL, DOCKED_ILLUM_LEVEL, DOC
int posIterator=0;
id dict_object;
Quaternion q_sun;
Vector sunPos,witchPos;
Vector sunPos;
sunDistanceModifier = [systeminfo oo_nonNegativeDoubleForKey:@"sun_distance_modifier" defaultValue:20.0];
// Any smaller than 6, the main planet can end up inside the sun
@ -1169,79 +1188,92 @@ GLfloat docked_light_specular[4] = { DOCKED_ILLUM_LEVEL, DOCKED_ILLUM_LEVEL, DOC
OO_DEBUG_PUSH_PROGRESS(@"setUpSpace - populate from wormholes");
[self populateSpaceFromActiveWormholes];
OO_DEBUG_POP_PROGRESS();
witchPos = [self randomizeFromSeedAndGetWitchspaceExitPosition]; //we need to use this value a few times, without resetting PRNG
OO_DEBUG_PUSH_PROGRESS(@"setUpSpace - populate from hyperpoint");
[self populateSpaceFromHyperPoint:witchPos toPlanetPosition: a_planet->position andSunPosition: a_sun->position];
OO_DEBUG_POP_PROGRESS();
OO_DEBUG_PUSH_PROGRESS(@"setUpSpace - nav beacons");
if (a_station != nil)
{
/*- nav beacon -*/
nav_buoy = [self newShipWithRole:@"buoy"]; // retain count = 1
if (nav_buoy)
{
[nav_buoy setRoll: 0.10];
[nav_buoy setPitch: 0.15];
[nav_buoy setPosition:[a_station beaconPosition]];
[nav_buoy setScanClass: CLASS_BUOY];
[self addEntity:nav_buoy]; // STATUS_IN_FLIGHT, AI state GLOBAL
[nav_buoy release];
}
}
/*--*/
/*- nav beacon witchpoint -*/
nav_buoy = [self newShipWithRole:@"buoy-witchpoint"]; // retain count = 1
if (nav_buoy)
{
[nav_buoy setRoll: 0.10];
[nav_buoy setPitch: 0.15];
[nav_buoy setPosition:witchPos]; // There should be no need to reset PRNG now.
[nav_buoy setScanClass: CLASS_BUOY];
[self addEntity:nav_buoy]; // STATUS_IN_FLIGHT, AI state GLOBAL
[nav_buoy release];
}
/*--*/
OO_DEBUG_POP_PROGRESS();
if (sunGoneNova)
{
OO_DEBUG_PUSH_PROGRESS(@"setUpSpace - post-nova");
Vector v0 = make_vector(0,0,34567.89);
Vector planetPos = a_planet->position;
double min_safe_dist2 = 5000000.0 * 5000000.0;
while (magnitude2(a_sun->position) < min_safe_dist2) // back off the planetary bodies
{
v0.z *= 2.0;
planetPos = vector_add([a_planet position], v0);
[a_planet setPosition:planetPos];
sunPos = vector_add(sunPos, v0);
[a_sun setPosition:sunPos]; // also sets light origin
stationPos = vector_add(stationPos, v0);
[a_station setPosition:stationPos];
}
[self removeEntity:a_planet]; // and Poof! it's gone
cachedPlanet = nil;
int i;
for (i = 0; i < 3; i++)
{
[self scatterAsteroidsAt:planetPos withVelocity:kZeroVector includingRockHermit:NO asCinders:YES];
[self scatterAsteroidsAt:witchPos withVelocity:kZeroVector includingRockHermit:NO asCinders:YES];
}
OO_DEBUG_POP_PROGRESS();
}
[a_sun release];
[a_station release];
}
- (void) populateNormalSpace
{
NSDictionary *systeminfo = [self generateSystemData:system_seed useCache:NO];
// Vector witchPos = [self randomizeFromSeedAndGetWitchspaceExitPosition]; //we need to use this value a few times, without resetting PRNG
OO_DEBUG_PUSH_PROGRESS(@"setUpSpace - populate from hyperpoint");
// [self populateSpaceFromHyperPoint:witchPos toPlanetPosition: a_planet->position andSunPosition: a_sun->position];
[self clearSystemPopulator];
NSString *populator = [systeminfo oo_stringForKey:@"populator" defaultValue:@"systemWillPopulate"];
JSContext *context = OOJSAcquireContext();
[PLAYER doWorldScriptEvent:OOJSIDFromString(populator) inContext:context withArguments:NULL count:0 timeLimit:kOOJSLongTimeLimit];
OOJSRelinquishContext(context);
[self populateSystemFromDictionariesWithSun:cachedSun andPlanet:cachedPlanet];
OO_DEBUG_POP_PROGRESS();
// OO_DEBUG_PUSH_PROGRESS(@"setUpSpace - nav beacons");
// if (a_station != nil)
// {
// /*- nav beacon -*/
// nav_buoy = [self newShipWithRole:@"buoy"]; // retain count = 1
// if (nav_buoy)
// {
// [nav_buoy setRoll: 0.10];
// [nav_buoy setPitch: 0.15];
// [nav_buoy setPosition:[a_station beaconPosition]];
// [nav_buoy setScanClass: CLASS_BUOY];
// [self addEntity:nav_buoy]; // STATUS_IN_FLIGHT, AI state GLOBAL
// [nav_buoy release];
// }
// }
// /*--*/
// /*- nav beacon witchpoint -*/
// nav_buoy = [self newShipWithRole:@"buoy-witchpoint"]; // retain count = 1
// if (nav_buoy)
// {
// [nav_buoy setRoll: 0.10];
// [nav_buoy setPitch: 0.15];
// [nav_buoy setPosition:witchPos]; // There should be no need to reset PRNG now.
// [nav_buoy setScanClass: CLASS_BUOY];
// [self addEntity:nav_buoy]; // STATUS_IN_FLIGHT, AI state GLOBAL
// [nav_buoy release];
// }
// /*--*/
// OO_DEBUG_POP_PROGRESS();
// if (sunGoneNova)
// {
// OO_DEBUG_PUSH_PROGRESS(@"setUpSpace - post-nova");
// Vector v0 = make_vector(0,0,34567.89);
// Vector planetPos = a_planet->position;
// double min_safe_dist2 = 5000000.0 * 5000000.0;
// while (magnitude2(a_sun->position) < min_safe_dist2) // back off the planetary bodies
// {
// v0.z *= 2.0;
// planetPos = vector_add([a_planet position], v0);
// [a_planet setPosition:planetPos];
// sunPos = vector_add(sunPos, v0);
// [a_sun setPosition:sunPos]; // also sets light origin
// stationPos = vector_add(stationPos, v0);
// [a_station setPosition:stationPos];
// }
// [self removeEntity:a_planet]; // and Poof! it's gone
// cachedPlanet = nil;
// int i;
// for (i = 0; i < 3; i++)
// {
// [self scatterAsteroidsAt:planetPos withVelocity:kZeroVector includingRockHermit:NO asCinders:YES];
// [self scatterAsteroidsAt:witchPos withVelocity:kZeroVector includingRockHermit:NO asCinders:YES];
// }
// OO_DEBUG_POP_PROGRESS();
// }
// systeminfo might have a 'script_actions' resource we want to activate now...
NSArray *script_actions = [systeminfo oo_arrayForKey:@"script_actions"];
if (script_actions != nil)
@ -1255,6 +1287,143 @@ GLfloat docked_light_specular[4] = { DOCKED_ILLUM_LEVEL, DOCKED_ILLUM_LEVEL, DOC
}
}
- (void) clearSystemPopulator
{
[populatorSettings release];
populatorSettings = [[NSMutableDictionary alloc] initWithCapacity:128];
}
- (NSDictionary *) populatorSettings
{
return populatorSettings;
}
- (void) setPopulatorSetting:(NSString *)key to:(NSDictionary *)setting
{
[populatorSettings setObject:setting forKey:key];
}
- (void) populateSystemFromDictionariesWithSun:(OOSunEntity *)sun andPlanet:(OOPlanetEntity *)planet
{
NSArray *blocks = [populatorSettings allValues];
NSEnumerator *enumerator = [[blocks sortedArrayUsingFunction:populatorPrioritySort context:nil] objectEnumerator];
NSDictionary *populator;
Vector location;
int locationSeed, groupCount, rndvalue;
unsigned i;
RANROTSeed rndcache, rndlocal;
NSString *locationCode;
OOJSPopulatorDefinition *pdef;
while ((populator = [enumerator nextObject])) {
locationSeed = [populator oo_intForKey:@"locationSeed" defaultValue:0];
groupCount = [populator oo_intForKey:@"groupCount" defaultValue:1];
for (i=0;i<groupCount;i++)
{
locationCode = [populator oo_stringForKey:@"location" defaultValue:@"COORDINATES"];
if ([locationCode isEqualToString:@"COORDINATES"])
{
location = [populator oo_vectorForKey:@"coordinates" defaultValue:kZeroVector];
}
else
{
if(locationSeed != 0)
{
rndcache = RANROTGetFullSeed();
// different place for system
rndlocal = RanrotSeedFromRandomSeed(system_seed);
rndvalue = RanrotWithSeed(&rndlocal);
// ...for location seed
rndlocal = MakeRanrotSeed(rndvalue+locationSeed);
rndvalue = RanrotWithSeed(&rndlocal);
// ...for iteration
RANROTSetFullSeed(MakeRanrotSeed(rndvalue+i));
}
if (sun == nil)
{
// all interstellar space locations equal to WITCHPOINT
location = [self locationByCode:@"WITCHPOINT" withSun:nil andPlanet:nil];
}
else
{
location = [self locationByCode:locationCode withSun:sun andPlanet:planet];
}
if(locationSeed != 0)
{
// go back to the main random sequence
RANROTSetFullSeed(rndcache);
}
}
// location now contains a Vector coordinate, one way or another
pdef = [populator objectForKey:@"callbackObj"];
[pdef runCallback:location];
}
}
}
- (Vector) locationByCode:(NSString *)code withSun:(OOSunEntity *)sun andPlanet:(OOPlanetEntity *)planet
{
Vector result = kZeroVector;
if ([code isEqualToString:@"WITCHPOINT"])
{
result = OOVectorRandomSpatial(SCANNER_MAX_RANGE);
}
// past this point, can assume non-nil sun, planet
else if ([code isEqualToString:@"LANE_WP"])
{
result = OORandomPositionInCylinder(kZeroVector,SCANNER_MAX_RANGE,[planet position],[planet radius]*3,LANE_WIDTH);
}
else if ([code isEqualToString:@"LANE_WS"])
{
result = OORandomPositionInCylinder(kZeroVector,SCANNER_MAX_RANGE,[sun position],[sun radius]*3,LANE_WIDTH);
}
else if ([code isEqualToString:@"LANE_PS"])
{
result = OORandomPositionInCylinder([planet position],[planet radius]*3,[sun position],[sun radius]*3,LANE_WIDTH);
}
else if ([code isEqualToString:@"STATION_AEGIS"])
{
do
{
result = OORandomPositionInShell([[self station] position],[[self station] collisionRadius]*1.2,SCANNER_MAX_RANGE*2.0);
} while(distance2(result,[planet position])<[planet radius]*[planet radius]*1.5);
// loop to make sure not generated too close to the planet's surface
}
else if ([code isEqualToString:@"PLANET_ORBIT_LOW"])
{
result = OORandomPositionInShell([planet position],[planet radius]*1.1,[planet radius]*2.0);
}
else if ([code isEqualToString:@"PLANET_ORBIT"])
{
result = OORandomPositionInShell([planet position],[planet radius]*2.0,[planet radius]*4.0);
}
else if ([code isEqualToString:@"PLANET_ORBIT_HIGH"])
{
result = OORandomPositionInShell([planet position],[planet radius]*4.0,[planet radius]*8.0);
}
else if ([code isEqualToString:@"STAR_ORBIT_LOW"])
{
result = OORandomPositionInShell([sun position],[sun radius]*1.1,[sun radius]*2.0);
}
else if ([code isEqualToString:@"STAR_ORBIT"])
{
result = OORandomPositionInShell([sun position],[sun radius]*2.0,[sun radius]*4.0);
}
else if ([code isEqualToString:@"STAR_ORBIT_HIGH"])
{
result = OORandomPositionInShell([sun position],[sun radius]*4.0,[sun radius]*8.0);
}
else
{
OOLog(kOOLogUniversePopulateError,@"Named populator region %@ is not implemented, falling back to WITCHPOINT",code);
result = OOVectorRandomSpatial(SCANNER_MAX_RANGE);
}
return result;
}
- (void) setLighting
{
@ -10770,6 +10939,17 @@ static void PreloadOneSound(NSString *soundName)
@end
NSComparisonResult populatorPrioritySort(id a, id b, void *context)
{
NSDictionary *one = (NSDictionary *)a;
NSDictionary *two = (NSDictionary *)b;
int pri_one = [one oo_intForKey:@"priority" defaultValue:100];
int pri_two = [two oo_intForKey:@"priority" defaultValue:100];
if (pri_one < pri_two) return NSOrderedAscending;
if (pri_one > pri_two) return NSOrderedDescending;
return NSOrderedSame;
}
NSString *OOLookUpDescriptionPRIV(NSString *key)
{