Oolite 1.91.0.7708-250910-30bbc4c
Loading...
Searching...
No Matches
OOJSEquipmentInfo.m
Go to the documentation of this file.
1/*
2
3OOJSEquipmentInfo.m
4
5
6Oolite
7Copyright (C) 2004-2013 Giles C Williams and contributors
8
9This program is free software; you can redistribute it and/or
10modify it under the terms of the GNU General Public License
11as published by the Free Software Foundation; either version 2
12of the License, or (at your option) any later version.
13
14This program is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
20along with this program; if not, write to the Free Software
21Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22MA 02110-1301, USA.
23
24*/
25
26#import "OOJSEquipmentInfo.h"
28#import "OOEquipmentType.h"
29#import "OOJSPlayer.h"
30#import "OODebugStandards.h"
31
32static JSObject *sEquipmentInfoPrototype;
33
34
35static JSBool EquipmentInfoGetProperty(JSContext *context, JSObject *this, jsid propID, jsval *value);
36static JSBool EquipmentInfoSetProperty(JSContext *context, JSObject *this, jsid propID, JSBool strict, jsval *value);
37
38static JSBool EquipmentInfoGetAllEqipment(JSContext *context, JSObject *this, jsid propID, jsval *value);
39
40
41// Methods
42static JSBool EquipmentInfoStaticInfoForKey(JSContext *context, uintN argc, jsval *vp);
43
44
45enum
46{
47 // Property IDs
65 kEquipmentInfo_isExternalStore, // is missile or mine
82 kEquipmentInfo_scriptInfo, // arbitrary data for scripts, dictionary, read-only
86};
87
88
89static JSPropertySpec sEquipmentInfoProperties[] =
90{
91 // JS name ID flags
118 { "requiresCleanLegalRecord", kEquipmentInfo_requiresCleanLegalRecord, OOJS_PROP_READONLY_CB },
121 { "requiresFreePassengerBerth", kEquipmentInfo_requiresFreePassengerBerth, OOJS_PROP_READONLY_CB },
124 { "requiresNonCleanLegalRecord", kEquipmentInfo_requiresNonCleanLegalRecord, OOJS_PROP_READONLY_CB },
130 { 0 }
131};
132
133
134static JSPropertySpec sEquipmentInfoStaticProperties[] =
135{
137 { 0 }
138};
139
140
141static JSFunctionSpec sEquipmentInfoMethods[] =
142{
143 // JS name Function min args
144 { "toString", OOJSObjectWrapperToString, 0 },
145 { 0 }
146};
147
148
149static JSFunctionSpec sEquipmentInfoStaticMethods[] =
150{
151 // JS name Function min args
152 { "infoForKey", EquipmentInfoStaticInfoForKey, 0 },
153 { 0 }
154};
155
156
157static JSClass sEquipmentInfoClass =
158{
159 "EquipmentInfo",
160 JSCLASS_HAS_PRIVATE,
161
162 JS_PropertyStub, // addProperty
163 JS_PropertyStub, // delProperty
164 EquipmentInfoGetProperty, // getProperty
165 EquipmentInfoSetProperty, // setProperty
166 JS_EnumerateStub, // enumerate
167 JS_ResolveStub, // resolve
168 JS_ConvertStub, // convert
169 OOJSObjectWrapperFinalize, // finalize
170 JSCLASS_NO_OPTIONAL_MEMBERS
171};
172
173
175
176
177// *** Public ***
178
185
186
187OOEquipmentType *JSValueToEquipmentType(JSContext *context, jsval value)
188{
190
191 if (JSVAL_IS_OBJECT(value))
192 {
193 JSObject *object = JSVAL_TO_OBJECT(value);
194 if (JS_InstanceOf(context, JSVAL_TO_OBJECT(value), &sEquipmentInfoClass, NULL))
195 {
196 return (OOEquipmentType *)JS_GetPrivate(context, object);
197 }
198 }
199
200 NSString *string = OOStringFromJSValue(context, value);
201 if (string != nil) return [OOEquipmentType equipmentTypeWithIdentifier:string];
202 return nil;
203
205}
206
207
208NSString *JSValueToEquipmentKey(JSContext *context, jsval value)
209{
210 return [JSValueToEquipmentType(context, value) identifier];
211}
212
213
214NSString *JSValueToEquipmentKeyRelaxed(JSContext *context, jsval value, BOOL *outExists)
215{
217
218 NSString *result = nil;
219 BOOL exists = NO;
220 id objValue = OOJSNativeObjectFromJSValue(context, value);
221
222 if ([objValue isKindOfClass:[OOEquipmentType class]])
223 {
224 result = [objValue identifier];
225 exists = YES;
226 }
227 else if ([objValue isKindOfClass:[NSString class]])
228 {
229 /* To enforce deliberate backwards incompatibility, reject strings
230 ending with _DAMAGED unless someone actually named an equip that
231 way.
232 */
233 exists = [OOEquipmentType equipmentTypeWithIdentifier:objValue] != nil;
234 if (exists || ![objValue hasSuffix:@"_DAMAGED"])
235 {
236 result = objValue;
237 }
238 }
239
240 if (outExists != NULL) *outExists = exists;
241 return result;
242
244}
245
246
247// *** Implementation stuff ***
248
249static JSBool EquipmentInfoGetProperty(JSContext *context, JSObject *this, jsid propID, jsval *value)
250{
251 if (!JSID_IS_INT(propID)) return YES;
252
253 OOJS_NATIVE_ENTER(context)
254
255 OOEquipmentType *eqType = nil;
256 id result = nil;
257 NSUInteger inst_time;
258
259 if (EXPECT_NOT(!JSEquipmentInfoGetEquipmentType(context, this, &eqType))) return NO;
260
261 switch (JSID_TO_INT(propID))
262 {
264 result = [eqType identifier];
265 break;
266
268 result = [eqType name];
269 break;
270
272 if ([[eqType identifier] isEqual:@"EQ_FUEL"])
273 {
274 return JS_NewNumberValue(context, (PLAYER_MAX_FUEL - [OOPlayerForScripting() fuel]) * [eqType price] * [OOPlayerForScripting() fuelChargeRate], value);
275 }
276 else if ([[eqType identifier] isEqual:@"EQ_RENOVATION"])
277 {
278 return JS_NewNumberValue(context, [OOPlayerForScripting() renovationCosts], value);
279 }
280 else
281 {
282 return JS_NewNumberValue(context, [OOPlayerForScripting() adjustPriceByScriptForEqKey:[eqType identifier] withCurrent:[eqType price]], value);
283 }
285 *value = OOJSValueFromBOOL([eqType canCarryMultiple]);
286 return YES;
287
289 *value = OOJSValueFromBOOL([eqType canBeDamaged]);
290 return YES;
291
293 result = [eqType descriptiveText];
294 break;
295
297 return JS_NewNumberValue(context, [eqType damageProbability], value);
298
300 result = [[eqType displayColor] normalizedArray];
301 break;
302
304 *value = OOJSValueFromBOOL([eqType fastAffinityDefensive]);
305 return YES;
306
308 *value = OOJSValueFromBOOL([eqType fastAffinityOffensive]);
309 return YES;
310
312 result = [eqType defaultActivateKey];
313 break;
314
316 result = [eqType defaultModeKey];
317 break;
318
320 *value = INT_TO_JSVAL((int32_t)[eqType techLevel]);
321 return YES;
322
324 *value = INT_TO_JSVAL((int32_t)[eqType effectiveTechLevel]);
325 return YES;
326
328 return JS_NewNumberValue(context, [eqType price], value);
329
331 result = [eqType providesForScripting];
332 break;
333
335 inst_time = [eqType installTime];
336 if (inst_time == 0)
337 {
338 inst_time = [eqType price] + 600;
339 }
340 *value = INT_TO_JSVAL((int32_t)inst_time);
341 return YES;
342
344 *value = OOJSValueFromBOOL([eqType isAvailableToAll]);
345 return YES;
346
348 *value = OOJSValueFromBOOL([eqType isAvailableToNPCs]);
349 return YES;
350
352 *value = OOJSValueFromBOOL([eqType isAvailableToPlayer]);
353 return YES;
354
356 *value = INT_TO_JSVAL((int32_t)[eqType repairTime]);
357 return YES;
358
360 *value = OOJSValueFromBOOL([eqType requiresEmptyPylon]);
361 return YES;
362
364 *value = OOJSValueFromBOOL([eqType requiresMountedPylon]);
365 return YES;
366
368 *value = OOJSValueFromBOOL([eqType requiresCleanLegalRecord]);
369 return YES;
370
372 *value = OOJSValueFromBOOL([eqType requiresNonCleanLegalRecord]);
373 return YES;
374
376 *value = OOJSValueFromBOOL([eqType requiresFreePassengerBerth]);
377 return YES;
378
380 *value = OOJSValueFromBOOL([eqType requiresFullFuel]);
381 return YES;
382
384 *value = OOJSValueFromBOOL([eqType requiresNonFullFuel]);
385 return YES;
386
388 *value = OOJSValueFromBOOL([eqType isMissileOrMine]);
389 return YES;
390
392 *value = OOJSValueFromBOOL([eqType isPortableBetweenShips]);
393 return YES;
394
396 *value = OOJSValueFromBOOL([eqType isVisible]);
397 return YES;
398
400 *value = INT_TO_JSVAL((int32_t)[eqType requiredCargoSpace]);
401 return YES;
402
404 result = [[eqType requiresEquipment] allObjects];
405 break;
406
408 result = [[eqType requiresAnyEquipment] allObjects];
409 break;
410
412 result = [[eqType incompatibleEquipment] allObjects];
413 break;
414
416 result = [eqType scriptInfo];
417 if (result == nil) result = [NSDictionary dictionary]; // empty rather than null
418 break;
419
421 result = [eqType scriptName];
422 if (result == nil) result = @"";
423 break;
424
426 result = [eqType weaponInfo];
427 if (result == nil) result = [NSDictionary dictionary]; // empty rather than null
428 break;
429
430 default:
432 return NO;
433 }
434
435 *value = OOJSValueFromNativeObject(context, result);
436 return YES;
437
439}
440
441
442static JSBool EquipmentInfoSetProperty(JSContext *context, JSObject *this, jsid propID, JSBool strict, jsval *value)
443{
444 if (!JSID_IS_INT(propID)) return YES;
445
446 OOJS_NATIVE_ENTER(context)
447
448 OOEquipmentType *eqType = nil;
449 int32 iValue;
450 OOColor *colorForScript = nil;
451
452 if (EXPECT_NOT(!JSEquipmentInfoGetEquipmentType(context, this, &eqType))) return NO;
453
454 switch (JSID_TO_INT(propID))
455 {
457 colorForScript = [OOColor colorWithDescription:OOJSNativeObjectFromJSValue(context, *value)];
458 if (colorForScript != nil || JSVAL_IS_NULL(*value))
459 {
460 [eqType setDisplayColor:colorForScript];
461 return YES;
462 }
463 break;
465 OOStandardsDeprecated([NSString stringWithFormat:@"TL99 for variable tech level is deprecated for %@",[eqType identifier]]);
466 if (!OOEnforceStandards() && [eqType techLevel] == kOOVariableTechLevel)
467 {
468 if (JSVAL_IS_NULL(*value))
469 {
470 // reset mission variable
472 forKey:[@"mission_TL_FOR_" stringByAppendingString:[eqType identifier]]];
473 return YES;
474 }
475 if (JS_ValueToInt32(context, *value, &iValue))
476 {
477 if (iValue < 0) iValue = 0;
478 if (15 < iValue && iValue != kOOVariableTechLevel) iValue = 15;
479 [OOPlayerForScripting() setMissionVariable:[NSString stringWithFormat:@"%u", iValue]
480 forKey:[@"mission_TL_FOR_" stringByAppendingString:[eqType identifier]]];
481 return YES;
482 }
483 }
484 else
485 {
486 OOJSReportWarning(context, @"Cannot modify effective tech level for %@, because its base tech level is not 99.", [eqType identifier]);
487 return YES;
488 }
489 break;
490
491 default:
493 return NO;
494 }
495
496 OOJSReportBadPropertyValue(context, this, propID, sEquipmentInfoProperties, *value);
497 return NO;
498
500}
501
502
503static JSBool EquipmentInfoGetAllEqipment(JSContext *context, JSObject *this, jsid propID, jsval *value)
504{
505 OOJS_NATIVE_ENTER(context)
506
507 *value = OOJSValueFromNativeObject(context, [OOEquipmentType allEquipmentTypes]);
508 return YES;
509
511}
512
513
514@implementation OOEquipmentType (OOJavaScriptExtensions)
515
516- (jsval) oo_jsValueInContext:(JSContext *)context
517{
518 if (_jsSelf == NULL)
519 {
520 _jsSelf = JS_NewObject(context, &sEquipmentInfoClass, sEquipmentInfoPrototype, NULL);
521 if (_jsSelf != NULL)
522 {
523 if (!JS_SetPrivate(context, _jsSelf, [self retain])) _jsSelf = NULL;
524 }
525 }
526
527 return OBJECT_TO_JSVAL(_jsSelf);
528}
529
530
531- (NSString *) oo_jsClassName
532{
533 return @"EquipmentInfo";
534}
535
536
537- (void) oo_clearJSSelf:(JSObject *)selfVal
538{
539 if (_jsSelf == selfVal) _jsSelf = NULL;
540}
541
542@end
543
544
545// *** Static methods ***
546
547// infoForKey(key : String): EquipmentInfo
548static JSBool EquipmentInfoStaticInfoForKey(JSContext *context, uintN argc, jsval *vp)
549{
550 OOJS_NATIVE_ENTER(context)
551
552 NSString *key = nil;
553
554 if (argc > 0) key = OOStringFromJSValue(context, OOJS_ARGV[0]);
555 if (key == nil)
556 {
557 OOJSReportBadArguments(context, @"EquipmentInfo", @"infoForKey", MIN(argc, 1U), OOJS_ARGV, nil, @"string");
558 return NO;
559 }
560
561 OOJS_RETURN_OBJECT([OOEquipmentType equipmentTypeWithIdentifier:key]);
562
564}
void OOStandardsDeprecated(NSString *message)
BOOL OOEnforceStandards(void)
#define EXPECT_NOT(x)
#define OOJS_PROFILE_EXIT
#define OOJS_NATIVE_ENTER(cx)
#define OOJS_NATIVE_EXIT
#define OOJS_PROFILE_ENTER
static JSBool EquipmentInfoGetProperty(JSContext *context, JSObject *this, jsid propID, jsval *value)
OOEquipmentType * JSValueToEquipmentType(JSContext *context, jsval value)
static JSObject * sEquipmentInfoPrototype
static JSClass sEquipmentInfoClass
static JSFunctionSpec sEquipmentInfoMethods[]
@ kEquipmentInfo_defaultActivateKey
@ kEquipmentInfo_installationTime
@ kEquipmentInfo_requiresAnyEquipment
@ kEquipmentInfo_canCarryMultiple
@ kEquipmentInfo_calculatedPrice
@ kEquipmentInfo_weaponInfo
@ kEquipmentInfo_effectiveTechLevel
@ kEquipmentInfo_requiresEquipment
@ kEquipmentInfo_equipmentKey
@ kEquipmentInfo_displayColor
@ kEquipmentInfo_isAvailableToAll
@ kEquipmentInfo_requiresFreePassengerBerth
@ kEquipmentInfo_damageProbability
@ kEquipmentInfo_requiresCleanLegalRecord
@ kEquipmentInfo_isVisible
@ kEquipmentInfo_isPortableBetweenShips
@ kEquipmentInfo_defaultModeKey
@ kEquipmentInfo_name
@ kEquipmentInfo_price
@ kEquipmentInfo_fastAffinityDefensive
@ kEquipmentInfo_isExternalStore
@ kEquipmentInfo_isAvailableToPlayer
@ kEquipmentInfo_canBeDamaged
@ kEquipmentInfo_description
@ kEquipmentInfo_techLevel
@ kEquipmentInfo_scriptName
@ kEquipmentInfo_scriptInfo
@ kEquipmentInfo_repairTime
@ kEquipmentInfo_provides
@ kEquipmentInfo_requiresFullFuel
@ kEquipmentInfo_requiresNonFullFuel
@ kEquipmentInfo_requiredCargoSpace
@ kEquipmentInfo_isAvailableToNPCs
@ kEquipmentInfo_incompatibleEquipment
@ kEquipmentInfo_requiresNonCleanLegalRecord
@ kEquipmentInfo_requiresMountedPylon
@ kEquipmentInfo_requiresEmptyPylon
@ kEquipmentInfo_fastAffinityOffensive
static JSBool EquipmentInfoSetProperty(JSContext *context, JSObject *this, jsid propID, JSBool strict, jsval *value)
void InitOOJSEquipmentInfo(JSContext *context, JSObject *global)
static JSFunctionSpec sEquipmentInfoStaticMethods[]
static JSPropertySpec sEquipmentInfoProperties[]
static JSBool EquipmentInfoStaticInfoForKey(JSContext *context, uintN argc, jsval *vp)
static JSBool EquipmentInfoGetAllEqipment(JSContext *context, JSObject *this, jsid propID, jsval *value)
NSString * JSValueToEquipmentKeyRelaxed(JSContext *context, jsval value, BOOL *outExists)
NSString * JSValueToEquipmentKey(JSContext *context, jsval value)
static JSPropertySpec sEquipmentInfoStaticProperties[]
PlayerEntity * OOPlayerForScripting(void)
Definition OOJSPlayer.m:191
id OOJSNativeObjectFromJSValue(JSContext *context, jsval value)
void OOJSReportWarning(JSContext *context, NSString *format,...)
JSBool OOJSObjectWrapperToString(JSContext *context, uintN argc, jsval *vp)
#define OOJS_PROP_READWRITE_CB
void OOJSRegisterObjectConverter(JSClass *theClass, OOJSClassConverterCallback converter)
OOINLINE jsval OOJSValueFromNativeObject(JSContext *context, id 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)
NSString * OOStringFromJSValue(JSContext *context, jsval value)
JSBool OOJSUnconstructableConstruct(JSContext *context, uintN argc, jsval *vp)
#define OOJS_ARGV
OOINLINE jsval OOJSValueFromBOOL(int b) INLINE_CONST_FUNC
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_PROP_READONLY_CB
#define MIN(A, B)
Definition OOMaths.h:111
return nil
@ kOOVariableTechLevel
Definition OOTypes.h:202
#define PLAYER_MAX_FUEL
OOColor * colorWithDescription:(id description)
Definition OOColor.m:127
NSArray * normalizedArray()
Definition OOColor.m:511
void setDisplayColor:(OOColor *newColor)
NSDictionary * weaponInfo()
NSString * scriptName()
NSSet * incompatibleEquipment()
NSDictionary * scriptInfo()
OOColor * displayColor()
NSArray * defaultActivateKey()
NSArray * defaultModeKey()
NSSet * requiresEquipment()
NSSet * requiresAnyEquipment()
OOEquipmentType * equipmentTypeWithIdentifier:(NSString *identifier)
OOCreditsQuantity price()
NSUInteger installTime()
NSArray * providesForScripting()
NSString * identifier()
NSString * descriptiveText()
void setMissionVariable:forKey:(NSString *value,[forKey] NSString *key)