Oolite 1.91.0.7645-241119-222d325
Loading...
Searching...
No Matches
OOJSShip.m
Go to the documentation of this file.
1/*
2
3OOJSShip.m
4
5Oolite
6Copyright (C) 2004-2013 Giles C Williams and contributors
7
8This program is free software; you can redistribute it and/or
9modify it under the terms of the GNU General Public License
10as published by the Free Software Foundation; either version 2
11of the License, or (at your option) any later version.
12
13This program is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with this program; if not, write to the Free Software
20Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21MA 02110-1301, USA.
22
23*/
24
25#import "OOJSShip.h"
26#import "OOJSEntity.h"
27#import "OOJSWormhole.h"
28#import "OOJSVector.h"
29#import "OOJSQuaternion.h"
30#import "OOJSEquipmentInfo.h"
32#import "ShipEntity.h"
33#import "ShipEntityAI.h"
35#import "StationEntity.h"
36#import "WormholeEntity.h"
37#import "AI.h"
38#import "OOStringParsing.h"
40#import "OORoleSet.h"
41#import "OOJSPlayer.h"
42#import "PlayerEntity.h"
44#import "OOShipGroup.h"
45#import "OOShipRegistry.h"
46#import "OOEquipmentType.h"
47#import "ResourceManager.h"
49#import "OOMesh.h"
50#import "OOConstToString.h"
52#import "OOCharacter.h"
53
54
55static JSObject *sShipPrototype;
56
57
58static JSBool ShipGetProperty(JSContext *context, JSObject *this, jsid propID, jsval *value);
59static JSBool ShipSetProperty(JSContext *context, JSObject *this, jsid propID, JSBool strict, jsval *value);
60
61static JSBool ShipSetScript(JSContext *context, uintN argc, jsval *vp);
62static JSBool ShipSetAI(JSContext *context, uintN argc, jsval *vp);
63static JSBool ShipSwitchAI(JSContext *context, uintN argc, jsval *vp);
64static JSBool ShipExitAI(JSContext *context, uintN argc, jsval *vp);
65static JSBool ShipReactToAIMessage(JSContext *context, uintN argc, jsval *vp);
66static JSBool ShipSendAIMessage(JSContext *context, uintN argc, jsval *vp);
67static JSBool ShipDeployEscorts(JSContext *context, uintN argc, jsval *vp);
68static JSBool ShipDockEscorts(JSContext *context, uintN argc, jsval *vp);
69static JSBool ShipHasRole(JSContext *context, uintN argc, jsval *vp);
70static JSBool ShipEjectItem(JSContext *context, uintN argc, jsval *vp);
71static JSBool ShipEjectSpecificItem(JSContext *context, uintN argc, jsval *vp);
72static JSBool ShipDumpCargo(JSContext *context, uintN argc, jsval *vp);
73static JSBool ShipAddCargoEntity(JSContext *context, uintN argc, jsval *vp);
74static JSBool ShipSpawn(JSContext *context, uintN argc, jsval *vp);
75static JSBool ShipDealEnergyDamage(JSContext *context, uintN argc, jsval *vp);
76static JSBool ShipExplode(JSContext *context, uintN argc, jsval *vp);
77static JSBool ShipRemove(JSContext *context, uintN argc, jsval *vp);
78static JSBool ShipRunLegacyScriptActions(JSContext *context, uintN argc, jsval *vp);
79static JSBool ShipCommsMessage(JSContext *context, uintN argc, jsval *vp);
80static JSBool ShipFireECM(JSContext *context, uintN argc, jsval *vp);
81static JSBool ShipAbandonShip(JSContext *context, uintN argc, jsval *vp);
82static JSBool ShipCanAwardEquipment(JSContext *context, uintN argc, jsval *vp);
83static JSBool ShipAwardEquipment(JSContext *context, uintN argc, jsval *vp);
84static JSBool ShipAdjustCargo(JSContext *context, uintN argc, jsval *vp);
85static JSBool ShipRequestHelpFromGroup(JSContext *context, uintN argc, jsval *vp);
86static JSBool ShipPatrolReportIn(JSContext *context, uintN argc, jsval *vp);
87
88static JSBool ShipRemoveEquipment(JSContext *context, uintN argc, jsval *vp);
89static JSBool ShipRestoreSubEntities(JSContext *context, uintN argc, jsval *vp);
90static JSBool ShipHasEquipmentProviding(JSContext *context, uintN argc, jsval *vp);
91static JSBool ShipEquipmentStatus(JSContext *context, uintN argc, jsval *vp);
92static JSBool ShipSetEquipmentStatus(JSContext *context, uintN argc, jsval *vp);
93static JSBool ShipSelectNewMissile(JSContext *context, uintN argc, jsval *vp);
94static JSBool ShipFireMissile(JSContext *context, uintN argc, jsval *vp);
95static JSBool ShipFindNearestStation(JSContext *context, uintN argc, jsval *vp);
96static JSBool ShipSetBounty(JSContext *context, uintN argc, jsval *vp);
97static JSBool ShipSetCargo(JSContext *context, uintN argc, jsval *vp);
98static JSBool ShipSetMaterials(JSContext *context, uintN argc, jsval *vp);
99static JSBool ShipSetShaders(JSContext *context, uintN argc, jsval *vp);
100static JSBool ShipExitSystem(JSContext *context, uintN argc, jsval *vp);
101static JSBool ShipUpdateEscortFormation(JSContext *context, uintN argc, jsval *vp);
102static JSBool ShipClearDefenseTargets(JSContext *context, uintN argc, jsval *vp);
103static JSBool ShipAddDefenseTarget(JSContext *context, uintN argc, jsval *vp);
104static JSBool ShipRemoveDefenseTarget(JSContext *context, uintN argc, jsval *vp);
105static JSBool ShipAddCollisionException(JSContext *context, uintN argc, jsval *vp);
106static JSBool ShipRemoveCollisionException(JSContext *context, uintN argc, jsval *vp);
107static JSBool ShipGetMaterials(JSContext *context, uintN argc, jsval *vp);
108static JSBool ShipGetShaders(JSContext *context, uintN argc, jsval *vp);
109static JSBool ShipBecomeCascadeExplosion(JSContext *context, uintN argc, jsval *vp);
110static JSBool ShipBroadcastCascadeImminent(JSContext *context, uintN argc, jsval *vp);
111static JSBool ShipBroadcastDistressMessage(JSContext *context, uintN argc, jsval *vp);
112static JSBool ShipOfferToEscort(JSContext *context, uintN argc, jsval *vp);
113static JSBool ShipMarkTargetForFines(JSContext *context, uintN argc, jsval *vp);
114static JSBool ShipEnterWormhole(JSContext *context, uintN argc, jsval *vp);
115static JSBool ShipNotifyGroupOfWormhole(JSContext *context, uintN argc, jsval *vp);
116static JSBool ShipThrowSpark(JSContext *context, uintN argc, jsval *vp);
117
118static JSBool ShipPerformAttack(JSContext *context, uintN argc, jsval *vp);
119static JSBool ShipPerformCollect(JSContext *context, uintN argc, jsval *vp);
120static JSBool ShipPerformEscort(JSContext *context, uintN argc, jsval *vp);
121static JSBool ShipPerformFaceDestination(JSContext *context, uintN argc, jsval *vp);
122static JSBool ShipPerformFlee(JSContext *context, uintN argc, jsval *vp);
123static JSBool ShipPerformFlyToRangeFromDestination(JSContext *context, uintN argc, jsval *vp);
124static JSBool ShipPerformHold(JSContext *context, uintN argc, jsval *vp);
125static JSBool ShipPerformIdle(JSContext *context, uintN argc, jsval *vp);
126static JSBool ShipPerformIntercept(JSContext *context, uintN argc, jsval *vp);
127static JSBool ShipPerformLandOnPlanet(JSContext *context, uintN argc, jsval *vp);
128static JSBool ShipPerformMining(JSContext *context, uintN argc, jsval *vp);
129static JSBool ShipPerformScriptedAI(JSContext *context, uintN argc, jsval *vp);
130static JSBool ShipPerformScriptedAttackAI(JSContext *context, uintN argc, jsval *vp);
131static JSBool ShipPerformStop(JSContext *context, uintN argc, jsval *vp);
132static JSBool ShipPerformTumble(JSContext *context, uintN argc, jsval *vp);
133
134static JSBool ShipRequestDockingInstructions(JSContext *context, uintN argc, jsval *vp);
135static JSBool ShipRecallDockingInstructions(JSContext *context, uintN argc, jsval *vp);
136static JSBool ShipCheckCourseToDestination(JSContext *context, uintN argc, jsval *vp);
137static JSBool ShipGetSafeCourseToDestination(JSContext *context, uintN argc, jsval *vp);
138static JSBool ShipCheckScanner(JSContext *context, uintN argc, jsval *vp);
139static JSBool ShipThreatAssessment(JSContext *context, uintN argc, jsval *vp);
140static JSBool ShipDamageAssessment(JSContext *context, uintN argc, jsval *vp);
142
143static JSBool ShipSetCargoType(JSContext *context, uintN argc, jsval *vp);
144static JSBool ShipSetCrew(JSContext *context, uintN argc, jsval *vp);
145
146static BOOL RemoveOrExplodeShip(JSContext *context, uintN argc, jsval *vp, BOOL explode);
147static JSBool ShipSetMaterialsInternal(JSContext *context, uintN argc, jsval *vp, ShipEntity *thisEnt, BOOL fromShaders);
148
149static JSBool ShipStaticKeysForRole(JSContext *context, uintN argc, jsval *vp);
150static JSBool ShipStaticKeys(JSContext *context, uintN argc, jsval *vp);
151static JSBool ShipStaticRoles(JSContext *context, uintN argc, jsval *vp);
152static JSBool ShipStaticRoleIsInCategory(JSContext *context, uintN argc, jsval *vp);
153static JSBool ShipStaticShipDataForKey(JSContext *context, uintN argc, jsval *vp);
154static JSBool ShipStaticSetShipDataForKey(JSContext *context, uintN argc, jsval *vp);
155
156static JSClass sShipClass =
157{
158 "Ship",
159 JSCLASS_HAS_PRIVATE,
160
161 JS_PropertyStub, // addProperty
162 JS_PropertyStub, // delProperty
163 ShipGetProperty, // getProperty
164 ShipSetProperty, // setProperty
165 JS_EnumerateStub, // enumerate
166 JS_ResolveStub, // resolve
167 JS_ConvertStub, // convert
168 OOJSObjectWrapperFinalize,// finalize
169 JSCLASS_NO_OPTIONAL_MEMBERS
170};
171
172
173/* It turns out that the value in SpiderMonkey used to identify these
174 * enums is an 8-bit signed int:
175 * developer.mozilla.org/en/docs/SpiderMonkey/JSAPI_Reference/JSPropertySpec
176 * which puts a limit of 256 properties on the ship object. Moved the
177 * enum to start at -128, so we can use the full 256 rather than just
178 * 128 of them. I don't think any of our other classes are getting
179 * close to the limit yet.
180 * - CIM 29/9/2013
181 */
182enum
183{
184 // Property IDs
185 kShip_accuracy = -128, // the ship's accuracy, float, read/write
186 kShip_aftWeapon, // the ship's aft weapon, equipmentType, read/write
187 kShip_AI, // AI state machine name, string, read-only
188 kShip_AIScript, // AI script, Script, read-only
189 kShip_AIScriptWakeTime, // next wakeup time, integer, read/write
190 kShip_AIState, // AI state machine state, string, read/write
191 kShip_AIFoundTarget, // AI "found target", entity, read/write
192 kShip_AIPrimaryAggressor, // AI "primary aggressor", entity, read/write
193 kShip_alertCondition, // number 0-3, read-only, combat alert level
194 kShip_autoAI, // bool, read-only, auto_ai from shipdata
195 kShip_autoWeapons, // bool, read-only, auto_weapons from shipdata
196 kShip_beaconCode, // beacon code, string, read/write
197 kShip_beaconLabel, // beacon label, string, read/write
198 kShip_boundingBox, // boundingBox, vector, read-only
199 kShip_bounty, // bounty, unsigned int, read/write
200 kShip_cargoList, // cargo on board, array of objects, read-only
201 kShip_cargoSpaceAvailable, // free cargo space, integer, read-only
202 kShip_cargoSpaceCapacity, // maximum cargo, integer, read/write
203 kShip_cargoSpaceUsed, // cargo on board, integer, read-only
204 kShip_collisionExceptions, // collision exception list, array, read-only
205 kShip_contracts, // cargo contracts contracts, array - strings & whatnot, read only
206 kShip_commodity, // commodity of a ship, read only
207 kShip_commodityAmount, // commodityAmount of a ship, read only
208 kShip_cloakAutomatic, // should cloack start by itself or by script, read/write
209 kShip_crew, // crew, list, read only
210 kShip_cruiseSpeed, // desired cruising speed, number, read only
211 kShip_currentWeapon, // the ship's active weapon, equipmentType, read/write
212 kShip_dataKey, // string, read-only, shipdata.plist key
213 kShip_defenseTargets, // array, read-only, defense targets
214 kShip_desiredRange, // desired Range, double, read/write
215 kShip_desiredSpeed, // AI desired flight speed, double, read/write
216 kShip_destination, // flight destination, Vector, read/write
217 kShip_destinationSystem, // destination system, number, read/write
218 kShip_displayName, // name displayed on screen, string, read/write
219 kShip_dockingInstructions, // name displayed on screen, string, read/write
220 kShip_energyRechargeRate, // energy recharge rate, float, read-only
221 kShip_entityPersonality, // per-ship random number, int, read-only
222 kShip_equipment, // the ship's equipment, array of EquipmentInfo, read only
223 kShip_escortGroup, // group, ShipGroup, read-only
224 kShip_escorts, // deployed escorts, array of Ship, read-only
225 kShip_exhaustEmissiveColor, // exhaust emissive color, array, read/write
226 kShip_exhausts, // exhausts, array, read-only
227 kShip_extraCargo, // cargo space increase granted by large cargo bay, int, read-only
228 kShip_flashers, // flashers, array, read-only
229 kShip_forwardWeapon, // the ship's forward weapon, equipmentType, read/write
230 kShip_fuel, // fuel, float, read/write
231 kShip_fuelChargeRate, // fuel scoop rate & charge multiplier, float, read-only
232 kShip_group, // group, ShipGroup, read/write
233 kShip_hasHostileTarget, // has hostile target, boolean, read-only
234 kShip_hasHyperspaceMotor, // has hyperspace motor, boolean, read-only
235 kShip_hasSuspendedAI, // AI has suspended states, boolean, read-only
236 kShip_heading, // forwardVector of a ship, read-only
237 kShip_heatInsulation, // hull heat insulation, double, read/write
238 kShip_homeSystem, // home system, number, read/write
239 kShip_hyperspaceSpinTime, // hyperspace spin time, float, read/write
240 kShip_injectorBurnRate, // injector burn rate, number, read/write dLY/s
241 kShip_injectorSpeedFactor, // injector speed factor, number, read/write
242 kShip_isBeacon, // is beacon, boolean, read-only
243 kShip_isBoulder, // is a boulder (generates splinters), boolean, read/write
244 kShip_isCargo, // contains cargo, boolean, read-only
245 kShip_isCloaked, // cloaked, boolean, read/write (if cloaking device installed)
246 kShip_isDerelict, // is an abandoned ship, boolean, read-only
247 kShip_isFrangible, // frangible, boolean, read-only
248 kShip_isFleeing, // is fleeing, boolean, read-only
249 kShip_isJamming, // jamming scanners, boolean, read/write (if jammer installed)
250 kShip_isMinable, // is a sensible target for mining, boolean, read-only
251 kShip_isMine, // is mine, boolean, read-only
252 kShip_isMissile, // is missile, boolean, read-only
253 kShip_isPiloted, // is piloted, boolean, read-only (includes stations)
254 kShip_isPirate, // is pirate, boolean, read-only
255 kShip_isPirateVictim, // is pirate victim, boolean, read-only
256 kShip_isPolice, // is police, boolean, read-only
257 kShip_isRock, // is a rock (hermits included), boolean, read-only
258 kShip_isThargoid, // is thargoid, boolean, read-only
259 kShip_isTurret, // is turret, boolean, read-only
260 kShip_isTrader, // is trader, boolean, read-only
261 kShip_isWeapon, // is missile or mine, boolean, read-only
262 kShip_laserHeatLevel, // active laser temperature, float, read-only
263 kShip_laserHeatLevelAft, // aft laser temperature, float, read-only
264 kShip_laserHeatLevelForward, // fore laser temperature, float, read-only
265 kShip_laserHeatLevelPort, // port laser temperature, float, read-only
266 kShip_laserHeatLevelStarboard, // starboard laser temperature, float, read-only
267 kShip_lightsActive, // flasher/shader light flag, boolean, read/write
268 kShip_markedForFines, // has been marked for fines
269 kShip_maxEscorts, // maximum escort count, int, read/write
270 kShip_maxPitch, // maximum flight pitch, double, read-only
271 kShip_maxSpeed, // maximum flight speed, double, read-only
272 kShip_maxRoll, // maximum flight roll, double, read-only
273 kShip_maxYaw, // maximum flight yaw, double, read-only
274 kShip_maxThrust, // maximum thrust, double, read-only
275 kShip_missileCapacity, // max missiles capacity, integer, read-only
276 kShip_missileLoadTime, // missile load time, double, read/write
277 kShip_missiles, // the ship's missiles / external storage, array of equipmentTypes, read only
278 kShip_name, // name, string, read-only
279 kShip_parcelCount, // number of parcels on ship, integer, read-only
280 kShip_parcels, // parcel contracts, array - strings & whatnot, read only
281 kShip_passengerCapacity, // amount of passenger space on ship, integer, read-only
282 kShip_passengerCount, // number of passengers on ship, integer, read-only
283 kShip_passengers, // passengers contracts, array - strings & whatnot, read only
284 kShip_pitch, // pitch level, float, read-only
285 kShip_portWeapon, // the ship's port weapon, equipmentType, read/write
286 kShip_potentialCollider, // "proximity alert" ship, Entity, read-only
287 kShip_primaryRole, // Primary role, string, read/write
288 kShip_reactionTime, // AI reaction time, read/write
289 kShip_reportAIMessages, // report AI messages, boolean, read/write
290 kShip_roleWeights, // roles and weights, dictionary, read-only
291 kShip_roles, // roles, array, read-only
292 kShip_roll, // roll level, float, read-only
293 kShip_savedCoordinates, // coordinates in system space for AI use, Vector, read/write
294 kShip_scanDescription, // STE scan class label, string, read/write
295 kShip_scannerDisplayColor1, // color of lollipop shown on scanner, array, read/write
296 kShip_scannerDisplayColor2, // color of lollipop shown on scanner when flashing, array, read/write
297 kShip_scannerHostileDisplayColor1, // color of lollipop shown on scanner, array, read/write
298 kShip_scannerHostileDisplayColor2, // color of lollipop shown on scanner when flashing, array, read/write
299 kShip_scannerRange, // scanner range, double, read-only
300 kShip_script, // script, Script, read-only
301 kShip_scriptedMisjump, // next jump will miss if set to true, boolean, read/write
302 kShip_scriptedMisjumpRange, // 0..1 range of next misjump, float, read/write
303 kShip_scriptInfo, // arbitrary data for scripts, dictionary, read-only
304 kShip_shipClassName, // ship type name, string, read/write
305 kShip_shipUniqueName, // uniqish name, string, read/write
306 kShip_speed, // current flight speed, double, read-only
307 kShip_starboardWeapon, // the ship's starboard weapon, equipmentType, read/write
308 kShip_subEntities, // subentities, array of Ship, read-only
309 kShip_subEntityCapacity, // max subentities for this ship, int, read-only
310 kShip_subEntityRotation, // subentity rotation velocity, quaternion, read/write
311 kShip_sunGlareFilter, // sun glare filter multiplier, float, read/write
312 kShip_target, // target, Ship, read/write
313 kShip_temperature, // hull temperature, double, read/write
314 kShip_thrust, // the ship's thrust, double, read/write
315 kShip_thrustVector, // thrust-related component of velocity, vector, read-only
316 kShip_trackCloseContacts, // generate close contact events, boolean, read/write
317 kShip_vectorForward, // forwardVector of a ship, read-only
318 kShip_vectorRight, // rightVector of a ship, read-only
319 kShip_vectorUp, // upVector of a ship, read-only
320 kShip_velocity, // velocity, vector, read/write
321 kShip_weaponFacings, // available facings, int, read-only
322 kShip_weaponPositionAft, // weapon offset, vector, read-only
323 kShip_weaponPositionForward, // weapon offset, vector, read-only
324 kShip_weaponPositionPort, // weapon offset, vector, read-only
325 kShip_weaponPositionStarboard, // weapon offset, vector, read-only
326 kShip_weaponRange, // weapon range, double, read-only
327 kShip_withinStationAegis, // within main station aegis, boolean, read/write
328 kShip_yaw, // yaw level, float, read-only
329};
330
331
332static JSPropertySpec sShipProperties[] =
333{
334 // JS name ID flags
335 { "accuracy", kShip_accuracy, OOJS_PROP_READWRITE_CB },
336 { "aftWeapon", kShip_aftWeapon, OOJS_PROP_READWRITE_CB },
338 { "AIScript", kShip_AIScript, OOJS_PROP_READONLY_CB },
339 { "AIScriptWakeTime", kShip_AIScriptWakeTime, OOJS_PROP_READWRITE_CB },
341 { "AIFoundTarget", kShip_AIFoundTarget, OOJS_PROP_READWRITE_CB },
342 { "AIPrimaryAggressor", kShip_AIPrimaryAggressor, OOJS_PROP_READWRITE_CB },
343 { "alertCondition", kShip_alertCondition, OOJS_PROP_READONLY_CB },
344 { "autoAI", kShip_autoAI, OOJS_PROP_READONLY_CB },
345 { "autoWeapons", kShip_autoWeapons, OOJS_PROP_READONLY_CB },
346 { "beaconCode", kShip_beaconCode, OOJS_PROP_READWRITE_CB },
347 { "beaconLabel", kShip_beaconLabel, OOJS_PROP_READWRITE_CB },
348 { "boundingBox", kShip_boundingBox, OOJS_PROP_READONLY_CB },
350 { "cargoList", kShip_cargoList, OOJS_PROP_READONLY_CB },
351 { "cargoSpaceUsed", kShip_cargoSpaceUsed, OOJS_PROP_READONLY_CB },
352 { "cargoSpaceCapacity", kShip_cargoSpaceCapacity, OOJS_PROP_READWRITE_CB },
353 { "cargoSpaceAvailable", kShip_cargoSpaceAvailable, OOJS_PROP_READONLY_CB },
354 { "collisionExceptions", kShip_collisionExceptions, OOJS_PROP_READONLY_CB },
355 { "commodity", kShip_commodity, OOJS_PROP_READONLY_CB },
356 { "commodityAmount", kShip_commodityAmount, OOJS_PROP_READONLY_CB },
357 // contracts instead of cargo to distinguish them from the manifest
358 { "contracts", kShip_contracts, OOJS_PROP_READONLY_CB },
359 { "cloakAutomatic", kShip_cloakAutomatic, OOJS_PROP_READWRITE_CB},
361 { "cruiseSpeed", kShip_cruiseSpeed, OOJS_PROP_READONLY_CB },
362 { "currentWeapon", kShip_currentWeapon, OOJS_PROP_READWRITE_CB },
363 { "dataKey", kShip_dataKey, OOJS_PROP_READONLY_CB },
364 { "defenseTargets", kShip_defenseTargets, OOJS_PROP_READONLY_CB },
365 { "desiredRange", kShip_desiredRange, OOJS_PROP_READWRITE_CB },
366 { "desiredSpeed", kShip_desiredSpeed, OOJS_PROP_READWRITE_CB },
367 { "destination", kShip_destination, OOJS_PROP_READWRITE_CB },
368 { "destinationSystem", kShip_destinationSystem, OOJS_PROP_READWRITE_CB },
369 { "displayName", kShip_displayName, OOJS_PROP_READWRITE_CB },
370 { "dockingInstructions", kShip_dockingInstructions, OOJS_PROP_READONLY_CB },
371 { "energyRechargeRate", kShip_energyRechargeRate, OOJS_PROP_READWRITE_CB },
372 { "entityPersonality", kShip_entityPersonality, OOJS_PROP_READWRITE_CB },
373 { "equipment", kShip_equipment, OOJS_PROP_READONLY_CB },
374 { "escorts", kShip_escorts, OOJS_PROP_READONLY_CB },
375 { "escortGroup", kShip_escortGroup, OOJS_PROP_READONLY_CB },
376 { "exhaustEmissiveColor", kShip_exhaustEmissiveColor, OOJS_PROP_READWRITE_CB },
377 { "exhausts", kShip_exhausts, OOJS_PROP_READONLY_CB },
378 { "extraCargo", kShip_extraCargo, OOJS_PROP_READONLY_CB },
379 { "flashers", kShip_flashers, OOJS_PROP_READONLY_CB },
380 { "forwardWeapon", kShip_forwardWeapon, OOJS_PROP_READWRITE_CB },
382 { "fuelChargeRate", kShip_fuelChargeRate, OOJS_PROP_READONLY_CB },
384 { "hasHostileTarget", kShip_hasHostileTarget, OOJS_PROP_READONLY_CB },
385 { "hasHyperspaceMotor", kShip_hasHyperspaceMotor, OOJS_PROP_READONLY_CB },
386 { "hasSuspendedAI", kShip_hasSuspendedAI, OOJS_PROP_READONLY_CB },
387 { "heatInsulation", kShip_heatInsulation, OOJS_PROP_READWRITE_CB },
388 { "heading", kShip_heading, OOJS_PROP_READONLY_CB },
389 { "homeSystem", kShip_homeSystem, OOJS_PROP_READWRITE_CB },
390 { "hyperspaceSpinTime", kShip_hyperspaceSpinTime, OOJS_PROP_READWRITE_CB },
391 { "injectorBurnRate", kShip_injectorBurnRate, OOJS_PROP_READWRITE_CB },
392 { "injectorSpeedFactor", kShip_injectorSpeedFactor, OOJS_PROP_READWRITE_CB },
393 { "homeSystem", kShip_homeSystem, OOJS_PROP_READWRITE_CB },
394 { "isBeacon", kShip_isBeacon, OOJS_PROP_READONLY_CB },
395 { "isCloaked", kShip_isCloaked, OOJS_PROP_READWRITE_CB },
396 { "isCargo", kShip_isCargo, OOJS_PROP_READONLY_CB },
397 { "isDerelict", kShip_isDerelict, OOJS_PROP_READONLY_CB },
398 { "isFrangible", kShip_isFrangible, OOJS_PROP_READONLY_CB },
399 { "isFleeing", kShip_isFleeing, OOJS_PROP_READONLY_CB },
400 { "isJamming", kShip_isJamming, OOJS_PROP_READONLY_CB },
401 { "isMinable", kShip_isMinable, OOJS_PROP_READONLY_CB },
402 { "isMine", kShip_isMine, OOJS_PROP_READONLY_CB },
403 { "isMissile", kShip_isMissile, OOJS_PROP_READONLY_CB },
404 { "isPiloted", kShip_isPiloted, OOJS_PROP_READONLY_CB },
405 { "isPirate", kShip_isPirate, OOJS_PROP_READONLY_CB },
406 { "isPirateVictim", kShip_isPirateVictim, OOJS_PROP_READONLY_CB },
407 { "isPolice", kShip_isPolice, OOJS_PROP_READONLY_CB },
408 { "isRock", kShip_isRock, OOJS_PROP_READONLY_CB },
409 { "isBoulder", kShip_isBoulder, OOJS_PROP_READWRITE_CB },
410 { "isThargoid", kShip_isThargoid, OOJS_PROP_READONLY_CB },
411 { "isTurret", kShip_isTurret, OOJS_PROP_READONLY_CB },
412 { "isTrader", kShip_isTrader, OOJS_PROP_READONLY_CB },
413 { "isWeapon", kShip_isWeapon, OOJS_PROP_READONLY_CB },
414 { "laserHeatLevel", kShip_laserHeatLevel, OOJS_PROP_READONLY_CB },
415 { "laserHeatLevelAft", kShip_laserHeatLevelAft, OOJS_PROP_READONLY_CB },
416 { "laserHeatLevelForward", kShip_laserHeatLevelForward, OOJS_PROP_READONLY_CB },
417 { "laserHeatLevelPort", kShip_laserHeatLevelPort, OOJS_PROP_READONLY_CB },
418 { "laserHeatLevelStarboard", kShip_laserHeatLevelStarboard, OOJS_PROP_READONLY_CB },
419 { "lightsActive", kShip_lightsActive, OOJS_PROP_READWRITE_CB },
420 { "markedForFines", kShip_markedForFines, OOJS_PROP_READONLY_CB },
421 { "maxEscorts", kShip_maxEscorts, OOJS_PROP_READWRITE_CB },
422 { "maxPitch", kShip_maxPitch, OOJS_PROP_READWRITE_CB },
423 { "maxSpeed", kShip_maxSpeed, OOJS_PROP_READWRITE_CB },
426 { "maxThrust", kShip_maxThrust, OOJS_PROP_READWRITE_CB },
427 { "missileCapacity", kShip_missileCapacity, OOJS_PROP_READONLY_CB },
428 { "missileLoadTime", kShip_missileLoadTime, OOJS_PROP_READWRITE_CB },
429 { "missiles", kShip_missiles, OOJS_PROP_READONLY_CB },
431 { "parcelCount", kShip_parcelCount, OOJS_PROP_READONLY_CB },
432 { "parcels", kShip_parcels, OOJS_PROP_READONLY_CB },
433 { "passengerCount", kShip_passengerCount, OOJS_PROP_READONLY_CB },
434 { "passengerCapacity", kShip_passengerCapacity, OOJS_PROP_READONLY_CB },
435 { "passengers", kShip_passengers, OOJS_PROP_READONLY_CB },
437 { "portWeapon", kShip_portWeapon, OOJS_PROP_READWRITE_CB },
438 { "potentialCollider", kShip_potentialCollider, OOJS_PROP_READONLY_CB },
439 { "primaryRole", kShip_primaryRole, OOJS_PROP_READWRITE_CB },
440 { "reactionTime", kShip_reactionTime, OOJS_PROP_READWRITE_CB },
441 { "reportAIMessages", kShip_reportAIMessages, OOJS_PROP_READWRITE_CB },
442 { "roleWeights", kShip_roleWeights, OOJS_PROP_READONLY_CB },
445 { "savedCoordinates", kShip_savedCoordinates, OOJS_PROP_READWRITE_CB },
446 { "scanDescription", kShip_scanDescription, OOJS_PROP_READWRITE_CB },
447 { "scannerDisplayColor1", kShip_scannerDisplayColor1, OOJS_PROP_READWRITE_CB },
448 { "scannerDisplayColor2", kShip_scannerDisplayColor2, OOJS_PROP_READWRITE_CB },
449 { "scannerHostileDisplayColor1", kShip_scannerHostileDisplayColor1, OOJS_PROP_READWRITE_CB },
450 { "scannerHostileDisplayColor2", kShip_scannerHostileDisplayColor2, OOJS_PROP_READWRITE_CB },
451 { "scannerRange", kShip_scannerRange, OOJS_PROP_READONLY_CB },
452 { "script", kShip_script, OOJS_PROP_READONLY_CB },
453 { "scriptedMisjump", kShip_scriptedMisjump, OOJS_PROP_READWRITE_CB },
454 { "scriptedMisjumpRange", kShip_scriptedMisjumpRange, OOJS_PROP_READWRITE_CB },
455 { "scriptInfo", kShip_scriptInfo, OOJS_PROP_READONLY_CB },
456 { "shipClassName", kShip_shipClassName, OOJS_PROP_READWRITE_CB },
457 { "shipUniqueName", kShip_shipUniqueName, OOJS_PROP_READWRITE_CB },
459 { "starboardWeapon", kShip_starboardWeapon, OOJS_PROP_READWRITE_CB },
460 { "subEntities", kShip_subEntities, OOJS_PROP_READONLY_CB },
461 { "subEntityCapacity", kShip_subEntityCapacity, OOJS_PROP_READONLY_CB },
462 { "subEntityRotation", kShip_subEntityRotation, OOJS_PROP_READWRITE_CB },
463 { "sunGlareFilter", kShip_sunGlareFilter, OOJS_PROP_READWRITE_CB },
465 { "temperature", kShip_temperature, OOJS_PROP_READWRITE_CB },
467 { "thrustVector", kShip_thrustVector, OOJS_PROP_READONLY_CB },
468 { "trackCloseContacts", kShip_trackCloseContacts, OOJS_PROP_READWRITE_CB },
469 { "vectorForward", kShip_vectorForward, OOJS_PROP_READONLY_CB },
470 { "vectorRight", kShip_vectorRight, OOJS_PROP_READONLY_CB },
471 { "vectorUp", kShip_vectorUp, OOJS_PROP_READONLY_CB },
472 { "velocity", kShip_velocity, OOJS_PROP_READWRITE_CB },
473 { "weaponFacings", kShip_weaponFacings, OOJS_PROP_READONLY_CB },
474 { "weaponPositionAft", kShip_weaponPositionAft, OOJS_PROP_READONLY_CB },
475 { "weaponPositionForward", kShip_weaponPositionForward, OOJS_PROP_READONLY_CB },
476 { "weaponPositionPort", kShip_weaponPositionPort, OOJS_PROP_READONLY_CB },
477 { "weaponPositionStarboard", kShip_weaponPositionStarboard, OOJS_PROP_READONLY_CB },
478 { "weaponRange", kShip_weaponRange, OOJS_PROP_READONLY_CB },
479 { "withinStationAegis", kShip_withinStationAegis, OOJS_PROP_READONLY_CB },
481 { 0 }
482};
483
484static JSFunctionSpec sShipMethods[] =
485{
486 // JS name Function min args
487 { "abandonShip", ShipAbandonShip, 0 },
488 { "addCargoEntity", ShipAddCargoEntity, 1 },
489 { "addCollisionException", ShipAddCollisionException, 1 },
490 { "addDefenseTarget", ShipAddDefenseTarget, 1 },
491 { "adjustCargo", ShipAdjustCargo, 2 },
492 { "awardEquipment", ShipAwardEquipment, 1 },
493 { "becomeCascadeExplosion", ShipBecomeCascadeExplosion, 0 },
494 { "broadcastCascadeImminent", ShipBroadcastCascadeImminent, 0 },
495 { "broadcastDistressMessage", ShipBroadcastDistressMessage, 0 },
496 { "canAwardEquipment", ShipCanAwardEquipment, 1 },
497 { "checkCourseToDestination", ShipCheckCourseToDestination, 0 },
498 { "checkScanner", ShipCheckScanner, 0 },
499 { "clearDefenseTargets", ShipClearDefenseTargets, 0 },
500 { "commsMessage", ShipCommsMessage, 1 },
501 { "damageAssessment", ShipDamageAssessment, 0 },
502 { "dealEnergyDamage", ShipDealEnergyDamage, 2 },
503 { "deployEscorts", ShipDeployEscorts, 0 },
504 { "dockEscorts", ShipDockEscorts, 0 },
505 { "dumpCargo", ShipDumpCargo, 0 },
506 { "ejectItem", ShipEjectItem, 1 },
507 { "ejectSpecificItem", ShipEjectSpecificItem, 1 },
508 { "enterWormhole", ShipEnterWormhole, 0 },
509 { "equipmentStatus", ShipEquipmentStatus, 1 },
510 { "exitAI", ShipExitAI, 0 },
511 { "exitSystem", ShipExitSystem, 0 },
512 { "explode", ShipExplode, 0 },
513 { "fireECM", ShipFireECM, 0 },
514 { "fireMissile", ShipFireMissile, 0 },
515 { "findNearestStation", ShipFindNearestStation, 0 },
516 { "getMaterials", ShipGetMaterials, 0 },
517 { "getSafeCourseToDestination", ShipGetSafeCourseToDestination, 0 },
518 { "getShaders", ShipGetShaders, 0 },
519 { "hasEquipmentProviding", ShipHasEquipmentProviding, 1 },
520 { "hasRole", ShipHasRole, 1 },
521 { "markTargetForFines", ShipMarkTargetForFines, 0 },
522 { "notifyGroupOfWormhole", ShipNotifyGroupOfWormhole, 0 },
523 { "offerToEscort", ShipOfferToEscort, 1 },
524 { "patrolReportIn", ShipPatrolReportIn, 1},
525 { "performAttack", ShipPerformAttack, 0 },
526 { "performCollect", ShipPerformCollect, 0 },
527 { "performEscort", ShipPerformEscort, 0 },
528 { "performFaceDestination", ShipPerformFaceDestination, 0 },
529 { "performFlee", ShipPerformFlee, 0 },
530 { "performFlyToRangeFromDestination", ShipPerformFlyToRangeFromDestination, 0 },
531 { "performHold", ShipPerformHold, 0 },
532 { "performIdle", ShipPerformIdle, 0 },
533 { "performIntercept", ShipPerformIntercept, 0 },
534 { "performLandOnPlanet", ShipPerformLandOnPlanet, 0 },
535 { "performMining", ShipPerformMining, 0 },
536 { "performScriptedAI", ShipPerformScriptedAI, 0 },
537 { "performScriptedAttackAI", ShipPerformScriptedAttackAI, 0 },
538 { "performStop", ShipPerformStop, 0 },
539 { "performTumble", ShipPerformTumble, 0 },
540
541 { "reactToAIMessage", ShipReactToAIMessage, 1 },
542 { "remove", ShipRemove, 0 },
543 { "removeCollisionException", ShipRemoveCollisionException, 1 },
544 { "removeDefenseTarget", ShipRemoveDefenseTarget, 1 },
545 { "removeEquipment", ShipRemoveEquipment, 1 },
546 { "requestHelpFromGroup", ShipRequestHelpFromGroup, 0},
547 { "requestDockingInstructions", ShipRequestDockingInstructions, 0},
548 { "recallDockingInstructions", ShipRecallDockingInstructions, 0},
549 { "restoreSubEntities", ShipRestoreSubEntities, 0 },
550 { "__runLegacyScriptActions", ShipRunLegacyScriptActions, 2 }, // Deliberately not documented
551 { "selectNewMissile", ShipSelectNewMissile, 0 },
552 { "sendAIMessage", ShipSendAIMessage, 1 },
553 { "setAI", ShipSetAI, 1 },
554 { "setBounty", ShipSetBounty, 2 },
555 { "setCargo", ShipSetCargo, 1 },
556 { "setCargoType", ShipSetCargoType, 1 },
557 { "setCrew", ShipSetCrew, 1 },
558 { "setEquipmentStatus", ShipSetEquipmentStatus, 2 },
559 { "setMaterials", ShipSetMaterials, 1 },
560 { "setScript", ShipSetScript, 1 },
561 { "setShaders", ShipSetShaders, 2 },
562 { "spawn", ShipSpawn, 1 },
563 // spawnOne() is defined in the prefix script.
564 { "switchAI", ShipSwitchAI, 1 },
565 { "threatAssessment", ShipThreatAssessment, 1 },
566 { "throwSpark", ShipThrowSpark, 0 },
567 { "updateEscortFormation", ShipUpdateEscortFormation, 0 },
568 { 0 }
569};
570
571static JSFunctionSpec sShipStaticMethods[] =
572{
573 // JS name Function min args
574 { "keys", ShipStaticKeys, 0 },
575 { "keysForRole", ShipStaticKeysForRole, 1 },
576 { "roleIsInCategory", ShipStaticRoleIsInCategory, 2 },
577 { "roles", ShipStaticRoles, 0 },
578 { "shipDataForKey", ShipStaticShipDataForKey, 1 },
579 { "setShipDataForKey", ShipStaticSetShipDataForKey, 2 },
580 { 0 }
581};
582
583
585
586
593
594
595JSClass *JSShipClass(void)
596{
597 return &sShipClass;
598}
599
600
601JSObject *JSShipPrototype(void)
602{
603 return sShipPrototype;
604}
605
606
607static JSBool ShipGetProperty(JSContext *context, JSObject *this, jsid propID, jsval *value)
608{
609 if (!JSID_IS_INT(propID)) return YES;
610
611 OOJS_NATIVE_ENTER(context)
612
613 ShipEntity *entity = nil;
614 id result = nil;
615
616 if (EXPECT_NOT(!JSShipGetShipEntity(context, this, &entity))) return NO;
617 if (OOIsStaleEntity(entity)) { *value = JSVAL_VOID; return YES; }
618
619 switch (JSID_TO_INT(propID))
620 {
621 case kShip_name:
622 result = [entity name];
623 break;
624
626 result = [entity displayName];
627 break;
628
630 result = [entity shipUniqueName];
631 break;
632
634 result = [entity shipClassName];
635 break;
636
638 result = [entity scanDescriptionForScripting];
639 break;
640
641 case kShip_roles:
642 result = [[entity roleSet] sortedRoles];
643 break;
644
646 result = [[entity roleSet] rolesAndProbabilities];
647 break;
648
650 result = [entity primaryRole];
651 break;
652
653 case kShip_AI:
654 result = [[entity getAI] name];
655 break;
656
657 case kShip_AIState:
658 result = [[entity getAI] state];
659 break;
660
662 result = [entity foundTarget];
663 break;
664
666 result = [entity primaryAggressor];
667 break;
668
670 return JS_NewNumberValue(context, [entity realAlertCondition], value);
671
672 case kShip_autoAI:
673 *value = OOJSValueFromBOOL([entity hasAutoAI]);
674 return YES;
675
677 *value = OOJSValueFromBOOL([entity hasAutoWeapons]);
678 return YES;
679
680 case kShip_accuracy:
681 return JS_NewNumberValue(context, [entity accuracy], value);
682
683 case kShip_fuel:
684 return JS_NewNumberValue(context, [entity fuel] * 0.1, value);
685
687 return JS_NewNumberValue(context, [entity fuelChargeRate], value);
688
689 case kShip_bounty:
690 return JS_NewNumberValue(context, [entity bounty], value);
691 return YES;
692
694 result = [entity subEntitiesForScript];
695 break;
696
697 case kShip_exhausts:
698 result = [[entity exhaustEnumerator] allObjects];
699 break;
700
701 case kShip_flashers:
702 result = [[entity flasherEnumerator] allObjects];
703 break;
704
706 return JS_NewNumberValue(context, [entity maxShipSubEntities], value);
707 return YES;
708
710 return QuaternionToJSValue(context, [entity subEntityRotationalVelocity], value);
711
713 *value = OOJSValueFromBOOL([[entity getAI] hasSuspendedStateMachines]);
714 return YES;
715
716 case kShip_target:
717 result = [entity primaryTarget];
718 break;
719
721 {
722 [entity validateDefenseTargets];
723 result = [NSMutableArray arrayWithCapacity:[entity defenseTargetCount]];
724 NSEnumerator *defTargets = [entity defenseTargetEnumerator];
725 Entity *target = nil;
726 while ((target = [[defTargets nextObject] weakRefUnderlyingObject]))
727 {
728 [result addObject:target];
729 }
730 break;
731 }
732
733 case kShip_crew:
734 result = [entity crewForScripting];
735 break;
736
737 case kShip_escorts:
738 result = [[entity escortGroup] memberArrayExcludingLeader];
739 break;
740
741 case kShip_group:
742 result = [entity group];
743 break;
744
746 result = [entity escortGroup];
747 break;
748
750 return JS_NewNumberValue(context, [entity temperature] / SHIP_MAX_CABIN_TEMP, value);
751
753 return JS_NewNumberValue(context, [entity heatInsulation], value);
754
755 case kShip_heading:
756 return VectorToJSValue(context, [entity forwardVector], value);
757
759 return JS_NewNumberValue(context, [entity energyRechargeRate], value);
760
762 *value = INT_TO_JSVAL([entity entityPersonalityInt]);
763 return YES;
764
765 case kShip_isBeacon:
766 *value = OOJSValueFromBOOL([entity isBeacon]);
767 return YES;
768
769 case kShip_beaconCode:
770 result = [entity beaconCode];
771 break;
772
774 result = [entity beaconLabel];
775 break;
776
778 *value = OOJSValueFromBOOL([entity isFrangible]);
779 return YES;
780
781 case kShip_isCloaked:
782 *value = OOJSValueFromBOOL([entity isCloaked]);
783 return YES;
784
786 *value = OOJSValueFromBOOL([entity hasAutoCloak]);
787 return YES;
788
789 case kShip_isJamming:
790 *value = OOJSValueFromBOOL([entity isJammingScanning]);
791 return YES;
792
794 result = [entity proximityAlert];
795 break;
796
798 *value = OOJSValueFromBOOL([entity hasHostileTarget]);
799 return YES;
800
802 *value = OOJSValueFromBOOL([entity hasHyperspaceMotor]);
803 return YES;
804
806 return JS_NewNumberValue(context, [entity hyperspaceSpinTime], value);
807
809 return JS_NewNumberValue(context, [entity weaponRange], value);
810
812 if ([entity isPlayer])
813 {
814 PlayerEntity *pent = (PlayerEntity*)entity;
815 return JS_NewNumberValue(context, [pent availableFacings], value);
816 }
817 return JS_NewNumberValue(context, [entity weaponFacings], value);
818
820 result = [entity aftWeaponOffset];
821 break;
822
824 result = [entity forwardWeaponOffset];
825 break;
826// return VectorToJSValue(context, [entity forwardWeaponOffset], value);
827
829 result = [entity portWeaponOffset];
830 break;
831
833 result = [entity starboardWeaponOffset];
834 break;
835
837 return JS_NewNumberValue(context, [entity scannerRange], value);
838
840 return JS_NewNumberValue(context, [entity reactionTime], value);
841
843 *value = OOJSValueFromBOOL([entity reportAIMessages]);
844 return YES;
845
847 *value = OOJSValueFromBOOL([entity withinStationAegis]);
848 return YES;
849
851 *value = INT_TO_JSVAL([entity maxAvailableCargoSpace]);
852 return YES;
853
855 *value = INT_TO_JSVAL([entity maxAvailableCargoSpace] - [entity availableCargoSpace]);
856 return YES;
857
859 *value = INT_TO_JSVAL([entity availableCargoSpace]);
860 return YES;
861
862 case kShip_cargoList:
863 result = [entity cargoListForScripting];
864 break;
865
866 case kShip_extraCargo:
867 return JS_NewNumberValue(context, [entity extraCargo], value);
868 return YES;
869
870 case kShip_commodity:
871 if ([entity commodityAmount] > 0)
872 {
873 result = [entity commodityType];
874 }
875 break;
876
878 *value = INT_TO_JSVAL([entity commodityAmount]);
879 return YES;
880
882 result = [entity collisionExceptions];
883 break;
884
885
886 case kShip_speed:
887 return JS_NewNumberValue(context, [entity flightSpeed], value);
888
890 return JS_NewNumberValue(context, [entity cruiseSpeed], value);
891
892 case kShip_dataKey:
893 result = [entity shipDataKey];
894 break;
895
897 return JS_NewNumberValue(context, [entity desiredRange], value);
898
900 return JS_NewNumberValue(context, [entity desiredSpeed], value);
901
903 return HPVectorToJSValue(context, [entity destination], value);
904
906 *value = OOJSValueFromBOOL([entity markedForFines]);
907 return YES;
908
909 case kShip_maxEscorts:
910 return JS_NewNumberValue(context, [entity maxEscortCount], value);
911
912 case kShip_maxPitch:
913 return JS_NewNumberValue(context, [entity maxFlightPitch], value);
914
915 case kShip_maxSpeed:
916 return JS_NewNumberValue(context, [entity maxFlightSpeed], value);
917
918 case kShip_maxRoll:
919 return JS_NewNumberValue(context, [entity maxFlightRoll], value);
920
921 case kShip_maxYaw:
922 return JS_NewNumberValue(context, [entity maxFlightYaw], value);
923
925 return JS_NewNumberValue(context, [entity afterburnerRate], value);
926
928 return JS_NewNumberValue(context, [entity afterburnerFactor], value);
929
930 case kShip_script:
931 result = [entity shipScript];
932 break;
933
934 case kShip_AIScript:
935 result = [entity shipAIScript];
936 break;
937
939 return JS_NewNumberValue(context, [entity shipAIScriptWakeTime], value);
940 break;
941
943 return JS_NewNumberValue(context, [entity destinationSystem], value);
944 break;
945
946 case kShip_homeSystem:
947 return JS_NewNumberValue(context, [entity homeSystem], value);
948 break;
949
950 case kShip_isPirate:
951 *value = OOJSValueFromBOOL([entity isPirate]);
952 return YES;
953
954 case kShip_isPolice:
955 *value = OOJSValueFromBOOL([entity isPolice]);
956 return YES;
957
958 case kShip_isThargoid:
959 *value = OOJSValueFromBOOL([entity isThargoid]);
960 return YES;
961
962 case kShip_isTurret:
963 *value = OOJSValueFromBOOL([entity isTurret]);
964 return YES;
965
966 case kShip_isTrader:
967 *value = OOJSValueFromBOOL([entity isTrader]);
968 return YES;
969
971 *value = OOJSValueFromBOOL([entity isPirateVictim]);
972 return YES;
973
974 case kShip_isMissile:
975 *value = OOJSValueFromBOOL([entity isMissile]);
976 return YES;
977
978 case kShip_isMine:
979 *value = OOJSValueFromBOOL([entity isMine]);
980 return YES;
981
982 case kShip_isWeapon:
983 *value = OOJSValueFromBOOL([entity isWeapon]);
984 return YES;
985
986 case kShip_isRock:
987 *value = OOJSValueFromBOOL([entity scanClass] == CLASS_ROCK); // hermits and asteroids!
988 return YES;
989
990 case kShip_isMinable:
991 *value = OOJSValueFromBOOL([entity isMinable]);
992 return YES;
993
994 case kShip_isBoulder:
995 *value = OOJSValueFromBOOL([entity isBoulder]);
996 return YES;
997
998 case kShip_isFleeing:
999 if ([entity isPlayer])
1000 {
1001 *value = OOJSValueFromBOOL([(PlayerEntity*)entity fleeingStatus] >= PLAYER_FLEEING_CARGO);
1002 }
1003 else
1004 {
1005 *value = OOJSValueFromBOOL([entity behaviour] == BEHAVIOUR_FLEE_TARGET || [entity behaviour] == BEHAVIOUR_FLEE_EVASIVE_ACTION);
1006 }
1007 return YES;
1008
1009 case kShip_isCargo:
1010 *value = OOJSValueFromBOOL([entity scanClass] == CLASS_CARGO && [entity commodityAmount] > 0);
1011 return YES;
1012
1013 case kShip_isDerelict:
1014 *value = OOJSValueFromBOOL([entity isHulk]);
1015 return YES;
1016
1017 case kShip_isPiloted:
1018 *value = OOJSValueFromBOOL([entity isPlayer] || [[entity crew] count] > 0);
1019 return YES;
1020
1022 *value = OOJSValueFromBOOL([entity scriptedMisjump]);
1023 return YES;
1024
1026 return JS_NewNumberValue(context, [entity scriptedMisjumpRange], value);
1027
1028 case kShip_scriptInfo:
1029 result = [entity scriptInfo];
1030 if (result == nil) result = [NSDictionary dictionary]; // empty rather than null
1031 break;
1032
1034 return JS_NewNumberValue(context, [entity sunGlareFilter], value);
1035
1037 *value = OOJSValueFromBOOL([entity trackCloseContacts]);
1038 return YES;
1039
1041 return JS_NewNumberValue(context, [entity passengerCount], value);
1042
1043 case kShip_parcelCount:
1044 return JS_NewNumberValue(context, [entity parcelCount], value);
1045
1047 return JS_NewNumberValue(context, [entity passengerCapacity], value);
1048
1050 return JS_NewNumberValue(context, [entity missileCapacity], value);
1051
1053 return JS_NewNumberValue(context, [entity missileLoadTime], value);
1054
1056 return HPVectorToJSValue(context,[entity coordinates], value);
1057
1058 case kShip_equipment:
1059 result = [entity equipmentListForScripting];
1060 break;
1061
1063 result = [entity weaponTypeForFacing:[entity currentWeaponFacing] strict:YES];
1064 break;
1065
1067 result = [entity weaponTypeForFacing:WEAPON_FACING_FORWARD strict:YES];
1068 break;
1069
1070 case kShip_aftWeapon:
1071 result = [entity weaponTypeForFacing:WEAPON_FACING_AFT strict:YES];
1072 break;
1073
1074 case kShip_portWeapon:
1075 result = [entity weaponTypeForFacing:WEAPON_FACING_PORT strict:YES];
1076 break;
1077
1079 result = [entity weaponTypeForFacing:WEAPON_FACING_STARBOARD strict:YES];
1080 break;
1081
1083 return JS_NewNumberValue(context, [entity laserHeatLevel], value);
1084
1086 return JS_NewNumberValue(context, [entity laserHeatLevelAft], value);
1087
1089 return JS_NewNumberValue(context, [entity laserHeatLevelForward], value);
1090
1092 return JS_NewNumberValue(context, [entity laserHeatLevelPort], value);
1093
1095 return JS_NewNumberValue(context, [entity laserHeatLevelStarboard], value);
1096
1097 case kShip_missiles:
1098 result = [entity missilesList];
1099 break;
1100
1101 case kShip_passengers:
1102 result = [entity passengerListForScripting];
1103 break;
1104
1105 case kShip_parcels:
1106 result = [entity parcelListForScripting];
1107 break;
1108
1109 case kShip_contracts:
1110 result = [entity contractListForScripting];
1111 break;
1112
1114 result = [entity dockingInstructions];
1115 break;
1116
1118 result = [[entity scannerDisplayColor1] normalizedArray];
1119 break;
1120
1122 result = [[entity scannerDisplayColor2] normalizedArray];
1123 break;
1124
1126 result = [[entity scannerDisplayColorHostile1] normalizedArray];
1127 break;
1128
1130 result = [[entity scannerDisplayColorHostile2] normalizedArray];
1131 break;
1132
1134 result = [[entity exhaustEmissiveColor] normalizedArray];
1135 break;
1136
1137 case kShip_maxThrust:
1138 return JS_NewNumberValue(context, [entity maxThrust], value);
1139
1140 case kShip_thrust:
1141 return JS_NewNumberValue(context, [entity thrust], value);
1142
1143 case kShip_lightsActive:
1144 *value = OOJSValueFromBOOL([entity lightsActive]);
1145 return YES;
1146
1147 case kShip_vectorRight:
1148 return VectorToJSValue(context, [entity rightVector], value);
1149
1151 return VectorToJSValue(context, [entity forwardVector], value);
1152
1153 case kShip_vectorUp:
1154 return VectorToJSValue(context, [entity upVector], value);
1155
1156 case kShip_velocity:
1157 return VectorToJSValue(context, [entity velocity], value);
1158
1159 case kShip_thrustVector:
1160 return VectorToJSValue(context, [entity thrustVector], value);
1161
1162 case kShip_pitch:
1163 return JS_NewNumberValue(context, [entity flightPitch], value);
1164
1165 case kShip_roll:
1166 return JS_NewNumberValue(context, [entity flightRoll], value);
1167
1168 case kShip_yaw:
1169 return JS_NewNumberValue(context, [entity flightYaw], value);
1170
1171 case kShip_boundingBox:
1172 {
1173 Vector bbvect;
1174 BoundingBox box;
1175
1176 if ([entity isSubEntity])
1177 {
1178 box = [entity boundingBox];
1179 }
1180 else
1181 {
1182 box = [entity totalBoundingBox];
1183 }
1184 bounding_box_get_dimensions(box,&bbvect.x,&bbvect.y,&bbvect.z);
1185 return VectorToJSValue(context, bbvect, value);
1186 }
1187
1188 default:
1189 OOJSReportBadPropertySelector(context, this, propID, sShipProperties);
1190 return NO;
1191 }
1192
1193 *value = OOJSValueFromNativeObject(context, result);
1194 return YES;
1195
1197}
1198
1199
1200static JSBool ShipSetProperty(JSContext *context, JSObject *this, jsid propID, JSBool strict, jsval *value)
1201{
1202 if (!JSID_IS_INT(propID)) return YES;
1203
1204 OOJS_NATIVE_ENTER(context)
1205
1206 ShipEntity *entity = nil;
1207 ShipEntity *target = nil;
1208 NSString *sValue = nil;
1209 jsdouble fValue;
1210 int32 iValue;
1211 JSBool bValue;
1212 Vector vValue;
1213 Quaternion qValue;
1214 HPVector hpvValue;
1215 OOShipGroup *group = nil;
1216 OOColor *colorForScript = nil;
1217 BOOL exists;
1218
1219 if (EXPECT_NOT(!JSShipGetShipEntity(context, this, &entity))) return NO;
1220 if (OOIsStaleEntity(entity)) return YES;
1221
1222 NSCAssert(![entity isTemplateCargoPod], @"-OOJSShip: a template cargo pod has become accessible to Javascript");
1223
1224 switch (JSID_TO_INT(propID))
1225 {
1226 case kShip_name:
1227 if (EXPECT_NOT([entity isPlayer])) goto playerReadOnly;
1228
1229 sValue = OOStringFromJSValue(context,*value);
1230 if (sValue != nil)
1231 {
1232 [entity setName:sValue];
1233 return YES;
1234 }
1235 break;
1236
1237 case kShip_displayName:
1238 if (EXPECT_NOT([entity isPlayer])) goto playerReadOnly;
1239
1240 sValue = OOStringFromJSValue(context,*value);
1241 if (sValue != nil)
1242 {
1243 [entity setDisplayName:sValue];
1244 return YES;
1245 }
1246 break;
1247
1249 sValue = OOStringFromJSValue(context,*value);
1250 if (sValue != nil)
1251 {
1252 [entity setShipUniqueName:sValue];
1253 return YES;
1254 }
1255 break;
1256
1258 sValue = OOStringFromJSValue(context,*value);
1259 if (sValue != nil)
1260 {
1261 [entity setShipClassName:sValue];
1262 return YES;
1263 }
1264 break;
1265
1266
1268 sValue = OOStringFromJSValue(context,*value);
1269 // can set to nil
1270 [entity setScanDescription:sValue];
1271 return YES;
1272
1273 case kShip_primaryRole:
1274 if (EXPECT_NOT([entity isPlayer])) goto playerReadOnly;
1275
1276 sValue = OOStringFromJSValue(context,*value);
1277 if (sValue != nil)
1278 {
1279 [entity setPrimaryRole:sValue];
1280 return YES;
1281 }
1282 break;
1283
1284 case kShip_AIState:
1285 if (EXPECT_NOT([entity isPlayer])) goto playerReadOnly;
1286
1287 sValue = OOStringFromJSValue(context,*value);
1288 if (sValue != nil)
1289 {
1290 [[entity getAI] setState:sValue];
1291 return YES;
1292 }
1293 break;
1294
1295 case kShip_beaconCode:
1296 if (EXPECT_NOT([entity isPlayer])) goto playerReadOnly;
1297
1298 sValue = OOStringFromJSValue(context,*value);
1299 if ([sValue length] == 0)
1300 {
1301 if ([entity isBeacon])
1302 {
1303 [UNIVERSE clearBeacon:entity];
1304 if ([PLAYER nextBeacon] == entity)
1305 {
1306 [PLAYER setCompassMode:COMPASS_MODE_PLANET];
1307 }
1308 }
1309 }
1310 else
1311 {
1312 if ([entity isBeacon])
1313 {
1314 [entity setBeaconCode:sValue];
1315 }
1316 else // Universe needs to update beacon lists in this case only
1317 {
1318 [entity setBeaconCode:sValue];
1319 [UNIVERSE setNextBeacon:entity];
1320 }
1321 }
1322 return YES;
1323 break;
1324
1325 case kShip_beaconLabel:
1326 if (EXPECT_NOT([entity isPlayer])) goto playerReadOnly;
1327 sValue = OOStringFromJSValue(context,*value);
1328 if (sValue != nil)
1329 {
1330 [entity setBeaconLabel:sValue];
1331 return YES;
1332 }
1333 break;
1334
1335 case kShip_accuracy:
1336 if (EXPECT_NOT([entity isPlayer])) goto playerReadOnly;
1337
1338 if (JS_ValueToNumber(context, *value, &fValue))
1339 {
1340 [entity setAccuracy:fValue];
1341 return YES;
1342 }
1343 break;
1344
1345 case kShip_fuel:
1346 if (JS_ValueToNumber(context, *value, &fValue))
1347 {
1348 fValue = OOClamp_0_max_d(fValue, MAX_JUMP_RANGE);
1349 [entity setFuel:lround(fValue * 10.0)];
1350 return YES;
1351 }
1352 break;
1353
1355 if (JS_ValueToInt32(context, *value, &iValue))
1356 {
1357 if (iValue < 0 || iValue > (int32)ENTITY_PERSONALITY_MAX)
1358 {
1359 OOJSReportError(context, @"ship.%@ must be >= 0 and <= %u.", OOStringFromJSPropertyIDAndSpec(context, propID, sShipProperties),ENTITY_PERSONALITY_MAX);
1360 return NO;
1361 }
1362 [entity setEntityPersonalityInt: iValue];
1363 return YES;
1364 }
1365
1367 if (JS_ValueToNumber(context, *value, &fValue))
1368 {
1369 [entity setHyperspaceSpinTime:fValue];
1370 return YES;
1371 }
1372 break;
1373
1374 case kShip_bounty:
1375 if (JS_ValueToInt32(context, *value, &iValue))
1376 {
1377 if (iValue < 0) iValue = 0;
1378 [entity setBounty:iValue withReason:kOOLegalStatusReasonByScript];
1379 return YES;
1380 }
1381 break;
1382
1384 if (JS_ValueToInt32(context, *value, &iValue))
1385 {
1386 if (iValue < 0) iValue = 0;
1387 // OXPs using equipment with weight requirements may make us end up with more allocated
1388 // cargo space than what we have available. Do not let iValue become negative.
1389 if ([entity maxAvailableCargoSpace] < [entity availableCargoSpace])
1390 {
1391 iValue = 0;
1392 }
1393 else if ((OOCargoQuantity)iValue < [entity maxAvailableCargoSpace] - [entity availableCargoSpace])
1394 {
1395 iValue = [entity maxAvailableCargoSpace] - [entity availableCargoSpace];
1396 }
1397 [entity setMaxAvailableCargoSpace:iValue];
1398 return YES;
1399 }
1400 break;
1401
1402
1404 if (JS_ValueToInt32(context, *value, &iValue))
1405 {
1406 if (iValue < 0) iValue = 0;
1407 [entity setDestinationSystem:iValue];
1408 return YES;
1409 }
1410 break;
1411
1412 case kShip_homeSystem:
1413 if (JS_ValueToInt32(context, *value, &iValue))
1414 {
1415 if (iValue < 0) iValue = 0;
1416 [entity setHomeSystem:iValue];
1417 return YES;
1418 }
1419 break;
1420
1421 case kShip_target:
1422 if (JSVAL_IS_NULL(*value))
1423 {
1424 [entity setTargetForScript:nil];
1425 return YES;
1426 }
1427 else if (JSValueToEntity(context, *value, &target) && [target isKindOfClass:[ShipEntity class]])
1428 {
1429 [entity setTargetForScript:target];
1430 return YES;
1431 }
1432 break;
1433
1435 if (EXPECT_NOT([entity isPlayer])) goto playerReadOnly;
1436
1437 if (JSVAL_IS_NULL(*value))
1438 {
1439 [entity setFoundTarget:nil];
1440 return YES;
1441 }
1442 else if (JSValueToEntity(context, *value, &target) && [target isKindOfClass:[ShipEntity class]])
1443 {
1444 [entity setFoundTarget:target];
1445 return YES;
1446 }
1447 break;
1448
1450 if (EXPECT_NOT([entity isPlayer])) goto playerReadOnly;
1451
1452 if (JSVAL_IS_NULL(*value))
1453 {
1454 [entity setPrimaryAggressor:nil];
1455 return YES;
1456 }
1457 else if (JSValueToEntity(context, *value, &target) && [target isKindOfClass:[ShipEntity class]])
1458 {
1459 [entity setPrimaryAggressor:target];
1460 return YES;
1461 }
1462 break;
1463
1464 case kShip_group:
1465 group = OOJSNativeObjectOfClassFromJSValue(context, *value, [OOShipGroup class]);
1466 if (group != nil || JSVAL_IS_NULL(*value))
1467 {
1468 [entity setGroup:group];
1469 return YES;
1470 }
1471 break;
1472
1474 if (JS_ValueToNumber(context, *value, &fValue))
1475 {
1476 [entity setAIScriptWakeTime:fValue];
1477 return YES;
1478 }
1479 break;
1480
1481 case kShip_temperature:
1482 if (JS_ValueToNumber(context, *value, &fValue))
1483 {
1484 fValue = fmax(fValue, 0.0);
1485 [entity setTemperature:fValue * SHIP_MAX_CABIN_TEMP];
1486 return YES;
1487 }
1488 break;
1489
1491 if (JS_ValueToNumber(context, *value, &fValue))
1492 {
1493 fValue = fmax(fValue, 0.125);
1494 [entity setHeatInsulation:fValue];
1495 return YES;
1496 }
1497 break;
1498
1499 case kShip_isCloaked:
1500 if (JS_ValueToBoolean(context, *value, &bValue))
1501 {
1502 [entity setCloaked:bValue];
1503 return YES;
1504 }
1505 break;
1506
1508 if (JS_ValueToBoolean(context, *value, &bValue))
1509 {
1510 [entity setAutoCloak:bValue];
1511 return YES;
1512 }
1513 break;
1514
1516 if (JS_ValueToNumber(context, *value, &fValue))
1517 {
1518 [entity setMissileLoadTime:fmax(0.0, fValue)];
1519 return YES;
1520 }
1521 break;
1522
1523 case kShip_reactionTime:
1524 if (EXPECT_NOT([entity isPlayer])) goto playerReadOnly;
1525
1526 if (JS_ValueToNumber(context, *value, &fValue))
1527 {
1528 [entity setReactionTime:fValue];
1529 return YES;
1530 }
1531 break;
1532
1534 if (JS_ValueToBoolean(context, *value, &bValue))
1535 {
1536 [entity setReportAIMessages:bValue];
1537 return YES;
1538 }
1539 break;
1540
1542 if (JS_ValueToBoolean(context, *value, &bValue))
1543 {
1544 [entity setTrackCloseContacts:bValue];
1545 return YES;
1546 }
1547 break;
1548
1549 case kShip_isBoulder:
1550 if (EXPECT_NOT([entity isPlayer])) goto playerReadOnly;
1551
1552 if (JS_ValueToBoolean(context, *value, &bValue))
1553 {
1554 [entity setIsBoulder:bValue];
1555 return YES;
1556 }
1557 break;
1558
1559 case kShip_destination:
1560 if (EXPECT_NOT([entity isPlayer])) goto playerReadOnly;
1561
1562 if (JSValueToHPVector(context, *value, &hpvValue))
1563 {
1564 // use setEscortDestination rather than setDestination as
1565 // scripted amendments shouldn't necessarily reset frustration
1566 [entity setEscortDestination:hpvValue];
1567 return YES;
1568 }
1569 break;
1570
1571 case kShip_desiredSpeed:
1572 if (EXPECT_NOT([entity isPlayer])) goto playerReadOnly;
1573
1574 if (JS_ValueToNumber(context, *value, &fValue))
1575 {
1576 [entity setDesiredSpeed:fmax(fValue, 0.0)];
1577 return YES;
1578 }
1579 break;
1580
1581 case kShip_desiredRange:
1582 if (EXPECT_NOT([entity isPlayer])) goto playerReadOnly;
1583
1584 if (JS_ValueToNumber(context, *value, &fValue))
1585 {
1586 [entity setDesiredRange:fmax(fValue, 0.0)];
1587 return YES;
1588 }
1589 break;
1590
1592 if (JSValueToHPVector(context, *value, &hpvValue))
1593 {
1594 [entity setCoordinate:hpvValue];
1595 return YES;
1596 }
1597 break;
1598
1600 colorForScript = [OOColor colorWithDescription:OOJSNativeObjectFromJSValue(context, *value)];
1601 if (colorForScript != nil || JSVAL_IS_NULL(*value))
1602 {
1603 [entity setScannerDisplayColor1:colorForScript];
1604 return YES;
1605 }
1606 break;
1607
1609 colorForScript = [OOColor colorWithDescription:OOJSNativeObjectFromJSValue(context, *value)];
1610 if (colorForScript != nil || JSVAL_IS_NULL(*value))
1611 {
1612 [entity setScannerDisplayColor2:colorForScript];
1613 return YES;
1614 }
1615 break;
1616
1618 colorForScript = [OOColor colorWithDescription:OOJSNativeObjectFromJSValue(context, *value)];
1619 if (colorForScript != nil || JSVAL_IS_NULL(*value))
1620 {
1621 [entity setScannerDisplayColorHostile1:colorForScript];
1622 return YES;
1623 }
1624 break;
1625
1627 colorForScript = [OOColor colorWithDescription:OOJSNativeObjectFromJSValue(context, *value)];
1628 if (colorForScript != nil || JSVAL_IS_NULL(*value))
1629 {
1630 [entity setScannerDisplayColorHostile2:colorForScript];
1631 return YES;
1632 }
1633 break;
1634
1636 colorForScript = [OOColor colorWithDescription:OOJSNativeObjectFromJSValue(context, *value)];
1637 if (colorForScript != nil || JSVAL_IS_NULL(*value))
1638 {
1639 [entity setExhaustEmissiveColor:colorForScript];
1640 return YES;
1641 }
1642 break;
1643
1645 if (JS_ValueToBoolean(context, *value, &bValue))
1646 {
1647 [entity setScriptedMisjump:bValue];
1648 return YES;
1649 }
1650 break;
1651
1653 if (JS_ValueToNumber(context, *value, &fValue))
1654 {
1655 if (fValue > 0.0 && fValue < 1.0)
1656 {
1657 [entity setScriptedMisjumpRange:fValue];
1658 return YES;
1659 }
1660 else
1661 {
1662 OOJSReportError(context, @"ship.%@ must be > 0.0 and < 1.0.", OOStringFromJSPropertyIDAndSpec(context, propID, sShipProperties));
1663 return NO;
1664 }
1665 }
1666 break;
1667
1669 if (JSValueToQuaternion(context, *value, &qValue))
1670 {
1671 [entity setSubEntityRotationalVelocity:qValue];
1672 return YES;
1673 }
1674 break;
1675
1676
1678 if (JS_ValueToNumber(context, *value, &fValue))
1679 {
1680 if (fValue >= 0.0f && fValue <= 1.0f)
1681 {
1682 [entity setSunGlareFilter:fValue];
1683 return YES;
1684 }
1685 else
1686 {
1687 OOJSReportError(context, @"ship.%@ must be > 0.0 and < 1.0.", OOStringFromJSPropertyIDAndSpec(context, propID, sShipProperties));
1688 return NO;
1689 }
1690 }
1691 break;
1692
1693 case kShip_thrust:
1694// if (EXPECT_NOT([entity isPlayer])) goto playerReadOnly;
1695
1696 if (JS_ValueToNumber(context, *value, &fValue))
1697 {
1698 [entity setThrust:OOClamp_0_max_f(fValue, [entity maxThrust])];
1699 return YES;
1700 }
1701 break;
1702
1703 case kShip_maxPitch:
1704 if (JS_ValueToNumber(context, *value, &fValue))
1705 {
1706 if (fValue < 0)
1707 {
1708 OOJSReportError(context, @"ship.maxPitch cannot be negative.");
1709 return NO;
1710 }
1711 [entity setMaxFlightPitch:fValue];
1712 return YES;
1713 }
1714 break;
1715
1716
1717 case kShip_maxSpeed:
1718 if (JS_ValueToNumber(context, *value, &fValue))
1719 {
1720 if (fValue < 0)
1721 {
1722 OOJSReportError(context, @"ship.maxSpeed cannot be negative.");
1723 return NO;
1724 }
1725 [entity setMaxFlightSpeed:fValue];
1726 return YES;
1727 }
1728 break;
1729
1730 case kShip_maxRoll:
1731 if (JS_ValueToNumber(context, *value, &fValue))
1732 {
1733 if (fValue < 0)
1734 {
1735 OOJSReportError(context, @"ship.maxRoll cannot be negative.");
1736 return NO;
1737 }
1738 [entity setMaxFlightRoll:fValue];
1739 return YES;
1740 }
1741 break;
1742
1743 case kShip_maxYaw:
1744 if (JS_ValueToNumber(context, *value, &fValue))
1745 {
1746 if (fValue < 0)
1747 {
1748 OOJSReportError(context, @"ship.maxYaw cannot be negative.");
1749 return NO;
1750 }
1751 [entity setMaxFlightYaw:fValue];
1752 return YES;
1753 }
1754 break;
1755
1757 if (JS_ValueToNumber(context, *value, &fValue))
1758 {
1759 if (fValue < 0)
1760 {
1761 OOJSReportError(context, @"ship.injectorBurnRate cannot be negative.");
1762 return NO;
1763 }
1764 [entity setAfterburnerRate:fValue];
1765 return YES;
1766 }
1767 break;
1768
1770 if (JS_ValueToNumber(context, *value, &fValue))
1771 {
1772 if (fValue < 1)
1773 {
1774 OOJSReportError(context, @"ship.injectorSpeedFactor cannot be less than 1.0.");
1775 return NO;
1776 }
1777#if OO_VARIABLE_TORUS_SPEED
1778 else if (fValue > MIN_HYPERSPEED_FACTOR)
1779 {
1780 OOJSReportError(context, @"ship.injectorSpeedFactor cannot be higher than minimum torus speed factor (%f).",MIN_HYPERSPEED_FACTOR);
1781#else
1782 else if (fValue > HYPERSPEED_FACTOR)
1783 {
1784 OOJSReportError(context, @"ship.injectorSpeedFactor cannot be higher than torus speed factor (%f).",HYPERSPEED_FACTOR);
1785#endif
1786 return NO;
1787 }
1788 [entity setAfterburnerFactor:fValue];
1789 return YES;
1790 }
1791 break;
1792
1793
1794 case kShip_maxThrust:
1795 if (JS_ValueToNumber(context, *value, &fValue))
1796 {
1797 if (fValue < 0)
1798 {
1799 OOJSReportError(context, @"ship.maxThrust cannot be negative.");
1800 return NO;
1801 }
1802 [entity setMaxThrust:fValue];
1803 return YES;
1804 }
1805 break;
1806
1808 if (JS_ValueToNumber(context, *value, &fValue))
1809 {
1810 if (fValue < 0)
1811 {
1812 OOJSReportError(context, @"ship.energyRechargeRate cannot be negative.");
1813 return NO;
1814 }
1815 [entity setEnergyRechargeRate:fValue];
1816 return YES;
1817 }
1818 break;
1819
1820
1821 case kShip_lightsActive:
1822 if (JS_ValueToBoolean(context, *value, &bValue))
1823 {
1824 if (bValue) [entity switchLightsOn];
1825 else [entity switchLightsOff];
1826 return YES;
1827 }
1828 break;
1829
1830 case kShip_velocity:
1831 if (JSValueToVector(context, *value, &vValue))
1832 {
1833 [entity setTotalVelocity:vValue];
1834 return YES;
1835 }
1836 break;
1837
1838 case kShip_portWeapon:
1840 case kShip_aftWeapon:
1843 sValue = JSValueToEquipmentKeyRelaxed(context, *value, &exists);
1844 if (sValue == nil)
1845 {
1846 sValue = @"EQ_WEAPON_NONE";
1847 }
1849 switch (JSID_TO_INT(propID))
1850 {
1851 case kShip_aftWeapon:
1852 facing = WEAPON_FACING_AFT;
1853 break;
1854 case kShip_forwardWeapon:
1855 facing = WEAPON_FACING_FORWARD;
1856 break;
1857 case kShip_portWeapon:
1858 facing = WEAPON_FACING_PORT;
1859 break;
1861 facing = WEAPON_FACING_STARBOARD;
1862 break;
1864 facing = [entity currentWeaponFacing];
1865 break;
1866 }
1867 if ([entity isPlayer])
1868 {
1869 PlayerEntity *pent = (PlayerEntity*)entity;
1870 [pent setWeaponMount:facing toWeapon:sValue inContext:@"scripted"];
1871 }
1872 else
1873 {
1874 [entity setWeaponMount:facing toWeapon:sValue];
1875 }
1876 return YES;
1877
1878 case kShip_maxEscorts:
1879 if (EXPECT_NOT([entity isPlayer])) goto playerReadOnly;
1880
1881 if (JS_ValueToInt32(context, *value, &iValue))
1882 {
1883 if ((NSInteger)iValue < (NSInteger)[[entity escortGroup] count] - 1)
1884 {
1885 OOJSReportError(context, @"ship.%@ must be >= current escort numbers.", OOStringFromJSPropertyIDAndSpec(context, propID, sShipProperties));
1886 return NO;
1887 }
1888 if (iValue > MAX_ESCORTS)
1889 {
1890 OOJSReportError(context, @"ship.%@ must be <= %d.", OOStringFromJSPropertyIDAndSpec(context, propID, sShipProperties),MAX_ESCORTS);
1891 return NO;
1892 }
1893 [entity setMaxEscortCount:iValue];
1894 return YES;
1895 }
1896
1897 break;
1898
1899
1900 default:
1901 OOJSReportBadPropertySelector(context, this, propID, sShipProperties);
1902 return NO;
1903 }
1904
1905 OOJSReportBadPropertyValue(context, this, propID, sShipProperties, *value);
1906 return NO;
1907
1908playerReadOnly:
1909 OOJSReportError(context, @"player.ship.%@ is read-only.", OOStringFromJSPropertyIDAndSpec(context, propID, sShipProperties));
1910 return NO;
1911
1912// Not used (yet)
1913/*
1914npcReadOnly:
1915 OOJSReportError(context, @"npc.ship.%@ is read-only.", OOStringFromJSPropertyIDAndSpec(context, propID, sShipProperties));
1916 return NO;
1917*/
1918
1920}
1921
1922
1923// *** Methods ***
1924
1925#define GET_THIS_SHIP(THISENT) do { \
1926 if (EXPECT_NOT(!JSShipGetShipEntity(context, OOJS_THIS, &THISENT))) return NO; /* Exception */ \
1927 if (OOIsStaleEntity(THISENT)) OOJS_RETURN_VOID; \
1928} while (0)
1929
1930
1931// setScript(scriptName : String)
1932static JSBool ShipSetScript(JSContext *context, uintN argc, jsval *vp)
1933{
1934 OOJS_NATIVE_ENTER(context)
1935
1936 ShipEntity *thisEnt = nil;
1937 NSString *name = nil;
1938
1939 GET_THIS_SHIP(thisEnt);
1940 if (argc > 0) name = OOStringFromJSValue(context, OOJS_ARGV[0]);
1941 if (EXPECT_NOT(name == nil))
1942 {
1943 OOJSReportBadArguments(context, @"Ship", @"setScript", MIN(argc, 1U), OOJS_ARGV, nil, @"string (script name)");
1944 return NO;
1945 }
1946 if (EXPECT_NOT([thisEnt isPlayer]))
1947 {
1948 OOJSReportErrorForCaller(context, @"Ship", @"setScript", @"Not valid for player ship.");
1949 return NO;
1950 }
1951
1952 [thisEnt setShipScript:name];
1954
1956}
1957
1958
1959// setAI(aiName : String)
1960static JSBool ShipSetAI(JSContext *context, uintN argc, jsval *vp)
1961{
1962 OOJS_NATIVE_ENTER(context)
1963
1964 ShipEntity *thisEnt = nil;
1965 NSString *name = nil;
1966
1967 GET_THIS_SHIP(thisEnt);
1968 if (argc > 0) name = OOStringFromJSValue(context, OOJS_ARGV[0]);
1969 if (EXPECT_NOT(name == nil))
1970 {
1971 OOJSReportBadArguments(context, @"Ship", @"setAI", MIN(argc, 1U), OOJS_ARGV, nil, @"string (AI name)");
1972 return NO;
1973 }
1974 if (EXPECT_NOT([thisEnt isPlayer]))
1975 {
1976 OOJSReportErrorForCaller(context, @"Ship", @"setAI", @"Not valid for player ship.");
1977 return NO;
1978 }
1979
1980 [thisEnt setAITo:name];
1982
1984}
1985
1986
1987// switchAI(aiName : String)
1988static JSBool ShipSwitchAI(JSContext *context, uintN argc, jsval *vp)
1989{
1990 OOJS_NATIVE_ENTER(context)
1991
1992 ShipEntity *thisEnt = nil;
1993 NSString *name = nil;
1994
1995 GET_THIS_SHIP(thisEnt);
1996 if (argc > 0) name = OOStringFromJSValue(context, OOJS_ARGV[0]);
1997 if (EXPECT_NOT(name == nil))
1998 {
1999 OOJSReportBadArguments(context, @"Ship", @"switchAI", MIN(argc, 1U), OOJS_ARGV, nil, @"string (AI name)");
2000 return NO;
2001 }
2002 if (EXPECT_NOT([thisEnt isPlayer]))
2003 {
2004 OOJSReportErrorForCaller(context, @"Ship", @"switchAI", @"Not valid for player ship.");
2005 return NO;
2006 }
2007
2008 [thisEnt switchAITo:name];
2010
2012}
2013
2014
2015// exitAI()
2016static JSBool ShipExitAI(JSContext *context, uintN argc, jsval *vp)
2017{
2018 OOJS_NATIVE_ENTER(context)
2019
2020 ShipEntity *thisEnt = nil;
2021 AI *thisAI = nil;
2022 NSString *message = nil;
2023
2024 GET_THIS_SHIP(thisEnt);
2025 if (EXPECT_NOT([thisEnt isPlayer]))
2026 {
2027 OOJSReportErrorForCaller(context, @"Ship", @"exitAI", @"Not valid for player ship.");
2028 return NO;
2029 }
2030 thisAI = [thisEnt getAI];
2031
2032 if ([thisAI hasSuspendedStateMachines])
2033 {
2034 if (argc > 0)
2035 {
2036 message = OOStringFromJSValue(context, OOJS_ARGV[0]);
2037 }
2038 // Else AI will default to RESTARTED.
2039
2040 [thisAI exitStateMachineWithMessage:message];
2041 }
2042 else
2043 {
2044 OOJSReportWarningForCaller(context, @"Ship", @"exitAI()", @"Cannot exit current AI state machine because there are no suspended state machines.");
2045 }
2047
2049}
2050
2051
2052// reactToAIMessage(message : String)
2053static JSBool ShipReactToAIMessage(JSContext *context, uintN argc, jsval *vp)
2054{
2055 OOJS_NATIVE_ENTER(context)
2056
2057 ShipEntity *thisEnt = nil;
2058 NSString *message = nil;
2059
2060 GET_THIS_SHIP(thisEnt);
2061 if (argc > 0) message = OOStringFromJSValue(context, OOJS_ARGV[0]);
2062 if (EXPECT_NOT(message == nil))
2063 {
2064 OOJSReportBadArguments(context, @"Ship", @"reactToAIMessage", MIN(argc, 1U), OOJS_ARGV, nil, @"string");
2065 return NO;
2066 }
2067 if (EXPECT_NOT([thisEnt isPlayer]))
2068 {
2069 OOJSReportErrorForCaller(context, @"Ship", @"reactToAIMessage", @"Not valid for player ship.");
2070 return NO;
2071 }
2072
2073 [thisEnt reactToAIMessage:message context:@"JavaScript reactToAIMessage()"];
2075
2077}
2078
2079
2080// sendAIMessage(message : String)
2081static JSBool ShipSendAIMessage(JSContext *context, uintN argc, jsval *vp)
2082{
2083 OOJS_NATIVE_ENTER(context)
2084
2085 ShipEntity *thisEnt = nil;
2086 NSString *message = nil;
2087
2088 GET_THIS_SHIP(thisEnt);
2089 if (argc > 0) message = OOStringFromJSValue(context, OOJS_ARGV[0]);
2090 if (EXPECT_NOT(message == nil))
2091 {
2092 OOJSReportBadArguments(context, @"Ship", @"sendAIMessage", MIN(argc, 1U), OOJS_ARGV, nil, @"string");
2093 return NO;
2094 }
2095 if (EXPECT_NOT([thisEnt isPlayer]))
2096 {
2097 OOJSReportErrorForCaller(context, @"Ship", @"sendAIMessage", @"Not valid for player ship.");
2098 return NO;
2099 }
2100
2101 [thisEnt sendAIMessage:message];
2103
2105}
2106
2107
2108// deployEscorts()
2109static JSBool ShipDeployEscorts(JSContext *context, uintN argc, jsval *vp)
2110{
2111 OOJS_NATIVE_ENTER(context)
2112
2113 ShipEntity *thisEnt = nil;
2114
2115 GET_THIS_SHIP(thisEnt);
2116
2117 [thisEnt deployEscorts];
2119
2121}
2122
2123
2124// dockEscorts()
2125static JSBool ShipDockEscorts(JSContext *context, uintN argc, jsval *vp)
2126{
2127 OOJS_NATIVE_ENTER(context)
2128
2129 ShipEntity *thisEnt = nil;
2130
2131 GET_THIS_SHIP(thisEnt);
2132
2133 [thisEnt dockEscorts];
2135
2137}
2138
2139
2140// hasEquipmentProviding(equipment : String) : Boolean
2141static JSBool ShipHasEquipmentProviding(JSContext *context, uintN argc, jsval *vp)
2142{
2143 OOJS_NATIVE_ENTER(context)
2144
2145 ShipEntity *thisEnt = nil;
2146 NSString *equipment = nil;
2147
2148 GET_THIS_SHIP(thisEnt);
2149
2150 if (argc > 0) equipment = OOStringFromJSValue(context, OOJS_ARGV[0]);
2151 if (EXPECT_NOT(equipment == nil))
2152 {
2153 OOJSReportBadArguments(context, @"Ship", @"hasEquipmentProviding", MIN(argc, 1U), OOJS_ARGV, nil, @"string (equipment)");
2154 return NO;
2155 }
2156
2157 OOJS_RETURN_BOOL([thisEnt hasEquipmentItemProviding:equipment]);
2158
2160}
2161
2162
2163// hasRole(role : String) : Boolean
2164static JSBool ShipHasRole(JSContext *context, uintN argc, jsval *vp)
2165{
2166 OOJS_NATIVE_ENTER(context)
2167
2168 ShipEntity *thisEnt = nil;
2169 NSString *role = nil;
2170
2171 GET_THIS_SHIP(thisEnt);
2172
2173 if (argc > 0) role = OOStringFromJSValue(context, OOJS_ARGV[0]);
2174 if (EXPECT_NOT(role == nil))
2175 {
2176 OOJSReportBadArguments(context, @"Ship", @"hasRole", MIN(argc, 1U), OOJS_ARGV, nil, @"string (role)");
2177 return NO;
2178 }
2179
2180 OOJS_RETURN_BOOL([thisEnt hasRole:role]);
2181
2183}
2184
2185
2186// ejectItem(role : String) : Ship
2187static JSBool ShipEjectItem(JSContext *context, uintN argc, jsval *vp)
2188{
2189 OOJS_NATIVE_ENTER(context)
2190
2191 ShipEntity *thisEnt = nil;
2192 NSString *role = nil;
2193
2194 GET_THIS_SHIP(thisEnt);
2195
2196 if (argc > 0) role = OOStringFromJSValue(context, OOJS_ARGV[0]);
2197 if (EXPECT_NOT(role == nil))
2198 {
2199 OOJSReportBadArguments(context, @"Ship", @"ejectItem", MIN(argc, 1U), OOJS_ARGV, nil, @"string (role)");
2200 return NO;
2201 }
2202
2203 OOJS_RETURN_OBJECT([thisEnt ejectShipOfRole:role]);
2204
2206}
2207
2208
2209// addCargoEntity: ship
2210static JSBool ShipAddCargoEntity(JSContext *context, uintN argc, jsval *vp)
2211{
2212 OOJS_NATIVE_ENTER(context)
2213 ShipEntity *thisEnt = nil;
2214 ShipEntity *target = nil;
2215 JSBool procEvents = NO;
2216 JSBool procMessages = NO;
2217
2218 GET_THIS_SHIP(thisEnt);
2219
2220 if (EXPECT_NOT([thisEnt isPlayer] && [(PlayerEntity *)thisEnt isDocked]))
2221 {
2222 OOJSReportWarningForCaller(context, @"PlayerShip", @"addCargoEntity", @"Can't add cargo entity while docked, ignoring.");
2223 return NO;
2224 }
2225 if (EXPECT_NOT(argc == 0 ||
2226 JSVAL_IS_NULL(OOJS_ARGV[0]) ||
2227 !JSVAL_IS_OBJECT(OOJS_ARGV[0]) ||
2228 !JSShipGetShipEntity(context, JSVAL_TO_OBJECT(OOJS_ARGV[0]), &target)))
2229 {
2230 OOJSReportBadArguments(context, @"PlayerShip", @"addCargoEntity", MIN(argc, 1U), OOJS_ARGV, nil, @"scoopable entity.");
2231 return NO;
2232 }
2233 if ([target scanClass] != CLASS_CARGO)
2234 {
2235 OOJSReportWarningForCaller(context, @"PlayerShip", @"addCargoEntity", @"Scoopable entity not cargo.");
2236 return NO;
2237 }
2238 if ([target status] != STATUS_IN_FLIGHT)
2239 {
2240 OOJSReportWarningForCaller(context, @"PlayerShip", @"addCargoEntity", @"Scoopable entity not in flight.");
2241 return NO;
2242 }
2243 if (argc >= 2 && EXPECT_NOT(!JS_ValueToBoolean(context, OOJS_ARGV[1], &procEvents)))
2244 {
2245 OOJSReportBadArguments(context, @"PlayerShip", @"addCargoEntity", MIN(argc, 2U), OOJS_ARGV, nil, @"boolean");
2246 return NO;
2247 }
2248 if (argc == 3 && EXPECT_NOT(!JS_ValueToBoolean(context, OOJS_ARGV[2], &procMessages)))
2249 {
2250 OOJSReportBadArguments(context, @"PlayerShip", @"addCargoEntity", MIN(argc, 3U), OOJS_ARGV, nil, @"boolean");
2251 return NO;
2252 }
2253
2254 // scoop the object, but don't process any events/messages unless requested
2255 OOJS_BEGIN_FULL_NATIVE(context)
2256 [thisEnt scoopUpProcess:target processEvents:procEvents processMessages:procMessages];
2258
2259 OOJS_RETURN_BOOL([target status] == STATUS_IN_HOLD);
2260
2262}
2263
2264
2265// ejectSpecificItem(itemKey : String) : Ship
2266static JSBool ShipEjectSpecificItem(JSContext *context, uintN argc, jsval *vp)
2267{
2268 OOJS_NATIVE_ENTER(context)
2269
2270 ShipEntity *thisEnt = nil;
2271 NSString *itemKey = nil;
2272
2273 GET_THIS_SHIP(thisEnt);
2274
2275 if (argc > 0) itemKey = OOStringFromJSValue(context, OOJS_ARGV[0]);
2276 if (EXPECT_NOT(itemKey == nil))
2277 {
2278 OOJSReportBadArguments(context, @"Ship", @"ejectSpecificItem", MIN(argc, 1U), OOJS_ARGV, nil, @"string (ship key)");
2279 return NO;
2280 }
2281
2282 OOJS_RETURN_OBJECT([thisEnt ejectShipOfType:itemKey]);
2283
2285}
2286
2287
2288// dumpCargo() : Ship
2289static JSBool ShipDumpCargo(JSContext *context, uintN argc, jsval *vp)
2290{
2291 OOJS_NATIVE_ENTER(context)
2292
2293 ShipEntity *thisEnt = nil;
2294 OOCommodityType pref = nil;
2295
2296 GET_THIS_SHIP(thisEnt);
2297
2298 if (EXPECT_NOT([thisEnt isPlayer] && [(PlayerEntity *)thisEnt isDocked]))
2299 {
2300 OOJSReportWarningForCaller(context, @"PlayerShip", @"dumpCargo", @"Can't dump cargo while docked, ignoring.");
2302 }
2303
2304 if (argc > 1)
2305 {
2306 pref = OOStringFromJSValue(context, OOJS_ARGV[1]);
2307 }
2308
2309 // NPCs can queue multiple items to dump
2310 if (!EXPECT_NOT([thisEnt isPlayer]))
2311 {
2312 int32 i, count = 1;
2313 BOOL gotCount = YES;
2314 if (argc > 0) gotCount = JS_ValueToInt32(context, OOJS_ARGV[0], &count);
2315 if (EXPECT_NOT(!gotCount || count < 1 || count > 64))
2316 {
2317 OOJSReportBadArguments(context, @"Ship", @"dumpCargo", MIN(argc, 1U), OOJS_ARGV, nil, @"optional quantity (1 to 64), optional preferred commodity");
2318 return NO;
2319 }
2320
2321 for (i = 1; i < count; i++)
2322 {
2323 [thisEnt performSelector:@selector(dumpCargo) withObject:nil afterDelay:0.75 * i]; // drop 3 canisters per 2 seconds
2324 }
2325 }
2326
2327 OOJS_RETURN_OBJECT([thisEnt dumpCargoItem:pref]);
2328
2330}
2331
2332
2333// spawn(role : String [, number : count]) : Array
2334static JSBool ShipSpawn(JSContext *context, uintN argc, jsval *vp)
2335{
2336 OOJS_NATIVE_ENTER(context)
2337
2338 ShipEntity *thisEnt = nil;
2339 NSString *role = nil;
2340 int32 count = 1;
2341 BOOL gotCount = YES;
2342 NSArray *result = nil;
2343
2344 GET_THIS_SHIP(thisEnt);
2345
2346 if (argc > 0) role = OOStringFromJSValue(context, OOJS_ARGV[0]);
2347 if (argc > 1) gotCount = JS_ValueToInt32(context, OOJS_ARGV[1], &count);
2348 if (EXPECT_NOT(role == nil || !gotCount || count < 1 || count > 64))
2349 {
2350 OOJSReportBadArguments(context, @"Ship", @"spawn", MIN(argc, 1U), OOJS_ARGV, nil, @"role and optional quantity (1 to 64)");
2351 return NO;
2352 }
2353
2354 OOJS_BEGIN_FULL_NATIVE(context)
2355 result = [thisEnt spawnShipsWithRole:role count:count];
2357
2358 OOJS_RETURN_OBJECT(result);
2359
2361}
2362
2363
2364// dealEnergyDamage(). Replaces AI's dealEnergyDamageWithinDesiredRange
2365static JSBool ShipDealEnergyDamage(JSContext *context, uintN argc, jsval *vp)
2366{
2367 OOJS_NATIVE_ENTER(context)
2368
2369 ShipEntity *thisEnt = nil;
2370 jsdouble baseDamage;
2371 jsdouble range;
2372 jsdouble velocityBias = 0.0;
2373 BOOL gotDamage;
2374 BOOL gotRange;
2375 BOOL gotVBias;
2376 GET_THIS_SHIP(thisEnt);
2377
2378 if (argc < 2)
2379 {
2380 OOJSReportBadArguments(context, @"Ship", @"dealEnergyDamage", argc, OOJS_ARGV, nil, @"damage and range needed");
2381 return NO;
2382 }
2383
2384 gotDamage = JS_ValueToNumber(context, OOJS_ARGV[0], &baseDamage);
2385 if (EXPECT_NOT(!gotDamage || baseDamage < 0))
2386 {
2387 OOJSReportBadArguments(context, @"Ship", @"dealEnergyDamage", argc, OOJS_ARGV, nil, @"damage must be positive");
2388 return NO;
2389 }
2390 gotRange = JS_ValueToNumber(context, OOJS_ARGV[1], &range);
2391 if (EXPECT_NOT(!gotRange || range < 0))
2392 {
2393 OOJSReportBadArguments(context, @"Ship", @"dealEnergyDamage", argc, OOJS_ARGV, nil, @"range must be positive");
2394 return NO;
2395 }
2396 if (argc >= 3)
2397 {
2398 gotVBias = JS_ValueToNumber(context, OOJS_ARGV[2], &velocityBias);
2399 if (!gotVBias)
2400 {
2401 OOJSReportBadArguments(context, @"Ship", @"dealEnergyDamage", argc, OOJS_ARGV, nil, @"velocity bias must be a number");
2402 return NO;
2403 }
2404 }
2405
2406 [thisEnt dealEnergyDamage:(GLfloat)baseDamage atRange:(GLfloat)range withBias:(GLfloat)velocityBias];
2407
2409
2411}
2412
2413
2414// explode()
2415static JSBool ShipExplode(JSContext *context, uintN argc, jsval *vp)
2416{
2417 OOJS_NATIVE_ENTER(context)
2418
2419 return RemoveOrExplodeShip(context, argc, vp, YES);
2420
2422}
2423
2424
2425// remove([suppressDeathEvent : Boolean = false])
2426static JSBool ShipRemove(JSContext *context, uintN argc, jsval *vp)
2427{
2428 OOJS_NATIVE_ENTER(context)
2429
2430 ShipEntity *thisEnt = nil;
2431 JSBool suppressDeathEvent = NO;
2432
2433 GET_THIS_SHIP(thisEnt);
2434
2435 if ([thisEnt isPlayer])
2436 {
2437 OOJSReportError(context, @"Cannot remove() player's ship.");
2438 return NO;
2439 }
2440
2441 if (argc > 0 && EXPECT_NOT(!JS_ValueToBoolean(context, OOJS_ARGV[0], &suppressDeathEvent)))
2442 {
2443 OOJSReportBadArguments(context, @"Ship", @"remove", argc, OOJS_ARGV, nil, @"boolean");
2444 return NO;
2445 }
2446
2447 [thisEnt doScriptEvent:OOJSID("shipRemoved") withArgument:[NSNumber numberWithBool:suppressDeathEvent]];
2448
2449 if (suppressDeathEvent)
2450 {
2451 [thisEnt removeScript];
2452 }
2453 return RemoveOrExplodeShip(context, argc, vp, NO);
2454
2456}
2457
2458
2459// __runLegacyScriptActions(target : Ship, actions : Array)
2460static JSBool ShipRunLegacyScriptActions(JSContext *context, uintN argc, jsval *vp)
2461{
2462 OOJS_NATIVE_ENTER(context)
2463
2464 ShipEntity *thisEnt = nil;
2465 PlayerEntity *player = nil;
2466 ShipEntity *target = nil;
2467 NSArray *actions = nil;
2468
2469 player = OOPlayerForScripting();
2470 GET_THIS_SHIP(thisEnt);
2471
2472 if (argc > 1) actions = OOJSNativeObjectFromJSValue(context, OOJS_ARGV[1]);
2473 if (EXPECT_NOT(argc != 2 ||
2474 !JSVAL_IS_OBJECT(OOJS_ARGV[0]) ||
2475 !JSShipGetShipEntity(context, JSVAL_TO_OBJECT(OOJS_ARGV[0]), &target) ||
2476 ![actions isKindOfClass:[NSArray class]]))
2477 {
2478 OOJSReportBadArguments(context, @"Ship", @"__runLegacyScriptActions", argc, OOJS_ARGV, nil, @"target and array of actions");
2479 return NO;
2480 }
2481
2482 if (target != nil) // Not stale reference
2483 {
2484 [player setScriptTarget:thisEnt];
2485 [player runUnsanitizedScriptActions:actions
2487 withContextName:[NSString stringWithFormat:@"<ship \"%@\" legacy actions>", [thisEnt name]]
2488 forTarget:target];
2489 }
2490
2492
2494}
2495
2496
2497// commsMessage(message : String[,target : Ship])
2498static JSBool ShipCommsMessage(JSContext *context, uintN argc, jsval *vp)
2499{
2500 OOJS_NATIVE_ENTER(context)
2501
2502 ShipEntity *thisEnt = nil;
2503 NSString *message = nil;
2504 ShipEntity *target = nil;
2505
2506 GET_THIS_SHIP(thisEnt);
2507
2508 if (argc > 0) message = OOStringFromJSValue(context, OOJS_ARGV[0]);
2509 if (EXPECT_NOT(message == nil || (argc > 1 && (JSVAL_IS_NULL(OOJS_ARGV[1]) || !JSVAL_IS_OBJECT(OOJS_ARGV[1]) || !JSShipGetShipEntity(context, JSVAL_TO_OBJECT(OOJS_ARGV[1]), &target)))))
2510 {
2511 OOJSReportBadArguments(context, @"Ship", @"commsMessage", MIN(argc, 1U), OOJS_ARGV, nil, @"message and optional target");
2512 return NO;
2513 }
2514
2515 if (argc < 2)
2516 {
2517 [thisEnt commsMessage:message withUnpilotedOverride:YES]; // generic broadcast
2518 }
2519 else if (target != nil) // Not stale reference
2520 {
2521 [thisEnt sendMessage:message toShip:target withUnpilotedOverride:YES]; // ship-to-ship narrowcast
2522 }
2524
2526}
2527
2528
2529// fireECM()
2530static JSBool ShipFireECM(JSContext *context, uintN argc, jsval *vp)
2531{
2532 OOJS_NATIVE_ENTER(context)
2533
2534 ShipEntity *thisEnt = nil;
2535 BOOL OK;
2536
2537 GET_THIS_SHIP(thisEnt);
2538
2539 OK = [thisEnt fireECM];
2540 if (!OK)
2541 {
2542 OOJSReportWarning(context, @"Ship %@ was requested to fire ECM burst but does not carry ECM equipment.", [thisEnt oo_jsDescription]);
2543 }
2544
2545 OOJS_RETURN_BOOL(OK);
2546
2548}
2549
2550
2551// abandonShip()
2552static JSBool ShipAbandonShip(JSContext *context, uintN argc, jsval *vp)
2553{
2554 OOJS_NATIVE_ENTER(context)
2555
2556 ShipEntity *thisEnt = nil;
2557
2558 GET_THIS_SHIP(thisEnt);
2559 OOJS_RETURN_BOOL([thisEnt hasEscapePod] && [thisEnt abandonShip]);
2560
2562}
2563
2564
2565// canAwardEquipment(type : equipmentInfoExpression)
2566static JSBool ShipCanAwardEquipment(JSContext *context, uintN argc, jsval *vp)
2567{
2568 OOJS_NATIVE_ENTER(context)
2569
2570 ShipEntity *thisEnt = nil;
2571 NSString *key = nil;
2572 NSString *ctx = @"scripted";
2573 BOOL result;
2574 BOOL exists;
2575
2576 GET_THIS_SHIP(thisEnt);
2577
2578 if (argc > 0) key = JSValueToEquipmentKeyRelaxed(context, OOJS_ARGV[0], &exists);
2579 if (EXPECT_NOT(key == nil))
2580 {
2581 OOJSReportBadArguments(context, @"Ship", @"canAwardEquipment", MIN(argc, 1U), OOJS_ARGV, nil, @"equipment type");
2582 return NO;
2583 }
2584
2585 if (exists)
2586 {
2587 if (argc > 1)
2588 {
2589 ctx = OOStringFromJSValue(context, OOJS_ARGV[1]);
2590 if (![ctx isEqualToString:@"scripted"] && ![ctx isEqualToString:@"purchase"] && ![ctx isEqualToString:@"newShip"] && ![ctx isEqualToString:@"npc"])
2591 {
2592 OOJSReportBadArguments(context, @"Ship", @"canAwardEquipment", MIN(argc, 2U), OOJS_ARGV, nil, @"context");
2593 return NO;
2594 }
2595 }
2596 result = YES;
2597
2598 // can't add fuel as equipment.
2599 if ([key isEqualToString:@"EQ_FUEL"]) result = NO;
2600
2601 if (result) result = [thisEnt canAddEquipment:key inContext:ctx];
2602 }
2603 else
2604 {
2605 // Unknown type.
2606 result = NO;
2607 }
2608
2609 OOJS_RETURN_BOOL(result);
2610
2612}
2613
2614
2615// awardEquipment(type : equipmentInfoExpression) : Boolean
2616static JSBool ShipAwardEquipment(JSContext *context, uintN argc, jsval *vp)
2617{
2618 OOJS_NATIVE_ENTER(context)
2619
2620 ShipEntity *thisEnt = nil;
2621 OOEquipmentType *eqType = nil;
2622 NSString *identifier = nil;
2623 BOOL OK = YES;
2624 BOOL berth;
2625 BOOL isRepair = NO;
2626
2627 GET_THIS_SHIP(thisEnt);
2628
2629 if (argc > 0) eqType = JSValueToEquipmentType(context, OOJS_ARGV[0]);
2630 if (EXPECT_NOT(eqType == nil))
2631 {
2632 OOJSReportBadArguments(context, @"Ship", @"awardEquipment", MIN(argc, 1U), OOJS_ARGV, nil, @"equipment type");
2633 return NO;
2634 }
2635
2636 // Check that equipment is permitted.
2637 identifier = [eqType identifier];
2638 berth = [identifier isEqualToString:@"EQ_PASSENGER_BERTH"];
2639 if (berth)
2640 {
2641 OK = [thisEnt availableCargoSpace] >= [eqType requiredCargoSpace];
2642 }
2643 else if ([identifier isEqualToString:@"EQ_FUEL"])
2644 {
2645 OK = NO;
2646 }
2647 else
2648 {
2649 OK = [eqType canCarryMultiple] || ![thisEnt hasEquipmentItem:identifier];
2650 }
2651
2652 if (OK)
2653 {
2654 if ([thisEnt isPlayer])
2655 {
2656 PlayerEntity *player = (PlayerEntity *)thisEnt;
2657
2658 if ([identifier isEqualToString:@"EQ_MISSILE_REMOVAL"])
2659 {
2660 [player removeMissiles];
2661 }
2662 else if ([eqType isMissileOrMine])
2663 {
2664 OK = [player mountMissileWithRole:identifier];
2665 }
2666 else if (berth)
2667 {
2668 OK = [player changePassengerBerths: +1];
2669 }
2670 else if ([identifier isEqualToString:@"EQ_PASSENGER_BERTH_REMOVAL"])
2671 {
2672 OK = [player changePassengerBerths: -1];
2673 }
2674 else
2675 {
2676 isRepair = [thisEnt hasEquipmentItem:[identifier stringByAppendingString:@"_DAMAGED"]];
2677 OK = [player addEquipmentItem:identifier withValidation:YES inContext:@"scripted"];
2678 if (OK && isRepair)
2679 {
2680 [player doScriptEvent:OOJSID("equipmentRepaired") withArgument:identifier];
2681 }
2682 }
2683 }
2684 else
2685 {
2686 if ([identifier isEqualToString:@"EQ_MISSILE_REMOVAL"])
2687 {
2688 [thisEnt removeMissiles];
2689 }
2690 // no passenger handling for NPCs. EQ_CARGO_BAY is dealt with inside addEquipmentItem
2691 else if (!berth && ![identifier isEqualToString:@"EQ_PASSENGER_BERTH_REMOVAL"])
2692 {
2693 OK = [thisEnt addEquipmentItem:identifier withValidation:YES inContext:@"scripted"];
2694 }
2695 else
2696 {
2697 OK = NO;
2698 }
2699 }
2700 }
2701
2702 OOJS_RETURN_BOOL(OK);
2703
2705}
2706
2707
2708// removeEquipment(type : equipmentInfoExpression)
2709static JSBool ShipRemoveEquipment(JSContext *context, uintN argc, jsval *vp)
2710{
2711 OOJS_NATIVE_ENTER(context)
2712
2713 ShipEntity *thisEnt = nil;
2714 NSString *key = nil;
2715 BOOL OK = YES;
2716
2717 GET_THIS_SHIP(thisEnt);
2718
2719 if (argc > 0) key = JSValueToEquipmentKey(context, OOJS_ARGV[0]);
2720 if (EXPECT_NOT(key == nil))
2721 {
2722 OOJSReportBadArguments(context, @"Ship", @"removeEquipment", MIN(argc, 1U), OOJS_ARGV, nil, @"equipment type");
2723 return NO;
2724 }
2725 // berths are not in hasOneEquipmentItem
2726 OK = [thisEnt hasOneEquipmentItem:key includeMissiles:YES whileLoading:NO] || ([key isEqualToString:@"EQ_PASSENGER_BERTH"] && [thisEnt passengerCapacity] > 0);
2727 if (!OK)
2728 {
2729 // Allow removal of damaged equipment.
2730 key = [key stringByAppendingString:@"_DAMAGED"];
2731 OK = [thisEnt hasOneEquipmentItem:key includeMissiles:NO whileLoading:NO];
2732 }
2733 if (OK)
2734 {
2735 //exceptions
2736 if ([key isEqualToString:@"EQ_PASSENGER_BERTH"] || [key isEqualToString:@"EQ_CARGO_BAY"])
2737 {
2738 if ([key isEqualToString:@"EQ_PASSENGER_BERTH"])
2739 {
2740 if ([thisEnt passengerCapacity] > [thisEnt passengerCount])
2741 {
2742 // must be the player's ship!
2743 if ([thisEnt isPlayer]) [(PlayerEntity*)thisEnt changePassengerBerths:-1];
2744 }
2745 else OK = NO;
2746 }
2747 else // EQ_CARGO_BAY
2748 {
2749 // player cargo bay removal handled in script
2750 if ([thisEnt isPlayer] || [thisEnt extraCargo] <= [thisEnt availableCargoSpace])
2751 {
2752 [thisEnt removeEquipmentItem:key];
2753 }
2754 else OK = NO;
2755 }
2756 }
2757 else
2758 [thisEnt removeEquipmentItem:key];
2759 }
2760
2761 OOJS_RETURN_BOOL(OK);
2762
2764}
2765
2766
2767// restoreSubEntities(): boolean
2768static JSBool ShipRestoreSubEntities(JSContext *context, uintN argc, jsval *vp)
2769{
2770 OOJS_NATIVE_ENTER(context)
2771
2772 ShipEntity *thisEnt = nil;
2773 NSUInteger numSubEntitiesRestored = 0U;
2774
2775 GET_THIS_SHIP(thisEnt);
2776
2777 NSUInteger subCount = [[thisEnt subEntitiesForScript] count];
2778
2779 [thisEnt clearSubEntities];
2780 [thisEnt setUpSubEntities];
2781
2782 if ([[thisEnt subEntitiesForScript] count] - subCount > 0) numSubEntitiesRestored = [[thisEnt subEntitiesForScript] count] - subCount;
2783
2784 // for each subentity restored, slightly increase the trade-in factor
2785 if ([thisEnt isPlayer])
2786 {
2787 int tradeInFactorChange = (int)MAX(PLAYER_SHIP_SUBENTITY_TRADE_IN_VALUE * numSubEntitiesRestored, 25U);
2788 [(PlayerEntity *)thisEnt adjustTradeInFactorBy:tradeInFactorChange];
2789 }
2790
2791 OOJS_RETURN_BOOL(numSubEntitiesRestored > 0);
2792
2794}
2795
2796
2797
2798// setEquipmentStatus(type : equipmentInfoExpression, status : String): boolean
2799static JSBool ShipSetEquipmentStatus(JSContext *context, uintN argc, jsval *vp)
2800{
2801 OOJS_NATIVE_ENTER(context)
2802
2803 // equipment status accepted: @"EQUIPMENT_OK", @"EQUIPMENT_DAMAGED"
2804
2805 ShipEntity *thisEnt = nil;
2806 OOEquipmentType *eqType = nil;
2807 NSString *key = nil;
2808 NSString *damagedKey = nil;
2809 NSString *status = nil;
2810 BOOL hasOK = NO, hasDamaged = NO;
2811
2812 GET_THIS_SHIP(thisEnt);
2813
2814 if (argc < 2)
2815 {
2816 OOJSReportBadArguments(context, @"Ship", @"setEquipmentStatus", argc, OOJS_ARGV, nil, @"equipment type and status");
2817 return NO;
2818 }
2819
2820 eqType = JSValueToEquipmentType(context, OOJS_ARGV[0]);
2821 if (EXPECT_NOT(eqType == nil))
2822 {
2823 OOJSReportBadArguments(context, @"Ship", @"setEquipmentStatus", 1, &OOJS_ARGV[0], nil, @"equipment type");
2824 return NO;
2825 }
2826
2827 status = OOStringFromJSValue(context, OOJS_ARGV[1]);
2828 if (EXPECT_NOT(status == nil))
2829 {
2830 OOJSReportBadArguments(context, @"Ship", @"setEquipmentStatus", 1, &OOJS_ARGV[1], nil, @"equipment status");
2831 return NO;
2832 }
2833
2834 // EMMSTRAN: use interned strings.
2835 if (![status isEqualToString:@"EQUIPMENT_OK"] && ![status isEqualToString:@"EQUIPMENT_DAMAGED"])
2836 {
2837 OOJSReportErrorForCaller(context, @"Ship", @"setEquipmentStatus", @"Second parameter for setEquipmentStatus must be either \"EQUIPMENT_OK\" or \"EQUIPMENT_DAMAGED\".");
2838 return NO;
2839 }
2840
2841 key = [eqType identifier];
2842 hasOK = [thisEnt hasEquipmentItem:key];
2843 BOOL setOK = [status isEqualToString:@"EQUIPMENT_OK"];
2844 BOOL setDamaged = [status isEqualToString:@"EQUIPMENT_DAMAGED"];
2845 if ([eqType canBeDamaged])
2846 {
2847 damagedKey = [key stringByAppendingString:@"_DAMAGED"];
2848 hasDamaged = [thisEnt hasEquipmentItem:damagedKey];
2849
2850 if ((setOK && hasDamaged) || (setDamaged && hasOK))
2851 {
2852 // the implementation is identical between player and ship.
2853 [thisEnt removeEquipmentItem:(setDamaged ? key : damagedKey)];
2854 if ([thisEnt isPlayer])
2855 {
2856 // these player methods are different to the ship ones.
2857 [(PlayerEntity*)thisEnt addEquipmentItem:(setDamaged ? damagedKey : key) withValidation:NO inContext:@"scripted"];
2858 if (setDamaged)
2859 {
2860 [(PlayerEntity*)thisEnt doScriptEvent:OOJSID("equipmentDamaged") withArgument:key];
2861 }
2862 else if (setOK)
2863 {
2864 [(PlayerEntity*)thisEnt doScriptEvent:OOJSID("equipmentRepaired") withArgument:key];
2865 }
2866
2867 // if player's Docking Computers are set to EQUIPMENT_DAMAGED while on, stop them
2868 // this is now done in a different method
2869 // if (hasOK && [key isEqualToString:@"EQ_DOCK_COMP"]) [(PlayerEntity*)thisEnt disengageAutopilot];
2870 }
2871 else
2872 {
2873 [thisEnt addEquipmentItem:(setDamaged ? damagedKey : key) withValidation:NO inContext:@"scripted"];
2874 if (hasOK) [thisEnt doScriptEvent:OOJSID("equipmentDamaged") withArgument:key];
2875 }
2876 }
2877 }
2878 else
2879 {
2880 if (hasOK && ![status isEqualToString:@"EQUIPMENT_OK"])
2881 {
2882 OOJSReportWarningForCaller(context, @"Ship", @"setEquipmentStatus", @"Equipment %@ cannot be damaged.", key);
2883 hasOK = NO;
2884 }
2885 }
2886
2887 OOJS_RETURN_BOOL(hasOK || hasDamaged);
2888
2890}
2891
2892
2893// equipmentStatus(type : equipmentInfoExpression) : String
2894static JSBool ShipEquipmentStatus(JSContext *context, uintN argc, jsval *vp)
2895{
2896 OOJS_NATIVE_ENTER(context)
2897
2898 /*
2899 Interned string constants.
2900 Interned strings are guaranteed to survive for the lifetime of the JS
2901 runtime, which lasts as long as Oolite is running.
2902 */
2903 static jsval strOK, strDamaged, strUnavailable, strUnknown;
2904 static BOOL inited = NO;
2905 if (EXPECT_NOT(!inited))
2906 {
2907 inited = YES;
2908 strOK = STRING_TO_JSVAL(JS_InternString(context, "EQUIPMENT_OK"));
2909 strDamaged = STRING_TO_JSVAL(JS_InternString(context, "EQUIPMENT_DAMAGED"));
2910 strUnavailable = STRING_TO_JSVAL(JS_InternString(context, "EQUIPMENT_UNAVAILABLE"));
2911 strUnknown = STRING_TO_JSVAL(JS_InternString(context, "EQUIPMENT_UNKNOWN"));
2912 }
2913
2914 ShipEntity *thisEnt = nil;
2915 NSString *key = nil;
2916 JSBool asDict = NO;
2917 NSDictionary *dict = nil;
2918
2919 GET_THIS_SHIP(thisEnt);
2920
2921 if (argc > 0) key = JSValueToEquipmentKey(context, OOJS_ARGV[0]);
2922 if (argc > 1) JS_ValueToBoolean(context, OOJS_ARGV[1], &asDict);
2923 if (EXPECT_NOT(key == nil))
2924 {
2925 if (argc > 0 && JSVAL_IS_STRING(OOJS_ARGV[0]))
2926 {
2927 if (asDict)
2928 {
2929 dict = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:1],@"EQUIPMENT_UNKNOWN",nil];
2930 OOJS_RETURN_OBJECT(dict);
2931 }
2932 else
2933 {
2934 OOJS_RETURN(strUnknown);
2935 }
2936 }
2937
2938 OOJSReportBadArguments(context, @"Ship", @"equipmentStatus", MIN(argc, 1U), &OOJS_ARGV[0], nil, @"equipment type");
2939 return NO;
2940 }
2941
2942
2943 if (asDict)
2944 {
2945 dict = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithUnsignedInteger:[thisEnt countEquipmentItem:key]],@"EQUIPMENT_OK",[NSNumber numberWithUnsignedInteger:[thisEnt countEquipmentItem:[key stringByAppendingString:@"_DAMAGED"]]],@"EQUIPMENT_DAMAGED",nil];
2946 OOJS_RETURN_OBJECT(dict);
2947 }
2948 else
2949 {
2950 if ([thisEnt hasEquipmentItem:key includeWeapons:YES whileLoading:NO]) OOJS_RETURN(strOK);
2951 else if ([thisEnt hasEquipmentItem:[key stringByAppendingString:@"_DAMAGED"]]) OOJS_RETURN(strDamaged);
2952
2953 OOJS_RETURN(strUnavailable);
2954 }
2956}
2957
2958
2959// selectNewMissile()
2960static JSBool ShipSelectNewMissile(JSContext *context, uintN argc, jsval *vp)
2961{
2962 OOJS_NATIVE_ENTER(context)
2963
2964 ShipEntity *thisEnt = nil;
2965
2966 GET_THIS_SHIP(thisEnt);
2967
2968 NSString *result = [[thisEnt selectMissile] identifier];
2969 // if there's a badly defined missile, selectMissile may return nil
2970 if (result == nil) result = @"EQ_MISSILE";
2971
2972 OOJS_RETURN_OBJECT(result);
2973
2975}
2976
2977
2978// fireMissile()
2979static JSBool ShipFireMissile(JSContext *context, uintN argc, jsval *vp)
2980{
2981 OOJS_NATIVE_ENTER(context)
2982
2983 ShipEntity *thisEnt = nil;
2984 id result = nil;
2985
2986 GET_THIS_SHIP(thisEnt);
2987
2988 if (argc > 0) result = [thisEnt fireMissileWithIdentifier:OOStringFromJSValue(context, OOJS_ARGV[0]) andTarget:[thisEnt primaryTarget]];
2989 else result = [thisEnt fireMissile];
2990
2991 OOJS_RETURN_OBJECT(result);
2992
2994}
2995
2996
2997// findNearestStation
2998static JSBool ShipFindNearestStation(JSContext *context, uintN argc, jsval *vp)
2999{
3000 OOJS_NATIVE_ENTER(context)
3001
3002 ShipEntity *thisEnt = nil;
3003 StationEntity *result = nil;
3004
3005 GET_THIS_SHIP(thisEnt);
3006
3007 double sdist, distance = 1E32;
3008
3009 NSEnumerator *statEnum = [[UNIVERSE stations] objectEnumerator];
3010 StationEntity *se = nil;
3011 while ((se = [statEnum nextObject]))
3012 {
3013 sdist = HPdistance2([thisEnt position],[se position]);
3014
3015 if (sdist < distance)
3016 {
3017 distance = sdist;
3018 result = se;
3019 }
3020 }
3021
3022 OOJS_RETURN_OBJECT(result);
3023
3025}
3026
3027
3028// setBounty(amount, reason)
3029static JSBool ShipSetBounty(JSContext *context, uintN argc, jsval *vp)
3030{
3031 OOJS_NATIVE_ENTER(context)
3032
3033 ShipEntity *thisEnt = nil;
3034 NSString *reason = nil;
3035 int32 newbounty = 0;
3036 BOOL gotBounty = YES;
3037
3038 GET_THIS_SHIP(thisEnt);
3039
3040 if (argc > 0) gotBounty = JS_ValueToInt32(context, OOJS_ARGV[0], &newbounty);
3041 if (argc > 1) reason = OOStringFromJSValue(context, OOJS_ARGV[1]);
3042 if (EXPECT_NOT(reason == nil || !gotBounty || newbounty < 0))
3043 {
3044 OOJSReportBadArguments(context, @"Ship", @"setBounty", argc, OOJS_ARGV, nil, @"new bounty and reason");
3045 return NO;
3046 }
3047
3048 [thisEnt setBounty:(OOCreditsQuantity)newbounty withReasonAsString:reason];
3049
3050 return YES;
3051
3053}
3054
3055
3056// setCargo(cargoType : String [, number : count])
3057static JSBool ShipSetCargo(JSContext *context, uintN argc, jsval *vp)
3058{
3059 OOJS_NATIVE_ENTER(context)
3060
3061 ShipEntity *thisEnt = nil;
3062 OOCommodityType commodity = nil;
3063 int32 count = 1;
3064 BOOL gotCount = YES;
3065
3066 GET_THIS_SHIP(thisEnt);
3067
3068 if (argc > 0) commodity = OOStringFromJSValue(context, OOJS_ARGV[0]);
3069 if (argc > 1) gotCount = JS_ValueToInt32(context, OOJS_ARGV[1], &count);
3070 if (EXPECT_NOT(commodity == nil || !gotCount || count < 1))
3071 {
3072 OOJSReportBadArguments(context, @"Ship", @"setCargo", argc, OOJS_ARGV, nil, @"cargo name and optional positive quantity");
3073 return NO;
3074 }
3075
3076 if ([[UNIVERSE commodities] goodDefined:commodity])
3077 {
3078 [thisEnt setCommodityForPod:commodity andAmount:count];
3079 }
3080
3081 OOJS_RETURN_BOOL([[UNIVERSE commodities] goodDefined:commodity]);
3082
3084}
3085
3086
3087// setCrew(crewDefinition : Object)
3088static JSBool ShipSetCrew(JSContext *context, uintN argc, jsval *vp)
3089{
3090 /* TODO: ships can in theory have multiple crew, so this could
3091 * allow that to be set. Probably not necessary for now. */
3092 OOJS_NATIVE_ENTER(context)
3093
3094 ShipEntity *thisEnt = nil;
3095 NSDictionary *crewDefinition = nil;
3096 JSObject *params = NULL;
3097
3098 GET_THIS_SHIP(thisEnt);
3099
3100 if (argc < 1 || (!JSVAL_IS_NULL(OOJS_ARGV[0]) && !JS_ValueToObject(context, OOJS_ARGV[0], &params)))
3101 {
3102 OOJSReportBadArguments(context, @"Ship", @"setCrew", MIN(argc, 1U), OOJS_ARGV, NULL, @"definition");
3103 return NO;
3104 }
3105 BOOL success = YES;
3106
3107 if (![thisEnt isExplicitlyUnpiloted])
3108 {
3109 if (JSVAL_IS_NULL(OOJS_ARGV[0]))
3110 {
3111 [thisEnt setCrew:nil];
3112 }
3113 else
3114 {
3115 crewDefinition = OOJSNativeObjectFromJSObject(context, JSVAL_TO_OBJECT(OOJS_ARGV[0]));
3116 OOCharacter *crew = [OOCharacter characterWithDictionary:crewDefinition];
3117 [thisEnt setCrew:[NSArray arrayWithObject:crew]];
3118 }
3119 }
3120 else
3121 {
3122 success = NO;
3123 }
3124
3125 OOJS_RETURN_BOOL(success);
3126
3128}
3129
3130
3131// setCargoType(cargoType : String)
3132static JSBool ShipSetCargoType(JSContext *context, uintN argc, jsval *vp)
3133{
3134 OOJS_NATIVE_ENTER(context)
3135
3136 ShipEntity *thisEnt = nil;
3137 NSString *cargoType = nil;
3138
3139 GET_THIS_SHIP(thisEnt);
3140
3141 if (argc > 0) cargoType = OOStringFromJSValue(context, OOJS_ARGV[0]);
3142 if (EXPECT_NOT(cargoType == nil))
3143 {
3144 OOJSReportBadArguments(context, @"Ship", @"setCargoType", argc, OOJS_ARGV, nil, @"cargo type name");
3145 return NO;
3146 }
3147 if ([thisEnt cargoType] != CARGO_NOT_CARGO)
3148 {
3149 OOJSReportBadArguments(context, @"Ship", @"setCargoType", argc, OOJS_ARGV, nil, [NSString stringWithFormat:@"Can only be used on cargo pod carriers, not cargo pods (%@)",[thisEnt shipDataKey]]);
3150 return NO;
3151 }
3152 BOOL ok = YES;
3153 if ([cargoType isEqualToString:@"SCARCE_GOODS"])
3154 {
3155 [thisEnt setCargoFlag:CARGO_FLAG_FULL_SCARCE];
3156 }
3157 else if ([cargoType isEqualToString:@"PLENTIFUL_GOODS"])
3158 {
3159 [thisEnt setCargoFlag:CARGO_FLAG_FULL_PLENTIFUL];
3160 }
3161 else if ([cargoType isEqualToString:@"MEDICAL_GOODS"])
3162 {
3163 [thisEnt setCargoFlag:CARGO_FLAG_FULL_MEDICAL];
3164 }
3165 else if ([cargoType isEqualToString:@"ILLEGAL_GOODS"])
3166 {
3167 [thisEnt setCargoFlag:CARGO_FLAG_FULL_CONTRABAND];
3168 }
3169 else if ([cargoType isEqualToString:@"PIRATE_GOODS"])
3170 {
3171 [thisEnt setCargoFlag:CARGO_FLAG_PIRATE];
3172 }
3173 else
3174 {
3175 ok = NO;
3176 }
3177 OOJS_RETURN_BOOL(ok);
3178
3180}
3181
3182// setMaterials(params: dict, [shaders: dict]) // sets materials dictionary. Optional parameter sets the shaders dictionary too.
3183static JSBool ShipSetMaterials(JSContext *context, uintN argc, jsval *vp)
3184{
3185 OOJS_NATIVE_ENTER(context)
3186
3187 ShipEntity *thisEnt = nil;
3188
3189 if (argc < 1)
3190 {
3191 OOJSReportBadArguments(context, @"Ship", @"setMaterials", 0, OOJS_ARGV, nil, @"parameter object");
3192 return NO;
3193 }
3194
3195 GET_THIS_SHIP(thisEnt);
3196
3197 return ShipSetMaterialsInternal(context, argc, vp, thisEnt, NO);
3198
3200}
3201
3202
3203// setShaders(params: dict)
3204static JSBool ShipSetShaders(JSContext *context, uintN argc, jsval *vp)
3205{
3206 OOJS_NATIVE_ENTER(context)
3207
3208 ShipEntity *thisEnt = nil;
3209
3210 GET_THIS_SHIP(thisEnt);
3211
3212 if (argc < 1)
3213 {
3214 OOJSReportBadArguments(context, @"Ship", @"setShaders", 0, OOJS_ARGV, nil, @"parameter object");
3215 return NO;
3216 }
3217
3218 if (JSVAL_IS_NULL(OOJS_ARGV[0]) || (!JSVAL_IS_NULL(OOJS_ARGV[0]) && !JSVAL_IS_OBJECT(OOJS_ARGV[0])))
3219 {
3220 // EMMSTRAN: JS_ValueToObject() and normal error handling here.
3221 OOJSReportWarning(context, @"Ship.%@: expected %@ instead of '%@'.", @"setShaders", @"object", OOStringFromJSValueEvenIfNull(context, OOJS_ARGV[0]));
3222 OOJS_RETURN_BOOL(NO);
3223 }
3224
3225 OOJS_ARGV[1] = OOJS_ARGV[0];
3226 return ShipSetMaterialsInternal(context, argc, vp, thisEnt, YES);
3227
3229}
3230
3231
3232static JSBool ShipSetMaterialsInternal(JSContext *context, uintN argc, jsval *vp, ShipEntity *thisEnt, BOOL fromShaders)
3233{
3235
3236 JSObject *params = NULL;
3237 NSDictionary *materials;
3238 NSDictionary *shaders;
3239 BOOL withShaders = NO;
3240 BOOL success = NO;
3241
3242 GET_THIS_SHIP(thisEnt);
3243
3244 if (JSVAL_IS_NULL(OOJS_ARGV[0]) || (!JSVAL_IS_NULL(OOJS_ARGV[0]) && !JSVAL_IS_OBJECT(OOJS_ARGV[0])))
3245 {
3246 OOJSReportWarning(context, @"Ship.%@: expected %@ instead of '%@'.", @"setMaterials", @"object", OOStringFromJSValueEvenIfNull(context, OOJS_ARGV[0]));
3247 OOJS_RETURN_BOOL(NO);
3248 }
3249
3250 if (argc > 1)
3251 {
3252 withShaders = YES;
3253 if (JSVAL_IS_NULL(OOJS_ARGV[1]) || (!JSVAL_IS_NULL(OOJS_ARGV[1]) && !JSVAL_IS_OBJECT(OOJS_ARGV[1])))
3254 {
3255 OOJSReportWarning(context, @"Ship.%@: expected %@ instead of '%@'.", @"setMaterials", @"object as second parameter", OOStringFromJSValueEvenIfNull(context, OOJS_ARGV[1]));
3256 withShaders = NO;
3257 }
3258 }
3259
3260 if (fromShaders)
3261 {
3262 materials = [[thisEnt mesh] materials];
3263 params = JSVAL_TO_OBJECT(OOJS_ARGV[0]);
3264 shaders = OOJSNativeObjectFromJSObject(context, params);
3265 }
3266 else
3267 {
3268 params = JSVAL_TO_OBJECT(OOJS_ARGV[0]);
3269 materials = OOJSNativeObjectFromJSObject(context, params);
3270 if (withShaders)
3271 {
3272 params = JSVAL_TO_OBJECT(OOJS_ARGV[1]);
3273 shaders = OOJSNativeObjectFromJSObject(context, params);
3274 }
3275 else
3276 {
3277 shaders = [[thisEnt mesh] shaders];
3278 }
3279 }
3280
3281 OOJS_BEGIN_FULL_NATIVE(context)
3282 NSDictionary *shipDict = [thisEnt shipInfoDictionary];
3283
3284 // First we test to see if we can create the mesh.
3285 OOMesh *mesh = [OOMesh meshWithName:[shipDict oo_stringForKey:@"model"]
3286 cacheKey:nil
3287 materialDictionary:materials
3288 shadersDictionary:shaders
3289 smooth:[shipDict oo_boolForKey:@"smooth" defaultValue:NO]
3290 shaderMacros:[[ResourceManager materialDefaults] oo_dictionaryForKey:@"ship-prefix-macros"]
3291 shaderBindingTarget:thisEnt];
3292
3293 if (mesh != nil)
3294 {
3295 [thisEnt setMesh:mesh];
3296 success = YES;
3297 }
3299
3300 OOJS_RETURN_BOOL(success);
3301
3303}
3304
3305
3306// exitSystem([int systemID])
3307static JSBool ShipExitSystem(JSContext *context, uintN argc, jsval *vp)
3308{
3309 OOJS_NATIVE_ENTER(context)
3310
3311 ShipEntity *thisEnt = nil;
3312 int32 systemID = -1;
3313 BOOL OK = NO;
3314
3315 GET_THIS_SHIP(thisEnt);
3316 if (EXPECT_NOT([thisEnt isPlayer]))
3317 {
3318 OOJSReportErrorForCaller(context, @"Ship", @"exitSystem", @"Not valid for player ship.");
3319 return NO;
3320 }
3321
3322 if (argc > 0)
3323 {
3324 if (!JS_ValueToInt32(context, OOJS_ARGV[0], &systemID) || systemID < 0 || 255 < systemID)
3325 {
3326 OOJSReportBadArguments(context, @"Ship", @"exitSystem", MIN(argc, 1U), OOJS_ARGV, nil, @"system ID");
3327 return NO;
3328 }
3329 }
3330
3331 OK = [thisEnt performHyperSpaceToSpecificSystem:systemID]; // -1 == random destination system
3332
3333 OOJS_RETURN_BOOL(OK);
3334
3336}
3337
3338
3339static JSBool ShipUpdateEscortFormation(JSContext *context, uintN argc, jsval *vp)
3340{
3342
3343 ShipEntity *thisEnt = nil;
3344 GET_THIS_SHIP(thisEnt);
3345 [thisEnt updateEscortFormation];
3346
3348
3350}
3351
3352static BOOL RemoveOrExplodeShip(JSContext *context, uintN argc, jsval *vp, BOOL explode)
3353{
3355
3356 ShipEntity *thisEnt = nil;
3357
3358 GET_THIS_SHIP(thisEnt);
3359
3360 if (EXPECT_NOT([thisEnt isPlayer]))
3361 {
3362 NSCAssert(explode, @"RemoveOrExplodeShip(): shouldn't be called for player with !explode."); // player.ship.remove() is blocked by caller.
3363 PlayerEntity *player = (PlayerEntity *)thisEnt;
3364
3365 if ([player isDocked])
3366 {
3367 OOJSReportError(context, @"Cannot explode() player's ship while docked.");
3368 return NO;
3369 }
3370 }
3371
3372 if (thisEnt == (ShipEntity *)[UNIVERSE station])
3373 {
3374 // Allow exploding of main station (e.g. nova mission)
3375 [UNIVERSE unMagicMainStation];
3376 }
3377
3378 if (EXPECT_NOT([thisEnt status] == STATUS_DOCKED))
3379 {
3380 /* If it's in the launch queue and hasn't yet been added to
3381 * the universe, set the status to DEAD (so it gets removed
3382 * from the launch queue) */
3383 [thisEnt setStatus:STATUS_DEAD];
3384 /* No shipDied event occurs in this place - it never really
3385 * existed. This case is just to prevent an error from the
3386 * usual code branch - removing ships while they're still
3387 * docked is not recommended. */
3388 }
3389 else
3390 {
3391 [thisEnt setSuppressExplosion:!explode];
3392 [thisEnt setEnergy:1];
3393 [thisEnt takeEnergyDamage:500000000.0 from:nil becauseOf:nil weaponIdentifier:@""];
3394 }
3395
3397
3399}
3400
3401static JSBool ShipClearDefenseTargets(JSContext *context, uintN argc, jsval *vp)
3402{
3404
3405 ShipEntity *thisEnt = nil;
3406 GET_THIS_SHIP(thisEnt);
3407 [thisEnt removeAllDefenseTargets];
3408
3410
3412}
3413
3414
3415static JSBool ShipAddDefenseTarget(JSContext *context, uintN argc, jsval *vp)
3416{
3418
3419 ShipEntity *thisEnt = nil;
3420 ShipEntity *target = nil;
3421
3422 GET_THIS_SHIP(thisEnt);
3423 if (EXPECT_NOT(argc == 0 || (argc > 0 && (JSVAL_IS_NULL(OOJS_ARGV[0]) || !JSVAL_IS_OBJECT(OOJS_ARGV[0]) || !JSShipGetShipEntity(context, JSVAL_TO_OBJECT(OOJS_ARGV[0]), &target)))))
3424 {
3425 OOJSReportBadArguments(context, @"Ship", @"addDefenseTarget", 1U, OOJS_ARGV, nil, @"target");
3426 return NO;
3427 }
3428
3429 [thisEnt addDefenseTarget:target];
3430
3432
3434}
3435
3436
3437static JSBool ShipRemoveDefenseTarget(JSContext *context, uintN argc, jsval *vp)
3438{
3440
3441 ShipEntity *thisEnt = nil;
3442 ShipEntity *target = nil;
3443
3444 GET_THIS_SHIP(thisEnt);
3445 if (EXPECT_NOT(argc == 0 || (argc > 0 && (JSVAL_IS_NULL(OOJS_ARGV[0]) || !JSVAL_IS_OBJECT(OOJS_ARGV[0]) || !JSShipGetShipEntity(context, JSVAL_TO_OBJECT(OOJS_ARGV[0]), &target)))))
3446 {
3447 OOJSReportBadArguments(context, @"Ship", @"removeDefenseTarget", 1U, OOJS_ARGV, nil, @"target");
3448 return NO;
3449 }
3450
3451 [thisEnt removeDefenseTarget:target];
3452
3454
3456}
3457
3458
3459static JSBool ShipAddCollisionException(JSContext *context, uintN argc, jsval *vp)
3460{
3462
3463 ShipEntity *thisEnt = nil;
3464 ShipEntity *target = nil;
3465
3466 GET_THIS_SHIP(thisEnt);
3467 if (EXPECT_NOT(argc == 0 || (argc > 0 && (JSVAL_IS_NULL(OOJS_ARGV[0]) || !JSVAL_IS_OBJECT(OOJS_ARGV[0]) || !JSShipGetShipEntity(context, JSVAL_TO_OBJECT(OOJS_ARGV[0]), &target)))))
3468 {
3469 OOJSReportBadArguments(context, @"Ship", @"addCollisionException", 1U, OOJS_ARGV, nil, @"other ship");
3470 return NO;
3471 }
3472
3473 // have to do it both ways because it's not defined which order
3474 // the collisions get tested in. More efficient to add both ways
3475 // than to test both ways
3476 [thisEnt addCollisionException:target];
3477 [target addCollisionException:thisEnt];
3478
3480
3482}
3483
3484
3485static JSBool ShipRemoveCollisionException(JSContext *context, uintN argc, jsval *vp)
3486{
3488
3489 ShipEntity *thisEnt = nil;
3490 ShipEntity *target = nil;
3491
3492 GET_THIS_SHIP(thisEnt);
3493 if (EXPECT_NOT(argc == 0 || (argc > 0 && (JSVAL_IS_NULL(OOJS_ARGV[0]) || !JSVAL_IS_OBJECT(OOJS_ARGV[0]) || !JSShipGetShipEntity(context, JSVAL_TO_OBJECT(OOJS_ARGV[0]), &target)))))
3494 {
3495 OOJSReportBadArguments(context, @"Ship", @"removeCollisionException", 1U, OOJS_ARGV, nil, @"other ship");
3496 return NO;
3497 }
3498
3499 // doesn't need a check to see if it was already gone
3500 [thisEnt removeCollisionException:target];
3501 [target removeCollisionException:thisEnt];
3502
3504
3506}
3507
3508
3509//getMaterials()
3510static JSBool ShipGetMaterials(JSContext *context, uintN argc, jsval *vp)
3511{
3513
3514 ShipEntity *thisEnt = nil;
3515 NSObject *result = nil;
3516
3517 GET_THIS_SHIP(thisEnt);
3518
3519 result = [[thisEnt mesh] materials];
3520 if (result == nil) result = [NSDictionary dictionary];
3521 OOJS_RETURN_OBJECT(result);
3522
3524}
3525
3526//getShaders()
3527static JSBool ShipGetShaders(JSContext *context, uintN argc, jsval *vp)
3528{
3530
3531 ShipEntity *thisEnt = nil;
3532 NSObject *result = nil;
3533
3534 GET_THIS_SHIP(thisEnt);
3535
3536 result = [[thisEnt mesh] shaders];
3537 if (result == nil) result = [NSDictionary dictionary];
3538 OOJS_RETURN_OBJECT(result);
3539
3541}
3542
3543static JSBool ShipBroadcastCascadeImminent(JSContext *context, uintN argc, jsval *vp)
3544{
3546
3547 ShipEntity *thisEnt = nil;
3548 GET_THIS_SHIP(thisEnt);
3549 [thisEnt broadcastEnergyBlastImminent];
3550
3552
3554}
3555
3556static JSBool ShipBecomeCascadeExplosion(JSContext *context, uintN argc, jsval *vp)
3557{
3559
3560 ShipEntity *thisEnt = nil;
3561 GET_THIS_SHIP(thisEnt);
3562 [thisEnt becomeEnergyBlast];
3563
3565
3567}
3568
3569
3570static JSBool ShipOfferToEscort(JSContext *context, uintN argc, jsval *vp)
3571{
3573
3574 ShipEntity *thisEnt = nil;
3575 ShipEntity *mother = nil;
3576
3577 GET_THIS_SHIP(thisEnt);
3578 if (EXPECT_NOT(argc == 0 || (argc > 0 && (JSVAL_IS_NULL(OOJS_ARGV[0]) || !JSVAL_IS_OBJECT(OOJS_ARGV[0]) || !JSShipGetShipEntity(context, JSVAL_TO_OBJECT(OOJS_ARGV[0]), &mother)))))
3579 {
3580 OOJSReportBadArguments(context, @"Ship", @"offerToEscort", 1U, OOJS_ARGV, nil, @"target");
3581 return NO;
3582 }
3583
3584 BOOL result = [thisEnt suggestEscortTo:mother];
3585
3586 OOJS_RETURN_BOOL(result);
3587
3589}
3590
3591
3592static JSBool ShipRequestHelpFromGroup(JSContext *context, uintN argc, jsval *vp)
3593{
3595
3596 ShipEntity *thisEnt = nil;
3597
3598 GET_THIS_SHIP(thisEnt);
3599
3600 [thisEnt groupAttackTarget];
3601
3603
3605}
3606
3607
3608static JSBool ShipPatrolReportIn(JSContext *context, uintN argc, jsval *vp)
3609{
3611
3612 ShipEntity *thisEnt = nil;
3613 ShipEntity *target = nil;
3614
3615 GET_THIS_SHIP(thisEnt);
3616 if (EXPECT_NOT(argc == 0 || (argc > 0 && (JSVAL_IS_NULL(OOJS_ARGV[0]) || !JSVAL_IS_OBJECT(OOJS_ARGV[0]) || !JSShipGetShipEntity(context, JSVAL_TO_OBJECT(OOJS_ARGV[0]), &target)))))
3617 {
3618 OOJSReportBadArguments(context, @"Ship", @"addDefenseTarget", 1U, OOJS_ARGV, nil, @"target");
3619 return NO;
3620 }
3621 if ([target isStation])
3622 {
3623 StationEntity *station = (StationEntity*)target;
3624 [station acceptPatrolReportFrom:thisEnt];
3625 }
3626
3628
3630}
3631
3632
3633static JSBool ShipMarkTargetForFines(JSContext *context, uintN argc, jsval *vp)
3634{
3636
3637 ShipEntity *thisEnt = nil;
3638
3639 GET_THIS_SHIP(thisEnt);
3640
3641 ShipEntity *ship = [thisEnt primaryTarget];
3642 BOOL ok = NO;
3643 if ((ship != nil) && ([ship status] != STATUS_DEAD) && ([ship status] != STATUS_DOCKED))
3644 {
3645 ok = [ship markForFines];
3646 }
3647
3648 OOJS_RETURN_BOOL(ok);
3649
3651}
3652
3653
3654static JSBool ShipEnterWormhole(JSContext *context, uintN argc, jsval *vp)
3655{
3657
3658 ShipEntity *thisEnt = nil;
3659 Entity *hole = nil;
3660
3661 if ([PLAYER status] != STATUS_ENTERING_WITCHSPACE)
3662 {
3663 OOJSReportError(context, @"Cannot use this function while player's ship not entering witchspace.");
3664 return NO;
3665 }
3666
3667 GET_THIS_SHIP(thisEnt);
3668 if (EXPECT_NOT(argc == 0 || (argc > 0 && !JSVAL_IS_NULL(OOJS_ARGV[0]) && (!JSVAL_IS_OBJECT(OOJS_ARGV[0]) || !OOJSEntityGetEntity(context, JSVAL_TO_OBJECT(OOJS_ARGV[0]), &hole)))))
3669 {
3670 [thisEnt enterPlayerWormhole];
3671 }
3672 else
3673 {
3674 if (![hole isWormhole])
3675 {
3676 OOJSReportBadArguments(context, @"Ship", @"enterWormhole", 1U, OOJS_ARGV, nil, @"[wormhole]");
3677 return NO;
3678 }
3679
3680 [thisEnt enterWormhole:(WormholeEntity*)hole];
3681 }
3682
3684
3686}
3687
3688
3689static JSBool ShipNotifyGroupOfWormhole(JSContext *context, uintN argc, jsval *vp)
3690{
3692
3693 ShipEntity *thisEnt = nil;
3694 GET_THIS_SHIP(thisEnt);
3695
3696 [thisEnt wormholeEntireGroup];
3697
3699
3701}
3702
3703
3704static JSBool ShipThrowSpark(JSContext *context, uintN argc, jsval *vp)
3705{
3707
3708 ShipEntity *thisEnt = nil;
3709 GET_THIS_SHIP(thisEnt);
3710 [thisEnt setThrowSparks:YES];
3711
3713
3715}
3716
3717
3718
3719static JSBool ShipPerformAttack(JSContext *context, uintN argc, jsval *vp)
3720{
3722
3723 ShipEntity *thisEnt = nil;
3724 GET_THIS_SHIP(thisEnt);
3725 [thisEnt performAttack];
3726
3728
3730}
3731
3732
3733static JSBool ShipPerformCollect(JSContext *context, uintN argc, jsval *vp)
3734{
3736
3737 ShipEntity *thisEnt = nil;
3738 GET_THIS_SHIP(thisEnt);
3739 [thisEnt performCollect];
3740
3742
3744}
3745
3746
3747static JSBool ShipPerformEscort(JSContext *context, uintN argc, jsval *vp)
3748{
3750
3751 ShipEntity *thisEnt = nil;
3752 GET_THIS_SHIP(thisEnt);
3753 [thisEnt performEscort];
3754
3756
3758}
3759
3760
3761static JSBool ShipPerformFaceDestination(JSContext *context, uintN argc, jsval *vp)
3762{
3764
3765 ShipEntity *thisEnt = nil;
3766 GET_THIS_SHIP(thisEnt);
3767 [thisEnt performFaceDestination];
3768
3770
3772}
3773
3774
3775static JSBool ShipPerformFlee(JSContext *context, uintN argc, jsval *vp)
3776{
3778
3779 ShipEntity *thisEnt = nil;
3780 GET_THIS_SHIP(thisEnt);
3781 [thisEnt performFlee];
3782
3784
3786}
3787
3788
3789static JSBool ShipPerformFlyToRangeFromDestination(JSContext *context, uintN argc, jsval *vp)
3790{
3792
3793 ShipEntity *thisEnt = nil;
3794 GET_THIS_SHIP(thisEnt);
3795 [thisEnt performFlyToRangeFromDestination];
3796
3798
3800}
3801
3802
3803static JSBool ShipPerformHold(JSContext *context, uintN argc, jsval *vp)
3804{
3806
3807 ShipEntity *thisEnt = nil;
3808 GET_THIS_SHIP(thisEnt);
3809 [thisEnt performHold];
3810
3812
3814}
3815
3816
3817static JSBool ShipPerformIdle(JSContext *context, uintN argc, jsval *vp)
3818{
3820
3821 ShipEntity *thisEnt = nil;
3822 GET_THIS_SHIP(thisEnt);
3823 [thisEnt performIdle];
3824
3826
3828}
3829
3830
3831static JSBool ShipPerformIntercept(JSContext *context, uintN argc, jsval *vp)
3832{
3834
3835 ShipEntity *thisEnt = nil;
3836 GET_THIS_SHIP(thisEnt);
3837 [thisEnt performIntercept];
3838
3840
3842}
3843
3844
3845static JSBool ShipPerformLandOnPlanet(JSContext *context, uintN argc, jsval *vp)
3846{
3848
3849 ShipEntity *thisEnt = nil;
3850 GET_THIS_SHIP(thisEnt);
3851 [thisEnt performLandOnPlanet];
3852
3854
3856}
3857
3858
3859static JSBool ShipPerformMining(JSContext *context, uintN argc, jsval *vp)
3860{
3862
3863 ShipEntity *thisEnt = nil;
3864 GET_THIS_SHIP(thisEnt);
3865 [thisEnt performMining];
3866
3868
3870}
3871
3872
3873static JSBool ShipPerformScriptedAI(JSContext *context, uintN argc, jsval *vp)
3874{
3876
3877 ShipEntity *thisEnt = nil;
3878 GET_THIS_SHIP(thisEnt);
3879 [thisEnt performScriptedAI];
3880
3882
3884}
3885
3886
3887static JSBool ShipPerformScriptedAttackAI(JSContext *context, uintN argc, jsval *vp)
3888{
3890
3891 ShipEntity *thisEnt = nil;
3892 GET_THIS_SHIP(thisEnt);
3893 [thisEnt performScriptedAttackAI];
3894
3896
3898}
3899
3900
3901static JSBool ShipPerformStop(JSContext *context, uintN argc, jsval *vp)
3902{
3904
3905 ShipEntity *thisEnt = nil;
3906 GET_THIS_SHIP(thisEnt);
3907 [thisEnt performStop];
3908
3910
3912}
3913
3914
3915static JSBool ShipPerformTumble(JSContext *context, uintN argc, jsval *vp)
3916{
3918
3919 ShipEntity *thisEnt = nil;
3920 GET_THIS_SHIP(thisEnt);
3921 [thisEnt performTumble];
3922
3924
3926}
3927
3928
3929static JSBool ShipRequestDockingInstructions(JSContext *context, uintN argc, jsval *vp)
3930{
3932
3933 ShipEntity *thisEnt = nil;
3934 GET_THIS_SHIP(thisEnt);
3935 [thisEnt requestDockingCoordinates];
3936
3937 NSDictionary *dockingInstructions = [thisEnt dockingInstructions];
3938 if (dockingInstructions != nil)
3939 {
3940 OOJS_RETURN_OBJECT(dockingInstructions);
3941 }
3942 else
3943 {
3945 }
3946
3948}
3949
3950
3951static JSBool ShipRecallDockingInstructions(JSContext *context, uintN argc, jsval *vp)
3952{
3954
3955 ShipEntity *thisEnt = nil;
3956 GET_THIS_SHIP(thisEnt);
3957 [thisEnt recallDockingInstructions];
3958
3959 NSDictionary *dockingInstructions = [thisEnt dockingInstructions];
3960 if (dockingInstructions != nil)
3961 {
3962 OOJS_RETURN_OBJECT(dockingInstructions);
3963 }
3964 else
3965 {
3967 }
3968
3970}
3971
3972
3973static JSBool ShipBroadcastDistressMessage(JSContext *context, uintN argc, jsval *vp)
3974{
3976
3977 ShipEntity *thisEnt = nil;
3978 GET_THIS_SHIP(thisEnt);
3979 [thisEnt broadcastDistressMessageWithDumping:NO];
3980
3982
3984}
3985
3986
3987static JSBool ShipCheckCourseToDestination(JSContext *context, uintN argc, jsval *vp)
3988{
3990
3991 ShipEntity *thisEnt = nil;
3992 GET_THIS_SHIP(thisEnt);
3993
3994 Entity *hazard = [UNIVERSE hazardOnRouteFromEntity:thisEnt toDistance:[thisEnt desiredRange] fromPoint:[thisEnt destination]];
3995
3996 OOJS_RETURN_OBJECT(hazard);
3997
3999}
4000
4001
4002static JSBool ShipGetSafeCourseToDestination(JSContext *context, uintN argc, jsval *vp)
4003{
4005
4006 ShipEntity *thisEnt = nil;
4007 GET_THIS_SHIP(thisEnt);
4008
4009 HPVector waypoint = [UNIVERSE getSafeVectorFromEntity:thisEnt toDistance:[thisEnt desiredRange] fromPoint:[thisEnt destination]];
4010
4011 OOJS_RETURN_HPVECTOR(waypoint);
4012
4014
4015}
4016
4017
4018static JSBool ShipCheckScanner(JSContext *context, uintN argc, jsval *vp)
4019{
4021
4022 ShipEntity *thisEnt = nil;
4023 JSBool onlyCheckPowered = NO;
4024
4025 GET_THIS_SHIP(thisEnt);
4026
4027 if (argc > 0 && EXPECT_NOT(!JS_ValueToBoolean(context, OOJS_ARGV[0], &onlyCheckPowered)))
4028 {
4029 OOJSReportBadArguments(context, @"Ship", @"checkScanner", argc, OOJS_ARGV, nil, @"boolean");
4030 return NO;
4031 }
4032
4033 if (onlyCheckPowered)
4034 {
4035 [thisEnt checkScannerIgnoringUnpowered];
4036 }
4037 else
4038 {
4039 [thisEnt checkScanner];
4040 }
4041 ShipEntity **scannedShips = [thisEnt scannedShips];
4042 unsigned num = [thisEnt numberOfScannedShips];
4043 NSMutableArray *scanResult = [NSMutableArray array];
4044 for (unsigned i = 0; i < num ; i++)
4045 {
4046 [scanResult addObject:scannedShips[i]];
4047 }
4048 OOJS_RETURN_OBJECT(scanResult);
4049
4051}
4052
4053
4054static JSBool ShipAdjustCargo(JSContext *context, uintN argc, jsval *vp)
4055{
4057
4058 ShipEntity *thisEnt = nil;
4059 NSString *commodity = @"";
4060 int32 adjustment = 0;
4061
4062 GET_THIS_SHIP(thisEnt);
4063
4064 if (argc < 2)
4065 {
4066 OOJSReportBadArguments(context, @"Ship", @"adjustCargo", argc, OOJS_ARGV, nil, @"commodity, amount");
4067 return NO;
4068 }
4069
4070 commodity = OOStringFromJSValue(context, OOJS_ARGV[0]);
4071 if (!JS_ValueToInt32(context, OOJS_ARGV[1], &adjustment))
4072 {
4073 OOJSReportBadArguments(context, @"Ship", @"adjustCargo", argc, OOJS_ARGV, nil, @"commodity, amount");
4074 return NO;
4075 }
4076
4077 if ([thisEnt cargoType] != CARGO_NOT_CARGO || [thisEnt isPlayer])
4078 {
4079 OOJSReportError(context, @"ship.adjustCargo may only be used on NPC cargo carriers");
4080 return NO;
4081 }
4082
4083 BOOL ok = YES;
4084
4085 if (adjustment > 0)
4086 {
4087 NSArray *cargo = [UNIVERSE getContainersOfCommodity:commodity :adjustment]; // non-reified templates
4088 ok = [thisEnt addCargo:cargo];
4089 }
4090 else if (adjustment < 0)
4091 {
4092 OOCargoQuantity r = (OOCargoQuantity)(-adjustment);
4093 ok = [thisEnt removeCargo:commodity amount:r];
4094 }
4095
4096
4097 OOJS_RETURN_BOOL(ok);
4098
4100}
4101
4102
4103/* 0 = no significant damage or consumable loss, higher numbers mean some */
4104static JSBool ShipDamageAssessment(JSContext *context, uintN argc, jsval *vp)
4105{
4107
4108 ShipEntity *thisEnt = nil;
4109 int assessment = 0;
4110
4111 GET_THIS_SHIP(thisEnt);
4112
4113 // if could have missiles but doesn't, consumables low
4114 if ([thisEnt missileCapacity] > 0 && [[thisEnt missilesList] count] == 0)
4115 {
4116 assessment++;
4117 }
4118 // if has injectors but fuel is low, consumables low
4119 // if no injectors, not a problem
4120 if ([thisEnt hasFuelInjection] && [thisEnt fuel] < 35)
4121 {
4122 assessment++;
4123 }
4124
4125 /* TODO: when NPC equipment can be damaged in combat, assess this
4126 * here */
4127
4128 OOJS_RETURN_INT(assessment);
4129
4131}
4132
4133
4134
4135static JSBool ShipThreatAssessment(JSContext *context, uintN argc, jsval *vp)
4136{
4138
4139 ShipEntity *thisEnt = nil;
4140 JSBool fullCheck = NO;
4141
4142 GET_THIS_SHIP(thisEnt);
4143
4144 if (argc > 0 && EXPECT_NOT(!JS_ValueToBoolean(context, OOJS_ARGV[0], &fullCheck)))
4145 {
4146 OOJSReportBadArguments(context, @"Ship", @"threatAssessment", argc, OOJS_ARGV, nil, @"boolean");
4147 return NO;
4148 }
4149 // start with 2.5 per ship
4150 double assessment = 2.5;
4151 // +/- 0.1 for speed, larger subtraction for very slow ships
4152 GLfloat maxspeed = [thisEnt maxFlightSpeed];
4153 assessment += (maxspeed-300)/1000;
4154 if (maxspeed < 200)
4155 {
4156 assessment += (maxspeed-200)/500;
4157 }
4158
4159 /* FIXME: at the moment this means NPCs can detect other NPCs shield
4160 * boosters, since they're implemented as extra energy */
4161 assessment += ([thisEnt maxEnergy]-200)/1000;
4162
4163 // add on some for missiles. Mostly ignore 3rd and subsequent
4164 // missiles: either they can be ECMd or the first two are already
4165 // too many.
4166 if ([thisEnt missileCapacity] > 2)
4167 {
4168 assessment += 0.5;
4169 }
4170 else
4171 {
4172 assessment += ((double)[thisEnt missileCapacity])/5.0;
4173 }
4174
4175 /* Turret count is public knowledge */
4176 /* TODO: consider making ship combat behaviour try to
4177 * stay at long range from enemies with turrets. Then
4178 * we could perhaps reduce this bonus a bit. */
4179 assessment += [thisEnt turretCount];
4180
4181 if (fullCheck)
4182 {
4183 // consider pilot skill
4184 if ([thisEnt isPlayer])
4185 {
4186 double score = (double)[PLAYER score];
4187 if (score > 6400)
4188 {
4189 score = 6400;
4190 }
4191 assessment += pow(score,0.33)/10;
4192 // 0 - 1.8
4193 }
4194 else
4195 {
4196 assessment += [thisEnt accuracy]/5;
4197 }
4198
4199 // check lasers
4200 OOWeaponType wt = [thisEnt weaponTypeIDForFacing:WEAPON_FACING_FORWARD strict:NO];
4201 /* Not affected by multiple mounts here: they're either just a
4202 * split of the power, or only more dangerous until they
4203 * overheat */
4204 assessment += ShipThreatAssessmentWeapon(wt);
4205 if (isWeaponNone(wt))
4206 {
4207 assessment -= 1.5; // further penalty for ships with no forward laser
4208 }
4209
4210 wt = [thisEnt weaponTypeIDForFacing:WEAPON_FACING_AFT strict:NO];
4211 if (!isWeaponNone(wt))
4212 {
4213 assessment += 1 + ShipThreatAssessmentWeapon(wt);
4214 }
4215 // port and starboard weapons less important
4216 wt = [thisEnt weaponTypeIDForFacing:WEAPON_FACING_PORT strict:NO];
4217 if (!isWeaponNone(wt))
4218 {
4219 assessment += 0.2 + ShipThreatAssessmentWeapon(wt)/5.0;
4220 }
4221 wt = [thisEnt weaponTypeIDForFacing:WEAPON_FACING_STARBOARD strict:NO];
4222 if (!isWeaponNone(wt))
4223 {
4224 assessment += 0.2 + ShipThreatAssessmentWeapon(wt)/5.0;
4225 }
4226
4227 // combat-related secondary equipment
4228 if ([thisEnt hasECM])
4229 {
4230 assessment += 0.5;
4231 }
4232 if ([thisEnt hasFuelInjection])
4233 {
4234 assessment += 0.5;
4235 }
4236
4237 }
4238 else
4239 {
4240 // consider thargoids dangerous
4241 if ([thisEnt isThargoid])
4242 {
4243 assessment *= 1.5;
4244 if ([thisEnt hasRole:@"thargoid-mothership"])
4245 {
4246 assessment += 5;
4247 }
4248 }
4249 else
4250 {
4251 // consider that armed ships might have a trick or two
4252 if ([thisEnt weaponFacings] == 1)
4253 {
4254 assessment += 0.25;
4255 }
4256 else
4257 {
4258 // and more than one trick if they can mount multiple lasers
4259 assessment += 0.5;
4260 }
4261 }
4262 }
4263
4264 // mostly ignore fleeing ships as threats
4265 if ([thisEnt behaviour] == BEHAVIOUR_FLEE_TARGET || [thisEnt behaviour] == BEHAVIOUR_FLEE_EVASIVE_ACTION)
4266 {
4267 assessment *= 0.2;
4268 }
4269 else if ([thisEnt isPlayer] && [(PlayerEntity*)thisEnt fleeingStatus] >= PLAYER_FLEEING_CARGO)
4270 {
4271 assessment *= 0.2;
4272 }
4273
4274 // don't go too low.
4275 if (assessment < 0.1)
4276 {
4277 assessment = 0.1;
4278 }
4279
4280 OOJS_RETURN_DOUBLE(assessment);
4281
4283}
4284
4286{
4287 if (wt == nil)
4288 {
4289 return -1.0;
4290 }
4291 return [wt weaponThreatAssessment];
4292}
4293
4294
4297static JSBool ShipStaticKeys(JSContext *context, uintN argc, jsval *vp)
4298{
4299 OOJS_NATIVE_ENTER(context);
4301
4302 NSArray *keys = [registry shipKeys];
4303 OOJS_RETURN_OBJECT(keys);
4304
4306}
4307
4308static JSBool ShipStaticKeysForRole(JSContext *context, uintN argc, jsval *vp)
4309{
4310 OOJS_NATIVE_ENTER(context);
4312
4313 if (argc > 0)
4314 {
4315 NSString *role = OOStringFromJSValue(context, OOJS_ARGV[0]);
4316 NSArray *keys = [registry shipKeysWithRole:role];
4317 OOJS_RETURN_OBJECT(keys);
4318 }
4319 else
4320 {
4321 OOJSReportBadArguments(context, @"Ship", @"shipKeysForRole", MIN(argc, 1U), OOJS_ARGV, nil, @"ship role");
4322 return NO;
4323 }
4324
4326}
4327
4328
4329static JSBool ShipStaticRoleIsInCategory(JSContext *context, uintN argc, jsval *vp)
4330{
4331 OOJS_NATIVE_ENTER(context);
4332
4333 if (argc > 1)
4334 {
4335 NSString *role = OOStringFromJSValue(context, OOJS_ARGV[0]);
4336 NSString *category = OOStringFromJSValue(context, OOJS_ARGV[1]);
4337
4338 OOJS_RETURN_BOOL([UNIVERSE role:role isInCategory:category]);
4339 }
4340 else
4341 {
4342 OOJSReportBadArguments(context, @"Ship", @"roleIsInCategory", MIN(argc, 2U), OOJS_ARGV, nil, @"role, category");
4343 return NO;
4344 }
4345
4347}
4348
4349
4350static JSBool ShipStaticRoles(JSContext *context, uintN argc, jsval *vp)
4351{
4352 OOJS_NATIVE_ENTER(context);
4354
4355 NSArray *keys = [registry shipRoles];
4356 OOJS_RETURN_OBJECT(keys);
4357
4359}
4360
4361
4362static JSBool ShipStaticShipDataForKey(JSContext *context, uintN argc, jsval *vp)
4363{
4364 OOJS_NATIVE_ENTER(context);
4366
4367 if (argc > 0)
4368 {
4369 NSString *key = OOStringFromJSValue(context, OOJS_ARGV[0]);
4370 NSDictionary *keys = [registry shipInfoForKey:key];
4371 OOJS_RETURN_OBJECT(keys);
4372 }
4373 else
4374 {
4375 OOJSReportBadArguments(context, @"Ship", @"shipDataForKey", MIN(argc, 1U), OOJS_ARGV, nil, @"key");
4376 return NO;
4377 }
4379}
4380
4381
4382static JSBool ShipStaticSetShipDataForKey(JSContext *context, uintN argc, jsval *vp)
4383{
4384 OOJS_NATIVE_ENTER(context);
4386
4387 if (argc >= 2)
4388 {
4389 NSString *key = OOStringFromJSValue(context, OOJS_ARGV[0]);
4390 NSDictionary *newShipData = OOJSNativeObjectFromJSObject(context, JSVAL_TO_OBJECT(OOJS_ARGV[1]));
4391 [registry setShipInfoForKey:key with:newShipData];
4392 OOJS_RETURN_BOOL(YES);
4393 }
4394 else
4395 {
4396 OOJSReportBadArguments(context, @"Ship", @"setShipInfoForKey", MIN(argc, 2U), OOJS_ARGV, nil, @"key shipdata");
4397 return NO;
4398 }
4400}
#define EXPECT_NOT(x)
#define OOJS_PROFILE_EXIT
#define OOJS_END_FULL_NATIVE
#define OOJS_BEGIN_FULL_NATIVE(context)
#define OOJS_NATIVE_ENTER(cx)
#define OOJS_NATIVE_EXIT
#define OOJS_PROFILE_ENTER
BOOL JSValueToEntity(JSContext *context, jsval value, Entity **outEntity)
Definition OOJSEntity.m:146
OOINLINE BOOL OOIsStaleEntity(Entity *entity)
Definition OOJSEntity.h:71
OOINLINE JSClass * JSEntityClass(void)
Definition OOJSEntity.h:42
OOINLINE JSObject * JSEntityPrototype(void)
Definition OOJSEntity.h:43
OOEquipmentType * JSValueToEquipmentType(JSContext *context, jsval value)
NSString * JSValueToEquipmentKeyRelaxed(JSContext *context, jsval value, BOOL *outExists)
NSString * JSValueToEquipmentKey(JSContext *context, jsval value)
PlayerEntity * OOPlayerForScripting(void)
Definition OOJSPlayer.m:191
BOOL JSValueToQuaternion(JSContext *context, jsval value, Quaternion *outQuaternion) NONNULL_FUNC
BOOL QuaternionToJSValue(JSContext *context, Quaternion quaternion, jsval *outValue) NONNULL_FUNC
static JSBool ShipPerformCollect(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:3733
static JSBool ShipRemoveDefenseTarget(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:3437
static JSBool ShipPatrolReportIn(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:3608
static JSBool ShipCheckCourseToDestination(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:3987
static JSBool ShipExitSystem(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:3307
static JSBool ShipPerformFlyToRangeFromDestination(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:3789
static JSBool ShipPerformEscort(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:3747
static JSBool ShipSwitchAI(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:1988
static JSBool ShipThreatAssessment(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:4135
static JSBool ShipHasRole(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:2164
static JSBool ShipAbandonShip(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:2552
static JSBool ShipRestoreSubEntities(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:2768
static JSBool ShipExitAI(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:2016
static JSBool ShipPerformMining(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:3859
static JSBool ShipSelectNewMissile(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:2960
@ kShip_isMissile
Definition OOJSShip.m:252
@ kShip_AIScriptWakeTime
Definition OOJSShip.m:189
@ kShip_weaponPositionPort
Definition OOJSShip.m:324
@ kShip_hyperspaceSpinTime
Definition OOJSShip.m:239
@ kShip_cargoSpaceUsed
Definition OOJSShip.m:203
@ kShip_destination
Definition OOJSShip.m:216
@ kShip_escorts
Definition OOJSShip.m:224
@ kShip_fuelChargeRate
Definition OOJSShip.m:231
@ kShip_missileCapacity
Definition OOJSShip.m:275
@ kShip_collisionExceptions
Definition OOJSShip.m:204
@ kShip_target
Definition OOJSShip.m:312
@ kShip_commodityAmount
Definition OOJSShip.m:207
@ kShip_autoWeapons
Definition OOJSShip.m:195
@ kShip_weaponFacings
Definition OOJSShip.m:321
@ kShip_subEntityCapacity
Definition OOJSShip.m:309
@ kShip_isFleeing
Definition OOJSShip.m:248
@ kShip_group
Definition OOJSShip.m:232
@ kShip_potentialCollider
Definition OOJSShip.m:286
@ kShip_thrustVector
Definition OOJSShip.m:315
@ kShip_AIState
Definition OOJSShip.m:190
@ kShip_accuracy
Definition OOJSShip.m:185
@ kShip_autoAI
Definition OOJSShip.m:194
@ kShip_isFrangible
Definition OOJSShip.m:247
@ kShip_maxPitch
Definition OOJSShip.m:270
@ kShip_alertCondition
Definition OOJSShip.m:193
@ kShip_hasHostileTarget
Definition OOJSShip.m:233
@ kShip_passengers
Definition OOJSShip.m:283
@ kShip_maxEscorts
Definition OOJSShip.m:269
@ kShip_exhaustEmissiveColor
Definition OOJSShip.m:225
@ kShip_weaponRange
Definition OOJSShip.m:326
@ kShip_cloakAutomatic
Definition OOJSShip.m:208
@ kShip_isRock
Definition OOJSShip.m:257
@ kShip_subEntities
Definition OOJSShip.m:308
@ kShip_injectorSpeedFactor
Definition OOJSShip.m:241
@ kShip_laserHeatLevelAft
Definition OOJSShip.m:263
@ kShip_AIPrimaryAggressor
Definition OOJSShip.m:192
@ kShip_escortGroup
Definition OOJSShip.m:223
@ kShip_maxThrust
Definition OOJSShip.m:274
@ kShip_isBoulder
Definition OOJSShip.m:243
@ kShip_displayName
Definition OOJSShip.m:218
@ kShip_scanDescription
Definition OOJSShip.m:294
@ kShip_dataKey
Definition OOJSShip.m:212
@ kShip_reportAIMessages
Definition OOJSShip.m:289
@ kShip_lightsActive
Definition OOJSShip.m:267
@ kShip_desiredSpeed
Definition OOJSShip.m:215
@ kShip_crew
Definition OOJSShip.m:209
@ kShip_isCargo
Definition OOJSShip.m:244
@ kShip_commodity
Definition OOJSShip.m:206
@ kShip_velocity
Definition OOJSShip.m:320
@ kShip_forwardWeapon
Definition OOJSShip.m:229
@ kShip_reactionTime
Definition OOJSShip.m:288
@ kShip_beaconLabel
Definition OOJSShip.m:197
@ kShip_extraCargo
Definition OOJSShip.m:227
@ kShip_heatInsulation
Definition OOJSShip.m:237
@ kShip_vectorForward
Definition OOJSShip.m:317
@ kShip_heading
Definition OOJSShip.m:236
@ kShip_currentWeapon
Definition OOJSShip.m:211
@ kShip_roles
Definition OOJSShip.m:291
@ kShip_weaponPositionForward
Definition OOJSShip.m:323
@ kShip_shipClassName
Definition OOJSShip.m:304
@ kShip_equipment
Definition OOJSShip.m:222
@ kShip_starboardWeapon
Definition OOJSShip.m:307
@ kShip_cargoList
Definition OOJSShip.m:200
@ kShip_name
Definition OOJSShip.m:278
@ kShip_defenseTargets
Definition OOJSShip.m:213
@ kShip_scannerDisplayColor2
Definition OOJSShip.m:296
@ kShip_vectorRight
Definition OOJSShip.m:318
@ kShip_markedForFines
Definition OOJSShip.m:268
@ kShip_AIScript
Definition OOJSShip.m:188
@ kShip_laserHeatLevelPort
Definition OOJSShip.m:265
@ kShip_passengerCount
Definition OOJSShip.m:282
@ kShip_roleWeights
Definition OOJSShip.m:290
@ kShip_weaponPositionAft
Definition OOJSShip.m:322
@ kShip_scriptedMisjump
Definition OOJSShip.m:301
@ kShip_shipUniqueName
Definition OOJSShip.m:305
@ kShip_isBeacon
Definition OOJSShip.m:242
@ kShip_isMine
Definition OOJSShip.m:251
@ kShip_scriptInfo
Definition OOJSShip.m:303
@ kShip_vectorUp
Definition OOJSShip.m:319
@ kShip_isWeapon
Definition OOJSShip.m:261
@ kShip_temperature
Definition OOJSShip.m:313
@ kShip_injectorBurnRate
Definition OOJSShip.m:240
@ kShip_isPirate
Definition OOJSShip.m:254
@ kShip_scannerDisplayColor1
Definition OOJSShip.m:295
@ kShip_bounty
Definition OOJSShip.m:199
@ kShip_hasHyperspaceMotor
Definition OOJSShip.m:234
@ kShip_cargoSpaceCapacity
Definition OOJSShip.m:202
@ kShip_isJamming
Definition OOJSShip.m:249
@ kShip_contracts
Definition OOJSShip.m:205
@ kShip_maxYaw
Definition OOJSShip.m:273
@ kShip_AIFoundTarget
Definition OOJSShip.m:191
@ kShip_isThargoid
Definition OOJSShip.m:258
@ kShip_isTrader
Definition OOJSShip.m:260
@ kShip_portWeapon
Definition OOJSShip.m:285
@ kShip_yaw
Definition OOJSShip.m:328
@ kShip_isPiloted
Definition OOJSShip.m:253
@ kShip_beaconCode
Definition OOJSShip.m:196
@ kShip_savedCoordinates
Definition OOJSShip.m:293
@ kShip_scannerHostileDisplayColor2
Definition OOJSShip.m:298
@ kShip_AI
Definition OOJSShip.m:187
@ kShip_sunGlareFilter
Definition OOJSShip.m:311
@ kShip_weaponPositionStarboard
Definition OOJSShip.m:325
@ kShip_boundingBox
Definition OOJSShip.m:198
@ kShip_scriptedMisjumpRange
Definition OOJSShip.m:302
@ kShip_homeSystem
Definition OOJSShip.m:238
@ kShip_laserHeatLevelStarboard
Definition OOJSShip.m:266
@ kShip_withinStationAegis
Definition OOJSShip.m:327
@ kShip_roll
Definition OOJSShip.m:292
@ kShip_speed
Definition OOJSShip.m:306
@ kShip_cargoSpaceAvailable
Definition OOJSShip.m:201
@ kShip_script
Definition OOJSShip.m:300
@ kShip_laserHeatLevelForward
Definition OOJSShip.m:264
@ kShip_laserHeatLevel
Definition OOJSShip.m:262
@ kShip_aftWeapon
Definition OOJSShip.m:186
@ kShip_exhausts
Definition OOJSShip.m:226
@ kShip_passengerCapacity
Definition OOJSShip.m:281
@ kShip_maxRoll
Definition OOJSShip.m:272
@ kShip_isPirateVictim
Definition OOJSShip.m:255
@ kShip_isDerelict
Definition OOJSShip.m:246
@ kShip_scannerHostileDisplayColor1
Definition OOJSShip.m:297
@ kShip_missileLoadTime
Definition OOJSShip.m:276
@ kShip_energyRechargeRate
Definition OOJSShip.m:220
@ kShip_trackCloseContacts
Definition OOJSShip.m:316
@ kShip_isCloaked
Definition OOJSShip.m:245
@ kShip_missiles
Definition OOJSShip.m:277
@ kShip_destinationSystem
Definition OOJSShip.m:217
@ kShip_isTurret
Definition OOJSShip.m:259
@ kShip_scannerRange
Definition OOJSShip.m:299
@ kShip_isPolice
Definition OOJSShip.m:256
@ kShip_isMinable
Definition OOJSShip.m:250
@ kShip_thrust
Definition OOJSShip.m:314
@ kShip_hasSuspendedAI
Definition OOJSShip.m:235
@ kShip_maxSpeed
Definition OOJSShip.m:271
@ kShip_fuel
Definition OOJSShip.m:230
@ kShip_pitch
Definition OOJSShip.m:284
@ kShip_entityPersonality
Definition OOJSShip.m:221
@ kShip_cruiseSpeed
Definition OOJSShip.m:210
@ kShip_desiredRange
Definition OOJSShip.m:214
@ kShip_dockingInstructions
Definition OOJSShip.m:219
@ kShip_parcels
Definition OOJSShip.m:280
@ kShip_parcelCount
Definition OOJSShip.m:279
@ kShip_flashers
Definition OOJSShip.m:228
@ kShip_subEntityRotation
Definition OOJSShip.m:310
@ kShip_primaryRole
Definition OOJSShip.m:287
void InitOOJSShip(JSContext *context, JSObject *global)
Definition OOJSShip.m:587
static JSBool ShipThrowSpark(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:3704
static JSBool ShipUpdateEscortFormation(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:3339
JSObject * JSShipPrototype(void)
Definition OOJSShip.m:601
static JSBool ShipSetCargo(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:3057
static JSBool ShipPerformFaceDestination(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:3761
static JSBool ShipSetShaders(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:3204
static JSBool ShipSetMaterials(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:3183
static JSBool ShipSendAIMessage(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:2081
static JSBool ShipBroadcastCascadeImminent(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:3543
static JSBool ShipFindNearestStation(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:2998
static JSBool ShipSpawn(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:2334
#define GET_THIS_SHIP(THISENT)
Definition OOJSShip.m:1925
static JSBool ShipGetShaders(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:3527
static JSBool ShipPerformScriptedAttackAI(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:3887
static JSBool ShipHasEquipmentProviding(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:2141
static JSBool ShipExplode(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:2415
static JSBool ShipCommsMessage(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:2498
static JSBool ShipDamageAssessment(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:4104
static JSBool ShipRemove(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:2426
static JSFunctionSpec sShipStaticMethods[]
Definition OOJSShip.m:571
static JSBool ShipClearDefenseTargets(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:3401
static JSBool ShipDealEnergyDamage(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:2365
static JSBool ShipEquipmentStatus(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:2894
static JSBool ShipPerformHold(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:3803
static JSBool ShipFireMissile(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:2979
static JSBool ShipAddCargoEntity(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:2210
static JSBool ShipRequestHelpFromGroup(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:3592
static JSBool ShipBecomeCascadeExplosion(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:3556
static JSBool ShipCanAwardEquipment(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:2566
static JSBool ShipStaticKeysForRole(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:4308
static JSBool ShipNotifyGroupOfWormhole(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:3689
static JSBool ShipSetCargoType(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:3132
static JSBool ShipDockEscorts(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:2125
static JSBool ShipPerformFlee(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:3775
static JSFunctionSpec sShipMethods[]
Definition OOJSShip.m:484
static JSClass sShipClass
Definition OOJSShip.m:156
static JSBool ShipStaticKeys(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:4297
static JSBool ShipDumpCargo(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:2289
static JSBool ShipSetProperty(JSContext *context, JSObject *this, jsid propID, JSBool strict, jsval *value)
Definition OOJSShip.m:1200
static JSBool ShipSetMaterialsInternal(JSContext *context, uintN argc, jsval *vp, ShipEntity *thisEnt, BOOL fromShaders)
Definition OOJSShip.m:3232
static JSBool ShipMarkTargetForFines(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:3633
static JSBool ShipReactToAIMessage(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:2053
static JSPropertySpec sShipProperties[]
Definition OOJSShip.m:332
static JSBool ShipSetEquipmentStatus(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:2799
static JSBool ShipSetScript(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:1932
static JSBool ShipPerformLandOnPlanet(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:3845
static JSBool ShipStaticShipDataForKey(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:4362
static JSBool ShipPerformIdle(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:3817
static JSBool ShipFireECM(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:2530
static JSBool ShipCheckScanner(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:4018
static JSBool ShipStaticRoleIsInCategory(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:4329
static JSObject * sShipPrototype
Definition OOJSShip.m:55
static JSBool ShipPerformIntercept(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:3831
static double ShipThreatAssessmentWeapon(OOWeaponType wt)
Definition OOJSShip.m:4285
static JSBool ShipStaticRoles(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:4350
static JSBool ShipEjectSpecificItem(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:2266
static JSBool ShipSetCrew(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:3088
static JSBool ShipRemoveCollisionException(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:3485
static JSBool ShipAddDefenseTarget(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:3415
static JSBool ShipAddCollisionException(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:3459
static JSBool ShipAwardEquipment(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:2616
static JSBool ShipDeployEscorts(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:2109
static JSBool ShipPerformStop(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:3901
static BOOL RemoveOrExplodeShip(JSContext *context, uintN argc, jsval *vp, BOOL explode)
Definition OOJSShip.m:3352
static JSBool ShipGetMaterials(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:3510
static JSBool ShipRequestDockingInstructions(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:3929
static JSBool ShipSetBounty(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:3029
static JSBool ShipGetSafeCourseToDestination(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:4002
JSClass * JSShipClass(void)
Definition OOJSShip.m:595
static JSBool ShipSetAI(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:1960
static JSBool ShipEnterWormhole(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:3654
static JSBool ShipEjectItem(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:2187
static JSBool ShipPerformScriptedAI(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:3873
static JSBool ShipStaticSetShipDataForKey(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:4382
static JSBool ShipPerformAttack(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:3719
static JSBool ShipRemoveEquipment(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:2709
static JSBool ShipBroadcastDistressMessage(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:3973
static JSBool ShipRunLegacyScriptActions(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:2460
static JSBool ShipGetProperty(JSContext *context, JSObject *this, jsid propID, jsval *value)
Definition OOJSShip.m:607
static JSBool ShipOfferToEscort(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:3570
static JSBool ShipRecallDockingInstructions(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:3951
static JSBool ShipPerformTumble(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:3915
static JSBool ShipAdjustCargo(JSContext *context, uintN argc, jsval *vp)
Definition OOJSShip.m:4054
BOOL JSValueToVector(JSContext *context, jsval value, Vector *outVector) NONNULL_FUNC
Definition OOJSVector.m:259
BOOL HPVectorToJSValue(JSContext *context, HPVector vector, jsval *outValue) NONNULL_FUNC
Definition OOJSVector.m:228
BOOL JSValueToHPVector(JSContext *context, jsval value, HPVector *outVector) NONNULL_FUNC
Definition OOJSVector.m:252
BOOL VectorToJSValue(JSContext *context, Vector vector, jsval *outValue) NONNULL_FUNC
Definition OOJSVector.m:185
id OOJSNativeObjectFromJSValue(JSContext *context, jsval value)
void OOJSReportWarning(JSContext *context, NSString *format,...)
#define OOJS_RETURN(v)
NSString * OOStringFromJSPropertyIDAndSpec(JSContext *context, jsid propID, JSPropertySpec *propertySpec)
#define OOJS_PROP_READWRITE_CB
void OOJSRegisterObjectConverter(JSClass *theClass, OOJSClassConverterCallback converter)
#define OOJS_RETURN_DOUBLE(value)
OOINLINE jsval OOJSValueFromNativeObject(JSContext *context, id object)
id OOJSNativeObjectFromJSObject(JSContext *context, JSObject *object)
#define DEFINE_JS_OBJECT_GETTER(NAME, JSCLASS, JSPROTO, OBJCCLASSNAME)
void OOJSObjectWrapperFinalize(JSContext *context, JSObject *this)
#define OOJS_RETURN_OBJECT(o)
void OOJSReportBadPropertySelector(JSContext *context, JSObject *thisObj, jsid propID, JSPropertySpec *propertySpec)
void OOJSReportWarningForCaller(JSContext *context, NSString *scriptClass, NSString *function, NSString *format,...)
#define OOJS_RETURN_BOOL(v)
void OOJSReportErrorForCaller(JSContext *context, NSString *scriptClass, NSString *function, NSString *format,...)
id OOJSNativeObjectOfClassFromJSValue(JSContext *context, jsval value, Class requiredClass)
NSString * OOStringFromJSValue(JSContext *context, jsval value)
JSBool OOJSUnconstructableConstruct(JSContext *context, uintN argc, jsval *vp)
void OOJSRegisterSubclass(JSClass *subclass, JSClass *superclass)
#define OOJS_RETURN_NULL
void OOJSReportError(JSContext *context, NSString *format,...)
#define OOJS_ARGV
OOINLINE jsval OOJSValueFromBOOL(int b) INLINE_CONST_FUNC
NSString * OOStringFromJSValueEvenIfNull(JSContext *context, jsval value)
void OOJSReportBadPropertyValue(JSContext *context, JSObject *thisObj, jsid propID, JSPropertySpec *propertySpec, jsval value)
id OOJSBasicPrivateObjectConverter(JSContext *context, JSObject *object)
void OOJSReportBadArguments(JSContext *context, NSString *scriptClass, NSString *function, uintN argc, jsval *argv, NSString *message, NSString *expectedArgsDescription)
#define OOJS_RETURN_HPVECTOR(value)
#define OOJS_PROP_READONLY_CB
#define OOJS_RETURN_VOID
#define OOJS_RETURN_INT(v)
#define MAX(A, B)
Definition OOMaths.h:114
#define MIN(A, B)
Definition OOMaths.h:111
unsigned count
return nil
NSString * OOCommodityType
Definition OOTypes.h:106
@ CARGO_NOT_CARGO
Definition OOTypes.h:70
uint32_t OOCargoQuantity
Definition OOTypes.h:176
OOWeaponFacing
Definition OOTypes.h:228
@ WEAPON_FACING_FORWARD
Definition OOTypes.h:229
@ WEAPON_FACING_AFT
Definition OOTypes.h:230
@ WEAPON_FACING_PORT
Definition OOTypes.h:231
@ WEAPON_FACING_STARBOARD
Definition OOTypes.h:232
@ PLAYER_FLEEING_CARGO
#define PLAYER_SHIP_SUBENTITY_TRADE_IN_VALUE
#define HYPERSPEED_FACTOR
#define MIN_HYPERSPEED_FACTOR
#define PLAYER
BOOL isWeaponNone(OOWeaponType weapon)
#define MAX_JUMP_RANGE
Definition ShipEntity.h:107
#define MAX_ESCORTS
Definition ShipEntity.h:74
#define ENTITY_PERSONALITY_MAX
Definition ShipEntity.h:110
#define SHIP_MAX_CABIN_TEMP
Definition ShipEntity.h:67
#define UNIVERSE
Definition Universe.h:833
Definition AI.h:38
void exitStateMachineWithMessage:(NSString *message)
Definition AI.m:296
NSString * name()
Definition AI.m:364
void setState:(NSString *stateName)
Definition AI.m:334
NSString * state()
Definition AI.m:376
BoundingBox boundingBox
Definition Entity.h:145
OOCharacter * characterWithDictionary:(NSDictionary *c_dict)
OOColor * colorWithDescription:(id description)
Definition OOColor.m:127
NSArray * normalizedArray()
Definition OOColor.m:511
GLfloat weaponThreatAssessment()
OOCargoQuantity requiredCargoSpace()
NSString * identifier()
NSDictionary * shaders()
Definition OOMesh.m:617
OOMaterial * materials[kOOMeshMaxMaterials]
Definition OOMesh.h:115
instancetype meshWithName:cacheKey:materialDictionary:shadersDictionary:smooth:shaderMacros:shaderBindingTarget:(NSString *name,[cacheKey] NSString *cacheKey,[materialDictionary] NSDictionary *materialDict,[shadersDictionary] NSDictionary *shadersDict,[smooth] BOOL smooth,[shaderMacros] NSDictionary *macros,[shaderBindingTarget] id< OOWeakReferenceSupport > object)
Definition OOMesh.m:233
NSArray * sortedRoles()
Definition OORoleSet.m:181
NSDictionary * rolesAndProbabilities()
Definition OORoleSet.m:187
NSArray * memberArrayExcludingLeader()
NSArray * shipRoles()
NSArray * shipKeysWithRole:(NSString *role)
OOShipRegistry * sharedRegistry()
NSDictionary * shipInfoForKey:(NSString *key)
NSArray * shipKeys()
void setShipInfoForKey:with:(NSString *key,[with] NSDictionary *newShipData)
BOOL addEquipmentItem:withValidation:inContext:(NSString *equipmentKey, [withValidation] BOOL validateAddition, [inContext] NSString *context)
BOOL changePassengerBerths:(int addRemove)
OOCreditsQuantity removeMissiles()
BOOL setWeaponMount:toWeapon:inContext:(OOWeaponFacing facing,[toWeapon] NSString *eqKey,[inContext] NSString *context)
void runUnsanitizedScriptActions:allowingAIMethods:withContextName:forTarget:(NSArray *unsanitizedActions,[allowingAIMethods] BOOL allowAIMethods,[withContextName] NSString *contextName,[forTarget] ShipEntity *target)
void setScriptTarget:(ShipEntity *ship)
BOOL mountMissileWithRole:(NSString *role)
NSDictionary * materialDefaults()
void setMaxFlightYaw:(GLfloat new)
void setBounty:withReasonAsString:(OOCreditsQuantity amount,[withReasonAsString] NSString *reason)
void setMesh:(OOMesh *mesh)
void setScannerDisplayColor1:(OOColor *color1)
void setExhaustEmissiveColor:(OOColor *color)
void setAfterburnerFactor:(GLfloat new)
void dealEnergyDamage:atRange:withBias:(GLfloat baseDamage,[atRange] GLfloat range,[withBias] GLfloat velocityBias)
OOEquipmentType * selectMissile()
NSArray * spawnShipsWithRole:count:(NSString *role,[count] NSUInteger count)
void setBounty:withReason:(OOCreditsQuantity amount,[withReason] OOLegalStatusReason reason)
BOOL markForFines()
float maxThrust()
void setPrimaryAggressor:(Entity *targetEntity)
void setDesiredSpeed:(double amount)
NSUInteger defenseTargetCount()
NSString * beaconLabel()
void setEnergyRechargeRate:(GLfloat new)
NSDictionary * shipInfoDictionary()
void removeEquipmentItem:(NSString *equipmentKey)
NSUInteger passengerCapacity()
NSDictionary * scriptInfo
Definition ShipEntity.h:431
OOScript * shipScript()
void setFuel:(OOFuelQuantity amount)
NSArray * contractListForScripting()
OOWeaponFacing currentWeaponFacing
Definition ShipEntity.h:312
void setCoordinate:(HPVector coord)
NSDictionary * dockingInstructions
Definition ShipEntity.h:227
void setMaxFlightRoll:(GLfloat new)
void setCargoFlag:(OOCargoFlag flag)
BOOL addEquipmentItem:withValidation:inContext:(NSString *equipmentKey,[withValidation] BOOL validateAddition,[inContext] NSString *context)
void setThrust:(double amount)
void setDestinationSystem:(OOSystemID s)
void setMaxAvailableCargoSpace:(OOCargoQuantity new)
OOShipGroup * escortGroup()
void switchLightsOn()
void setScannerDisplayColorHostile1:(OOColor *color1)
void setAIScriptWakeTime:(OOTimeAbsolute t)
NSString * shipDataKey()
OORoleSet * roleSet
Definition ShipEntity.h:332
void setGroup:(OOShipGroup *group)
NSString * primaryRole
Definition ShipEntity.h:333
NSString * beaconCode()
void setEscortDestination:(HPVector dest)
OOShipGroup * group()
OOCargoQuantity availableCargoSpace()
void setDisplayName:(NSString *inName)
OOColor * scannerDisplayColor2()
void setAccuracy:(GLfloat new_accuracy)
void setAutoCloak:(BOOL automatic)
void setAfterburnerRate:(GLfloat new)
NSString * name
Definition ShipEntity.h:327
NSArray * portWeaponOffset
Definition ShipEntity.h:395
NSString * shipClassName
Definition ShipEntity.h:329
Entity * primaryAggressor()
void setPrimaryRole:(NSString *role)
void validateDefenseTargets()
NSArray * equipmentListForScripting()
void deployEscorts()
BoundingBox totalBoundingBox
Definition ShipEntity.h:213
OOCreditsQuantity removeMissiles()
void setShipScript:(NSString *script_name)
BOOL hasEquipmentItem:(id equipmentKeys)
NSEnumerator * defenseTargetEnumerator()
BOOL performHyperSpaceToSpecificSystem:(OOSystemID systemID)
NSArray * starboardWeaponOffset
Definition ShipEntity.h:396
void setHeatInsulation:(GLfloat value)
void setScannerDisplayColor2:(OOColor *color2)
NSArray * parcelListForScripting()
BOOL setWeaponMount:toWeapon:(OOWeaponFacing facing,[toWeapon] NSString *eqKey)
NSArray * cargoListForScripting()
NSEnumerator * flasherEnumerator()
Entity * proximityAlert()
void scoopUpProcess:processEvents:processMessages:(ShipEntity *other,[processEvents] BOOL proc_events,[processMessages] BOOL proc_messages)
void setTargetForScript:(ShipEntity *target)
ShipEntity * fireMissile()
void setName:(NSString *inName)
NSString * shipUniqueName
Definition ShipEntity.h:328
NSString * scanDescriptionForScripting()
void setBeaconCode:(NSString *bcode)
void setScanDescription:(NSString *inName)
void setAITo:(NSString *aiString)
void sendMessage:toShip:withUnpilotedOverride:(NSString *message_text,[toShip] ShipEntity *other_ship,[withUnpilotedOverride] BOOL unpilotedOverride)
BOOL canAddEquipment:inContext:(NSString *equipmentKey,[inContext] NSString *context)
void commsMessage:withUnpilotedOverride:(NSString *valueString,[withUnpilotedOverride] BOOL unpilotedOverride)
OOColor * scannerDisplayColorHostile2()
NSArray * missilesList()
void switchLightsOff()
void dockEscorts()
NSEnumerator * exhaustEnumerator()
void removeCollisionException:(ShipEntity *ship)
void setMaxFlightPitch:(GLfloat new)
NSArray * aftWeaponOffset
Definition ShipEntity.h:394
void addCollisionException:(ShipEntity *ship)
void setReactionTime:(float newReactionTime)
NSArray * forwardWeaponOffset
Definition ShipEntity.h:393
NSArray * passengerListForScripting()
NSArray * collisionExceptions()
void setScriptedMisjumpRange:(GLfloat newValue)
OOColor * scannerDisplayColorHostile1()
void setEntityPersonalityInt:(uint16_t value)
void setReportAIMessages:(BOOL yn)
OOColor * exhaustEmissiveColor()
void setTrackCloseContacts:(BOOL value)
void setSubEntityRotationalVelocity:(Quaternion rv)
void clearSubEntities()
void setMaxFlightSpeed:(GLfloat new)
OOCargoQuantity maxAvailableCargoSpace()
void setTemperature:(GLfloat value)
BOOL setUpSubEntities()
Definition ShipEntity.m:855
void setScriptedMisjump:(BOOL newValue)
ShipEntity * fireMissileWithIdentifier:andTarget:(NSString *identifier,[andTarget] Entity *target)
void setTotalVelocity:(Vector vel)
void setSunGlareFilter:(GLfloat newValue)
void setCloaked:(BOOL cloak)
void setIsBoulder:(BOOL flag)
OOEquipmentType * weaponTypeForFacing:strict:(OOWeaponFacing facing,[strict] BOOL strict)
NSArray * crewForScripting()
void setCrew:(NSArray *crewArray)
void setCommodityForPod:andAmount:(OOCommodityType co_type,[andAmount] OOCargoQuantity co_amount)
void setMaxEscortCount:(uint8_t newCount)
void doScriptEvent:withArgument:(jsid message,[withArgument] id argument)
void switchAITo:(NSString *aiString)
OOMesh * mesh()
void setBeaconLabel:(NSString *blabel)
void reactToAIMessage:context:(NSString *message,[context] NSString *debugContext)
void setFoundTarget:(Entity *targetEntity)
void setScannerDisplayColorHostile2:(OOColor *color2)
void sendAIMessage:(NSString *message)
void setMissileLoadTime:(OOTimeDelta newMissileLoadTime)
OOCommodityType commodityType()
NSString * displayName
Definition ShipEntity.h:330
NSUInteger countEquipmentItem:(NSString *eqkey)
void setDesiredRange:(double amount)
BOOL hasOneEquipmentItem:includeMissiles:whileLoading:(NSString *itemKey,[includeMissiles] BOOL includeMissiles,[whileLoading] BOOL loading)
void removeScript()
Entity * foundTarget()
OOColor * scannerDisplayColor1()
OOScript * shipAIScript()
void setHomeSystem:(OOSystemID s)
void setHyperspaceSpinTime:(float new)
void setShipUniqueName:(NSString *inName)
void setMaxThrust:(GLfloat new)
void setShipClassName:(NSString *inName)
void acceptPatrolReportFrom:(ShipEntity *patrol_ship)
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque