Line data Source code
1 0 : /*
2 :
3 : OOJSPlayerShip.h
4 :
5 : Oolite
6 : Copyright (C) 2004-2013 Giles C Williams and contributors
7 :
8 : This program is free software; you can redistribute it and/or
9 : modify it under the terms of the GNU General Public License
10 : as published by the Free Software Foundation; either version 2
11 : of the License, or (at your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : GNU General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program; if not, write to the Free Software
20 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21 : MA 02110-1301, USA.
22 :
23 : */
24 :
25 : #import "OOCollectionExtractors.h"
26 : #import "OOJSPlayer.h"
27 : #import "OOJSEntity.h"
28 : #import "OOJSShip.h"
29 : #import "OOJSVector.h"
30 : #import "OOJSQuaternion.h"
31 : #import "OOJavaScriptEngine.h"
32 : #import "EntityOOJavaScriptExtensions.h"
33 : #import "OOSystemDescriptionManager.h"
34 : #import "PlayerEntity.h"
35 : #import "PlayerEntityControls.h"
36 : #import "PlayerEntityContracts.h"
37 : #import "PlayerEntityScriptMethods.h"
38 : #import "PlayerEntityLegacyScriptEngine.h"
39 : #import "PlayerEntitySound.h"
40 : #import "HeadUpDisplay.h"
41 : #import "StationEntity.h"
42 :
43 : #import "OOConstToJSString.h"
44 : #import "OOConstToString.h"
45 : #import "OOFunctionAttributes.h"
46 : #import "OOEquipmentType.h"
47 : #import "OOJSEquipmentInfo.h"
48 :
49 :
50 0 : static JSObject *sPlayerShipPrototype;
51 0 : static JSObject *sPlayerShipObject;
52 :
53 :
54 : static JSBool PlayerShipGetProperty(JSContext *context, JSObject *this, jsid propID, jsval *value);
55 : static JSBool PlayerShipSetProperty(JSContext *context, JSObject *this, jsid propID, JSBool strict, jsval *value);
56 :
57 : static JSBool PlayerShipLaunch(JSContext *context, uintN argc, jsval *vp);
58 : static JSBool PlayerShipRemoveAllCargo(JSContext *context, uintN argc, jsval *vp);
59 : static JSBool PlayerShipUseSpecialCargo(JSContext *context, uintN argc, jsval *vp);
60 : static JSBool PlayerShipEngageAutopilotToStation(JSContext *context, uintN argc, jsval *vp);
61 : static JSBool PlayerShipDisengageAutopilot(JSContext *context, uintN argc, jsval *vp);
62 : static JSBool PlayerShipRequestDockingClearance(JSContext *context, uintN argc, jsval *vp);
63 : static JSBool PlayerShipCancelDockingRequest(JSContext *context, uintN argc, jsval *vp);
64 : static JSBool PlayerShipAwardEquipmentToCurrentPylon(JSContext *context, uintN argc, jsval *vp);
65 : static JSBool PlayerShipAddPassenger(JSContext *context, uintN argc, jsval *vp);
66 : static JSBool PlayerShipRemovePassenger(JSContext *context, uintN argc, jsval *vp);
67 : static JSBool PlayerShipAddParcel(JSContext *context, uintN argc, jsval *vp);
68 : static JSBool PlayerShipRemoveParcel(JSContext *context, uintN argc, jsval *vp);
69 : static JSBool PlayerShipAwardContract(JSContext *context, uintN argc, jsval *vp);
70 : static JSBool PlayerShipRemoveContract(JSContext *context, uintN argc, jsval *vp);
71 : static JSBool PlayerShipSetCustomView(JSContext *context, uintN argc, jsval *vp);
72 : static JSBool PlayerShipSetPrimedEquipment(JSContext *context, uintN argc, jsval *vp);
73 : static JSBool PlayerShipResetCustomView(JSContext *context, uintN argc, jsval *vp);
74 : static JSBool PlayerShipResetScannerZoom(JSContext *context, uintN argc, jsval *vp);
75 : static JSBool PlayerShipTakeInternalDamage(JSContext *context, uintN argc, jsval *vp);
76 : static JSBool PlayerShipBeginHyperspaceCountdown(JSContext *context, uintN argc, jsval *vp);
77 : static JSBool PlayerShipCancelHyperspaceCountdown(JSContext *context, uintN argc, jsval *vp);
78 : static JSBool PlayerShipBeginGalacticHyperspaceCountdown(JSContext *context, uintN argc, jsval *vp);
79 : static JSBool PlayerShipSetMultiFunctionDisplay(JSContext *context, uintN argc, jsval *vp);
80 : static JSBool PlayerShipSetMultiFunctionText(JSContext *context, uintN argc, jsval *vp);
81 : static JSBool PlayerShipHideHUDSelector(JSContext *context, uintN argc, jsval *vp);
82 : static JSBool PlayerShipShowHUDSelector(JSContext *context, uintN argc, jsval *vp);
83 : static JSBool PlayerShipSetCustomHUDDial(JSContext *context, uintN argc, jsval *vp);
84 :
85 : static BOOL ValidateContracts(JSContext *context, uintN argc, jsval *vp, BOOL isCargo, OOSystemID *start, OOSystemID *destination, double *eta, double *fee, double *premium, NSString *functionName, unsigned *risk);
86 :
87 :
88 0 : static JSClass sPlayerShipClass =
89 : {
90 : "PlayerShip",
91 : JSCLASS_HAS_PRIVATE,
92 :
93 : JS_PropertyStub, // addProperty
94 : JS_PropertyStub, // delProperty
95 : PlayerShipGetProperty, // getProperty
96 : PlayerShipSetProperty, // setProperty
97 : JS_EnumerateStub, // enumerate
98 : JS_ResolveStub, // resolve
99 : JS_ConvertStub, // convert
100 : OOJSObjectWrapperFinalize,// finalize
101 : JSCLASS_NO_OPTIONAL_MEMBERS
102 : };
103 :
104 :
105 0 : enum
106 : {
107 : // Property IDs
108 : kPlayerShip_activeMissile, // index in 'missiles' array of current active missile
109 : kPlayerShip_aftShield, // aft shield charge level, nonnegative float, read/write
110 : kPlayerShip_aftShieldRechargeRate, // aft shield recharge rate, positive float, read-only
111 : kPlayerShip_chartHightlightMode, // what type of information is being shown on the chart
112 : kPlayerShip_compassMode, // compass mode, string, read/write
113 : kPlayerShip_compassTarget, // object targeted by the compass, entity, read/write
114 : kPlayerShip_compassType, // basic / advanced, string, read/write
115 : kPlayerShip_currentWeapon, // shortcut property to _aftWeapon, etc. overrides kShip generic version
116 : kPlayerShip_crosshairs, // custom plist file defining crosshairs
117 : kPlayerShip_cursorCoordinates, // cursor coordinates (unscaled), Vector3D, read only
118 : kPlayerShip_cursorCoordinatesInLY, // cursor coordinates (in LY), Vector3D, read only
119 : kPlayerShip_docked, // docked, boolean, read-only
120 : kPlayerShip_dockedStation, // docked station, entity, read-only
121 : kPlayerShip_fastEquipmentA, // fast equipment A, string, read/write
122 : kPlayerShip_fastEquipmentB, // fast equipment B, string, read/write
123 : kPlayerShip_forwardShield, // forward shield charge level, nonnegative float, read/write
124 : kPlayerShip_forwardShieldRechargeRate, // forward shield recharge rate, positive float, read-only
125 : kPlayerShip_fuelLeakRate, // fuel leak rate, float, read/write
126 : kPlayerShip_galacticHyperspaceBehaviour, // can be standard, all systems reachable or fixed coordinates, integer, read-only
127 : kPlayerShip_galacticHyperspaceFixedCoords, // used when fixed coords behaviour is selected, Vector3D, read/write
128 : kPlayerShip_galacticHyperspaceFixedCoordsInLY, // used when fixed coords behaviour is selected, Vector3D, read/write
129 : kPlayerShip_galaxyCoordinates, // galaxy coordinates (unscaled), Vector3D, read only
130 : kPlayerShip_galaxyCoordinatesInLY, // galaxy coordinates (in LY), Vector3D, read only
131 : kPlayerShip_hud, // hud name identifier, string, read/write
132 : kPlayerShip_hudAllowsBigGui, // hud big gui, string, read only
133 : kPlayerShip_hudHidden, // hud visibility, boolean, read/write
134 : kPlayerShip_injectorsEngaged, // injectors in use, boolean, read-only
135 : kPlayerShip_massLockable, // mass-lockability of player ship, read/write
136 : kPlayerShip_maxAftShield, // maximum aft shield charge level, positive float, read-only
137 : kPlayerShip_maxForwardShield, // maximum forward shield charge level, positive float, read-only
138 : kPlayerShip_messageGuiTextColor, // message gui standard text color, array, read/write
139 : kPlayerShip_messageGuiTextCommsColor, // message gui incoming comms text color, array, read/write
140 : kPlayerShip_multiFunctionDisplays, // mfd count, positive int, read-only
141 : kPlayerShip_multiFunctionDisplayList, // active mfd list, array, read-only
142 : kPlayerShip_missilesOnline, // bool (false for ident mode, true for missile mode)
143 : kPlayerShip_pitch, // pitch (overrules Ship)
144 : kPlayerShip_price, // idealised trade-in value decicredits, positive int, read-only
145 : kPlayerShip_primedEquipment, // currently primed equipment, string, read/write
146 : kPlayerShip_renovationCost, // int read-only current renovation cost
147 : kPlayerShip_reticleColorTarget, // Reticle color for normal targets, array, read/write
148 : kPlayerShip_reticleColorTargetSensitive, // Reticle color for targets picked up when sensitive mode is on, array, read/write
149 : kPlayerShip_reticleColorWormhole, // REticle color for wormholes, array, read/write
150 : kPlayerShip_renovationMultiplier, // float read-only multiplier for renovation costs
151 : kPlayerShip_reticleTargetSensitive, // target box changes color when primary target in crosshairs, boolean, read/write
152 : kPlayerShip_roll, // roll (overrules Ship)
153 : kPlayerShip_routeMode, // ANA mode
154 : kPlayerShip_scannerMinimalistic , // essentially scanner without gridlines
155 : kPlayerShip_scannerNonLinear, // non linear scanner setting, boolean, read/write
156 : kPlayerShip_scannerUltraZoom, // scanner zoom in powers of 2, boolean, read/write
157 : kPlayerShip_scoopOverride, // Scooping
158 : kPlayerShip_serviceLevel, // servicing level, positive int 75-100, read-only
159 : kPlayerShip_specialCargo, // special cargo, string, read-only
160 : kPlayerShip_targetSystem, // target system id, int, read-write
161 : kPlayerShip_nextSystem, // next hop system id, read-only
162 : kPlayerShip_infoSystem, // info (F7 screen) system id, int, read-write
163 : kPlayerShip_previousSystem, // previous system id, read-only
164 : kPlayerShip_torusEngaged, // torus in use, boolean, read-only
165 : kPlayerShip_viewDirection, // view direction identifier, string, read-only
166 : kPlayerShip_viewPositionAft, // view position offset, vector, read-only
167 : kPlayerShip_viewPositionForward, // view position offset, vector, read-only
168 : kPlayerShip_viewPositionPort, // view position offset, vector, read-only
169 : kPlayerShip_viewPositionStarboard, // view position offset, vector, read-only
170 : kPlayerShip_weaponsOnline, // weapons online status, boolean, read-only
171 : kPlayerShip_yaw, // yaw (overrules Ship)
172 : };
173 :
174 :
175 0 : static JSPropertySpec sPlayerShipProperties[] =
176 : {
177 : // JS name ID flags
178 : { "activeMissile", kPlayerShip_activeMissile, OOJS_PROP_READONLY_CB },
179 : { "aftShield", kPlayerShip_aftShield, OOJS_PROP_READWRITE_CB },
180 : { "aftShieldRechargeRate", kPlayerShip_aftShieldRechargeRate, OOJS_PROP_READWRITE_CB },
181 : { "chartHighlightMode", kPlayerShip_chartHightlightMode, OOJS_PROP_READWRITE_CB },
182 : { "compassMode", kPlayerShip_compassMode, OOJS_PROP_READWRITE_CB },
183 : { "compassTarget", kPlayerShip_compassTarget, OOJS_PROP_READWRITE_CB },
184 : { "compassType", kPlayerShip_compassType, OOJS_PROP_READWRITE_CB },
185 : { "currentWeapon", kPlayerShip_currentWeapon, OOJS_PROP_READWRITE_CB },
186 : { "crosshairs", kPlayerShip_crosshairs, OOJS_PROP_READWRITE_CB },
187 : { "cursorCoordinates", kPlayerShip_cursorCoordinates, OOJS_PROP_READONLY_CB },
188 : { "cursorCoordinatesInLY", kPlayerShip_cursorCoordinatesInLY, OOJS_PROP_READONLY_CB },
189 : { "docked", kPlayerShip_docked, OOJS_PROP_READONLY_CB },
190 : { "dockedStation", kPlayerShip_dockedStation, OOJS_PROP_READONLY_CB },
191 : { "fastEquipmentA", kPlayerShip_fastEquipmentA, OOJS_PROP_READWRITE_CB },
192 : { "fastEquipmentB", kPlayerShip_fastEquipmentB, OOJS_PROP_READWRITE_CB },
193 : { "forwardShield", kPlayerShip_forwardShield, OOJS_PROP_READWRITE_CB },
194 : { "forwardShieldRechargeRate", kPlayerShip_forwardShieldRechargeRate, OOJS_PROP_READWRITE_CB },
195 : { "fuelLeakRate", kPlayerShip_fuelLeakRate, OOJS_PROP_READWRITE_CB },
196 : { "galacticHyperspaceBehaviour", kPlayerShip_galacticHyperspaceBehaviour, OOJS_PROP_READWRITE_CB },
197 : { "galacticHyperspaceFixedCoords", kPlayerShip_galacticHyperspaceFixedCoords, OOJS_PROP_READWRITE_CB },
198 : { "galacticHyperspaceFixedCoordsInLY", kPlayerShip_galacticHyperspaceFixedCoordsInLY, OOJS_PROP_READWRITE_CB },
199 : { "galaxyCoordinates", kPlayerShip_galaxyCoordinates, OOJS_PROP_READONLY_CB },
200 : { "galaxyCoordinatesInLY", kPlayerShip_galaxyCoordinatesInLY, OOJS_PROP_READONLY_CB },
201 : { "hud", kPlayerShip_hud, OOJS_PROP_READWRITE_CB },
202 : { "hudAllowsBigGui", kPlayerShip_hudAllowsBigGui, OOJS_PROP_READONLY_CB },
203 : { "hudHidden", kPlayerShip_hudHidden, OOJS_PROP_READWRITE_CB },
204 : { "injectorsEngaged", kPlayerShip_injectorsEngaged, OOJS_PROP_READONLY_CB },
205 : { "massLockable", kPlayerShip_massLockable, OOJS_PROP_READWRITE_CB },
206 : // manifest defined in OOJSManifest.m
207 : { "maxAftShield", kPlayerShip_maxAftShield, OOJS_PROP_READWRITE_CB },
208 : { "maxForwardShield", kPlayerShip_maxForwardShield, OOJS_PROP_READWRITE_CB },
209 : { "messageGuiTextColor", kPlayerShip_messageGuiTextColor, OOJS_PROP_READWRITE_CB },
210 : { "messageGuiTextCommsColor", kPlayerShip_messageGuiTextCommsColor, OOJS_PROP_READWRITE_CB },
211 : { "missilesOnline", kPlayerShip_missilesOnline, OOJS_PROP_READONLY_CB },
212 : { "multiFunctionDisplays", kPlayerShip_multiFunctionDisplays, OOJS_PROP_READONLY_CB },
213 : { "multiFunctionDisplayList", kPlayerShip_multiFunctionDisplayList, OOJS_PROP_READONLY_CB },
214 : { "price", kPlayerShip_price, OOJS_PROP_READONLY_CB },
215 : { "pitch", kPlayerShip_pitch, OOJS_PROP_READWRITE_CB },
216 : { "primedEquipment", kPlayerShip_primedEquipment, OOJS_PROP_READWRITE_CB },
217 : { "renovationCost", kPlayerShip_renovationCost, OOJS_PROP_READONLY_CB },
218 : { "reticleColorTarget", kPlayerShip_reticleColorTarget, OOJS_PROP_READWRITE_CB },
219 : { "reticleColorTargetSensitive", kPlayerShip_reticleColorTargetSensitive, OOJS_PROP_READWRITE_CB },
220 : { "reticleColorWormhole", kPlayerShip_reticleColorWormhole, OOJS_PROP_READWRITE_CB },
221 : { "renovationMultiplier", kPlayerShip_renovationMultiplier, OOJS_PROP_READONLY_CB },
222 : { "reticleTargetSensitive", kPlayerShip_reticleTargetSensitive, OOJS_PROP_READWRITE_CB },
223 : { "roll", kPlayerShip_roll, OOJS_PROP_READWRITE_CB },
224 : { "routeMode", kPlayerShip_routeMode, OOJS_PROP_READONLY_CB },
225 : { "scannerMinimalistic", kPlayerShip_scannerMinimalistic, OOJS_PROP_READWRITE_CB },
226 : { "scannerNonLinear", kPlayerShip_scannerNonLinear, OOJS_PROP_READWRITE_CB },
227 : { "scannerUltraZoom", kPlayerShip_scannerUltraZoom, OOJS_PROP_READWRITE_CB },
228 : { "scoopOverride", kPlayerShip_scoopOverride, OOJS_PROP_READWRITE_CB },
229 : { "serviceLevel", kPlayerShip_serviceLevel, OOJS_PROP_READWRITE_CB },
230 : { "specialCargo", kPlayerShip_specialCargo, OOJS_PROP_READONLY_CB },
231 : { "targetSystem", kPlayerShip_targetSystem, OOJS_PROP_READWRITE_CB },
232 : { "nextSystem", kPlayerShip_nextSystem, OOJS_PROP_READONLY_CB },
233 : { "infoSystem", kPlayerShip_infoSystem, OOJS_PROP_READWRITE_CB },
234 : { "previousSystem", kPlayerShip_previousSystem, OOJS_PROP_READONLY_CB },
235 : { "torusEngaged", kPlayerShip_torusEngaged, OOJS_PROP_READONLY_CB },
236 : { "viewDirection", kPlayerShip_viewDirection, OOJS_PROP_READONLY_CB },
237 : { "viewPositionAft", kPlayerShip_viewPositionAft, OOJS_PROP_READONLY_CB },
238 : { "viewPositionForward", kPlayerShip_viewPositionForward, OOJS_PROP_READONLY_CB },
239 : { "viewPositionPort", kPlayerShip_viewPositionPort, OOJS_PROP_READONLY_CB },
240 : { "viewPositionStarboard", kPlayerShip_viewPositionStarboard, OOJS_PROP_READONLY_CB },
241 : { "weaponsOnline", kPlayerShip_weaponsOnline, OOJS_PROP_READONLY_CB },
242 : { "yaw", kPlayerShip_yaw, OOJS_PROP_READWRITE_CB },
243 : { 0 }
244 : };
245 :
246 :
247 0 : static JSFunctionSpec sPlayerShipMethods[] =
248 : {
249 : // JS name Function min args
250 : { "addParcel", PlayerShipAddParcel, 0 },
251 : { "addPassenger", PlayerShipAddPassenger, 0 },
252 : { "awardContract", PlayerShipAwardContract, 0 },
253 : { "awardEquipmentToCurrentPylon", PlayerShipAwardEquipmentToCurrentPylon, 1 },
254 : { "beginHyperspaceCountdown", PlayerShipBeginHyperspaceCountdown, 0 },
255 : { "cancelDockingRequest", PlayerShipCancelDockingRequest, 1 },
256 : { "cancelHyperspaceCountdown", PlayerShipCancelHyperspaceCountdown, 0 },
257 : { "beginGalacticHyperspaceCountdown", PlayerShipBeginGalacticHyperspaceCountdown, 1 },
258 : { "disengageAutopilot", PlayerShipDisengageAutopilot, 0 },
259 : { "engageAutopilotToStation", PlayerShipEngageAutopilotToStation, 1 },
260 : { "hideHUDSelector", PlayerShipHideHUDSelector, 1 },
261 : { "launch", PlayerShipLaunch, 0 },
262 : { "removeAllCargo", PlayerShipRemoveAllCargo, 0 },
263 : { "removeContract", PlayerShipRemoveContract, 2 },
264 : { "removeParcel", PlayerShipRemoveParcel, 1 },
265 : { "removePassenger", PlayerShipRemovePassenger, 1 },
266 : { "requestDockingClearance", PlayerShipRequestDockingClearance, 1 },
267 : { "resetCustomView", PlayerShipResetCustomView, 0 },
268 : { "resetScannerZoom", PlayerShipResetScannerZoom, 0 },
269 : { "setCustomView", PlayerShipSetCustomView, 2 },
270 : { "setCustomHUDDial", PlayerShipSetCustomHUDDial, 2 },
271 : { "setMultiFunctionDisplay", PlayerShipSetMultiFunctionDisplay, 1 },
272 : { "setMultiFunctionText", PlayerShipSetMultiFunctionText, 1 },
273 : { "setPrimedEquipment", PlayerShipSetPrimedEquipment, 1 },
274 : { "showHUDSelector", PlayerShipShowHUDSelector, 1 },
275 : { "takeInternalDamage", PlayerShipTakeInternalDamage, 0 },
276 : { "useSpecialCargo", PlayerShipUseSpecialCargo, 1 },
277 : { 0 }
278 : };
279 :
280 :
281 0 : void InitOOJSPlayerShip(JSContext *context, JSObject *global)
282 : {
283 : sPlayerShipPrototype = JS_InitClass(context, global, JSShipPrototype(), &sPlayerShipClass, OOJSUnconstructableConstruct, 0, sPlayerShipProperties, sPlayerShipMethods, NULL, NULL);
284 : OOJSRegisterObjectConverter(&sPlayerShipClass, OOJSBasicPrivateObjectConverter);
285 : OOJSRegisterSubclass(&sPlayerShipClass, JSShipClass());
286 :
287 : PlayerEntity *player = [PlayerEntity sharedPlayer]; // NOTE: at time of writing, this creates the player entity. Don't use PLAYER here.
288 :
289 : // Create ship object as a property of the player object.
290 : sPlayerShipObject = JS_DefineObject(context, JSPlayerObject(), "ship", &sPlayerShipClass, sPlayerShipPrototype, OOJS_PROP_READONLY);
291 : JS_SetPrivate(context, sPlayerShipObject, OOConsumeReference([player weakRetain]));
292 : [player setJSSelf:sPlayerShipObject context:context];
293 : // Analyzer: object leaked. [Expected, object is retained by JS object.]
294 : }
295 :
296 :
297 0 : JSClass *JSPlayerShipClass(void)
298 : {
299 : return &sPlayerShipClass;
300 : }
301 :
302 :
303 0 : JSObject *JSPlayerShipPrototype(void)
304 : {
305 : return sPlayerShipPrototype;
306 : }
307 :
308 :
309 0 : JSObject *JSPlayerShipObject(void)
310 : {
311 : return sPlayerShipObject;
312 : }
313 :
314 :
315 : @implementation PlayerEntity (OOJavaScriptExtensions)
316 :
317 0 : - (NSString *) oo_jsClassName
318 : {
319 : return @"PlayerShip";
320 : }
321 :
322 :
323 : - (void) setJSSelf:(JSObject *)val context:(JSContext *)context
324 : {
325 : _jsSelf = val;
326 : OOJSAddGCObjectRoot(context, &_jsSelf, "Player jsSelf");
327 :
328 : [[NSNotificationCenter defaultCenter] addObserver:self
329 : selector:@selector(javaScriptEngineWillReset:)
330 : name:kOOJavaScriptEngineWillResetNotification
331 : object:[OOJavaScriptEngine sharedEngine]];
332 : }
333 :
334 :
335 0 : - (void) javaScriptEngineWillReset:(NSNotification *)notification
336 : {
337 : [[NSNotificationCenter defaultCenter] removeObserver:self
338 : name:kOOJavaScriptEngineWillResetNotification
339 : object:[OOJavaScriptEngine sharedEngine]];
340 :
341 : if (_jsSelf != NULL)
342 : {
343 :
344 : JSContext *context = OOJSAcquireContext();
345 : JS_RemoveObjectRoot(context, &_jsSelf);
346 : _jsSelf = NULL;
347 : OOJSRelinquishContext(context);
348 : }
349 : }
350 :
351 : @end
352 :
353 :
354 0 : static JSBool PlayerShipGetProperty(JSContext *context, JSObject *this, jsid propID, jsval *value)
355 : {
356 : if (!JSID_IS_INT(propID)) return YES;
357 :
358 : OOJS_NATIVE_ENTER(context)
359 :
360 : if (EXPECT_NOT(OOIsPlayerStale() || this == sPlayerShipPrototype)) { *value = JSVAL_VOID; return YES; }
361 :
362 : id result = nil;
363 : PlayerEntity *player = OOPlayerForScripting();
364 :
365 : switch (JSID_TO_INT(propID))
366 : {
367 : case kPlayerShip_activeMissile:
368 : return JS_NewNumberValue(context, [player activeMissile], value);
369 :
370 : case kPlayerShip_fuelLeakRate:
371 : return JS_NewNumberValue(context, [player fuelLeakRate], value);
372 :
373 : case kPlayerShip_docked:
374 : *value = OOJSValueFromBOOL([player isDocked]);
375 : return YES;
376 :
377 : case kPlayerShip_dockedStation:
378 : result = [player dockedStation];
379 : break;
380 :
381 : case kPlayerShip_specialCargo:
382 : result = [player specialCargo];
383 : break;
384 :
385 : case kPlayerShip_reticleColorTarget:
386 : result = [[[player hud] reticleColorForIndex:OO_RETICLE_COLOR_TARGET] normalizedArray];
387 : break;
388 :
389 : case kPlayerShip_reticleColorTargetSensitive:
390 : result = [[[player hud] reticleColorForIndex:OO_RETICLE_COLOR_TARGET_SENSITIVE] normalizedArray];
391 : break;
392 :
393 : case kPlayerShip_reticleColorWormhole:
394 : result = [[[player hud] reticleColorForIndex:OO_RETICLE_COLOR_WORMHOLE] normalizedArray];
395 : break;
396 :
397 : case kPlayerShip_reticleTargetSensitive:
398 : *value = OOJSValueFromBOOL([[player hud] reticleTargetSensitive]);
399 : return YES;
400 :
401 : case kPlayerShip_galacticHyperspaceBehaviour:
402 : *value = OOJSValueFromGalacticHyperspaceBehaviour(context, [player galacticHyperspaceBehaviour]);
403 : return YES;
404 :
405 : case kPlayerShip_galacticHyperspaceFixedCoords:
406 : return NSPointToVectorJSValue(context, [player galacticHyperspaceFixedCoords], value);
407 :
408 : case kPlayerShip_galacticHyperspaceFixedCoordsInLY:
409 : return VectorToJSValue(context, OOGalacticCoordinatesFromInternal([player galacticHyperspaceFixedCoords]), value);
410 :
411 : case kPlayerShip_fastEquipmentA:
412 : result = [player fastEquipmentA];
413 : break;
414 :
415 : case kPlayerShip_fastEquipmentB:
416 : result = [player fastEquipmentB];
417 : break;
418 :
419 : case kPlayerShip_primedEquipment:
420 : result = [player currentPrimedEquipment];
421 : break;
422 :
423 : case kPlayerShip_forwardShield:
424 : return JS_NewNumberValue(context, [player forwardShieldLevel], value);
425 :
426 : case kPlayerShip_aftShield:
427 : return JS_NewNumberValue(context, [player aftShieldLevel], value);
428 :
429 : case kPlayerShip_maxForwardShield:
430 : return JS_NewNumberValue(context, [player maxForwardShieldLevel], value);
431 :
432 : case kPlayerShip_maxAftShield:
433 : return JS_NewNumberValue(context, [player maxAftShieldLevel], value);
434 :
435 : case kPlayerShip_forwardShieldRechargeRate:
436 : // No distinction made internally
437 : return JS_NewNumberValue(context, [player forwardShieldRechargeRate], value);
438 :
439 : case kPlayerShip_aftShieldRechargeRate:
440 : // No distinction made internally
441 : return JS_NewNumberValue(context, [player aftShieldRechargeRate], value);
442 :
443 : case kPlayerShip_multiFunctionDisplays:
444 : return JS_NewNumberValue(context, [[player hud] mfdCount], value);
445 :
446 : case kPlayerShip_multiFunctionDisplayList:
447 : result = [player multiFunctionDisplayList];
448 : break;
449 :
450 : case kPlayerShip_missilesOnline:
451 : *value = OOJSValueFromBOOL(![player dialIdentEngaged]);
452 : return YES;
453 :
454 : case kPlayerShip_chartHightlightMode:
455 : result = OOStringFromLongRangeChartMode([player longRangeChartMode]);
456 : break;
457 :
458 : case kPlayerShip_galaxyCoordinates:
459 : return NSPointToVectorJSValue(context, [player galaxy_coordinates], value);
460 :
461 : case kPlayerShip_galaxyCoordinatesInLY:
462 : return VectorToJSValue(context, OOGalacticCoordinatesFromInternal([player galaxy_coordinates]), value);
463 :
464 : case kPlayerShip_cursorCoordinates:
465 : return NSPointToVectorJSValue(context, [player cursor_coordinates], value);
466 :
467 : case kPlayerShip_cursorCoordinatesInLY:
468 : return VectorToJSValue(context, OOGalacticCoordinatesFromInternal([player cursor_coordinates]), value);
469 :
470 : case kPlayerShip_targetSystem:
471 : *value = INT_TO_JSVAL([player targetSystemID]);
472 : return YES;
473 :
474 : case kPlayerShip_nextSystem:
475 : *value = INT_TO_JSVAL([player nextHopTargetSystemID]);
476 : return YES;
477 :
478 : case kPlayerShip_infoSystem:
479 : *value = INT_TO_JSVAL([player infoSystemID]);
480 : return YES;
481 :
482 : case kPlayerShip_previousSystem:
483 : *value = INT_TO_JSVAL([player previousSystemID]);
484 : return YES;
485 :
486 : case kPlayerShip_routeMode:
487 : {
488 : OORouteType route = [player ANAMode];
489 : switch (route)
490 : {
491 : case OPTIMIZED_BY_TIME:
492 : result = @"OPTIMIZED_BY_TIME";
493 : break;
494 : case OPTIMIZED_BY_JUMPS:
495 : result = @"OPTIMIZED_BY_JUMPS";
496 : break;
497 : case OPTIMIZED_BY_NONE:
498 : result = @"OPTIMIZED_BY_NONE";
499 : break;
500 : }
501 : break;
502 : }
503 :
504 : case kPlayerShip_scannerMinimalistic:
505 : *value = OOJSValueFromBOOL([[player hud] minimalisticScanner]);
506 : return YES;
507 :
508 : case kPlayerShip_scannerNonLinear:
509 : *value = OOJSValueFromBOOL([[player hud] nonlinearScanner]);
510 : return YES;
511 :
512 : case kPlayerShip_scannerUltraZoom:
513 : *value = OOJSValueFromBOOL([[player hud] scannerUltraZoom]);
514 : return YES;
515 :
516 : case kPlayerShip_scoopOverride:
517 : *value = OOJSValueFromBOOL([player scoopOverride]);
518 : return YES;
519 :
520 : case kPlayerShip_injectorsEngaged:
521 : *value = OOJSValueFromBOOL([player injectorsEngaged]);
522 : return YES;
523 :
524 : case kPlayerShip_massLockable:
525 : *value = OOJSValueFromBOOL([player massLockable]);
526 : return YES;
527 :
528 : case kPlayerShip_torusEngaged:
529 : *value = OOJSValueFromBOOL([player hyperspeedEngaged]);
530 : return YES;
531 :
532 : case kPlayerShip_compassTarget:
533 : result = [player compassTarget];
534 : break;
535 :
536 : case kPlayerShip_compassType:
537 : result = [OOStringFromCompassMode([player compassMode]) isEqualToString:@"COMPASS_MODE_BASIC"] ?
538 : @"OO_COMPASSTYPE_BASIC" : @"OO_COMPASSTYPE_ADVANCED";
539 : break;
540 :
541 : case kPlayerShip_compassMode:
542 : *value = OOJSValueFromCompassMode(context, [player compassMode]);
543 : return YES;
544 :
545 : case kPlayerShip_hud:
546 : result = [[player hud] hudName];
547 : break;
548 :
549 : case kPlayerShip_crosshairs:
550 : result = [[player hud] crosshairDefinition];
551 : break;
552 :
553 : case kPlayerShip_hudAllowsBigGui:
554 : *value = OOJSValueFromBOOL([[player hud] allowBigGui]);
555 : return YES;
556 :
557 : case kPlayerShip_hudHidden:
558 : *value = OOJSValueFromBOOL([[player hud] isHidden]);
559 : return YES;
560 :
561 : case kPlayerShip_weaponsOnline:
562 : *value = OOJSValueFromBOOL([player weaponsOnline]);
563 : return YES;
564 :
565 : case kPlayerShip_viewDirection:
566 : *value = OOJSValueFromViewID(context, [UNIVERSE viewDirection]);
567 : return YES;
568 :
569 : case kPlayerShip_viewPositionAft:
570 : return VectorToJSValue(context, [player viewpointOffsetAft], value);
571 :
572 : case kPlayerShip_viewPositionForward:
573 : return VectorToJSValue(context, [player viewpointOffsetForward], value);
574 :
575 : case kPlayerShip_viewPositionPort:
576 : return VectorToJSValue(context, [player viewpointOffsetPort], value);
577 :
578 : case kPlayerShip_viewPositionStarboard:
579 : return VectorToJSValue(context, [player viewpointOffsetStarboard], value);
580 :
581 : case kPlayerShip_currentWeapon:
582 : result = [player weaponTypeForFacing:[player currentWeaponFacing] strict:NO];
583 : break;
584 :
585 : case kPlayerShip_price:
586 : return JS_NewNumberValue(context, [UNIVERSE tradeInValueForCommanderDictionary:[player commanderDataDictionary]], value);
587 :
588 : case kPlayerShip_serviceLevel:
589 : return JS_NewNumberValue(context, [player tradeInFactor], value);
590 :
591 : case kPlayerShip_renovationCost:
592 : return JS_NewNumberValue(context, [player renovationCosts], value);
593 :
594 : case kPlayerShip_renovationMultiplier:
595 : return JS_NewNumberValue(context, [player renovationFactor], value);
596 :
597 :
598 : // make roll, pitch, yaw reported to JS use same +/- convention as
599 : // for NPC ships
600 : case kPlayerShip_pitch:
601 : return JS_NewNumberValue(context, -[player flightPitch], value);
602 :
603 : case kPlayerShip_roll:
604 : return JS_NewNumberValue(context, -[player flightRoll], value);
605 :
606 : case kPlayerShip_yaw:
607 : return JS_NewNumberValue(context, -[player flightYaw], value);
608 :
609 : case kPlayerShip_messageGuiTextColor:
610 : result = [[[UNIVERSE messageGUI] textColor] normalizedArray];
611 : break;
612 :
613 : case kPlayerShip_messageGuiTextCommsColor:
614 : result = [[[UNIVERSE messageGUI] textCommsColor] normalizedArray];
615 : break;
616 :
617 : default:
618 : OOJSReportBadPropertySelector(context, this, propID, sPlayerShipProperties);
619 : }
620 :
621 : *value = OOJSValueFromNativeObject(context, result);
622 : return YES;
623 :
624 : OOJS_NATIVE_EXIT
625 : }
626 :
627 :
628 0 : static JSBool PlayerShipSetProperty(JSContext *context, JSObject *this, jsid propID, JSBool strict, jsval *value)
629 : {
630 : if (!JSID_IS_INT(propID)) return YES;
631 :
632 : OOJS_NATIVE_ENTER(context)
633 :
634 : if (EXPECT_NOT(OOIsPlayerStale())) return YES;
635 :
636 : PlayerEntity *player = OOPlayerForScripting();
637 : jsdouble fValue;
638 : JSBool bValue;
639 : int32 iValue;
640 : NSString *sValue = nil;
641 : OOGalacticHyperspaceBehaviour ghBehaviour;
642 : Vector vValue;
643 : OOColor *colorForScript = nil;
644 : Entity *eValue = nil;
645 :
646 : switch (JSID_TO_INT(propID))
647 : {
648 : case kPlayerShip_fuelLeakRate:
649 : if (JS_ValueToNumber(context, *value, &fValue))
650 : {
651 : [player setFuelLeakRate:fValue];
652 : return YES;
653 : }
654 : break;
655 :
656 : case kPlayerShip_massLockable:
657 : if (JS_ValueToBoolean(context, *value, &bValue))
658 : {
659 : [player setMassLockable:bValue];
660 : return YES;
661 : }
662 : break;
663 :
664 : case kPlayerShip_reticleTargetSensitive:
665 : if (JS_ValueToBoolean(context, *value, &bValue))
666 : {
667 : [[player hud] setReticleTargetSensitive:bValue];
668 : return YES;
669 : }
670 : break;
671 :
672 : case kPlayerShip_chartHightlightMode:
673 : sValue = OOStringFromJSValue(context, *value);
674 : if (sValue != nil)
675 : {
676 : OOLongRangeChartMode chartMode = OOLongRangeChartModeFromString(sValue);
677 : if (chartMode > OOLRC_MODE_UNKNOWN)
678 : {
679 : [player setLongRangeChartMode:chartMode];
680 : [player doScriptEvent:OOJSID("chartHighlightModeChanged") withArgument:OOStringFromLongRangeChartMode([player longRangeChartMode])];
681 : return YES;
682 : }
683 : else
684 : {
685 : OOJSReportError(context, @"Unknown chart hightlight mode specified - must be either OOLRC_MODE_SUNCOLOR, OOLRC_MODE_ECONOMY, OOLRC_MODE_GOVERNMENT or OOLRC_MODE_TECHLEVEL.");
686 : }
687 : }
688 : return NO; // not reachable if successfully set
689 : break;
690 :
691 : case kPlayerShip_compassMode:
692 : sValue = OOStringFromJSValue(context, *value);
693 : if(sValue != nil)
694 : {
695 : OOCompassMode mode = OOCompassModeFromJSValue(context, *value);
696 : [player setCompassMode:mode];
697 : [player validateCompassTarget];
698 : return YES;
699 : }
700 : break;
701 :
702 : case kPlayerShip_compassType:
703 : sValue = OOStringFromJSValue(context, *value);
704 : if (sValue != nil)
705 : {
706 : if ([sValue isEqualToString:@"OO_COMPASSTYPE_BASIC"])
707 : {
708 : [player setCompassMode:COMPASS_MODE_BASIC];
709 : }
710 : else if([sValue isEqualToString:@"OO_COMPASSTYPE_ADVANCED"])
711 : {
712 : if (![player hasEquipmentItemProviding:@"EQ_ADVANCED_COMPASS"])
713 : {
714 : OOJSReportWarning(context, @"Advanced Compass type requested and set but player ship does not carry the EQ_ADVANCED_COMPASS equipment or has it damaged.");
715 : }
716 : [player setCompassMode:COMPASS_MODE_PLANET];
717 : }
718 : else
719 : {
720 : OOJSReportError(context, @"Unknown compass type specified - must be either OO_COMPASSTYPE_BASIC or OO_COMPASSTYPE_ADVANCED.");
721 : return NO;
722 : }
723 : return YES;
724 : }
725 : break;
726 :
727 : case kPlayerShip_compassTarget:
728 : // can't change compass target in basic mode
729 : if (![player hasEquipmentItemProviding:@"EQ_ADVANCED_COMPASS"])
730 : {
731 : OOJSReportError(context, @"Compass target cannot be set with a basic compass.");
732 : return NO;
733 : }
734 : // make sure we have a valid entity
735 : if (!JSVAL_IS_NULL(*value) && JSValueToEntity(context, *value, &eValue))
736 : {
737 : Entity *current = [player compassTarget];
738 : [player setNextCompassMode];
739 : [player validateCompassTarget];
740 : // cycle the targets until we either get back to the start (entity not found) or we find the one we're looking for
741 : while ([player compassTarget] != current && [player compassTarget] != eValue)
742 : {
743 : [player setNextCompassMode];
744 : [player validateCompassTarget];
745 : }
746 : return [player compassTarget] != current;
747 : }
748 : else
749 : {
750 : OOJSReportError(context, @"Invalid compass target entity provided.");
751 : return NO;
752 : }
753 : break;
754 :
755 : case kPlayerShip_galacticHyperspaceBehaviour:
756 : ghBehaviour = OOGalacticHyperspaceBehaviourFromJSValue(context, *value);
757 : if (ghBehaviour != GALACTIC_HYPERSPACE_BEHAVIOUR_UNKNOWN)
758 : {
759 : [player setGalacticHyperspaceBehaviour:ghBehaviour];
760 : return YES;
761 : }
762 : break;
763 :
764 : case kPlayerShip_galacticHyperspaceFixedCoords:
765 : if (JSValueToVector(context, *value, &vValue))
766 : {
767 : NSPoint coords = { vValue.x, vValue.y };
768 : [player setGalacticHyperspaceFixedCoords:coords];
769 : return YES;
770 : }
771 : break;
772 :
773 : case kPlayerShip_galacticHyperspaceFixedCoordsInLY:
774 : if (JSValueToVector(context, *value, &vValue))
775 : {
776 : NSPoint coords = OOInternalCoordinatesFromGalactic(vValue);
777 : [player setGalacticHyperspaceFixedCoords:coords];
778 : return YES;
779 : }
780 : break;
781 :
782 : case kPlayerShip_fastEquipmentA:
783 : sValue = OOStringFromJSValue(context, *value);
784 : if (sValue != nil)
785 : {
786 : [player setFastEquipmentA:sValue];
787 : return YES;
788 : }
789 : break;
790 :
791 : case kPlayerShip_fastEquipmentB:
792 : sValue = OOStringFromJSValue(context, *value);
793 : if (sValue != nil)
794 : {
795 : [player setFastEquipmentB:sValue];
796 : return YES;
797 : }
798 : break;
799 :
800 : case kPlayerShip_primedEquipment:
801 : sValue = OOStringFromJSValue(context, *value);
802 : if (sValue != nil)
803 : {
804 : return [player setPrimedEquipment:sValue showMessage:NO];
805 : }
806 : break;
807 :
808 : case kPlayerShip_pitch:
809 : if (JS_ValueToNumber(context, *value, &fValue))
810 : {
811 : if (!isnan(fValue)) // guard against undefined
812 : {
813 : [player decrease_flight_pitch:[player flightPitch] + fValue];
814 : }
815 : return YES;
816 : }
817 : break;
818 :
819 : case kPlayerShip_roll:
820 : if (JS_ValueToNumber(context, *value, &fValue))
821 : {
822 : if (!isnan(fValue)) // guard against undefined
823 : {
824 : [player decrease_flight_roll:[player flightRoll] + fValue];
825 : }
826 : return YES;
827 : }
828 : break;
829 :
830 : case kPlayerShip_yaw:
831 : if (JS_ValueToNumber(context, *value, &fValue))
832 : {
833 : if (!isnan(fValue)) // guard against undefined
834 : {
835 : [player decrease_flight_yaw:[player flightYaw] + fValue];
836 : }
837 : return YES;
838 : }
839 : break;
840 :
841 : case kPlayerShip_forwardShield:
842 : if (JS_ValueToNumber(context, *value, &fValue))
843 : {
844 : [player setForwardShieldLevel:fValue];
845 : return YES;
846 : }
847 : break;
848 :
849 : case kPlayerShip_aftShield:
850 : if (JS_ValueToNumber(context, *value, &fValue))
851 : {
852 : [player setAftShieldLevel:fValue];
853 : return YES;
854 : }
855 : break;
856 :
857 : case kPlayerShip_maxForwardShield:
858 : if (JS_ValueToNumber(context, *value, &fValue))
859 : {
860 : [player setMaxForwardShieldLevel:fValue];
861 : return YES;
862 : }
863 : break;
864 :
865 : case kPlayerShip_maxAftShield:
866 : if (JS_ValueToNumber(context, *value, &fValue))
867 : {
868 : [player setMaxAftShieldLevel:fValue];
869 : return YES;
870 : }
871 : break;
872 :
873 : case kPlayerShip_forwardShieldRechargeRate:
874 : if (JS_ValueToNumber(context, *value, &fValue))
875 : {
876 : [player setForwardShieldRechargeRate:fValue];
877 : return YES;
878 : }
879 : break;
880 :
881 : case kPlayerShip_aftShieldRechargeRate:
882 : if (JS_ValueToNumber(context, *value, &fValue))
883 : {
884 : [player setAftShieldRechargeRate:fValue];
885 : return YES;
886 : }
887 : break;
888 :
889 : case kPlayerShip_scannerMinimalistic:
890 : if (JS_ValueToBoolean(context, *value, &bValue))
891 : {
892 : [[player hud] setMinimalisticScanner:bValue];
893 : return YES;
894 : }
895 : break;
896 :
897 : case kPlayerShip_scannerNonLinear:
898 : if (JS_ValueToBoolean(context, *value, &bValue))
899 : {
900 : [[player hud] setNonlinearScanner:bValue];
901 : return YES;
902 : }
903 : break;
904 :
905 : case kPlayerShip_scannerUltraZoom:
906 : if (JS_ValueToBoolean(context, *value, &bValue))
907 : {
908 : [[player hud] setScannerUltraZoom:bValue];
909 : return YES;
910 : }
911 : break;
912 :
913 : case kPlayerShip_scoopOverride:
914 : if (JS_ValueToBoolean(context, *value, &bValue))
915 : {
916 : [player setScoopOverride:bValue];
917 : return YES;
918 : }
919 : break;
920 :
921 : case kPlayerShip_hud:
922 : sValue = OOStringFromJSValue(context, *value);
923 : if (sValue != nil)
924 : {
925 : [player switchHudTo:sValue]; // EMMSTRAN: logged error should be a JS warning.
926 : return YES;
927 : }
928 : else
929 : {
930 : [player resetHud];
931 : return YES;
932 : }
933 : break;
934 :
935 : case kPlayerShip_crosshairs:
936 : sValue = OOStringFromJSValue(context, *value);
937 : if (sValue == nil)
938 : {
939 : // reset HUD back to its plist settings
940 : NSString *hud = [[[player hud] hudName] retain];
941 : [player switchHudTo:hud];
942 : [hud release];
943 : return YES;
944 : }
945 : else
946 : {
947 : if (![[player hud] setCrosshairDefinition:sValue])
948 : {
949 : OOJSReportWarning(context, @"Crosshair definition file %@ not found or invalid", sValue);
950 : }
951 : return YES;
952 : }
953 : break;
954 :
955 : case kPlayerShip_hudHidden:
956 : if (JS_ValueToBoolean(context, *value, &bValue))
957 : {
958 : [[player hud] setHidden:bValue];
959 : return YES;
960 : }
961 : break;
962 :
963 : case kPlayerShip_serviceLevel:
964 : if (JS_ValueToNumber(context, *value, &fValue))
965 : {
966 : int newLevel = (int)fValue;
967 : [player adjustTradeInFactorBy:(newLevel-[player tradeInFactor])];
968 : return YES;
969 : }
970 :
971 : case kPlayerShip_currentWeapon:
972 : {
973 : BOOL exists = NO;
974 : sValue = JSValueToEquipmentKeyRelaxed(context, *value, &exists);
975 : if (!exists || sValue == nil)
976 : {
977 : sValue = @"EQ_WEAPON_NONE";
978 : }
979 : [player setWeaponMount:[player currentWeaponFacing] toWeapon:sValue inContext:@"scripted"];
980 : return YES;
981 : }
982 :
983 : case kPlayerShip_targetSystem:
984 : /* This first check is essential: if removed, it would be
985 : * possible to make jumps of arbitrary length - CIM */
986 : if ([player status] != STATUS_ENTERING_WITCHSPACE)
987 : {
988 : /* These checks though similar are less important. The
989 : * consequences of allowing jump destination to be set in
990 : * flight are not as severe and do not allow the 7LY limit to
991 : * be broken. Nevertheless, it is not allowed. - CIM */
992 : // (except when compiled in debugging mode)
993 : #ifndef OO_DUMP_PLANETINFO
994 : if (EXPECT_NOT([player status] != STATUS_DOCKED && [player status] != STATUS_LAUNCHING))
995 : {
996 : OOJSReportError(context, @"player.ship.targetSystem is read-only unless called when docked.");
997 : return NO;
998 : }
999 : #endif
1000 :
1001 : if (JS_ValueToInt32(context, *value, &iValue))
1002 : {
1003 : if (iValue >= 0 && iValue < OO_SYSTEMS_PER_GALAXY)
1004 : {
1005 : [player setTargetSystemID:iValue];
1006 : return YES;
1007 : }
1008 : else
1009 : {
1010 : return NO;
1011 : }
1012 : }
1013 : }
1014 : else
1015 : {
1016 : OOJSReportError(context, @"player.ship.targetSystem is read-only unless called when docked.");
1017 : return NO;
1018 : }
1019 :
1020 : case kPlayerShip_infoSystem:
1021 : if (JS_ValueToInt32(context, *value, &iValue))
1022 : {
1023 : if (iValue >= 0 && iValue < OO_SYSTEMS_PER_GALAXY)
1024 : {
1025 : [player setInfoSystemID:iValue moveChart: YES];
1026 : return YES;
1027 : }
1028 : else
1029 : {
1030 : return NO;
1031 : }
1032 : }
1033 : break;
1034 :
1035 : case kPlayerShip_messageGuiTextColor:
1036 : colorForScript = [OOColor colorWithDescription:OOJSNativeObjectFromJSValue(context, *value)];
1037 : if (colorForScript != nil || JSVAL_IS_NULL(*value))
1038 : {
1039 : [[UNIVERSE messageGUI] setTextColor:colorForScript];
1040 : return YES;
1041 : }
1042 : break;
1043 :
1044 : case kPlayerShip_messageGuiTextCommsColor:
1045 : colorForScript = [OOColor colorWithDescription:OOJSNativeObjectFromJSValue(context, *value)];
1046 : if (colorForScript != nil || JSVAL_IS_NULL(*value))
1047 : {
1048 : [[UNIVERSE messageGUI] setTextCommsColor:colorForScript];
1049 : return YES;
1050 : }
1051 : break;
1052 :
1053 : case kPlayerShip_reticleColorTarget:
1054 : colorForScript = [OOColor colorWithDescription:OOJSNativeObjectFromJSValue(context, *value)];
1055 : if (colorForScript != nil || JSVAL_IS_NULL(*value))
1056 : {
1057 : return [[player hud] setReticleColorForIndex:OO_RETICLE_COLOR_TARGET toColor:colorForScript];
1058 : }
1059 : break;
1060 :
1061 : case kPlayerShip_reticleColorTargetSensitive:
1062 : colorForScript = [OOColor colorWithDescription:OOJSNativeObjectFromJSValue(context, *value)];
1063 : if (colorForScript != nil || JSVAL_IS_NULL(*value))
1064 : {
1065 : return [[player hud] setReticleColorForIndex:OO_RETICLE_COLOR_TARGET_SENSITIVE toColor:colorForScript];
1066 : }
1067 : break;
1068 :
1069 : case kPlayerShip_reticleColorWormhole:
1070 : colorForScript = [OOColor colorWithDescription:OOJSNativeObjectFromJSValue(context, *value)];
1071 : if (colorForScript != nil || JSVAL_IS_NULL(*value))
1072 : {
1073 : return [[player hud] setReticleColorForIndex:OO_RETICLE_COLOR_WORMHOLE toColor:colorForScript];
1074 : }
1075 : break;
1076 :
1077 : default:
1078 : OOJSReportBadPropertySelector(context, this, propID, sPlayerShipProperties);
1079 : return NO;
1080 : }
1081 :
1082 : OOJSReportBadPropertyValue(context, this, propID, sPlayerShipProperties, *value);
1083 : return NO;
1084 :
1085 : OOJS_NATIVE_EXIT
1086 : }
1087 :
1088 :
1089 : // *** Methods ***
1090 :
1091 : // launch()
1092 0 : static JSBool PlayerShipLaunch(JSContext *context, uintN argc, jsval *vp)
1093 : {
1094 : OOJS_NATIVE_ENTER(context)
1095 :
1096 : if (EXPECT_NOT(OOIsPlayerStale())) OOJS_RETURN_VOID;
1097 :
1098 : [OOPlayerForScripting() launchFromStation];
1099 : OOJS_RETURN_VOID;
1100 :
1101 : OOJS_NATIVE_EXIT
1102 : }
1103 :
1104 :
1105 : // removeAllCargo()
1106 0 : static JSBool PlayerShipRemoveAllCargo(JSContext *context, uintN argc, jsval *vp)
1107 : {
1108 : OOJS_NATIVE_ENTER(context)
1109 :
1110 : if (EXPECT_NOT(OOIsPlayerStale())) OOJS_RETURN_VOID;
1111 :
1112 : PlayerEntity *player = OOPlayerForScripting();
1113 :
1114 : if ([player isDocked])
1115 : {
1116 : [player removeAllCargo];
1117 : OOJS_RETURN_VOID;
1118 : }
1119 : else
1120 : {
1121 : OOJSReportError(context, @"PlayerShip.removeAllCargo only works when docked.");
1122 : return NO;
1123 : }
1124 :
1125 : OOJS_NATIVE_EXIT
1126 : }
1127 :
1128 :
1129 : // useSpecialCargo(name : String)
1130 0 : static JSBool PlayerShipUseSpecialCargo(JSContext *context, uintN argc, jsval *vp)
1131 : {
1132 : OOJS_NATIVE_ENTER(context)
1133 :
1134 : if (EXPECT_NOT(OOIsPlayerStale())) OOJS_RETURN_VOID;
1135 :
1136 : PlayerEntity *player = OOPlayerForScripting();
1137 : NSString *name = nil;
1138 :
1139 : if (argc > 0) name = OOStringFromJSValue(context, OOJS_ARGV[0]);
1140 : if (EXPECT_NOT(name == nil))
1141 : {
1142 : OOJSReportBadArguments(context, @"PlayerShip", @"useSpecialCargo", MIN(argc, 1U), OOJS_ARGV, nil, @"string (special cargo description)");
1143 : return NO;
1144 : }
1145 :
1146 : [player useSpecialCargo:OOStringFromJSValue(context, OOJS_ARGV[0])];
1147 : OOJS_RETURN_VOID;
1148 :
1149 : OOJS_NATIVE_EXIT
1150 : }
1151 :
1152 :
1153 : // engageAutopilotToStation(stationForDocking : Station) : Boolean
1154 0 : static JSBool PlayerShipEngageAutopilotToStation(JSContext *context, uintN argc, jsval *vp)
1155 : {
1156 : OOJS_NATIVE_ENTER(context)
1157 :
1158 : if (EXPECT_NOT(OOIsPlayerStale())) OOJS_RETURN_VOID;
1159 :
1160 : PlayerEntity *player = OOPlayerForScripting();
1161 : StationEntity *stationForDocking = nil;
1162 :
1163 : if (argc > 0) stationForDocking = OOJSNativeObjectOfClassFromJSValue(context, OOJS_ARGV[0], [StationEntity class]);
1164 : if (stationForDocking == nil)
1165 : {
1166 : OOJSReportBadArguments(context, @"PlayerShip", @"engageAutopilot", MIN(argc, 1U), OOJS_ARGV, nil, @"station");
1167 : return NO;
1168 : }
1169 :
1170 : OOJS_RETURN_BOOL([player engageAutopilotToStation:stationForDocking]);
1171 :
1172 : OOJS_NATIVE_EXIT
1173 : }
1174 :
1175 :
1176 : // disengageAutopilot()
1177 0 : static JSBool PlayerShipDisengageAutopilot(JSContext *context, uintN argc, jsval *vp)
1178 : {
1179 : OOJS_NATIVE_ENTER(context)
1180 :
1181 : if (EXPECT_NOT(OOIsPlayerStale())) OOJS_RETURN_VOID;
1182 :
1183 : [OOPlayerForScripting() disengageAutopilot];
1184 : OOJS_RETURN_VOID;
1185 :
1186 : OOJS_NATIVE_EXIT
1187 : }
1188 :
1189 0 : static JSBool PlayerShipRequestDockingClearance(JSContext *context, uintN argc, jsval *vp)
1190 : {
1191 : OOJS_NATIVE_ENTER(context)
1192 :
1193 : if (EXPECT_NOT(OOIsPlayerStale())) OOJS_RETURN_VOID;
1194 :
1195 : PlayerEntity *player = OOPlayerForScripting();
1196 : StationEntity *stationForDocking = nil;
1197 :
1198 : if (argc > 0) stationForDocking = OOJSNativeObjectOfClassFromJSValue(context, OOJS_ARGV[0], [StationEntity class]);
1199 : if (stationForDocking == nil)
1200 : {
1201 : OOJSReportBadArguments(context, @"PlayerShip", @"requestDockingClearance", MIN(argc, 1U), OOJS_ARGV, nil, @"station");
1202 : return NO;
1203 : }
1204 :
1205 : [player requestDockingClearance:stationForDocking];
1206 : OOJS_RETURN_VOID;
1207 :
1208 : OOJS_NATIVE_EXIT
1209 : }
1210 :
1211 0 : static JSBool PlayerShipCancelDockingRequest(JSContext *context, uintN argc, jsval *vp)
1212 : {
1213 : OOJS_NATIVE_ENTER(context)
1214 :
1215 : if (EXPECT_NOT(OOIsPlayerStale())) OOJS_RETURN_VOID;
1216 :
1217 : PlayerEntity *player = OOPlayerForScripting();
1218 : StationEntity *stationForDocking = nil;
1219 :
1220 : if (argc > 0) stationForDocking = OOJSNativeObjectOfClassFromJSValue(context, OOJS_ARGV[0], [StationEntity class]);
1221 : if (stationForDocking == nil)
1222 : {
1223 : OOJSReportBadArguments(context, @"PlayerShip", @"cancelDockingRequest", MIN(argc, 1U), OOJS_ARGV, nil, @"station");
1224 : return NO;
1225 : }
1226 :
1227 : [player cancelDockingRequest:stationForDocking];
1228 : OOJS_RETURN_VOID;
1229 :
1230 : OOJS_NATIVE_EXIT
1231 : }
1232 :
1233 : // awardEquipmentToCurrentPylon(externalTank: equipmentInfoExpression) : Boolean
1234 0 : static JSBool PlayerShipAwardEquipmentToCurrentPylon(JSContext *context, uintN argc, jsval *vp)
1235 : {
1236 : OOJS_NATIVE_ENTER(context)
1237 :
1238 : if (EXPECT_NOT(OOIsPlayerStale())) OOJS_RETURN_VOID;
1239 :
1240 : PlayerEntity *player = OOPlayerForScripting();
1241 : NSString *key = nil;
1242 : OOEquipmentType *eqType = nil;
1243 :
1244 : if (argc > 0) key = JSValueToEquipmentKey(context, OOJS_ARGV[0]);
1245 : if (key != nil) eqType = [OOEquipmentType equipmentTypeWithIdentifier:key];
1246 : if (EXPECT_NOT(![eqType isMissileOrMine]))
1247 : {
1248 : OOJSReportBadArguments(context, @"PlayerShip", @"awardEquipmentToCurrentPylon", MIN(argc, 1U), OOJS_ARGV, nil, @"equipment type (external store)");
1249 : return NO;
1250 : }
1251 :
1252 : OOJS_RETURN_BOOL([player assignToActivePylon:key]);
1253 :
1254 : OOJS_NATIVE_EXIT
1255 : }
1256 :
1257 :
1258 : // addPassenger(name: string, start: int, destination: int, ETA: double, fee: double) : Boolean
1259 0 : static JSBool PlayerShipAddPassenger(JSContext *context, uintN argc, jsval *vp)
1260 : {
1261 : OOJS_NATIVE_ENTER(context)
1262 :
1263 : PlayerEntity *player = OOPlayerForScripting();
1264 : NSString *name = nil;
1265 : OOSystemID start = 0, destination = 0;
1266 : jsdouble eta = 0.0, fee = 0.0, advance = 0.0;
1267 : unsigned risk = 0;
1268 :
1269 : if (argc < 5)
1270 : {
1271 : OOJSReportBadArguments(context, @"PlayerShip", @"addPassenger", argc, OOJS_ARGV, nil, @"name, start, destination, ETA, fee");
1272 : return NO;
1273 : }
1274 :
1275 : name = OOStringFromJSValue(context, OOJS_ARGV[0]);
1276 : if (EXPECT_NOT(name == nil))
1277 : {
1278 : OOJSReportBadArguments(context, @"PlayerShip", @"addPassenger", 1, &OOJS_ARGV[0], nil, @"string");
1279 : return NO;
1280 : }
1281 :
1282 : if (!ValidateContracts(context, argc, vp, NO, &start, &destination, &eta, &fee, &advance, @"addPassenger", &risk)) return NO; // always go through validate contracts (passenger)
1283 :
1284 : // Ensure there's space.
1285 : if ([player passengerCount] >= [player passengerCapacity]) OOJS_RETURN_BOOL(NO);
1286 :
1287 : BOOL OK = [player addPassenger:name start:start destination:destination eta:eta fee:fee advance:advance risk:risk];
1288 : OOJS_RETURN_BOOL(OK);
1289 :
1290 : OOJS_NATIVE_EXIT
1291 : }
1292 :
1293 :
1294 : // removePassenger(name :string)
1295 0 : static JSBool PlayerShipRemovePassenger(JSContext *context, uintN argc, jsval *vp)
1296 : {
1297 : OOJS_NATIVE_ENTER(context)
1298 :
1299 : PlayerEntity *player = OOPlayerForScripting();
1300 : NSString *name = nil;
1301 : BOOL OK = YES;
1302 :
1303 : if (argc > 0) name = OOStringFromJSValue(context, OOJS_ARGV[0]);
1304 : if (EXPECT_NOT(name == nil))
1305 : {
1306 : OOJSReportBadArguments(context, @"PlayerShip", @"removePassenger", MIN(argc, 1U), OOJS_ARGV, nil, @"string");
1307 : return NO;
1308 : }
1309 :
1310 : OK = [player passengerCount] > 0 && [name length] > 0;
1311 : if (OK) OK = [player removePassenger:name];
1312 :
1313 : OOJS_RETURN_BOOL(OK);
1314 :
1315 : OOJS_NATIVE_EXIT
1316 : }
1317 :
1318 :
1319 : // addParcel(description: string, start: int, destination: int, ETA: double, fee: double) : Boolean
1320 0 : static JSBool PlayerShipAddParcel(JSContext *context, uintN argc, jsval *vp)
1321 : {
1322 : OOJS_NATIVE_ENTER(context)
1323 :
1324 : PlayerEntity *player = OOPlayerForScripting();
1325 : NSString *name = nil;
1326 : OOSystemID start = 0, destination = 0;
1327 : jsdouble eta = 0.0, fee = 0.0, premium = 0.0;
1328 : unsigned risk = 0;
1329 :
1330 : if (argc < 5)
1331 : {
1332 : OOJSReportBadArguments(context, @"PlayerShip", @"addParcel", argc, OOJS_ARGV, nil, @"name, start, destination, ETA, fee");
1333 : return NO;
1334 : }
1335 :
1336 : name = OOStringFromJSValue(context, OOJS_ARGV[0]);
1337 : if (EXPECT_NOT(name == nil))
1338 : {
1339 : OOJSReportBadArguments(context, @"PlayerShip", @"addParcel", 1, &OOJS_ARGV[0], nil, @"string");
1340 : return NO;
1341 : }
1342 :
1343 : if (!ValidateContracts(context, argc, vp, NO, &start, &destination, &eta, &fee, &premium, @"addParcel", &risk)) return NO; // always go through validate contracts (passenger/parcel mode)
1344 :
1345 : // Ensure there's space.
1346 :
1347 : BOOL OK = [player addParcel:name start:start destination:destination eta:eta fee:fee premium:premium risk:risk];
1348 : OOJS_RETURN_BOOL(OK);
1349 :
1350 : OOJS_NATIVE_EXIT
1351 : }
1352 :
1353 :
1354 : // removeParcel(description :string)
1355 0 : static JSBool PlayerShipRemoveParcel(JSContext *context, uintN argc, jsval *vp)
1356 : {
1357 : OOJS_NATIVE_ENTER(context)
1358 :
1359 : PlayerEntity *player = OOPlayerForScripting();
1360 : NSString *name = nil;
1361 : BOOL OK = YES;
1362 :
1363 : if (argc > 0) name = OOStringFromJSValue(context, OOJS_ARGV[0]);
1364 : if (EXPECT_NOT(name == nil))
1365 : {
1366 : OOJSReportBadArguments(context, @"PlayerShip", @"removeParcel", MIN(argc, 1U), OOJS_ARGV, nil, @"string");
1367 : return NO;
1368 : }
1369 :
1370 : OK = [player parcelCount] > 0 && [name length] > 0;
1371 : if (OK) OK = [player removeParcel:name];
1372 :
1373 : OOJS_RETURN_BOOL(OK);
1374 :
1375 : OOJS_NATIVE_EXIT
1376 : }
1377 :
1378 :
1379 : // awardContract(quantity: int, commodity: string, start: int, destination: int, eta: double, fee: double) : Boolean
1380 0 : static JSBool PlayerShipAwardContract(JSContext *context, uintN argc, jsval *vp)
1381 : {
1382 : OOJS_NATIVE_ENTER(context)
1383 :
1384 : PlayerEntity *player = OOPlayerForScripting();
1385 : NSString *key = nil;
1386 : int32 qty = 0;
1387 : OOSystemID start = 0, destination = 0;
1388 : jsdouble eta = 0.0, fee = 0.0, premium = 0.0;
1389 :
1390 : if (argc < 6)
1391 : {
1392 : OOJSReportBadArguments(context, @"PlayerShip", @"awardContract", argc, OOJS_ARGV, nil, @"quantity, commodity, start, destination, ETA, fee");
1393 : return NO;
1394 : }
1395 :
1396 : if (!JS_ValueToInt32(context, OOJS_ARGV[0], &qty))
1397 : {
1398 : OOJSReportBadArguments(context, @"PlayerShip", @"awardContract", 1, &OOJS_ARGV[0], nil, @"positive integer (cargo quantity)");
1399 : return NO;
1400 : }
1401 :
1402 : key = OOStringFromJSValue(context, OOJS_ARGV[1]);
1403 : if (EXPECT_NOT(key == nil))
1404 : {
1405 : OOJSReportBadArguments(context, @"PlayerShip", @"awardContract", 1, &OOJS_ARGV[1], nil, @"string (commodity identifier)");
1406 : return NO;
1407 : }
1408 :
1409 : if (!ValidateContracts(context, argc, vp, YES, &start, &destination, &eta, &fee, &premium, @"awardContract", NULL)) return NO; // always go through validate contracts (cargo)
1410 :
1411 : BOOL OK = [player awardContract:qty commodity:key start:start destination:destination eta:eta fee:fee premium:premium];
1412 : OOJS_RETURN_BOOL(OK);
1413 :
1414 : OOJS_NATIVE_EXIT
1415 : }
1416 :
1417 :
1418 : // removeContract(commodity: string, destination: int)
1419 0 : static JSBool PlayerShipRemoveContract(JSContext *context, uintN argc, jsval *vp)
1420 : {
1421 : OOJS_NATIVE_ENTER(context)
1422 :
1423 : PlayerEntity *player = OOPlayerForScripting();
1424 : NSString *key = nil;
1425 : int32 dest = 0;
1426 :
1427 : if (argc < 2)
1428 : {
1429 : OOJSReportBadArguments(context, @"PlayerShip", @"removeContract", argc, OOJS_ARGV, nil, @"commodity, destination");
1430 : return NO;
1431 : }
1432 :
1433 : key = OOStringFromJSValue(context, OOJS_ARGV[0]);
1434 :
1435 : if (EXPECT_NOT(key == nil))
1436 : {
1437 : OOJSReportBadArguments(context, @"PlayerShip", @"removeContract", 1, &OOJS_ARGV[0], nil, @"string (commodity identifier)");
1438 : return NO;
1439 : }
1440 :
1441 : if (!JS_ValueToInt32(context, OOJS_ARGV[1], &dest) || dest < 0 || dest > 255)
1442 : {
1443 : OOJSReportBadArguments(context, @"PlayerShip", @"removeContract", 1, &OOJS_ARGV[1], nil, @"system ID");
1444 : return NO;
1445 : }
1446 :
1447 : BOOL OK = [player removeContract:key destination:(unsigned)dest];
1448 : OOJS_RETURN_BOOL(OK);
1449 :
1450 : OOJS_NATIVE_EXIT
1451 : }
1452 :
1453 :
1454 : // setCustomView(position:vector, orientation:quaternion [, weapon:string])
1455 0 : static JSBool PlayerShipSetCustomView(JSContext *context, uintN argc, jsval *vp)
1456 : {
1457 : OOJS_NATIVE_ENTER(context)
1458 :
1459 : PlayerEntity *player = OOPlayerForScripting();
1460 :
1461 : if (argc < 2)
1462 : {
1463 : OOJSReportBadArguments(context, @"PlayerShip", @"setCustomView", argc, OOJS_ARGV, nil, @"position, orientiation, [weapon]");
1464 : return NO;
1465 : }
1466 :
1467 : // must be in custom view
1468 : if ([UNIVERSE viewDirection] != VIEW_CUSTOM)
1469 : {
1470 : OOJSReportError(context, @"PlayerShip.setCustomView only works when custom view is active.");
1471 : return NO;
1472 : }
1473 :
1474 : NSMutableDictionary *viewData = [NSMutableDictionary dictionaryWithCapacity:3];
1475 :
1476 : Vector position = kZeroVector;
1477 : BOOL gotpos = JSValueToVector(context, OOJS_ARGV[0], &position);
1478 : if (!gotpos)
1479 : {
1480 : OOJSReportBadArguments(context, @"PlayerShip", @"setCustomView", argc, OOJS_ARGV, nil, @"position, orientiation, [weapon]");
1481 : return NO;
1482 : }
1483 : NSString *positionstr = [[NSString alloc] initWithFormat:@"%f %f %f",position.x,position.y,position.z];
1484 :
1485 : Quaternion orientation = kIdentityQuaternion;
1486 : BOOL gotquat = JSValueToQuaternion(context, OOJS_ARGV[1], &orientation);
1487 : if (!gotquat)
1488 : {
1489 : OOJSReportBadArguments(context, @"PlayerShip", @"setCustomView", argc, OOJS_ARGV, nil, @"position, orientiation, [weapon]");
1490 : return NO;
1491 : }
1492 : NSString *orientationstr = [[NSString alloc] initWithFormat:@"%f %f %f %f",orientation.w,orientation.x,orientation.y,orientation.z];
1493 :
1494 : [viewData setObject:positionstr forKey:@"view_position"];
1495 : [viewData setObject:orientationstr forKey:@"view_orientation"];
1496 :
1497 : if (argc > 2)
1498 : {
1499 : NSString* facing = OOStringFromJSValue(context,OOJS_ARGV[2]);
1500 : [viewData setObject:facing forKey:@"weapon_facing"];
1501 : }
1502 :
1503 : [player setCustomViewDataFromDictionary:viewData withScaling:NO];
1504 : [player noteSwitchToView:VIEW_CUSTOM fromView:VIEW_CUSTOM];
1505 :
1506 : [positionstr release];
1507 : [orientationstr release];
1508 :
1509 : OOJS_RETURN_BOOL(YES);
1510 : OOJS_NATIVE_EXIT
1511 : }
1512 :
1513 :
1514 : // resetCustomView()
1515 0 : static JSBool PlayerShipResetCustomView(JSContext *context, uintN argc, jsval *vp)
1516 : {
1517 : OOJS_NATIVE_ENTER(context)
1518 :
1519 : PlayerEntity *player = OOPlayerForScripting();
1520 :
1521 : // must be in custom view
1522 : if ([UNIVERSE viewDirection] != VIEW_CUSTOM)
1523 : {
1524 : OOJSReportError(context, @"PlayerShip.setCustomView only works when custom view is active.");
1525 : return NO;
1526 : }
1527 :
1528 : [player resetCustomView];
1529 : [player noteSwitchToView:VIEW_CUSTOM fromView:VIEW_CUSTOM];
1530 :
1531 : OOJS_RETURN_BOOL(YES);
1532 : OOJS_NATIVE_EXIT
1533 : }
1534 :
1535 :
1536 : // resetScannerZoom()
1537 0 : static JSBool PlayerShipResetScannerZoom(JSContext *context, uintN argc, jsval *vp)
1538 : {
1539 : OOJS_NATIVE_ENTER(context)
1540 :
1541 : PlayerEntity *player = OOPlayerForScripting();
1542 :
1543 : [player resetScannerZoom];
1544 :
1545 : OOJS_RETURN_VOID;
1546 : OOJS_NATIVE_EXIT
1547 : }
1548 :
1549 :
1550 : // takeInternalDamage()
1551 0 : static JSBool PlayerShipTakeInternalDamage(JSContext *context, uintN argc, jsval *vp)
1552 : {
1553 : OOJS_NATIVE_ENTER(context)
1554 :
1555 : PlayerEntity *player = OOPlayerForScripting();
1556 :
1557 : BOOL took = [player takeInternalDamage];
1558 :
1559 : OOJS_RETURN_BOOL(took);
1560 : OOJS_NATIVE_EXIT
1561 : }
1562 :
1563 :
1564 : // beginHyperspaceCountdown([int: spin_time])
1565 0 : static JSBool PlayerShipBeginHyperspaceCountdown(JSContext *context, uintN argc, jsval *vp)
1566 : {
1567 : OOJS_NATIVE_ENTER(context)
1568 :
1569 : PlayerEntity *player = OOPlayerForScripting();
1570 : int32 spin_time;
1571 : int32 witchspaceSpinUpTime = 0;
1572 : BOOL begun = NO;
1573 : if (argc < 1)
1574 : {
1575 : witchspaceSpinUpTime = 0;
1576 : #ifdef OO_DUMP_PLANETINFO
1577 : // quick intersystem jumps for debugging
1578 : witchspaceSpinUpTime = 1;
1579 : #endif
1580 : }
1581 : else
1582 : {
1583 : if (!JS_ValueToInt32(context, OOJS_ARGV[0], &spin_time) || spin_time < 5 || spin_time > 60)
1584 : {
1585 : OOJSReportBadArguments(context, @"PlayerShip", @"beginHyperspaceCountdown", 1, &OOJS_ARGV[0], nil, @"between 5 and 60 seconds");
1586 : return NO;
1587 : }
1588 : if (spin_time < 5)
1589 : {
1590 : witchspaceSpinUpTime = 5;
1591 : }
1592 : else
1593 : {
1594 : witchspaceSpinUpTime = spin_time;
1595 : }
1596 : }
1597 : if ([player hasHyperspaceMotor] && [player status] == STATUS_IN_FLIGHT && [player witchJumpChecklist:false])
1598 : {
1599 : [player beginWitchspaceCountdown:witchspaceSpinUpTime];
1600 : begun = YES;
1601 : }
1602 : OOJS_RETURN_BOOL(begun);
1603 : OOJS_NATIVE_EXIT
1604 : }
1605 :
1606 :
1607 : // cancelHyperspaceCountdown()
1608 0 : static JSBool PlayerShipCancelHyperspaceCountdown(JSContext *context, uintN argc, jsval *vp)
1609 : {
1610 : OOJS_NATIVE_ENTER(context)
1611 :
1612 : PlayerEntity *player = OOPlayerForScripting();
1613 :
1614 : BOOL cancelled = NO;
1615 : if ([player hasHyperspaceMotor] && [player status] == STATUS_WITCHSPACE_COUNTDOWN)
1616 : {
1617 : [player cancelWitchspaceCountdown];
1618 : [player setJumpType:false];
1619 : cancelled = YES;
1620 : }
1621 :
1622 : OOJS_RETURN_BOOL(cancelled);
1623 : OOJS_NATIVE_EXIT
1624 :
1625 : }
1626 :
1627 :
1628 0 : static JSBool PlayerShipBeginGalacticHyperspaceCountdown(JSContext *context, uintN argc, jsval *vp)
1629 : {
1630 : OOJS_NATIVE_ENTER(context)
1631 :
1632 : PlayerEntity *player = OOPlayerForScripting();
1633 : int32 spin_time;
1634 : int32 witchspaceSpinUpTime = 5;
1635 : BOOL begun = NO;
1636 : if (argc == 1)
1637 : {
1638 :
1639 : if (!JS_ValueToInt32(context, OOJS_ARGV[0], &spin_time) || spin_time < 5 || spin_time > 60)
1640 : {
1641 : OOJSReportBadArguments(context, @"PlayerShip", @"beginGalacticHyperspaceCountdown", 1, &OOJS_ARGV[0], nil, @"between 5 and 60 seconds");
1642 : return NO;
1643 : }
1644 : if (spin_time < 5)
1645 : {
1646 : witchspaceSpinUpTime = 5;
1647 : }
1648 : else
1649 : {
1650 : witchspaceSpinUpTime = spin_time;
1651 : }
1652 : }
1653 : if ([player hasEquipmentItemProviding:@"EQ_GAL_DRIVE"] && [player status] == STATUS_IN_FLIGHT && [player witchJumpChecklist:true])
1654 : {
1655 : [player setJumpType:YES];
1656 : [player setWitchspaceCountdown:witchspaceSpinUpTime];
1657 : [player setStatus:STATUS_WITCHSPACE_COUNTDOWN];
1658 : [player playGalacticHyperspace];
1659 : // say it!
1660 : [UNIVERSE addMessage:[NSString stringWithFormat:DESC(@"witch-galactic-in-f-seconds"), witchspaceSpinUpTime] forCount:1.0];
1661 : begun = YES;
1662 : }
1663 : OOJS_RETURN_BOOL(begun);
1664 : OOJS_NATIVE_EXIT
1665 : }
1666 :
1667 :
1668 : // setMultiFunctionDisplay(index,key)
1669 0 : static JSBool PlayerShipSetMultiFunctionDisplay(JSContext *context, uintN argc, jsval *vp)
1670 : {
1671 : OOJS_NATIVE_ENTER(context)
1672 :
1673 : NSString *key = nil;
1674 : uint32 index = 0;
1675 : PlayerEntity *player = OOPlayerForScripting();
1676 : BOOL OK = YES;
1677 :
1678 : if (argc > 0)
1679 : {
1680 : if (!JS_ValueToECMAUint32(context,OOJS_ARGV[0],&index))
1681 : {
1682 : OOJSReportBadArguments(context, @"PlayerShip", @"setMultiFunctionDisplay", MIN(argc, 1U), OOJS_ARGV, nil, @"number (index) [, string (key)]");
1683 : return NO;
1684 : }
1685 : }
1686 :
1687 : if (argc > 1)
1688 : {
1689 : key = OOStringFromJSValue(context, OOJS_ARGV[1]);
1690 : }
1691 :
1692 : OK = [player setMultiFunctionDisplay:index toKey:key];
1693 :
1694 : OOJS_RETURN_BOOL(OK);
1695 :
1696 : OOJS_NATIVE_EXIT
1697 : }
1698 :
1699 :
1700 : // setMultiFunctionText(key,value)
1701 0 : static JSBool PlayerShipSetMultiFunctionText(JSContext *context, uintN argc, jsval *vp)
1702 : {
1703 : OOJS_NATIVE_ENTER(context)
1704 :
1705 : NSString *key = nil;
1706 : NSString *value = nil;
1707 : PlayerEntity *player = OOPlayerForScripting();
1708 : JSBool reflow = NO;
1709 :
1710 : if (argc > 0)
1711 : {
1712 : key = OOStringFromJSValue(context, OOJS_ARGV[0]);
1713 : }
1714 : if (key == nil)
1715 : {
1716 : OOJSReportBadArguments(context, @"PlayerShip", @"setMultiFunctionText", MIN(argc, 1U), OOJS_ARGV, nil, @"string (key) [, string (text)]");
1717 : return NO;
1718 : }
1719 : if (argc > 1)
1720 : {
1721 : value = OOStringFromJSValue(context, OOJS_ARGV[1]);
1722 : }
1723 : if (argc > 2 && EXPECT_NOT(!JS_ValueToBoolean(context, OOJS_ARGV[2], &reflow)))
1724 : {
1725 : OOJSReportBadArguments(context, @"setMultiFunctionText", @"reflow", argc, OOJS_ARGV, nil, @"boolean");
1726 : return NO;
1727 : }
1728 :
1729 : if (!reflow)
1730 : {
1731 : [player setMultiFunctionText:value forKey:key];
1732 : }
1733 : else
1734 : {
1735 : GuiDisplayGen *gui = [UNIVERSE gui];
1736 : NSString *formatted = [gui reflowTextForMFD:value];
1737 : [player setMultiFunctionText:formatted forKey:key];
1738 : }
1739 :
1740 : OOJS_RETURN_VOID;
1741 :
1742 : OOJS_NATIVE_EXIT
1743 : }
1744 :
1745 : // setPrimedEquipment(key, [noMessage])
1746 0 : static JSBool PlayerShipSetPrimedEquipment(JSContext *context, uintN argc, jsval *vp)
1747 : {
1748 : OOJS_NATIVE_ENTER(context)
1749 :
1750 : NSString *key = nil;
1751 : PlayerEntity *player = OOPlayerForScripting();
1752 : JSBool showMsg = YES;
1753 :
1754 : if (argc > 0)
1755 : {
1756 : key = OOStringFromJSValue(context, OOJS_ARGV[0]);
1757 : }
1758 : if (key == nil)
1759 : {
1760 : OOJSReportBadArguments(context, @"PlayerShip", @"setPrimedEquipment", MIN(argc, 1U), OOJS_ARGV, nil, @"string (key)");
1761 : return NO;
1762 : }
1763 : if (argc > 1 && EXPECT_NOT(!JS_ValueToBoolean(context, OOJS_ARGV[1], &showMsg)))
1764 : {
1765 : OOJSReportBadArguments(context, @"PlayerShip", @"setPrimedEquipment", MIN(argc, 2U), OOJS_ARGV, nil, @"boolean");
1766 : return NO;
1767 : }
1768 :
1769 : OOJS_RETURN_BOOL([player setPrimedEquipment:key showMessage:showMsg]);
1770 :
1771 : OOJS_NATIVE_EXIT
1772 : }
1773 :
1774 :
1775 : // setCustomHUDDial(key,value)
1776 0 : static JSBool PlayerShipSetCustomHUDDial(JSContext *context, uintN argc, jsval *vp)
1777 : {
1778 : OOJS_NATIVE_ENTER(context)
1779 :
1780 : NSString *key = nil;
1781 : id value = nil;
1782 : PlayerEntity *player = OOPlayerForScripting();
1783 :
1784 : if (argc > 0)
1785 : {
1786 : key = OOStringFromJSValue(context, OOJS_ARGV[0]);
1787 : }
1788 : if (key == nil)
1789 : {
1790 : OOJSReportBadArguments(context, @"PlayerShip", @"setCustomHUDDial", MIN(argc, 1U), OOJS_ARGV, nil, @"string (key), value]");
1791 : return NO;
1792 : }
1793 : if (argc > 1)
1794 : {
1795 : value = OOJSNativeObjectFromJSValue(context, OOJS_ARGV[1]);
1796 : }
1797 : else
1798 : {
1799 : value = @"";
1800 : }
1801 :
1802 : [player setDialCustom:value forKey:key];
1803 :
1804 :
1805 : OOJS_RETURN_VOID;
1806 :
1807 : OOJS_NATIVE_EXIT
1808 : }
1809 :
1810 :
1811 0 : static JSBool PlayerShipHideHUDSelector(JSContext *context, uintN argc, jsval *vp)
1812 : {
1813 : OOJS_NATIVE_ENTER(context)
1814 :
1815 : NSString *key = nil;
1816 : PlayerEntity *player = OOPlayerForScripting();
1817 :
1818 : if (argc > 0)
1819 : {
1820 : key = OOStringFromJSValue(context, OOJS_ARGV[0]);
1821 : }
1822 : if (key == nil)
1823 : {
1824 : OOJSReportBadArguments(context, @"PlayerShip", @"hideHUDSelector", MIN(argc, 1U), OOJS_ARGV, nil, @"string (selector)");
1825 : return NO;
1826 : }
1827 : [[player hud] setHiddenSelector:key hidden:YES];
1828 :
1829 : OOJS_RETURN_VOID;
1830 :
1831 : OOJS_NATIVE_EXIT
1832 : }
1833 :
1834 :
1835 0 : static JSBool PlayerShipShowHUDSelector(JSContext *context, uintN argc, jsval *vp)
1836 : {
1837 : OOJS_NATIVE_ENTER(context)
1838 :
1839 : NSString *key = nil;
1840 : PlayerEntity *player = OOPlayerForScripting();
1841 :
1842 : if (argc > 0)
1843 : {
1844 : key = OOStringFromJSValue(context, OOJS_ARGV[0]);
1845 : }
1846 : if (key == nil)
1847 : {
1848 : OOJSReportBadArguments(context, @"PlayerShip", @"hideHUDSelector", MIN(argc, 1U), OOJS_ARGV, nil, @"string (selector)");
1849 : return NO;
1850 : }
1851 : [[player hud] setHiddenSelector:key hidden:NO];
1852 :
1853 : OOJS_RETURN_VOID;
1854 :
1855 : OOJS_NATIVE_EXIT
1856 : }
1857 :
1858 :
1859 :
1860 0 : static BOOL ValidateContracts(JSContext *context, uintN argc, jsval *vp, BOOL isCargo, OOSystemID *start, OOSystemID *destination, double *eta, double *fee, double *premium, NSString *functionName, unsigned *risk)
1861 : {
1862 : OOJS_PROFILE_ENTER
1863 :
1864 : NSCParameterAssert(context != NULL && vp != NULL && start != NULL && destination != NULL && eta != NULL && fee != NULL);
1865 :
1866 : unsigned uValue, offset = isCargo ? 2 : 1;
1867 : jsdouble fValue;
1868 : int32 iValue;
1869 :
1870 : if (!JS_ValueToInt32(context, OOJS_ARGV[offset + 0], &iValue) || iValue < 0 || iValue > kOOMaximumSystemID)
1871 : {
1872 : OOJSReportBadArguments(context, @"PlayerShip", functionName, 1, &OOJS_ARGV[offset + 0], nil, @"system ID");
1873 : return NO;
1874 : }
1875 : *start = iValue;
1876 :
1877 : if (!JS_ValueToInt32(context, OOJS_ARGV[offset + 1], &iValue) || iValue < 0 || iValue > kOOMaximumSystemID)
1878 : {
1879 : OOJSReportBadArguments(context, @"PlayerShip", functionName, 1, &OOJS_ARGV[offset + 1], nil, @"system ID");
1880 : return NO;
1881 : }
1882 : *destination = iValue;
1883 :
1884 :
1885 : if (!JS_ValueToNumber(context, OOJS_ARGV[offset + 2], &fValue) || !isfinite(fValue) || fValue <= [PLAYER clockTime])
1886 : {
1887 : OOJSReportBadArguments(context, @"PlayerShip", functionName, 1, &OOJS_ARGV[offset + 2], nil, @"number (future time)");
1888 : return NO;
1889 : }
1890 : *eta = fValue;
1891 :
1892 : if (!JS_ValueToNumber(context, OOJS_ARGV[offset + 3], &fValue) || !isfinite(fValue) || fValue < 0.0)
1893 : {
1894 : OOJSReportBadArguments(context, @"PlayerShip", functionName, 1, &OOJS_ARGV[offset + 3], nil, @"number (credits quantity)");
1895 : return NO;
1896 : }
1897 : *fee = fValue;
1898 :
1899 : if (argc > offset+4 && JS_ValueToNumber(context, OOJS_ARGV[offset + 4], &fValue) && isfinite(fValue) && fValue >= 0.0)
1900 : {
1901 : *premium = fValue;
1902 : }
1903 :
1904 : if (!isCargo)
1905 : {
1906 : if (argc > offset+5 && JS_ValueToECMAUint32(context, OOJS_ARGV[offset + 5], &uValue) && isfinite((double)uValue))
1907 : {
1908 : *risk = uValue;
1909 : }
1910 : }
1911 :
1912 : return YES;
1913 :
1914 : OOJS_PROFILE_EXIT
1915 : }
|