Oolite 1.91.0.7604-240417-a536cbe
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
64 kEquipmentInfo_isExternalStore, // is missile or mine
80 kEquipmentInfo_scriptInfo, // arbitrary data for scripts, dictionary, read-only
84};
85
86
87static JSPropertySpec sEquipmentInfoProperties[] =
88{
89 // JS name ID flags
114 { "requiresCleanLegalRecord", kEquipmentInfo_requiresCleanLegalRecord, OOJS_PROP_READONLY_CB },
117 { "requiresFreePassengerBerth", kEquipmentInfo_requiresFreePassengerBerth, OOJS_PROP_READONLY_CB },
120 { "requiresNonCleanLegalRecord", kEquipmentInfo_requiresNonCleanLegalRecord, OOJS_PROP_READONLY_CB },
126 { 0 }
127};
128
129
130static JSPropertySpec sEquipmentInfoStaticProperties[] =
131{
133 { 0 }
134};
135
136
137static JSFunctionSpec sEquipmentInfoMethods[] =
138{
139 // JS name Function min args
140 { "toString", OOJSObjectWrapperToString, 0 },
141 { 0 }
142};
143
144
145static JSFunctionSpec sEquipmentInfoStaticMethods[] =
146{
147 // JS name Function min args
148 { "infoForKey", EquipmentInfoStaticInfoForKey, 0 },
149 { 0 }
150};
151
152
153static JSClass sEquipmentInfoClass =
154{
155 "EquipmentInfo",
156 JSCLASS_HAS_PRIVATE,
157
158 JS_PropertyStub, // addProperty
159 JS_PropertyStub, // delProperty
160 EquipmentInfoGetProperty, // getProperty
161 EquipmentInfoSetProperty, // setProperty
162 JS_EnumerateStub, // enumerate
163 JS_ResolveStub, // resolve
164 JS_ConvertStub, // convert
165 OOJSObjectWrapperFinalize, // finalize
166 JSCLASS_NO_OPTIONAL_MEMBERS
167};
168
169
171
172
173// *** Public ***
174
181
182
183OOEquipmentType *JSValueToEquipmentType(JSContext *context, jsval value)
184{
186
187 if (JSVAL_IS_OBJECT(value))
188 {
189 JSObject *object = JSVAL_TO_OBJECT(value);
190 if (JS_InstanceOf(context, JSVAL_TO_OBJECT(value), &sEquipmentInfoClass, NULL))
191 {
192 return (OOEquipmentType *)JS_GetPrivate(context, object);
193 }
194 }
195
196 NSString *string = OOStringFromJSValue(context, value);
197 if (string != nil) return [OOEquipmentType equipmentTypeWithIdentifier:string];
198 return nil;
199
201}
202
203
204NSString *JSValueToEquipmentKey(JSContext *context, jsval value)
205{
206 return [JSValueToEquipmentType(context, value) identifier];
207}
208
209
210NSString *JSValueToEquipmentKeyRelaxed(JSContext *context, jsval value, BOOL *outExists)
211{
213
214 NSString *result = nil;
215 BOOL exists = NO;
216 id objValue = OOJSNativeObjectFromJSValue(context, value);
217
218 if ([objValue isKindOfClass:[OOEquipmentType class]])
219 {
220 result = [objValue identifier];
221 exists = YES;
222 }
223 else if ([objValue isKindOfClass:[NSString class]])
224 {
225 /* To enforce deliberate backwards incompatibility, reject strings
226 ending with _DAMAGED unless someone actually named an equip that
227 way.
228 */
229 exists = [OOEquipmentType equipmentTypeWithIdentifier:objValue] != nil;
230 if (exists || ![objValue hasSuffix:@"_DAMAGED"])
231 {
232 result = objValue;
233 }
234 }
235
236 if (outExists != NULL) *outExists = exists;
237 return result;
238
240}
241
242
243// *** Implementation stuff ***
244
245static JSBool EquipmentInfoGetProperty(JSContext *context, JSObject *this, jsid propID, jsval *value)
246{
247 if (!JSID_IS_INT(propID)) return YES;
248
249 OOJS_NATIVE_ENTER(context)
250
251 OOEquipmentType *eqType = nil;
252 id result = nil;
253
254 if (EXPECT_NOT(!JSEquipmentInfoGetEquipmentType(context, this, &eqType))) return NO;
255
256 switch (JSID_TO_INT(propID))
257 {
259 result = [eqType identifier];
260 break;
261
263 result = [eqType name];
264 break;
265
267 if ([[eqType identifier] isEqual:@"EQ_FUEL"])
268 {
269 return JS_NewNumberValue(context, (PLAYER_MAX_FUEL - [OOPlayerForScripting() fuel]) * [eqType price] * [OOPlayerForScripting() fuelChargeRate], value);
270 }
271 else if ([[eqType identifier] isEqual:@"EQ_RENOVATION"])
272 {
273 return JS_NewNumberValue(context, [OOPlayerForScripting() renovationCosts], value);
274 }
275 else
276 {
277 return JS_NewNumberValue(context, [OOPlayerForScripting() adjustPriceByScriptForEqKey:[eqType identifier] withCurrent:[eqType price]], value);
278 }
280 *value = OOJSValueFromBOOL([eqType canCarryMultiple]);
281 return YES;
282
284 *value = OOJSValueFromBOOL([eqType canBeDamaged]);
285 return YES;
286
288 result = [eqType descriptiveText];
289 break;
290
292 return JS_NewNumberValue(context, [eqType damageProbability], value);
293
295 result = [[eqType displayColor] normalizedArray];
296 break;
297
299 *value = OOJSValueFromBOOL([eqType fastAffinityDefensive]);
300 return YES;
301
303 *value = OOJSValueFromBOOL([eqType fastAffinityOffensive]);
304 return YES;
305
307 result = [eqType defaultActivateKey];
308 break;
309
311 result = [eqType defaultModeKey];
312 break;
313
315 *value = INT_TO_JSVAL((int32_t)[eqType techLevel]);
316 return YES;
317
319 *value = INT_TO_JSVAL((int32_t)[eqType effectiveTechLevel]);
320 return YES;
321
323 return JS_NewNumberValue(context, [eqType price], value);
324
326 result = [eqType providesForScripting];
327 break;
328
330 *value = OOJSValueFromBOOL([eqType isAvailableToAll]);
331 return YES;
332
334 *value = OOJSValueFromBOOL([eqType isAvailableToNPCs]);
335 return YES;
336
338 *value = OOJSValueFromBOOL([eqType isAvailableToPlayer]);
339 return YES;
340
342 *value = OOJSValueFromBOOL([eqType requiresEmptyPylon]);
343 return YES;
344
346 *value = OOJSValueFromBOOL([eqType requiresMountedPylon]);
347 return YES;
348
350 *value = OOJSValueFromBOOL([eqType requiresCleanLegalRecord]);
351 return YES;
352
354 *value = OOJSValueFromBOOL([eqType requiresNonCleanLegalRecord]);
355 return YES;
356
358 *value = OOJSValueFromBOOL([eqType requiresFreePassengerBerth]);
359 return YES;
360
362 *value = OOJSValueFromBOOL([eqType requiresFullFuel]);
363 return YES;
364
366 *value = OOJSValueFromBOOL([eqType requiresNonFullFuel]);
367 return YES;
368
370 *value = OOJSValueFromBOOL([eqType isMissileOrMine]);
371 return YES;
372
374 *value = OOJSValueFromBOOL([eqType isPortableBetweenShips]);
375 return YES;
376
378 *value = OOJSValueFromBOOL([eqType isVisible]);
379 return YES;
380
382 *value = INT_TO_JSVAL((int32_t)[eqType requiredCargoSpace]);
383 return YES;
384
386 result = [[eqType requiresEquipment] allObjects];
387 break;
388
390 result = [[eqType requiresAnyEquipment] allObjects];
391 break;
392
394 result = [[eqType incompatibleEquipment] allObjects];
395 break;
396
398 result = [eqType scriptInfo];
399 if (result == nil) result = [NSDictionary dictionary]; // empty rather than null
400 break;
401
403 result = [eqType scriptName];
404 if (result == nil) result = @"";
405 break;
406
408 result = [eqType weaponInfo];
409 if (result == nil) result = [NSDictionary dictionary]; // empty rather than null
410 break;
411
412 default:
414 return NO;
415 }
416
417 *value = OOJSValueFromNativeObject(context, result);
418 return YES;
419
421}
422
423
424static JSBool EquipmentInfoSetProperty(JSContext *context, JSObject *this, jsid propID, JSBool strict, jsval *value)
425{
426 if (!JSID_IS_INT(propID)) return YES;
427
428 OOJS_NATIVE_ENTER(context)
429
430 OOEquipmentType *eqType = nil;
431 int32 iValue;
432 OOColor *colorForScript = nil;
433
434 if (EXPECT_NOT(!JSEquipmentInfoGetEquipmentType(context, this, &eqType))) return NO;
435
436 switch (JSID_TO_INT(propID))
437 {
439 colorForScript = [OOColor colorWithDescription:OOJSNativeObjectFromJSValue(context, *value)];
440 if (colorForScript != nil || JSVAL_IS_NULL(*value))
441 {
442 [eqType setDisplayColor:colorForScript];
443 return YES;
444 }
445 break;
447 OOStandardsDeprecated([NSString stringWithFormat:@"TL99 for variable tech level is deprecated for %@",[eqType identifier]]);
449 {
450 if (JSVAL_IS_NULL(*value))
451 {
452 // reset mission variable
453 [OOPlayerForScripting() setMissionVariable:nil
454 forKey:[@"mission_TL_FOR_" stringByAppendingString:[eqType identifier]]];
455 return YES;
456 }
457 if (JS_ValueToInt32(context, *value, &iValue))
458 {
459 if (iValue < 0) iValue = 0;
460 if (15 < iValue && iValue != kOOVariableTechLevel) iValue = 15;
461 [OOPlayerForScripting() setMissionVariable:[NSString stringWithFormat:@"%u", iValue]
462 forKey:[@"mission_TL_FOR_" stringByAppendingString:[eqType identifier]]];
463 return YES;
464 }
465 }
466 else
467 {
468 OOJSReportWarning(context, @"Cannot modify effective tech level for %@, because its base tech level is not 99.", [eqType identifier]);
469 return YES;
470 }
471 break;
472
473 default:
475 return NO;
476 }
477
478 OOJSReportBadPropertyValue(context, this, propID, sEquipmentInfoProperties, *value);
479 return NO;
480
482}
483
484
485static JSBool EquipmentInfoGetAllEqipment(JSContext *context, JSObject *this, jsid propID, jsval *value)
486{
487 OOJS_NATIVE_ENTER(context)
488
489 *value = OOJSValueFromNativeObject(context, [OOEquipmentType allEquipmentTypes]);
490 return YES;
491
493}
494
495
496@implementation OOEquipmentType (OOJavaScriptExtensions)
497
498- (jsval) oo_jsValueInContext:(JSContext *)context
499{
500 if (_jsSelf == NULL)
501 {
502 _jsSelf = JS_NewObject(context, &sEquipmentInfoClass, sEquipmentInfoPrototype, NULL);
503 if (_jsSelf != NULL)
504 {
505 if (!JS_SetPrivate(context, _jsSelf, [self retain])) _jsSelf = NULL;
506 }
507 }
508
509 return OBJECT_TO_JSVAL(_jsSelf);
510}
511
512
513- (NSString *) oo_jsClassName
514{
515 return @"EquipmentInfo";
516}
517
518
519- (void) oo_clearJSSelf:(JSObject *)selfVal
520{
521 if (_jsSelf == selfVal) _jsSelf = NULL;
522}
523
524@end
525
526
527// *** Static methods ***
528
529// infoForKey(key : String): EquipmentInfo
530static JSBool EquipmentInfoStaticInfoForKey(JSContext *context, uintN argc, jsval *vp)
531{
532 OOJS_NATIVE_ENTER(context)
533
534 NSString *key = nil;
535
536 if (argc > 0) key = OOStringFromJSValue(context, OOJS_ARGV[0]);
537 if (key == nil)
538 {
539 OOJSReportBadArguments(context, @"EquipmentInfo", @"infoForKey", MIN(argc, 1U), OOJS_ARGV, nil, @"string");
540 return NO;
541 }
542
543 OOJS_RETURN_OBJECT([OOEquipmentType equipmentTypeWithIdentifier:key]);
544
546}
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[]
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)
@ kEquipmentInfo_defaultActivateKey
@ 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_provides
@ kEquipmentInfo_requiresFullFuel
@ kEquipmentInfo_requiresNonFullFuel
@ kEquipmentInfo_requiredCargoSpace
@ kEquipmentInfo_isAvailableToNPCs
@ kEquipmentInfo_incompatibleEquipment
@ kEquipmentInfo_requiresNonCleanLegalRecord
@ kEquipmentInfo_requiresMountedPylon
@ kEquipmentInfo_requiresEmptyPylon
@ kEquipmentInfo_fastAffinityOffensive
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()
OOTechLevelID techLevel()
NSString * scriptName()
NSSet * incompatibleEquipment()
NSDictionary * scriptInfo()
OOColor * displayColor()
NSArray * defaultActivateKey()
NSArray * defaultModeKey()
NSSet * requiresEquipment()
NSSet * requiresAnyEquipment()
OOEquipmentType * equipmentTypeWithIdentifier:(NSString *identifier)
OOCreditsQuantity price()
NSArray * providesForScripting()
NSString * identifier()
NSString * descriptiveText()