Line data Source code
1 0 : /*
2 :
3 : OOJSSystem.m
4 :
5 :
6 : Oolite
7 : Copyright (C) 2004-2013 Giles C Williams and contributors
8 :
9 : This program is free software; you can redistribute it and/or
10 : modify it under the terms of the GNU General Public License
11 : as published by the Free Software Foundation; either version 2
12 : of the License, or (at your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program; if not, write to the Free Software
21 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22 : MA 02110-1301, USA.
23 :
24 : */
25 :
26 : #import "OOJSSystem.h"
27 : #import "OOJavaScriptEngine.h"
28 :
29 : #import "OOJSVector.h"
30 : #import "OOJSQuaternion.h"
31 : #import "OOJSEntity.h"
32 : #import "OOJSPlayer.h"
33 : #import "Universe.h"
34 : #import "OOPlanetEntity.h"
35 : #import "PlayerEntityScriptMethods.h"
36 : #import "OOJSSystemInfo.h"
37 :
38 : #import "OOCollectionExtractors.h"
39 : #import "OOConstToString.h"
40 : #import "OOConstToJSString.h"
41 : #import "OOEntityFilterPredicate.h"
42 : #import "OOFilteringEnumerator.h"
43 : #import "OOJSPopulatorDefinition.h"
44 : #import "OODebugStandards.h"
45 : #import "EntityOOJavaScriptExtensions.h"
46 :
47 0 : static JSObject *sSystemPrototype;
48 :
49 :
50 : // Support functions for entity search methods.
51 : static BOOL GetRelativeToAndRange(JSContext *context, NSString *methodName, uintN *ioArgc, jsval **ioArgv, Entity **outRelativeTo, double *outRange);
52 : static NSArray *FindJSVisibleEntities(EntityFilterPredicate predicate, void *parameter, Entity *relativeTo, double range);
53 : static NSArray *FindShips(EntityFilterPredicate predicate, void *parameter, Entity *relativeTo, double range);
54 : static NSComparisonResult CompareEntitiesByDistance(id a, id b, void *relativeTo);
55 :
56 : static JSBool SystemAddShipsOrGroup(JSContext *context, uintN argc, jsval *vp, BOOL isGroup);
57 : static JSBool SystemAddShipsOrGroupToRoute(JSContext *context, uintN argc, jsval *vp, BOOL isGroup);
58 :
59 :
60 : static JSBool SystemGetProperty(JSContext *context, JSObject *this, jsid propID, jsval *value);
61 : static JSBool SystemSetProperty(JSContext *context, JSObject *this, jsid propID, JSBool strict, jsval *value);
62 :
63 : static JSBool SystemToString(JSContext *context, uintN argc, jsval *vp);
64 : static JSBool SystemAddPlanet(JSContext *context, uintN argc, jsval *vp);
65 : static JSBool SystemAddMoon(JSContext *context, uintN argc, jsval *vp);
66 : static JSBool SystemSendAllShipsAway(JSContext *context, uintN argc, jsval *vp);
67 : static JSBool SystemCountShipsWithPrimaryRole(JSContext *context, uintN argc, jsval *vp);
68 : static JSBool SystemCountShipsWithRole(JSContext *context, uintN argc, jsval *vp);
69 : static JSBool SystemCountEntitiesWithScanClass(JSContext *context, uintN argc, jsval *vp);
70 : static JSBool SystemShipsWithPrimaryRole(JSContext *context, uintN argc, jsval *vp);
71 : static JSBool SystemShipsWithRole(JSContext *context, uintN argc, jsval *vp);
72 : static JSBool SystemEntitiesWithScanClass(JSContext *context, uintN argc, jsval *vp);
73 : static JSBool SystemFilteredEntities(JSContext *context, uintN argc, jsval *vp);
74 :
75 : static JSBool SystemLocationFromCode(JSContext *context, uintN argc, jsval *vp);
76 : static JSBool SystemAddShips(JSContext *context, uintN argc, jsval *vp);
77 : static JSBool SystemAddGroup(JSContext *context, uintN argc, jsval *vp);
78 : static JSBool SystemAddShipsToRoute(JSContext *context, uintN argc, jsval *vp);
79 : static JSBool SystemAddGroupToRoute(JSContext *context, uintN argc, jsval *vp);
80 : static JSBool SystemAddVisualEffect(JSContext *context, uintN argc, jsval *vp);
81 : static JSBool SystemSetPopulator(JSContext *context, uintN argc, jsval *vp);
82 : static JSBool SystemSetWaypoint(JSContext *context, uintN argc, jsval *vp);
83 :
84 : static JSBool SystemLegacyAddShips(JSContext *context, uintN argc, jsval *vp);
85 : static JSBool SystemLegacyAddSystemShips(JSContext *context, uintN argc, jsval *vp);
86 : static JSBool SystemLegacyAddShipsAt(JSContext *context, uintN argc, jsval *vp);
87 : static JSBool SystemLegacyAddShipsAtPrecisely(JSContext *context, uintN argc, jsval *vp);
88 : static JSBool SystemLegacyAddShipsWithinRadius(JSContext *context, uintN argc, jsval *vp);
89 : static JSBool SystemLegacySpawnShip(JSContext *context, uintN argc, jsval *vp);
90 :
91 : static JSBool SystemStaticSystemNameForID(JSContext *context, uintN argc, jsval *vp);
92 : static JSBool SystemStaticSystemIDForName(JSContext *context, uintN argc, jsval *vp);
93 : static JSBool SystemStaticInfoForSystem(JSContext *context, uintN argc, jsval *vp);
94 :
95 :
96 0 : static JSClass sSystemClass =
97 : {
98 : "System",
99 : 0,
100 :
101 : JS_PropertyStub,
102 : JS_PropertyStub,
103 : SystemGetProperty,
104 : SystemSetProperty,
105 : JS_EnumerateStub,
106 : JS_ResolveStub,
107 : JS_ConvertStub,
108 : JS_FinalizeStub
109 : };
110 :
111 :
112 0 : enum
113 : {
114 : // Property IDs
115 : kSystem_allDemoShips, // demo ships, array of Ship, read-only
116 : kSystem_allShips, // ships in system, array of Ship, read-only
117 : kSystem_allVisualEffects, // VEs in system, array of VEs, read-only
118 : kSystem_ambientLevel, // ambient light level, float, read/write
119 : kSystem_breakPattern, // witchspace break pattern shown
120 : kSystem_description, // description, string, read/write
121 : kSystem_economy, // economy ID, integer, read/write
122 : kSystem_economyDescription, // economy ID description, string, read-only
123 : kSystem_government, // government ID, integer, read/write
124 : kSystem_governmentDescription, // government ID description, string, read-only
125 : kSystem_ID, // planet number, integer, read-only
126 : kSystem_info, // system info dictionary, SystemInfo, read/write
127 : kSystem_inhabitantsDescription, // description of inhabitant species, string, read/write
128 : kSystem_isInterstellarSpace, // is interstellar space, boolean, read-only
129 : kSystem_mainPlanet, // system's main planet, Planet, read-only
130 : kSystem_mainStation, // system's main station, Station, read-only
131 : kSystem_name, // name, string, read/write
132 : kSystem_planets, // planets in system, array of Planet, read-only
133 : kSystem_population, // population, integer, read/write
134 : kSystem_populatorSettings, // populator settings, dictionary, read-only
135 : kSystem_productivity, // productivity, integer, read/write
136 : kSystem_pseudoRandom100, // constant-per-system pseudorandom number in [0..100), integer, read-only
137 : kSystem_pseudoRandom256, // constant-per-system pseudorandom number in [0..256), integer, read-only
138 : kSystem_pseudoRandomNumber, // constant-per-system pseudorandom number in [0..1), double, read-only
139 : kSystem_sun, // system's sun, Planet, read-only
140 : kSystem_stations, // list of dockable entities, read-only
141 : kSystem_techLevel, // tech level ID, integer, read/write
142 : kSystem_waypoints, // dictionary of current player waypoints, read-only
143 : kSystem_wormholes, // list of active entry wormholes, read-only
144 :
145 : };
146 :
147 :
148 0 : static JSPropertySpec sSystemProperties[] =
149 : {
150 : // JS name ID flags
151 : { "allDemoShips", kSystem_allDemoShips, OOJS_PROP_READONLY_CB },
152 : { "allShips", kSystem_allShips, OOJS_PROP_READONLY_CB },
153 : { "allVisualEffects", kSystem_allVisualEffects, OOJS_PROP_READONLY_CB },
154 : { "ambientLevel", kSystem_ambientLevel, OOJS_PROP_READWRITE_CB },
155 : { "breakPattern", kSystem_breakPattern, OOJS_PROP_READWRITE_CB },
156 : { "description", kSystem_description, OOJS_PROP_READWRITE_CB },
157 : { "economy", kSystem_economy, OOJS_PROP_READWRITE_CB },
158 : { "economyDescription", kSystem_economyDescription, OOJS_PROP_READONLY_CB },
159 : { "government", kSystem_government, OOJS_PROP_READWRITE_CB },
160 : { "governmentDescription", kSystem_governmentDescription, OOJS_PROP_READONLY_CB },
161 : { "ID", kSystem_ID, OOJS_PROP_READONLY_CB },
162 : { "info", kSystem_info, OOJS_PROP_READONLY_CB },
163 : { "inhabitantsDescription", kSystem_inhabitantsDescription, OOJS_PROP_READWRITE_CB },
164 : { "isInterstellarSpace", kSystem_isInterstellarSpace, OOJS_PROP_READONLY_CB},
165 : { "mainPlanet", kSystem_mainPlanet, OOJS_PROP_READONLY_CB },
166 : { "mainStation", kSystem_mainStation, OOJS_PROP_READONLY_CB },
167 : { "name", kSystem_name, OOJS_PROP_READWRITE_CB },
168 : { "planets", kSystem_planets, OOJS_PROP_READONLY_CB },
169 : { "population", kSystem_population, OOJS_PROP_READWRITE_CB },
170 : { "populatorSettings", kSystem_populatorSettings, OOJS_PROP_READONLY_CB },
171 : { "productivity", kSystem_productivity, OOJS_PROP_READWRITE_CB },
172 : { "pseudoRandom100", kSystem_pseudoRandom100, OOJS_PROP_READONLY_CB },
173 : { "pseudoRandom256", kSystem_pseudoRandom256, OOJS_PROP_READONLY_CB },
174 : { "pseudoRandomNumber", kSystem_pseudoRandomNumber, OOJS_PROP_READONLY_CB },
175 : { "stations", kSystem_stations, OOJS_PROP_READONLY_CB },
176 : { "sun", kSystem_sun, OOJS_PROP_READONLY_CB },
177 : { "techLevel", kSystem_techLevel, OOJS_PROP_READWRITE_CB },
178 : { "waypoints", kSystem_waypoints, OOJS_PROP_READONLY_CB },
179 : { "wormholes", kSystem_wormholes, OOJS_PROP_READONLY_CB },
180 : { 0 }
181 : };
182 :
183 :
184 0 : static JSFunctionSpec sSystemMethods[] =
185 : {
186 : // JS name Function min args
187 : { "toString", SystemToString, 0 },
188 : { "addGroup", SystemAddGroup, 3 },
189 : { "addGroupToRoute", SystemAddGroupToRoute, 2 },
190 : { "addMoon", SystemAddMoon, 1 },
191 : { "addPlanet", SystemAddPlanet, 1 },
192 : { "addShips", SystemAddShips, 3 },
193 : { "addShipsToRoute", SystemAddShipsToRoute, 2 },
194 : { "addVisualEffect", SystemAddVisualEffect, 2 },
195 : { "countEntitiesWithScanClass", SystemCountEntitiesWithScanClass, 1 },
196 : { "countShipsWithPrimaryRole", SystemCountShipsWithPrimaryRole, 1 },
197 : { "countShipsWithRole", SystemCountShipsWithRole, 1 },
198 : { "entitiesWithScanClass", SystemEntitiesWithScanClass, 1 },
199 : { "filteredEntities", SystemFilteredEntities, 2 },
200 : { "locationFromCode", SystemLocationFromCode, 1 },
201 : // scrambledPseudoRandomNumber is implemented in oolite-global-prefix.js
202 : { "sendAllShipsAway", SystemSendAllShipsAway, 1 },
203 : { "setPopulator", SystemSetPopulator, 2 },
204 : { "setWaypoint", SystemSetWaypoint, 4 },
205 : { "shipsWithPrimaryRole", SystemShipsWithPrimaryRole, 1 },
206 : { "shipsWithRole", SystemShipsWithRole, 1 },
207 :
208 : { "legacy_addShips", SystemLegacyAddShips, 2 },
209 : { "legacy_addSystemShips", SystemLegacyAddSystemShips, 3 },
210 : { "legacy_addShipsAt", SystemLegacyAddShipsAt, 6 },
211 : { "legacy_addShipsAtPrecisely", SystemLegacyAddShipsAtPrecisely, 6 },
212 : { "legacy_addShipsWithinRadius", SystemLegacyAddShipsWithinRadius, 7 },
213 : { "legacy_spawnShip", SystemLegacySpawnShip, 1 },
214 : { 0 }
215 : };
216 :
217 :
218 0 : static JSFunctionSpec sSystemStaticMethods[] =
219 : {
220 : { "infoForSystem", SystemStaticInfoForSystem, 2 },
221 : { "systemIDForName", SystemStaticSystemIDForName, 1 },
222 : { "systemNameForID", SystemStaticSystemNameForID, 1 },
223 : { 0 }
224 : };
225 :
226 :
227 0 : void InitOOJSSystem(JSContext *context, JSObject *global)
228 : {
229 : sSystemPrototype = JS_InitClass(context, global, NULL, &sSystemClass, OOJSUnconstructableConstruct, 0, sSystemProperties, sSystemMethods, NULL, sSystemStaticMethods);
230 :
231 : // Create system object as a property of the global object.
232 : JS_DefineObject(context, global, "system", &sSystemClass, sSystemPrototype, OOJS_PROP_READONLY);
233 : }
234 :
235 :
236 0 : static JSBool SystemGetProperty(JSContext *context, JSObject *this, jsid propID, jsval *value)
237 : {
238 : if (!JSID_IS_INT(propID)) return YES;
239 :
240 : OOJS_NATIVE_ENTER(context)
241 :
242 : id result = nil;
243 : PlayerEntity *player = nil;
244 : NSDictionary *systemData = nil;
245 : BOOL handled = NO;
246 :
247 : player = OOPlayerForScripting();
248 :
249 : // Handle cases which don't require systemData.
250 : switch (JSID_TO_INT(propID))
251 : {
252 : case kSystem_ID:
253 : *value = INT_TO_JSVAL([player currentSystemID]);
254 : return YES;
255 :
256 : case kSystem_isInterstellarSpace:
257 : *value = OOJSValueFromBOOL([UNIVERSE inInterstellarSpace]);
258 : return YES;
259 :
260 : case kSystem_mainStation:
261 : result = [UNIVERSE station];
262 : handled = YES;
263 : break;
264 :
265 : case kSystem_mainPlanet:
266 : result = [UNIVERSE planet];
267 : handled = YES;
268 : break;
269 :
270 : case kSystem_sun:
271 : result = [UNIVERSE sun];
272 : handled = YES;
273 : break;
274 :
275 : case kSystem_planets:
276 : result = [[[UNIVERSE planets] objectEnumeratorFilteredWithSelector:@selector(isVisibleToScripts)] allObjects];
277 : handled = YES;
278 : break;
279 :
280 : case kSystem_stations:
281 : result = [UNIVERSE stations];
282 : handled = YES;
283 : break;
284 :
285 : case kSystem_waypoints:
286 : result = [UNIVERSE currentWaypoints];
287 : handled = YES;
288 : break;
289 :
290 : case kSystem_wormholes:
291 : result = [UNIVERSE wormholes];
292 : handled = YES;
293 : break;
294 :
295 : case kSystem_allShips:
296 : OOJS_BEGIN_FULL_NATIVE(context)
297 : result = [UNIVERSE findShipsMatchingPredicate:JSEntityIsJavaScriptSearchablePredicate parameter:NULL inRange:-1 ofEntity:nil];
298 : OOJS_END_FULL_NATIVE
299 : handled = YES;
300 : break;
301 :
302 : case kSystem_allDemoShips:
303 : OOJS_BEGIN_FULL_NATIVE(context)
304 : result = [UNIVERSE findShipsMatchingPredicate:JSEntityIsDemoShipPredicate parameter:NULL inRange:-1 ofEntity:nil];
305 : OOJS_END_FULL_NATIVE
306 : handled = YES;
307 : break;
308 :
309 :
310 : case kSystem_allVisualEffects:
311 : OOJS_BEGIN_FULL_NATIVE(context)
312 : result = [UNIVERSE findVisualEffectsMatchingPredicate:JSEntityIsJavaScriptSearchablePredicate parameter:NULL inRange:-1 ofEntity:nil];
313 : OOJS_END_FULL_NATIVE
314 : handled = YES;
315 : break;
316 :
317 : case kSystem_ambientLevel:
318 : return JS_NewNumberValue(context, [UNIVERSE ambientLightLevel], value);
319 :
320 : case kSystem_info:
321 : *value = GetJSSystemInfoForSystem(context, [player currentGalaxyID], [player currentSystemID]);
322 : return YES;
323 :
324 : case kSystem_pseudoRandomNumber:
325 : return JS_NewNumberValue(context, [player systemPseudoRandomFloat], value);
326 :
327 : case kSystem_pseudoRandom100:
328 : *value = INT_TO_JSVAL([player systemPseudoRandom100]);
329 : return YES;
330 :
331 : case kSystem_pseudoRandom256:
332 : *value = INT_TO_JSVAL([player systemPseudoRandom256]);
333 : return YES;
334 :
335 : case kSystem_breakPattern:
336 : *value = OOJSValueFromBOOL([UNIVERSE witchspaceBreakPattern]);
337 : return YES;
338 :
339 : case kSystem_populatorSettings:
340 : *value = OOJSValueFromNativeObject(context, [UNIVERSE getPopulatorSettings]);
341 : return YES;
342 : }
343 :
344 : if (!handled)
345 : {
346 : // Handle cases which do require systemData.
347 : if (EXPECT (![UNIVERSE inInterstellarSpace]))
348 : {
349 : systemData = [UNIVERSE currentSystemData];
350 :
351 : switch (JSID_TO_INT(propID))
352 : {
353 : case kSystem_name:
354 : result = [systemData objectForKey:KEY_NAME];
355 : break;
356 :
357 : case kSystem_description:
358 : result = [systemData objectForKey:KEY_DESCRIPTION];
359 : break;
360 :
361 : case kSystem_inhabitantsDescription:
362 : result = [systemData objectForKey:KEY_INHABITANTS];
363 : break;
364 :
365 : case kSystem_government:
366 : *value = INT_TO_JSVAL([systemData oo_intForKey:KEY_GOVERNMENT]);
367 : return YES;
368 :
369 : case kSystem_governmentDescription:
370 : result = OODisplayStringFromGovernmentID([systemData oo_intForKey:KEY_GOVERNMENT]);
371 : if (result == nil) result = DESC(@"not-applicable");
372 : break;
373 :
374 : case kSystem_economy:
375 : *value = INT_TO_JSVAL([systemData oo_intForKey:KEY_ECONOMY]);
376 : return YES;
377 :
378 : case kSystem_economyDescription:
379 : result = OODisplayStringFromEconomyID([systemData oo_intForKey:KEY_ECONOMY]);
380 : if (result == nil) result = DESC(@"not-applicable");
381 : break;
382 :
383 : case kSystem_techLevel:
384 : *value = INT_TO_JSVAL([systemData oo_intForKey:KEY_TECHLEVEL]);
385 : return YES;
386 :
387 : case kSystem_population:
388 : *value = INT_TO_JSVAL([systemData oo_intForKey:KEY_POPULATION]);
389 : return YES;
390 :
391 : case kSystem_productivity:
392 : *value = INT_TO_JSVAL([systemData oo_intForKey:KEY_PRODUCTIVITY]);
393 : return YES;
394 :
395 : default:
396 : OOJSReportBadPropertySelector(context, this, propID, sSystemProperties);
397 : return NO;
398 : }
399 : }
400 : else
401 : {
402 : // if in interstellar space, systemData values are null & void!
403 : switch (JSID_TO_INT(propID))
404 : {
405 : case kSystem_name:
406 : result = DESC(@"interstellar-space");
407 : break;
408 :
409 : case kSystem_description:
410 : result = @"";
411 : break;
412 :
413 : case kSystem_inhabitantsDescription:
414 : result = DESC(@"not-applicable");
415 : break;
416 :
417 : case kSystem_government:
418 : *value = INT_TO_JSVAL(-1);
419 : return YES;
420 :
421 : case kSystem_governmentDescription:
422 : result = DESC(@"not-applicable");
423 : break;
424 :
425 : case kSystem_economy:
426 : *value = INT_TO_JSVAL(-1);
427 : return YES;
428 :
429 : case kSystem_economyDescription:
430 : result = DESC(@"not-applicable");
431 : break;
432 :
433 : case kSystem_techLevel:
434 : *value = INT_TO_JSVAL(-1);
435 : return YES;
436 :
437 : case kSystem_population:
438 : *value = INT_TO_JSVAL(0);
439 : return YES;
440 :
441 : case kSystem_productivity:
442 : *value = INT_TO_JSVAL(0);
443 : return YES;
444 :
445 : default:
446 : OOJSReportBadPropertySelector(context, this, propID, sSystemProperties);
447 : return NO;
448 : }
449 : }
450 : }
451 :
452 : *value = OOJSValueFromNativeObject(context, result);
453 : return YES;
454 :
455 : OOJS_NATIVE_EXIT
456 : }
457 :
458 :
459 0 : static JSBool SystemSetProperty(JSContext *context, JSObject *this, jsid propID, JSBool strict, jsval *value)
460 : {
461 : if (!JSID_IS_INT(propID)) return YES;
462 :
463 : OOJS_NATIVE_ENTER(context)
464 :
465 : PlayerEntity *player = nil;
466 : OOGalaxyID galaxy;
467 : OOSystemID system;
468 : NSString *stringValue = nil;
469 : NSString *manifest = nil;
470 : jsdouble fValue;
471 : int32 iValue;
472 : JSBool bValue;
473 :
474 : player = OOPlayerForScripting();
475 :
476 : galaxy = [player currentGalaxyID];
477 : system = [player currentSystemID];
478 :
479 : switch (JSID_TO_INT(propID))
480 : {
481 : case kSystem_ambientLevel:
482 : if (JS_ValueToNumber(context, *value, &fValue))
483 : {
484 : [UNIVERSE setAmbientLightLevel:fValue];
485 : [UNIVERSE setLighting];
486 : return YES;
487 : }
488 : break;
489 :
490 : case kSystem_breakPattern:
491 : if (JS_ValueToBoolean(context, *value, &bValue))
492 : {
493 : [UNIVERSE setWitchspaceBreakPattern:bValue];
494 : return YES;
495 : }
496 :
497 : break;
498 : default:
499 : {}// do nothing yet
500 : }
501 :
502 :
503 : if (system == -1) return YES; // Can't change anything else in interstellar space.
504 :
505 : manifest = [[OOJSScript currentlyRunningScript] propertyNamed:kLocalManifestProperty];
506 :
507 : switch (JSID_TO_INT(propID))
508 : {
509 : case kSystem_name:
510 : stringValue = OOStringFromJSValue(context, *value);
511 : if (stringValue != nil)
512 : {
513 : [UNIVERSE setSystemDataForGalaxy:galaxy planet:system key:KEY_NAME value:stringValue fromManifest:manifest forLayer:OO_LAYER_OXP_DYNAMIC];
514 : return YES;
515 : }
516 : break;
517 :
518 : case kSystem_description:
519 : stringValue = OOStringFromJSValue(context, *value);
520 : if (stringValue != nil)
521 : {
522 : [UNIVERSE setSystemDataForGalaxy:galaxy planet:system key:KEY_DESCRIPTION value:stringValue fromManifest:manifest forLayer:OO_LAYER_OXP_DYNAMIC];
523 : return YES;
524 : }
525 : break;
526 :
527 : case kSystem_inhabitantsDescription:
528 : stringValue = OOStringFromJSValue(context, *value);
529 : if (stringValue != nil)
530 : {
531 : [UNIVERSE setSystemDataForGalaxy:galaxy planet:system key:KEY_INHABITANTS value:stringValue fromManifest:manifest forLayer:OO_LAYER_OXP_DYNAMIC];
532 : return YES;
533 : }
534 : break;
535 :
536 : case kSystem_government:
537 : if (JS_ValueToInt32(context, *value, &iValue))
538 : {
539 : if (iValue < 0) iValue = 0;
540 : if (7 < iValue) iValue = 7;
541 : [UNIVERSE setSystemDataForGalaxy:galaxy planet:system key:KEY_GOVERNMENT value:[NSNumber numberWithInt:iValue] fromManifest:manifest forLayer:OO_LAYER_OXP_DYNAMIC];
542 : return YES;
543 : }
544 : break;
545 :
546 : case kSystem_economy:
547 : if (JS_ValueToInt32(context, *value, &iValue))
548 : {
549 : if (iValue < 0) iValue = 0;
550 : if (7 < iValue) iValue = 7;
551 : [UNIVERSE setSystemDataForGalaxy:galaxy planet:system key:KEY_ECONOMY value:[NSNumber numberWithInt:iValue] fromManifest:manifest forLayer:OO_LAYER_OXP_DYNAMIC];
552 : return YES;
553 : }
554 : break;
555 :
556 : case kSystem_techLevel:
557 : if (JS_ValueToInt32(context, *value, &iValue))
558 : {
559 : if (iValue < 0) iValue = 0;
560 : if (15 < iValue) iValue = 15;
561 : [UNIVERSE setSystemDataForGalaxy:galaxy planet:system key:KEY_TECHLEVEL value:[NSNumber numberWithInt:iValue] fromManifest:manifest forLayer:OO_LAYER_OXP_DYNAMIC];
562 : return YES;
563 : }
564 : break;
565 :
566 : case kSystem_population:
567 : if (JS_ValueToInt32(context, *value, &iValue))
568 : {
569 : [UNIVERSE setSystemDataForGalaxy:galaxy planet:system key:KEY_POPULATION value:[NSNumber numberWithInt:iValue] fromManifest:manifest forLayer:OO_LAYER_OXP_DYNAMIC];
570 : return YES;
571 : }
572 : break;
573 :
574 : case kSystem_productivity:
575 : if (JS_ValueToInt32(context, *value, &iValue))
576 : {
577 : [UNIVERSE setSystemDataForGalaxy:galaxy planet:system key:KEY_PRODUCTIVITY value:[NSNumber numberWithInt:iValue] fromManifest:manifest forLayer:OO_LAYER_OXP_DYNAMIC];
578 : return YES;
579 : }
580 : break;
581 :
582 : default:
583 : OOJSReportBadPropertySelector(context, this, propID, sSystemProperties);
584 : return NO;
585 : }
586 :
587 : OOJSReportBadPropertyValue(context, this, propID, sSystemProperties, *value);
588 : return NO;
589 :
590 : OOJS_NATIVE_EXIT
591 : }
592 :
593 :
594 : // *** Methods ***
595 :
596 : // toString() : String
597 0 : static JSBool SystemToString(JSContext *context, uintN argc, jsval *vp)
598 : {
599 : OOJS_NATIVE_ENTER(context)
600 :
601 : PlayerEntity *player = OOPlayerForScripting();
602 : NSString *systemDesc = nil;
603 :
604 : systemDesc = [NSString stringWithFormat:@"[System %u:%u \"%@\"]", [player currentGalaxyID], [player currentSystemID], [[UNIVERSE currentSystemData] objectForKey:KEY_NAME]];
605 : OOJS_RETURN_OBJECT(systemDesc);
606 :
607 : OOJS_NATIVE_EXIT
608 : }
609 :
610 :
611 : // addPlanet(key : String) : Planet
612 0 : static JSBool SystemAddPlanet(JSContext *context, uintN argc, jsval *vp)
613 : {
614 : OOJS_NATIVE_ENTER(context)
615 :
616 : PlayerEntity *player = OOPlayerForScripting();
617 : NSString *key = nil;
618 : OOPlanetEntity *planet = nil;
619 :
620 : if (argc > 0) key = OOStringFromJSValue(context, OOJS_ARGV[0]);
621 : if (EXPECT_NOT(key == nil))
622 : {
623 : OOJSReportBadArguments(context, @"System", @"addPlanet", MIN(argc, 1U), OOJS_ARGV, nil, @"string (planet key)");
624 : return NO;
625 : }
626 :
627 : OOJS_BEGIN_FULL_NATIVE(context)
628 : planet = [player addPlanet:key];
629 : OOJS_END_FULL_NATIVE
630 :
631 : OOJS_RETURN_OBJECT(planet);
632 :
633 : OOJS_NATIVE_EXIT
634 : }
635 :
636 :
637 : // addMoon(key : String) : Planet
638 0 : static JSBool SystemAddMoon(JSContext *context, uintN argc, jsval *vp)
639 : {
640 : OOJS_NATIVE_ENTER(context)
641 :
642 : PlayerEntity *player = OOPlayerForScripting();
643 : NSString *key = nil;
644 : OOPlanetEntity *planet = nil;
645 :
646 : if (argc > 0) key = OOStringFromJSValue(context, OOJS_ARGV[0]);
647 : if (EXPECT_NOT(key == nil))
648 : {
649 : OOJSReportBadArguments(context, @"System", @"addMoon", MIN(argc, 1U), OOJS_ARGV, nil, @"string (planet key)");
650 : return NO;
651 : }
652 :
653 : OOJS_BEGIN_FULL_NATIVE(context)
654 : planet = [player addMoon:key];
655 : OOJS_END_FULL_NATIVE
656 :
657 : OOJS_RETURN_OBJECT(planet);
658 :
659 : OOJS_NATIVE_EXIT
660 : }
661 :
662 :
663 : // sendAllShipsAway()
664 0 : static JSBool SystemSendAllShipsAway(JSContext *context, uintN argc, jsval *vp)
665 : {
666 : OOJS_NATIVE_ENTER(context)
667 :
668 : PlayerEntity *player = OOPlayerForScripting();
669 :
670 : [player sendAllShipsAway];
671 : OOJS_RETURN_VOID;
672 :
673 : OOJS_NATIVE_EXIT
674 : }
675 :
676 :
677 : // countShipsWithPrimaryRole(role : String [, relativeTo : Entity [, range : Number]]) : Number
678 0 : static JSBool SystemCountShipsWithPrimaryRole(JSContext *context, uintN argc, jsval *vp)
679 : {
680 : OOJS_NATIVE_ENTER(context)
681 :
682 : NSString *role = nil;
683 : Entity *relativeTo = nil;
684 : double range = -1;
685 : unsigned result;
686 :
687 : if (argc > 0) role = OOStringFromJSValue(context, OOJS_ARGV[0]);
688 : if (EXPECT_NOT(role == nil))
689 : {
690 : OOJSReportBadArguments(context, @"System", @"countShipsWithPrimaryRole", MIN(argc, 1U), OOJS_ARGV, nil, @"string (role)");
691 : return NO;
692 : }
693 :
694 : // Get optional arguments
695 : argc -= 1;
696 : jsval *argv = OOJS_ARGV + 1;
697 : if (EXPECT_NOT(!GetRelativeToAndRange(context, @"countShipsWithPrimaryRole", &argc, &argv, &relativeTo, &range))) return NO;
698 :
699 : OOJS_BEGIN_FULL_NATIVE(context)
700 : result = [UNIVERSE countShipsWithPrimaryRole:role inRange:range ofEntity:relativeTo];
701 : OOJS_END_FULL_NATIVE
702 :
703 : OOJS_RETURN_INT(result);
704 :
705 : OOJS_NATIVE_EXIT
706 : }
707 :
708 :
709 : // countShipsWithRole(role : String [, relativeTo : Entity [, range : Number]]) : Number
710 0 : static JSBool SystemCountShipsWithRole(JSContext *context, uintN argc, jsval *vp)
711 : {
712 : OOJS_NATIVE_ENTER(context)
713 :
714 : NSString *role = nil;
715 : Entity *relativeTo = nil;
716 : double range = -1;
717 : unsigned result;
718 :
719 : if (argc > 0) role = OOStringFromJSValue(context, OOJS_ARGV[0]);
720 : if (EXPECT_NOT(role == nil))
721 : {
722 : OOJSReportBadArguments(context, @"System", @"countShipsWithRole", MIN(argc, 1U), OOJS_ARGV, nil, @"string (role)");
723 : return NO;
724 : }
725 :
726 : // Get optional arguments
727 : argc -= 1;
728 : jsval *argv = OOJS_ARGV + 1;
729 : if (EXPECT_NOT(!GetRelativeToAndRange(context, @"countShipsWithRole", &argc, &argv, &relativeTo, &range))) return NO;
730 :
731 : OOJS_BEGIN_FULL_NATIVE(context)
732 : result = [UNIVERSE countShipsWithRole:role inRange:range ofEntity:relativeTo];
733 : OOJS_END_FULL_NATIVE
734 :
735 : OOJS_RETURN_INT(result);
736 :
737 : OOJS_NATIVE_EXIT
738 : }
739 :
740 :
741 : // shipsWithPrimaryRole(role : String [, relativeTo : Entity [, range : Number]]) : Array (Entity)
742 0 : static JSBool SystemShipsWithPrimaryRole(JSContext *context, uintN argc, jsval *vp)
743 : {
744 : OOJS_NATIVE_ENTER(context)
745 :
746 : NSString *role = nil;
747 : Entity *relativeTo = nil;
748 : double range = -1;
749 : NSArray *result = nil;
750 :
751 : if (argc > 0) role = OOStringFromJSValue(context, OOJS_ARGV[0]);
752 : if (EXPECT_NOT(role == nil))
753 : {
754 : OOJSReportBadArguments(context, @"System", @"countShipsWithRole", MIN(argc, 1U), OOJS_ARGV, nil, @"string (role)");
755 : return NO;
756 : }
757 :
758 : // Get optional arguments
759 : argc -= 1;
760 : jsval *argv = OOJS_ARGV + 1;
761 : if (EXPECT_NOT(!GetRelativeToAndRange(context, @"shipsWithPrimaryRole", &argc, &argv, &relativeTo, &range))) return NO;
762 :
763 : // Search for entities
764 : OOJS_BEGIN_FULL_NATIVE(context)
765 : result = FindShips(HasPrimaryRolePredicate, role, relativeTo, range);
766 : OOJS_END_FULL_NATIVE
767 :
768 : OOJS_RETURN_OBJECT(result);
769 :
770 : OOJS_NATIVE_EXIT
771 : }
772 :
773 :
774 : // shipsWithRole(role : String [, relativeTo : Entity [, range : Number]]) : Array (Entity)
775 0 : static JSBool SystemShipsWithRole(JSContext *context, uintN argc, jsval *vp)
776 : {
777 : OOJS_NATIVE_ENTER(context)
778 :
779 : NSString *role = nil;
780 : Entity *relativeTo = nil;
781 : double range = -1;
782 : NSArray *result = nil;
783 :
784 : if (argc > 0) role = OOStringFromJSValue(context, OOJS_ARGV[0]);
785 : if (EXPECT_NOT(role == nil))
786 : {
787 : OOJSReportBadArguments(context, @"System", @"shipsWithRole", MIN(argc, 1U), OOJS_ARGV, nil, @"string (role)");
788 : return NO;
789 : }
790 :
791 : // Get optional arguments
792 : argc -= 1;
793 : jsval *subargv = OOJS_ARGV + 1;
794 : if (EXPECT_NOT(!GetRelativeToAndRange(context, @"shipsWithRole", &argc, &subargv, &relativeTo, &range))) return NO;
795 :
796 : // Search for entities
797 : OOJS_BEGIN_FULL_NATIVE(context)
798 : result = FindShips(HasRolePredicate, role, relativeTo, range);
799 : OOJS_END_FULL_NATIVE
800 :
801 : OOJS_RETURN_OBJECT(result);
802 :
803 : OOJS_NATIVE_EXIT
804 : }
805 :
806 :
807 : // countEntitiesWithScanClass(scanClass : String [, relativeTo : Entity [, range : Number]]) : Number
808 0 : static JSBool SystemCountEntitiesWithScanClass(JSContext *context, uintN argc, jsval *vp)
809 : {
810 : OOJS_NATIVE_ENTER(context)
811 :
812 : OOScanClass scanClass = CLASS_NOT_SET;
813 : Entity *relativeTo = nil;
814 : double range = -1;
815 : unsigned result;
816 :
817 : if (argc > 0) scanClass = OOScanClassFromJSValue(context, OOJS_ARGV[0]);
818 : if (scanClass == CLASS_NOT_SET)
819 : {
820 : OOJSReportBadArguments(context, @"System", @"countEntitiesWithScanClass", MIN(argc, 1U), OOJS_ARGV, nil, @"string (scan class)");
821 : return NO;
822 : }
823 :
824 : // Get optional arguments
825 : argc -= 1;
826 : jsval *argv = OOJS_ARGV + 1;
827 : if (EXPECT_NOT(!GetRelativeToAndRange(context, @"countEntitiesWithScanClass", &argc, &argv, &relativeTo, &range))) return NO;
828 :
829 : OOJS_BEGIN_FULL_NATIVE(context)
830 : result = [UNIVERSE countShipsWithScanClass:scanClass inRange:range ofEntity:relativeTo];
831 : OOJS_END_FULL_NATIVE
832 :
833 : OOJS_RETURN_INT(result);
834 :
835 : OOJS_NATIVE_EXIT
836 : }
837 :
838 :
839 : // entitiesWithScanClass(scanClass : String [, relativeTo : Entity [, range : Number]]) : Array (Entity)
840 0 : static JSBool SystemEntitiesWithScanClass(JSContext *context, uintN argc, jsval *vp)
841 : {
842 : OOJS_NATIVE_ENTER(context)
843 :
844 : OOScanClass scanClass = CLASS_NOT_SET;
845 : Entity *relativeTo = nil;
846 : double range = -1;
847 : NSArray *result = nil;
848 :
849 : if (argc > 0) scanClass = OOScanClassFromJSValue(context, OOJS_ARGV[0]);
850 : if (scanClass == CLASS_NOT_SET)
851 : {
852 : OOJSReportBadArguments(context, @"System", @"countEntitiesWithScanClass", MIN(argc, 1U), OOJS_ARGV, nil, @"string (scan class)");
853 : return NO;
854 : }
855 :
856 : // Get optional arguments
857 : argc -= 1;
858 : jsval *argv = OOJS_ARGV + 1;
859 : if (EXPECT_NOT(!GetRelativeToAndRange(context, @"entitiesWithScanClass", &argc, &argv, &relativeTo, &range))) return NO;
860 :
861 : // Search for entities
862 : OOJS_BEGIN_FULL_NATIVE(context)
863 : result = FindJSVisibleEntities(HasScanClassPredicate, [NSNumber numberWithInt:scanClass], relativeTo, range);
864 : OOJS_END_FULL_NATIVE
865 :
866 : OOJS_RETURN_OBJECT(result);
867 :
868 : OOJS_NATIVE_EXIT
869 : }
870 :
871 :
872 : // filteredEntities(this : Object, predicate : Function [, relativeTo : Entity [, range : Number]]) : Array (Entity)
873 0 : static JSBool SystemFilteredEntities(JSContext *context, uintN argc, jsval *vp)
874 : {
875 : OOJS_NATIVE_ENTER(context)
876 :
877 : JSObject *jsThis = NULL;
878 : jsval predicate;
879 : Entity *relativeTo = nil;
880 : double range = -1;
881 : NSArray *result = nil;
882 :
883 : // Get this and predicate arguments
884 : if (argc < 2 || !OOJSValueIsFunction(context, OOJS_ARGV[1]) || !JS_ValueToObject(context, OOJS_ARGV[0], &jsThis))
885 : {
886 : OOJSReportBadArguments(context, @"System", @"filteredEntities", argc, OOJS_ARGV, nil, @"this, predicate function, and optional reference entity and range");
887 : return NO;
888 : }
889 : predicate = OOJS_ARGV[1];
890 :
891 : // Get optional arguments
892 : argc -= 2;
893 : jsval *argv = OOJS_ARGV + 2;
894 : if (EXPECT_NOT(!GetRelativeToAndRange(context, @"filteredEntities", &argc, &argv, &relativeTo, &range))) return NO;
895 :
896 : // Search for entities
897 : JSFunctionPredicateParameter param = { context, predicate, jsThis, NO };
898 : OOJSPauseTimeLimiter();
899 : result = FindJSVisibleEntities(JSFunctionPredicate, ¶m, relativeTo, range);
900 : OOJSResumeTimeLimiter();
901 :
902 : if (EXPECT_NOT(param.errorFlag)) return NO;
903 :
904 : OOJS_RETURN_OBJECT(result);
905 :
906 : OOJS_NATIVE_EXIT
907 : }
908 :
909 :
910 : // locationFromCode(populator_named_region : String)
911 0 : static JSBool SystemLocationFromCode(JSContext *context, uintN argc, jsval *vp)
912 : {
913 : OOJS_NATIVE_ENTER(context)
914 :
915 : NSString *code = nil;
916 : if (argc > 0)
917 : {
918 : code = OOStringFromJSValue(context, OOJS_ARGV[0]);
919 : }
920 : if (EXPECT_NOT(code == nil))
921 : {
922 : OOJSReportBadArguments(context, @"System", @"locationFromCode", argc, OOJS_ARGV, nil, @"location code");
923 : return NO;
924 : }
925 : OOSunEntity *sun = [UNIVERSE sun];
926 : OOPlanetEntity *planet = [UNIVERSE planet];
927 : HPVector position = kZeroHPVector;
928 : if (sun == nil || planet == nil)
929 : {
930 : position = [UNIVERSE locationByCode:@"WITCHPOINT" withSun:nil andPlanet:nil];
931 : }
932 : else
933 : {
934 : position = [UNIVERSE locationByCode:code withSun:sun andPlanet:planet];
935 : }
936 :
937 : OOJS_RETURN_HPVECTOR(position);
938 :
939 : OOJS_NATIVE_EXIT
940 : }
941 :
942 :
943 : // addShips(role : String, count : Number [, position: Vector [, radius: Number]]) : Array
944 0 : static JSBool SystemAddShips(JSContext *context, uintN argc, jsval *vp)
945 : {
946 : return SystemAddShipsOrGroup(context, argc, vp, NO);
947 : }
948 :
949 :
950 : // addGroup(role : String, count : Number [, position: Vector [, radius: Number]]) : Array
951 0 : static JSBool SystemAddGroup(JSContext *context, uintN argc, jsval *vp)
952 : {
953 : return SystemAddShipsOrGroup(context, argc, vp, YES);
954 : }
955 :
956 :
957 : // addShipsToRoute(role : String, count : Number [, position: Number [, route: String]])
958 0 : static JSBool SystemAddShipsToRoute(JSContext *context, uintN argc, jsval *vp)
959 : {
960 : return SystemAddShipsOrGroupToRoute(context, argc, vp, NO);
961 : }
962 :
963 :
964 : // addGroupToRoute(role : String, count : Number, position: Number[, route: String])
965 0 : static JSBool SystemAddGroupToRoute(JSContext *context, uintN argc, jsval *vp)
966 : {
967 : return SystemAddShipsOrGroupToRoute(context, argc, vp, YES);
968 : }
969 :
970 :
971 : // legacy_addShips(role : String, count : Number)
972 0 : static JSBool SystemLegacyAddShips(JSContext *context, uintN argc, jsval *vp)
973 : {
974 : OOStandardsDeprecated(@"system.legacy_addShips() is deprecated");
975 : OOJS_NATIVE_ENTER(context)
976 :
977 : NSString *role = nil;
978 : int32 count;
979 :
980 : if (argc > 0) role = OOStringFromJSValue(context, OOJS_ARGV[0]);
981 : if (EXPECT_NOT(role == nil ||
982 : !JS_ValueToInt32(context, OOJS_ARGV[1], &count) ||
983 : argc < 2 ||
984 : count < 1 || 64 < count))
985 : {
986 : OOJSReportBadArguments(context, @"System", @"legacy_addShips", argc, OOJS_ARGV, nil, @"role and positive count no greater than 64");
987 : return NO;
988 : }
989 :
990 : OOJS_BEGIN_FULL_NATIVE(context)
991 : while (count--) [UNIVERSE witchspaceShipWithPrimaryRole:role];
992 : OOJS_END_FULL_NATIVE
993 :
994 : OOJS_RETURN_VOID;
995 :
996 : OOJS_NATIVE_EXIT
997 : }
998 :
999 :
1000 : // legacy_addSystemShips(role : String, count : Number, location : Number)
1001 0 : static JSBool SystemLegacyAddSystemShips(JSContext *context, uintN argc, jsval *vp)
1002 : {
1003 : OOStandardsDeprecated(@"system.legacy_addSystemShips() is deprecated");
1004 : OOJS_NATIVE_ENTER(context)
1005 :
1006 : jsdouble position;
1007 : NSString *role = nil;
1008 : int32 count;
1009 :
1010 : if (argc > 0) role = OOStringFromJSValue(context, OOJS_ARGV[0]);
1011 : if (EXPECT_NOT(role == nil ||
1012 : !JS_ValueToInt32(context, OOJS_ARGV[1], &count) ||
1013 : count < 1 || 64 < count ||
1014 : argc < 3 ||
1015 : !JS_ValueToNumber(context, OOJS_ARGV[2], &position)))
1016 : {
1017 : OOJSReportBadArguments(context, @"System", @"legacy_addSystemShips", argc, OOJS_ARGV, nil, @"role, positive count no greater than 64, and position along route");
1018 : return NO;
1019 : }
1020 :
1021 : OOJS_BEGIN_FULL_NATIVE(context)
1022 : while (count--) [UNIVERSE addShipWithRole:role nearRouteOneAt:position];
1023 : OOJS_END_FULL_NATIVE
1024 :
1025 : OOJS_RETURN_VOID;
1026 :
1027 : OOJS_NATIVE_EXIT
1028 : }
1029 :
1030 :
1031 : // legacy_addShipsAt(role : String, count : Number, coordScheme : String, coords : vectorExpression)
1032 0 : static JSBool SystemLegacyAddShipsAt(JSContext *context, uintN argc, jsval *vp)
1033 : {
1034 : OOStandardsDeprecated(@"system.legacy_addShipsAt() is deprecated");
1035 : OOJS_NATIVE_ENTER(context)
1036 :
1037 : PlayerEntity *player = OOPlayerForScripting();
1038 : HPVector where;
1039 : NSString *role = nil;
1040 : int32 count;
1041 : NSString *coordScheme = nil;
1042 : NSString *arg = nil;
1043 :
1044 : if (argc > 0) role = OOStringFromJSValue(context, OOJS_ARGV[0]);
1045 : coordScheme = OOStringFromJSValue(context, OOJS_ARGV[2]);
1046 : if (EXPECT_NOT(role == nil ||
1047 : !JS_ValueToInt32(context, OOJS_ARGV[1], &count) ||
1048 : count < 1 || 64 < count ||
1049 : coordScheme == nil ||
1050 : argc < 4 ||
1051 : !VectorFromArgumentListNoError(context, argc - 3, OOJS_ARGV + 3, &where, NULL)))
1052 : {
1053 : OOJSReportBadArguments(context, @"System", @"legacy_addShipsAt", argc, OOJS_ARGV, nil, @"role, positive count no greater than 64, coordinate scheme and coordinates");
1054 : return NO;
1055 : }
1056 :
1057 : OOJS_BEGIN_FULL_NATIVE(context)
1058 : arg = [NSString stringWithFormat:@"%@ %d %@ %f %f %f", role, count, coordScheme, where.x, where.y, where.z];
1059 : [player addShipsAt:arg];
1060 : OOJS_END_FULL_NATIVE
1061 :
1062 : OOJS_RETURN_VOID;
1063 :
1064 : OOJS_NATIVE_EXIT
1065 : }
1066 :
1067 :
1068 : // legacy_addShipsAtPrecisely(role : String, count : Number, coordScheme : String, coords : vectorExpression)
1069 0 : static JSBool SystemLegacyAddShipsAtPrecisely(JSContext *context, uintN argc, jsval *vp)
1070 : {
1071 : OOStandardsDeprecated(@"system.legacy_addShipsAtPrecisely() is deprecated");
1072 : OOJS_NATIVE_ENTER(context)
1073 :
1074 : PlayerEntity *player = OOPlayerForScripting();
1075 : HPVector where;
1076 : NSString *role = nil;
1077 : int32 count;
1078 : NSString *coordScheme = nil;
1079 : NSString *arg = nil;
1080 :
1081 : if (argc > 0) role = OOStringFromJSValue(context, OOJS_ARGV[0]);
1082 : coordScheme = OOStringFromJSValue(context, OOJS_ARGV[2]);
1083 : if (EXPECT_NOT(role == nil ||
1084 : !JS_ValueToInt32(context, OOJS_ARGV[1], &count) ||
1085 : count < 1 || 64 < count ||
1086 : coordScheme == nil ||
1087 : argc < 4 ||
1088 : !VectorFromArgumentListNoError(context, argc - 3, OOJS_ARGV + 3, &where, NULL)))
1089 : {
1090 : OOJSReportBadArguments(context, @"System", @"legacy_addShipsAtPrecisely", argc, OOJS_ARGV, nil, @"role, positive count no greater than 64, coordinate scheme and coordinates");
1091 : return NO;
1092 : }
1093 :
1094 : OOJS_BEGIN_FULL_NATIVE(context)
1095 : arg = [NSString stringWithFormat:@"%@ %d %@ %f %f %f", role, count, coordScheme, where.x, where.y, where.z];
1096 : [player addShipsAtPrecisely:arg];
1097 : OOJS_END_FULL_NATIVE
1098 :
1099 : OOJS_RETURN_VOID;
1100 :
1101 : OOJS_NATIVE_EXIT
1102 : }
1103 :
1104 :
1105 : // legacy_addShipsWithinRadius(role : String, count : Number, coordScheme : String, coords : vectorExpression, radius : Number)
1106 0 : static JSBool SystemLegacyAddShipsWithinRadius(JSContext *context, uintN argc, jsval *vp)
1107 : {
1108 : OOStandardsDeprecated(@"system.legacy_addShipsWithinRadius() is deprecated");
1109 : OOJS_NATIVE_ENTER(context)
1110 :
1111 : PlayerEntity *player = OOPlayerForScripting();
1112 : HPVector where;
1113 : jsdouble radius;
1114 : NSString *role = nil;
1115 : int32 count;
1116 : NSString *coordScheme = nil;
1117 : NSString *arg = nil;
1118 : uintN consumed = 0;
1119 :
1120 : if (argc > 0) role = OOStringFromJSValue(context, OOJS_ARGV[0]);
1121 : if (argc > 2) coordScheme = OOStringFromJSValue(context, OOJS_ARGV[2]);
1122 : if (EXPECT_NOT(role == nil ||
1123 : !JS_ValueToInt32(context, OOJS_ARGV[1], &count) ||
1124 : count < 1 || 64 < count ||
1125 : coordScheme == nil ||
1126 : argc < 5 ||
1127 : !VectorFromArgumentListNoError(context, argc - 3, OOJS_ARGV + 3, &where, &consumed) ||
1128 : !JS_ValueToNumber(context, OOJS_ARGV[3 + consumed], &radius)))
1129 : {
1130 : OOJSReportBadArguments(context, @"System", @"legacy_addShipWithinRadius", argc, OOJS_ARGV, nil, @"role, positive count no greater than 64, coordinate scheme, coordinates and radius");
1131 : return NO;
1132 : }
1133 :
1134 : OOJS_BEGIN_FULL_NATIVE(context)
1135 : arg = [NSString stringWithFormat:@"%@ %d %@ %f %f %f %f", role, count, coordScheme, where.x, where.y, where.z, radius];
1136 : [player addShipsWithinRadius:arg];
1137 : OOJS_END_FULL_NATIVE
1138 :
1139 : OOJS_RETURN_VOID;
1140 :
1141 : OOJS_NATIVE_EXIT
1142 : }
1143 :
1144 :
1145 : // legacy_spawnShip(key : string)
1146 0 : static JSBool SystemLegacySpawnShip(JSContext *context, uintN argc, jsval *vp)
1147 : {
1148 : OOStandardsDeprecated(@"system.legacy_spawnShip() is deprecated");
1149 : OOJS_NATIVE_ENTER(context)
1150 :
1151 : NSString *key = nil;
1152 : OOPlayerForScripting(); // For backwards-compatibility
1153 :
1154 : if (argc > 0) key = OOStringFromJSValue(context, OOJS_ARGV[0]);
1155 : if (key == nil)
1156 : {
1157 : OOJSReportBadArguments(context, @"System", @"legacy_spawnShip", MIN(argc, 1U), OOJS_ARGV, nil, @"string (ship key)");
1158 : return NO;
1159 : }
1160 :
1161 : OOJS_BEGIN_FULL_NATIVE(context)
1162 : [UNIVERSE spawnShip:key];
1163 : OOJS_END_FULL_NATIVE
1164 :
1165 : OOJS_RETURN_VOID;
1166 :
1167 : OOJS_NATIVE_EXIT
1168 : }
1169 :
1170 :
1171 : // *** Static methods ***
1172 :
1173 : // systemNameForID(ID : Number) : String
1174 0 : static JSBool SystemStaticSystemNameForID(JSContext *context, uintN argc, jsval *vp)
1175 : {
1176 : OOJS_NATIVE_ENTER(context)
1177 :
1178 : int32 systemID;
1179 :
1180 : if (argc < 1 || !JS_ValueToInt32(context, OOJS_ARGV[0], &systemID) || systemID < -1 || kOOMaximumSystemID < systemID) // -1 interstellar space!
1181 : {
1182 : OOJSReportBadArguments(context, @"System", @"systemNameForID", MIN(argc, 1U), OOJS_ARGV, nil, @"system ID");
1183 : return NO;
1184 : }
1185 :
1186 : if (systemID == -1)
1187 : OOJS_RETURN_OBJECT(DESC(@"interstellar-space"));
1188 : else
1189 : OOJS_RETURN_OBJECT([UNIVERSE getSystemName:systemID]);
1190 :
1191 : OOJS_NATIVE_EXIT
1192 : }
1193 :
1194 :
1195 : // systemIDForName(name : String) : Number
1196 0 : static JSBool SystemStaticSystemIDForName(JSContext *context, uintN argc, jsval *vp)
1197 : {
1198 : OOJS_NATIVE_ENTER(context)
1199 :
1200 : NSString *name = nil;
1201 : unsigned result;
1202 :
1203 : if (argc > 0) name = OOStringFromJSValue(context, OOJS_ARGV[0]);
1204 : if (name == nil)
1205 : {
1206 : OOJSReportBadArguments(context, @"System", @"systemIDForName", MIN(argc, 1U), OOJS_ARGV, nil, @"string");
1207 : return NO;
1208 : }
1209 :
1210 : OOJS_BEGIN_FULL_NATIVE(context)
1211 :
1212 : result = [UNIVERSE findSystemFromName:name];
1213 :
1214 : OOJS_END_FULL_NATIVE
1215 :
1216 : OOJS_RETURN_INT(result);
1217 :
1218 : OOJS_NATIVE_EXIT
1219 : }
1220 :
1221 :
1222 : // infoForSystem(galaxyID : Number, systemID : Number) : SystemInfo
1223 0 : static JSBool SystemStaticInfoForSystem(JSContext *context, uintN argc, jsval *vp)
1224 : {
1225 : OOJS_NATIVE_ENTER(context)
1226 :
1227 : int32 galaxyID;
1228 : int32 systemID;
1229 :
1230 : if (argc < 2 || !JS_ValueToInt32(context, OOJS_ARGV[0], &galaxyID) || !JS_ValueToInt32(context, OOJS_ARGV[1], &systemID))
1231 : {
1232 : OOJSReportBadArguments(context, @"System", @"infoForSystem", argc, OOJS_ARGV, nil, @"galaxy ID and system ID");
1233 : return NO;
1234 : }
1235 :
1236 : if (galaxyID < 0 || galaxyID > kOOMaximumGalaxyID)
1237 : {
1238 : OOJSReportBadArguments(context, @"System", @"infoForSystem", 1, OOJS_ARGV, @"Invalid galaxy ID", [NSString stringWithFormat:@"number in the range 0 to %u", kOOMaximumGalaxyID]);
1239 : return NO;
1240 : }
1241 :
1242 : if (systemID < kOOMinimumSystemID || systemID > kOOMaximumSystemID)
1243 : {
1244 : OOJSReportBadArguments(context, @"System", @"infoForSystem", 1, OOJS_ARGV + 1, @"Invalid system ID", [NSString stringWithFormat:@"number in the range %i to %i", kOOMinimumSystemID, kOOMaximumSystemID]);
1245 : return NO;
1246 : }
1247 :
1248 : OOJS_RETURN(GetJSSystemInfoForSystem(context, galaxyID, systemID));
1249 :
1250 : OOJS_NATIVE_EXIT
1251 : }
1252 :
1253 :
1254 0 : static JSBool SystemAddVisualEffect(JSContext *context, uintN argc, jsval *vp)
1255 : {
1256 : OOJS_NATIVE_ENTER(context)
1257 :
1258 : NSString *key = nil;
1259 : HPVector where;
1260 :
1261 : uintN consumed = 0;
1262 :
1263 : if (argc > 0) key = OOStringFromJSValue(context, OOJS_ARGV[0]);
1264 : if (key == nil)
1265 : {
1266 : OOJSReportBadArguments(context, @"System", @"addVisualEffect", MIN(argc, 1U), &OOJS_ARGV[0], nil, @"string (key)");
1267 : return NO;
1268 : }
1269 :
1270 : if (!VectorFromArgumentListNoError(context, argc - 1, OOJS_ARGV + 1, &where, &consumed))
1271 : {
1272 : OOJSReportBadArguments(context, @"System", @"addVisualEffect", MIN(argc - 1, 1U), &OOJS_ARGV[1], nil, @"vector");
1273 : return NO;
1274 : }
1275 :
1276 : OOVisualEffectEntity *result = nil;
1277 :
1278 : OOJS_BEGIN_FULL_NATIVE(context)
1279 :
1280 : result = [UNIVERSE addVisualEffectAt:where withKey:key];
1281 :
1282 : OOJS_END_FULL_NATIVE
1283 :
1284 : OOJS_RETURN_OBJECT(result);
1285 :
1286 : OOJS_NATIVE_EXIT
1287 : }
1288 :
1289 0 : static JSBool SystemSetPopulator(JSContext *context, uintN argc, jsval *vp)
1290 : {
1291 : OOJS_NATIVE_ENTER(context)
1292 :
1293 : NSString *key;
1294 : NSMutableDictionary *settings;
1295 : JSObject *params = NULL;
1296 :
1297 : if (argc < 1)
1298 : {
1299 : OOJSReportBadArguments(context, @"System", @"setPopulator", MIN(argc, 0U), &OOJS_ARGV[0], nil, @"string (key), object (settings)");
1300 : return NO;
1301 : }
1302 : key = OOStringFromJSValue(context, OOJS_ARGV[0]);
1303 : if (key == nil)
1304 : {
1305 : OOJSReportBadArguments(context, @"System", @"setPopulator", MIN(argc, 0U), &OOJS_ARGV[0], nil, @"key, settings");
1306 : return NO;
1307 : }
1308 : if (argc < 2 || JSVAL_IS_NULL(OOJS_ARGV[1]))
1309 : {
1310 : // clearing
1311 : [UNIVERSE setPopulatorSetting:key to:nil];
1312 : }
1313 : else
1314 : {
1315 : // adding
1316 : if (!JS_ValueToObject(context, OOJS_ARGV[1], ¶ms))
1317 : {
1318 : OOJSReportBadArguments(context, @"System", @"setPopulator", MIN(argc, 1U), OOJS_ARGV, NULL, @"key, settings");
1319 : return NO;
1320 : }
1321 : jsval callback = JSVAL_NULL;
1322 : if (JS_GetProperty(context, params, "callback", &callback) == JS_FALSE || JSVAL_IS_VOID(callback))
1323 : {
1324 : OOJSReportBadArguments(context, @"System", @"setPopulator", MIN(argc, 1U), OOJS_ARGV, NULL, @"settings must have a 'callback' property.");
1325 : return NO;
1326 : }
1327 :
1328 : OOJSPopulatorDefinition *populator = [[OOJSPopulatorDefinition alloc] init];
1329 : [populator setCallback:callback];
1330 :
1331 : settings = OOJSNativeObjectFromJSObject(context, JSVAL_TO_OBJECT(OOJS_ARGV[1]));
1332 : [settings setObject:populator forKey:@"callbackObj"];
1333 :
1334 : jsval coords = JSVAL_NULL;
1335 : if (JS_GetProperty(context, params, "coordinates", &coords) != JS_FALSE && !JSVAL_IS_VOID(coords))
1336 : {
1337 : Vector coordinates = kZeroVector;
1338 : if (JSValueToVector(context, coords, &coordinates))
1339 : {
1340 : // convert vector in NS-storable form
1341 : [settings setObject:[NSArray arrayWithObjects:[NSNumber numberWithFloat:coordinates.x],[NSNumber numberWithFloat:coordinates.y],[NSNumber numberWithFloat:coordinates.z],nil] forKey:@"coordinates"];
1342 : }
1343 : }
1344 :
1345 : [populator release];
1346 :
1347 : [UNIVERSE setPopulatorSetting:key to:settings];
1348 : }
1349 :
1350 : OOJS_RETURN_VOID;
1351 :
1352 : OOJS_NATIVE_EXIT
1353 : }
1354 :
1355 :
1356 0 : static JSBool SystemSetWaypoint(JSContext *context, uintN argc, jsval *vp)
1357 : {
1358 : OOJS_NATIVE_ENTER(context)
1359 :
1360 : NSString *key;
1361 : NSMutableDictionary *settings;
1362 : HPVector position;
1363 : Quaternion orientation;
1364 :
1365 : if (argc < 1)
1366 : {
1367 : OOJSReportBadArguments(context, @"System", @"setWaypoint", MIN(argc, 0U), &OOJS_ARGV[0], nil, @"key, position, orientation, definition");
1368 : return NO;
1369 : }
1370 : key = OOStringFromJSValue(context, OOJS_ARGV[0]);
1371 : if (key == nil)
1372 : {
1373 : OOJSReportBadArguments(context, @"System", @"setWaypoint", MIN(argc, 0U), &OOJS_ARGV[0], nil, @"key, position, orientation, definition");
1374 : return NO;
1375 : }
1376 : if (argc < 4 || JSVAL_IS_NULL(OOJS_ARGV[3]))
1377 : {
1378 : // clearing
1379 : [UNIVERSE defineWaypoint:nil forKey:key];
1380 : }
1381 : else
1382 : {
1383 : // adding
1384 : if (!JSValueToHPVector(context, OOJS_ARGV[1], &position))
1385 : {
1386 : OOJSReportBadArguments(context, @"System", @"setWaypoint", MIN(argc, 2U), OOJS_ARGV, NULL, @"key, position, orientation, definition");
1387 : return NO;
1388 : }
1389 : if (!JSValueToQuaternion(context, OOJS_ARGV[2], &orientation))
1390 : {
1391 : OOJSReportBadArguments(context, @"System", @"setWaypoint", MIN(argc, 3U), OOJS_ARGV, NULL, @"key, position, orientation, definition");
1392 : return NO;
1393 : }
1394 : if (!JSVAL_IS_OBJECT(OOJS_ARGV[3]) || JSVAL_IS_NULL(OOJS_ARGV[3]))
1395 : {
1396 : OOJSReportBadArguments(context, @"System", @"setWaypoint", MIN(argc, 4U), OOJS_ARGV, NULL, @"key, position, orientation, definition");
1397 : return NO;
1398 : }
1399 :
1400 : settings = [[OOJSNativeObjectFromJSObject(context, JSVAL_TO_OBJECT(OOJS_ARGV[3])) mutableCopy] autorelease];
1401 : [settings setObject:[NSArray arrayWithObjects:[NSNumber numberWithDouble:position.x],[NSNumber numberWithDouble:position.y],[NSNumber numberWithDouble:position.z],nil] forKey:@"position"];
1402 : [settings setObject:[NSArray arrayWithObjects:[NSNumber numberWithDouble:orientation.w],[NSNumber numberWithDouble:orientation.x],[NSNumber numberWithDouble:orientation.y],[NSNumber numberWithDouble:orientation.z],nil] forKey:@"orientation"];
1403 :
1404 : [UNIVERSE defineWaypoint:settings forKey:key];
1405 : }
1406 :
1407 : OOJS_RETURN_VOID;
1408 :
1409 : OOJS_NATIVE_EXIT
1410 : }
1411 :
1412 : // *** Helper functions ***
1413 :
1414 : // Shared implementation of addShips() and addGroup().
1415 0 : static JSBool SystemAddShipsOrGroup(JSContext *context, uintN argc, jsval *vp, BOOL isGroup)
1416 : {
1417 : OOJS_NATIVE_ENTER(context)
1418 :
1419 : NSString *role = nil;
1420 : int32 count = 0;
1421 : uintN consumed = 0;
1422 : HPVector where;
1423 : double radius = NSNotFound; // a negative value means
1424 : id result = nil;
1425 :
1426 : NSString *func = isGroup ? @"addGroup" : @"addShips";
1427 :
1428 : if (argc > 0) role = OOStringFromJSValue(context, OOJS_ARGV[0]);
1429 : if (role == nil)
1430 : {
1431 : OOJSReportBadArguments(context, @"System", func, MIN(argc, 1U), &OOJS_ARGV[0], nil, @"string (role)");
1432 : return NO;
1433 : }
1434 : if (argc < 2 || !JS_ValueToInt32(context, OOJS_ARGV[1], &count) || count < 1 || 64 < count)
1435 : {
1436 : OOJSReportBadArguments(context, @"System", func, MIN(argc - 1, 1U), &OOJS_ARGV[1], nil, @"number (positive count no greater than 64)");
1437 : return NO;
1438 : }
1439 :
1440 : if (argc < 3)
1441 : {
1442 : where = [UNIVERSE getWitchspaceExitPosition];
1443 : radius = SCANNER_MAX_RANGE;
1444 : }
1445 : else
1446 : {
1447 : if (!VectorFromArgumentListNoError(context, argc - 2, OOJS_ARGV + 2, &where, &consumed))
1448 : {
1449 : OOJSReportBadArguments(context, @"System", func, MIN(argc - 2, 1U), &OOJS_ARGV[2], nil, @"vector");
1450 : return NO;
1451 : }
1452 :
1453 : if (argc > 2 + consumed)
1454 : {
1455 : if (!JS_ValueToNumber(context, OOJS_ARGV[2 + consumed], &radius))
1456 : {
1457 : OOJSReportBadArguments(context, @"System", func, MIN(argc - 2 - consumed, 1U), &OOJS_ARGV[2 + consumed], nil, @"number (radius)");
1458 : return NO;
1459 : }
1460 : }
1461 : }
1462 :
1463 : OOJS_BEGIN_FULL_NATIVE(context)
1464 : // Note: the use of witchspace-in effects (as in legacy_addShips) depends on proximity to the witchpoint.
1465 : result = [UNIVERSE addShipsAt:where withRole:role quantity:count withinRadius:radius asGroup:isGroup];
1466 :
1467 : if (isGroup)
1468 : {
1469 : NSArray *array = result;
1470 : if ([array count] > 0) result = [(ShipEntity *)[array objectAtIndex:0] group];
1471 : else result = nil;
1472 : }
1473 : OOJS_END_FULL_NATIVE
1474 :
1475 : OOJS_RETURN_OBJECT(result);
1476 :
1477 : OOJS_NATIVE_EXIT
1478 : }
1479 :
1480 :
1481 0 : static JSBool SystemAddShipsOrGroupToRoute(JSContext *context, uintN argc, jsval *vp, BOOL isGroup)
1482 : {
1483 : OOJS_NATIVE_ENTER(context)
1484 :
1485 : NSString *role = nil;
1486 : NSString *route = @"st"; // default route witchpoint -> station. ("st" itself is not selectable by script)
1487 : static NSSet *validRoutes = nil;
1488 : int32 count = 0;
1489 : double where = NSNotFound; // a negative value means random positioning!
1490 : id result = nil;
1491 :
1492 : NSString *func = isGroup ? @"addGroup" : @"addShips";
1493 :
1494 : if (argc > 0) role = OOStringFromJSValue(context, OOJS_ARGV[0]);
1495 : if (role == nil)
1496 : {
1497 : OOJSReportBadArguments(context, @"System", func, MIN(argc, 1U), &OOJS_ARGV[0], nil, @"string (role)");
1498 : return NO;
1499 : }
1500 : if (argc < 2 || !JS_ValueToInt32(context, OOJS_ARGV[1], &count) || count < 1 || 64 < count)
1501 : {
1502 : OOJSReportBadArguments(context, @"System", func, MIN(argc - 1, 1U), &OOJS_ARGV[1], nil, @"number (positive count no greater than 64)");
1503 : return NO;
1504 : }
1505 :
1506 : if (argc > 2)
1507 : {
1508 : if (!JS_ValueToNumber(context, OOJS_ARGV[2], &where) || !isfinite(where) || where < 0.0f || where > 1.0f)
1509 : {
1510 : OOJSReportBadArguments(context, @"System", func, MIN(argc - 2, 1U), &OOJS_ARGV[2], nil, @"number (position along route)");
1511 : return NO;
1512 : }
1513 :
1514 : if (argc > 3)
1515 : {
1516 : route = [OOStringFromJSValue(context, OOJS_ARGV[3]) lowercaseString];
1517 :
1518 : if (validRoutes == nil)
1519 : {
1520 : validRoutes = [[NSSet alloc] initWithObjects:@"wp", @"pw", @"ws", @"sw", @"sp", @"ps", nil];
1521 : }
1522 :
1523 : if (route == nil || ![validRoutes containsObject:route])
1524 : {
1525 : OOJSReportBadArguments(context, @"System", func, MIN(argc - 3, 1U), &OOJS_ARGV[3], nil, @"string (route specifier)");
1526 : return NO;
1527 : }
1528 : }
1529 : }
1530 :
1531 : OOJS_BEGIN_FULL_NATIVE(context)
1532 : // Note: the use of witchspace-in effects (as in legacy_addShips) depends on proximity to the witchpoint.
1533 : result = [UNIVERSE addShipsToRoute:route withRole:role quantity:count routeFraction:where asGroup:isGroup];
1534 :
1535 : if (isGroup)
1536 : {
1537 : NSArray *array = result;
1538 : if ([array count] > 0) result = [(ShipEntity *)[array objectAtIndex:0] group];
1539 : else result = nil;
1540 : }
1541 : OOJS_END_FULL_NATIVE
1542 :
1543 : OOJS_RETURN_OBJECT(result);
1544 :
1545 : OOJS_NATIVE_EXIT
1546 : }
1547 :
1548 :
1549 0 : static BOOL GetRelativeToAndRange(JSContext *context, NSString *methodName, uintN *ioArgc, jsval **ioArgv, Entity **outRelativeTo, double *outRange)
1550 : {
1551 : OOJS_PROFILE_ENTER
1552 :
1553 : // No NULL arguments accepted.
1554 : assert(ioArgc && ioArgv && outRelativeTo && outRange);
1555 :
1556 : // Get optional argument relativeTo : Entity
1557 : if (*ioArgc != 0)
1558 : {
1559 : if (EXPECT_NOT(JSVAL_IS_NULL(**ioArgv) || !JSValueToEntity(context, **ioArgv, outRelativeTo)))
1560 : {
1561 : OOJSReportBadArguments(context, @"System", methodName, 1, *ioArgv, nil, @"entity");
1562 : return NO;
1563 : }
1564 : (*ioArgv)++; (*ioArgc)--;
1565 : }
1566 :
1567 : // Get optional argument range : Number
1568 : if (*ioArgc != 0)
1569 : {
1570 : if (!EXPECT_NOT(JS_ValueToNumber(context, **ioArgv, outRange)))
1571 : {
1572 : OOJSReportBadArguments(context, @"System", methodName, 1, *ioArgv, nil, @"number");
1573 : return NO;
1574 : }
1575 : (*ioArgv)++; (*ioArgc)--;
1576 : }
1577 :
1578 : return YES;
1579 :
1580 : OOJS_PROFILE_EXIT
1581 : }
1582 :
1583 :
1584 0 : static NSArray *FindJSVisibleEntities(EntityFilterPredicate predicate, void *parameter, Entity *relativeTo, double range)
1585 : {
1586 : OOJS_PROFILE_ENTER
1587 :
1588 : NSMutableArray *result = nil;
1589 : BinaryOperationPredicateParameter param =
1590 : {
1591 : JSEntityIsJavaScriptSearchablePredicate, NULL,
1592 : predicate, parameter
1593 : };
1594 :
1595 : result = [UNIVERSE findEntitiesMatchingPredicate:ANDPredicate
1596 : parameter:¶m
1597 : inRange:range
1598 : ofEntity:relativeTo];
1599 :
1600 : if (result != nil && relativeTo != nil && ![relativeTo isPlayer])
1601 : {
1602 : [result sortUsingFunction:CompareEntitiesByDistance context:relativeTo];
1603 : }
1604 : if (result == nil) return [NSArray array];
1605 : return result;
1606 :
1607 : OOJS_PROFILE_EXIT
1608 : }
1609 :
1610 :
1611 0 : static NSArray *FindShips(EntityFilterPredicate predicate, void *parameter, Entity *relativeTo, double range)
1612 : {
1613 : OOJS_PROFILE_ENTER
1614 :
1615 : BinaryOperationPredicateParameter param =
1616 : {
1617 : IsShipPredicate, NULL,
1618 : predicate, parameter
1619 : };
1620 : return FindJSVisibleEntities(ANDPredicate, ¶m, relativeTo, range);
1621 :
1622 : OOJS_PROFILE_EXIT
1623 : }
1624 :
1625 :
1626 0 : static NSComparisonResult CompareEntitiesByDistance(id a, id b, void *relativeTo)
1627 : {
1628 : OOJS_PROFILE_ENTER
1629 :
1630 : Entity *ea = a,
1631 : *eb = b,
1632 : *r = (id)relativeTo;
1633 : float d1, d2;
1634 :
1635 : d1 = HPdistance2(ea->position, r->position);
1636 : d2 = HPdistance2(eb->position, r->position);
1637 :
1638 : if (d1 < d2) return NSOrderedAscending;
1639 : else if (d1 > d2) return NSOrderedDescending;
1640 : else return NSOrderedSame;
1641 :
1642 : OOJS_PROFILE_EXIT
1643 : }
|