LCOV - code coverage report
Current view: top level - Core/Scripting - OOJSStation.m (source / functions) Hit Total Coverage
Test: coverxygen.info Lines: 0 33 0.0 %
Date: 2025-05-28 07:50:54 Functions: 0 0 -

          Line data    Source code
       1           0 : /*
       2             : OOJSStation.m
       3             : 
       4             : Oolite
       5             : Copyright (C) 2004-2013 Giles C Williams and contributors
       6             : 
       7             : This program is free software; you can redistribute it and/or
       8             : modify it under the terms of the GNU General Public License
       9             : as published by the Free Software Foundation; either version 2
      10             : of the License, or (at your option) any later version.
      11             : 
      12             : This program is distributed in the hope that it will be useful,
      13             : but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             : GNU General Public License for more details.
      16             : 
      17             : You should have received a copy of the GNU General Public License
      18             : along with this program; if not, write to the Free Software
      19             : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
      20             : MA 02110-1301, USA.
      21             : 
      22             :  */
      23             : 
      24             : #import "OOJSStation.h"
      25             : #import "OOJSEntity.h"
      26             : #import "OOJSShip.h"
      27             : #import "OOJSPlayer.h"
      28             : #import "PlayerEntityContracts.h"
      29             : #import "OOJavaScriptEngine.h"
      30             : #import "OOJSInterfaceDefinition.h"
      31             : 
      32             : #import "OOCollectionExtractors.h"
      33             : #import "OOEquipmentType.h"
      34             : #import "OOShipRegistry.h"
      35             : #import "OOConstToString.h"
      36             : #import "StationEntity.h"
      37             : #import "GameController.h"
      38             : 
      39             : 
      40           0 : static JSObject         *sStationPrototype;
      41             : 
      42             : static BOOL JSStationGetStationEntity(JSContext *context, JSObject *stationObj, StationEntity **outEntity);
      43             : 
      44             : 
      45             : static JSBool StationGetProperty(JSContext *context, JSObject *this, jsid propID, jsval *value);
      46             : static JSBool StationSetProperty(JSContext *context, JSObject *this, jsid propID, JSBool strict, jsval *value);
      47             : 
      48             : static JSBool StationAbortAllDockings(JSContext *context, uintN argc, jsval *vp);
      49             : static JSBool StationAbortDockingForShip(JSContext *context, uintN argc, jsval *vp);
      50             : static JSBool StationCanDockShip(JSContext *context, uintN argc, jsval *vp);
      51             : static JSBool StationDockPlayer(JSContext *context, uintN argc, jsval *vp);
      52             : static JSBool StationIncreaseAlertLevel(JSContext *context, uintN argc, jsval *vp);
      53             : static JSBool StationDecreaseAlertLevel(JSContext *context, uintN argc, jsval *vp);
      54             : static JSBool StationLaunchShipWithRole(JSContext *context, uintN argc, jsval *vp);
      55             : static JSBool StationLaunchDefenseShip(JSContext *context, uintN argc, jsval *vp);
      56             : static JSBool StationLaunchEscort(JSContext *context, uintN argc, jsval *vp);
      57             : static JSBool StationLaunchScavenger(JSContext *context, uintN argc, jsval *vp);
      58             : static JSBool StationLaunchMiner(JSContext *context, uintN argc, jsval *vp);
      59             : static JSBool StationLaunchPirateShip(JSContext *context, uintN argc, jsval *vp);
      60             : static JSBool StationLaunchShuttle(JSContext *context, uintN argc, jsval *vp);
      61             : static JSBool StationLaunchPatrol(JSContext *context, uintN argc, jsval *vp);
      62             : static JSBool StationLaunchPolice(JSContext *context, uintN argc, jsval *vp);
      63             : static JSBool StationSetInterface(JSContext *context, uintN argc, jsval *vp);
      64             : static JSBool StationSetMarketPrice(JSContext *context, uintN argc, jsval *vp);
      65             : static JSBool StationSetMarketQuantity(JSContext *context, uintN argc, jsval *vp);
      66             : static JSBool StationAddShipToShipyard(JSContext *context, uintN argc, jsval *vp);
      67             : static JSBool StationRemoveShipFromShipyard(JSContext *context, uintN argc, jsval *vp);
      68             : 
      69           0 : static JSClass sStationClass =
      70             : {
      71             :         "Station",
      72             :         JSCLASS_HAS_PRIVATE,
      73             :         
      74             :         JS_PropertyStub,                // addProperty
      75             :         JS_PropertyStub,                // delProperty
      76             :         StationGetProperty,             // getProperty
      77             :         StationSetProperty,             // setProperty
      78             :         JS_EnumerateStub,               // enumerate
      79             :         JS_ResolveStub,                 // resolve
      80             :         JS_ConvertStub,                 // convert
      81             :         OOJSObjectWrapperFinalize,// finalize
      82             :         JSCLASS_NO_OPTIONAL_MEMBERS
      83             : };
      84             : 
      85             : 
      86           0 : enum
      87             : {
      88             :         // Property IDs
      89             :         kStation_alertCondition,
      90             :         kStation_allegiance,
      91             :         kStation_allowsAutoDocking,
      92             :         kStation_allowsFastDocking,
      93             :         kStation_breakPattern,
      94             :         kStation_dockedContractors, // miners and scavengers.
      95             :         kStation_dockedDefenders,
      96             :         kStation_dockedPolice,
      97             :         kStation_equipmentPriceFactor,
      98             :         kStation_equivalentTechLevel,
      99             :         kStation_hasNPCTraffic,
     100             :         kStation_hasShipyard,
     101             :         kStation_isMainStation,         // Is [UNIVERSE station], boolean, read-only
     102             :         kStation_market,
     103             :         kStation_requiresDockingClearance,
     104             :         kStation_roll,
     105             :         kStation_suppressArrivalReports,
     106             :         kStation_shipyard,
     107             : };
     108             : 
     109             : 
     110           0 : static JSPropertySpec sStationProperties[] =
     111             : {
     112             :         // JS name                                              ID                                                                      flags
     113             :         { "alertCondition",                           kStation_alertCondition,                        OOJS_PROP_READWRITE_CB },
     114             :         { "allegiance",                                       kStation_allegiance,                            OOJS_PROP_READWRITE_CB },
     115             :         { "allowsAutoDocking",                        kStation_allowsAutoDocking,                     OOJS_PROP_READWRITE_CB },
     116             :         { "allowsFastDocking",                        kStation_allowsFastDocking,                     OOJS_PROP_READWRITE_CB },
     117             :         { "breakPattern",                             kStation_breakPattern,                          OOJS_PROP_READWRITE_CB },
     118             :         { "dockedContractors",                        kStation_dockedContractors,                     OOJS_PROP_READONLY_CB },
     119             :         { "dockedDefenders",                  kStation_dockedDefenders,                       OOJS_PROP_READONLY_CB },
     120             :         { "dockedPolice",                             kStation_dockedPolice,                          OOJS_PROP_READONLY_CB },
     121             :         { "equipmentPriceFactor",             kStation_equipmentPriceFactor,          OOJS_PROP_READONLY_CB },
     122             :         { "equivalentTechLevel",              kStation_equivalentTechLevel,           OOJS_PROP_READONLY_CB },
     123             :         { "hasNPCTraffic",                            kStation_hasNPCTraffic,                         OOJS_PROP_READWRITE_CB },
     124             :         { "hasShipyard",                              kStation_hasShipyard,                           OOJS_PROP_READONLY_CB },
     125             :         { "isMainStation",                            kStation_isMainStation,                         OOJS_PROP_READONLY_CB },
     126             :         { "market",        kStation_market,     OOJS_PROP_READONLY_CB },
     127             :         { "requiresDockingClearance", kStation_requiresDockingClearance,      OOJS_PROP_READWRITE_CB },
     128             :         { "roll",                                             kStation_roll,                                          OOJS_PROP_READWRITE_CB },
     129             :         { "suppressArrivalReports",           kStation_suppressArrivalReports,        OOJS_PROP_READWRITE_CB },
     130             :         { "shipyard",                   kStation_shipyard,                  OOJS_PROP_READONLY_CB },
     131             :         { 0 }
     132             : };
     133             : 
     134             : 
     135           0 : static JSFunctionSpec sStationMethods[] =
     136             : {
     137             :         // JS name                                      Function                                                min args
     138             :         { "abortAllDockings",         StationAbortAllDockings,                0 },
     139             :         { "abortDockingForShip",      StationAbortDockingForShip,             1 },
     140             :         { "canDockShip",            StationCanDockShip,                               1 },    
     141             :         { "dockPlayer",                               StationDockPlayer,                              0 },
     142             :         { "increaseAlertLevel",     StationIncreaseAlertLevel,      0 },
     143             :         { "decreaseAlertLevel",     StationDecreaseAlertLevel,      0 },
     144             :         { "launchDefenseShip",                StationLaunchDefenseShip,               0 },
     145             :         { "launchEscort",                     StationLaunchEscort,                    0 },
     146             :         { "launchMiner",                      StationLaunchMiner,                             0 },
     147             :         { "launchPatrol",                     StationLaunchPatrol,                    0 },
     148             :         { "launchPirateShip",         StationLaunchPirateShip,                0 },
     149             :         { "launchPolice",                     StationLaunchPolice,                    0 },
     150             :         { "launchScavenger",          StationLaunchScavenger,                 0 },
     151             :         { "launchShipWithRole",               StationLaunchShipWithRole,              1 },
     152             :         { "launchShuttle",                    StationLaunchShuttle,                   0 },
     153             :         { "setInterface",                     StationSetInterface,                    0 },
     154             :         { "setMarketPrice",                   StationSetMarketPrice,                  2 },
     155             :         { "setMarketQuantity",                StationSetMarketQuantity,               2 },
     156             :         { "addShipToShipyard",      StationAddShipToShipyard,       1 },
     157             :         { "removeShipFromShipyard", StationRemoveShipFromShipyard,  1 },
     158             :         { 0 }
     159             : };
     160             : 
     161             : 
     162           0 : void InitOOJSStation(JSContext *context, JSObject *global)
     163             : {
     164             :         sStationPrototype = JS_InitClass(context, global, JSShipPrototype(), &sStationClass, OOJSUnconstructableConstruct, 0, sStationProperties, sStationMethods, NULL, NULL);
     165             :         OOJSRegisterObjectConverter(&sStationClass, OOJSBasicPrivateObjectConverter);
     166             :         OOJSRegisterSubclass(&sStationClass, JSShipClass());
     167             : }
     168             : 
     169             : 
     170           0 : static BOOL JSStationGetStationEntity(JSContext *context, JSObject *stationObj, StationEntity **outEntity)
     171             : {
     172             :         OOJS_PROFILE_ENTER
     173             :         
     174             :         BOOL                                            result;
     175             :         Entity                                          *entity = nil;
     176             :         
     177             :         if (outEntity == NULL)  return NO;
     178             :         *outEntity = nil;
     179             :         
     180             :         result = OOJSEntityGetEntity(context, stationObj, &entity);
     181             :         if (!result)  return NO;
     182             :         
     183             :         if (![entity isKindOfClass:[StationEntity class]])  return NO;
     184             :         
     185             :         *outEntity = (StationEntity *)entity;
     186             :         return YES;
     187             :         
     188             :         OOJS_PROFILE_EXIT
     189             : }
     190             : 
     191           0 : static BOOL JSStationGetShipEntity(JSContext *context, JSObject *shipObj, ShipEntity **outEntity)
     192             : {
     193             :         OOJS_PROFILE_ENTER
     194             :         
     195             :         BOOL                                            result;
     196             :         Entity                                          *entity = nil;
     197             :         
     198             :         if (outEntity == NULL)  return NO;
     199             :         *outEntity = nil;
     200             :         
     201             :         result = OOJSEntityGetEntity(context, shipObj, &entity);
     202             :         if (!result)  return NO;
     203             :         
     204             :         if (![entity isKindOfClass:[ShipEntity class]])  return NO;
     205             :         
     206             :         *outEntity = (ShipEntity *)entity;
     207             :         return YES;
     208             :         
     209             :         OOJS_PROFILE_EXIT
     210             : }
     211             : 
     212             : 
     213             : @implementation StationEntity (OOJavaScriptExtensions)
     214             : 
     215           0 : - (void)getJSClass:(JSClass **)outClass andPrototype:(JSObject **)outPrototype
     216             : {
     217             :         *outClass = &sStationClass;
     218             :         *outPrototype = sStationPrototype;
     219             : }
     220             : 
     221             : 
     222           0 : - (NSString *) oo_jsClassName
     223             : {
     224             :         return @"Station";
     225             : }
     226             : 
     227             : @end
     228             : 
     229             : 
     230           0 : static JSBool StationGetProperty(JSContext *context, JSObject *this, jsid propID, jsval *value)
     231             : {
     232             :         if (!JSID_IS_INT(propID))  return YES;
     233             :         
     234             :         OOJS_NATIVE_ENTER(context)
     235             :         
     236             :         StationEntity                           *entity = nil;
     237             :         
     238             :         if (!JSStationGetStationEntity(context, this, &entity))  return NO;
     239             :         if (entity == nil)  { *value = JSVAL_VOID; return YES; }
     240             :         
     241             :         switch (JSID_TO_INT(propID))
     242             :         {
     243             :                 case kStation_isMainStation:
     244             :                         *value = OOJSValueFromBOOL(entity == [UNIVERSE station]);
     245             :                         return YES;
     246             :                 
     247             :                 case kStation_hasNPCTraffic:
     248             :                         *value = OOJSValueFromBOOL([entity hasNPCTraffic]);
     249             :                         return YES;
     250             :                         
     251             :                 case kStation_hasShipyard:
     252             :                         *value = OOJSValueFromBOOL([entity hasShipyard]);
     253             :                         return YES;
     254             :                 
     255             :                 case kStation_alertCondition:
     256             :                         *value = INT_TO_JSVAL([entity alertLevel]);
     257             :                         return YES;
     258             : 
     259             :                 case kStation_allegiance:
     260             :                 {
     261             :                         NSString *result = [entity allegiance];
     262             :                         *value = OOJSValueFromNativeObject(context, result);
     263             :                         return YES;
     264             :                 }
     265             :                         
     266             :                 case kStation_requiresDockingClearance:
     267             :                         *value = OOJSValueFromBOOL([entity requiresDockingClearance]);
     268             :                         return YES;
     269             :                         
     270             :                 case kStation_roll:
     271             :                         // same as in ship definition, but this time read/write below
     272             :                         return JS_NewNumberValue(context, [entity flightRoll], value);
     273             :                         
     274             :                 case kStation_allowsFastDocking:
     275             :                         *value = OOJSValueFromBOOL([entity allowsFastDocking]);
     276             :                         return YES;
     277             :                         
     278             :                 case kStation_allowsAutoDocking:
     279             :                         *value = OOJSValueFromBOOL([entity allowsAutoDocking]);
     280             :                         return YES;
     281             : 
     282             :                 case kStation_dockedContractors:
     283             :                         *value = INT_TO_JSVAL([entity countOfDockedContractors]);
     284             :                         return YES;
     285             :                         
     286             :                 case kStation_dockedPolice:
     287             :                         *value = INT_TO_JSVAL([entity countOfDockedPolice]);
     288             :                         return YES;
     289             :                         
     290             :                 case kStation_dockedDefenders:
     291             :                         *value = INT_TO_JSVAL([entity countOfDockedDefenders]);
     292             :                         return YES;
     293             :                         
     294             :                 case kStation_equivalentTechLevel:
     295             :                         *value = INT_TO_JSVAL((int32_t)[entity equivalentTechLevel]);
     296             :                         return YES;
     297             :                         
     298             :                 case kStation_equipmentPriceFactor:
     299             :                         return JS_NewNumberValue(context, [entity equipmentPriceFactor], value);
     300             :                         
     301             :                 case kStation_suppressArrivalReports:
     302             :                         *value = OOJSValueFromBOOL([entity suppressArrivalReports]);
     303             :                         return YES;
     304             :                         
     305             :                 case kStation_breakPattern:
     306             :                         *value = OOJSValueFromBOOL([entity hasBreakPattern]);
     307             :                         return YES;
     308             : 
     309             :                 case kStation_shipyard:
     310             :                 {
     311             :                         if (![entity hasShipyard]) 
     312             :                         {
     313             :                                 // return null if station has no shipyard
     314             :                                 *value = OOJSValueFromNativeObject(context, nil);
     315             :                         } 
     316             :                         else 
     317             :                         {
     318             :                                 if ([entity localShipyard] == nil) [entity generateShipyard];
     319             :                                 NSMutableArray *shipyard = [entity localShipyard];
     320             :                                 *value = OOJSValueFromNativeObject(context, shipyard);
     321             :                         }
     322             :                         return YES;
     323             :                 }
     324             : 
     325             :                 case kStation_market:
     326             :                 {
     327             :                         NSDictionary *market = [entity localMarketForScripting];
     328             :                         *value = OOJSValueFromNativeObject(context, market);
     329             :                         return YES;
     330             :                 }
     331             : 
     332             :                 default:
     333             :                         OOJSReportBadPropertySelector(context, this, propID, sStationProperties);
     334             :                         return NO;
     335             :         }
     336             :         
     337             :         OOJS_NATIVE_EXIT
     338             : }
     339             : 
     340             : 
     341           0 : static JSBool StationSetProperty(JSContext *context, JSObject *this, jsid propID, JSBool strict, jsval *value)
     342             : {
     343             :         if (!JSID_IS_INT(propID))  return YES;
     344             :         
     345             :         OOJS_NATIVE_ENTER(context)
     346             :         
     347             :         StationEntity                           *entity = nil;
     348             :         JSBool                                          bValue;
     349             :         int32                                           iValue;
     350             :         jsdouble                                        fValue;
     351             :         NSString                                        *sValue = nil;
     352             :         
     353             :         if (!JSStationGetStationEntity(context, this, &entity)) return NO;
     354             :         if (entity == nil)  return YES;
     355             :         
     356             :         switch (JSID_TO_INT(propID))
     357             :         {
     358             :                 case kStation_hasNPCTraffic:
     359             :                         if (JS_ValueToBoolean(context, *value, &bValue))
     360             :                         {
     361             :                                 [entity setHasNPCTraffic:bValue];
     362             :                                 return YES;
     363             :                         }
     364             :                         break;
     365             :                 
     366             :                 case kStation_alertCondition:
     367             :                         if (JS_ValueToInt32(context, *value, &iValue))
     368             :                         {
     369             :                                 [entity setAlertLevel:iValue signallingScript:NO];      // Performs range checking
     370             :                                 return YES;
     371             :                         }
     372             :                         break;
     373             : 
     374             :                 case kStation_allegiance:
     375             :                         sValue = OOStringFromJSValue(context,*value);
     376             :                         if (sValue != nil)
     377             :                         {
     378             :                                 [entity setAllegiance:sValue];
     379             :                                 return YES;
     380             :                         }
     381             :                         break;
     382             : 
     383             :                         
     384             :                 case kStation_requiresDockingClearance:
     385             :                         if (JS_ValueToBoolean(context, *value, &bValue))
     386             :                         {
     387             :                                 [entity setRequiresDockingClearance:bValue];
     388             :                                 return YES;
     389             :                         }
     390             :                         break;
     391             :                         
     392             :                 case kStation_roll:
     393             :                         if (JS_ValueToNumber(context, *value, &fValue))
     394             :                         {
     395             : /*                              if (fValue < -2.0)  fValue = -2.0;
     396             :                                 if (fValue > 2.0)  fValue = 2.0;     // clamping to -2.0...2.0 gives us ±M_PI actual maximum rotation
     397             :                                 [entity setRoll:fValue]; */
     398             :                                 // use setRawRoll to make the units here equal to those in kShip_roll
     399             :                                 if (fValue < -M_PI)  fValue = -M_PI;
     400             :                                 else if (fValue > M_PI)  fValue = M_PI;
     401             :                                 [entity setRawRoll:fValue];
     402             :                                 return YES;
     403             :                         }
     404             :                         break;
     405             : 
     406             :                 case kStation_allowsFastDocking:
     407             :                         if (JS_ValueToBoolean(context, *value, &bValue))
     408             :                         {
     409             :                                 [entity setAllowsFastDocking:bValue];
     410             :                                 return YES;
     411             :                         }
     412             :                         break;
     413             :                         
     414             :                 case kStation_allowsAutoDocking:
     415             :                         if (JS_ValueToBoolean(context, *value, &bValue))
     416             :                         {
     417             :                                 [entity setAllowsAutoDocking:bValue];
     418             :                                 return YES;
     419             :                         }
     420             :                         break;
     421             : 
     422             :                 case kStation_suppressArrivalReports:
     423             :                         if (JS_ValueToBoolean(context, *value, &bValue))
     424             :                         {
     425             :                                 [entity setSuppressArrivalReports:bValue];
     426             :                                 return YES;
     427             :                         }
     428             :                         break;
     429             : 
     430             :                 case kStation_breakPattern:
     431             :                         if (JS_ValueToBoolean(context, *value, &bValue))
     432             :                         {
     433             :                                 [entity setHasBreakPattern:bValue];
     434             :                                 return YES;
     435             :                         }
     436             :                         break;
     437             :                 
     438             :                 default:
     439             :                         OOJSReportBadPropertySelector(context, this, propID, sStationProperties);
     440             :                         return NO;
     441             :         }
     442             :         
     443             :         OOJSReportBadPropertyValue(context, this, propID, sStationProperties, *value);
     444             :         return NO;
     445             :         
     446             :         OOJS_NATIVE_EXIT
     447             : }
     448             : 
     449             : 
     450             : // *** Methods ***
     451             : 
     452           0 : static JSBool StationAbortAllDockings(JSContext *context, uintN argc, jsval *vp)
     453             : {
     454             :         OOJS_NATIVE_ENTER(context)
     455             :         
     456             :         StationEntity *station = nil;
     457             :         JSStationGetStationEntity(context, OOJS_THIS, &station); 
     458             :         [station abortAllDockings];
     459             :         
     460             :         OOJS_RETURN_VOID;
     461             :         
     462             :         OOJS_NATIVE_EXIT
     463             : }
     464             : 
     465           0 : static JSBool StationAbortDockingForShip(JSContext *context, uintN argc, jsval *vp)
     466             : {
     467             :         OOJS_NATIVE_ENTER(context)
     468             :         
     469             :         StationEntity *station = nil;
     470             :         JSStationGetStationEntity(context, OOJS_THIS, &station); 
     471             :         if (argc == 0)
     472             :         {
     473             :                 OOJSReportBadArguments(context, @"Station", @"abortDockingForShip", MIN(argc, 1U), OOJS_ARGV, nil, @"ship in docking queue");
     474             :                 return NO;
     475             :         }
     476             :         if (!JSVAL_IS_OBJECT(OOJS_ARGV[0]))  return NO;
     477             :         ShipEntity *ship = nil;
     478             :         JSStationGetShipEntity(context, JSVAL_TO_OBJECT(OOJS_ARGV[0]), &ship);
     479             :         if (ship != nil)
     480             :         {
     481             :                 [station abortDockingForShip:ship];
     482             :         }
     483             :         
     484             :         OOJS_RETURN_VOID;
     485             :         
     486             :         OOJS_NATIVE_EXIT
     487             : }
     488             : 
     489             : // canDockShip(shipEntity) : boolean
     490             : // Proposed by phkb (Nick Rogers) 20161206
     491           0 : static JSBool StationCanDockShip(JSContext *context, uintN argc, jsval *vp)
     492             : {
     493             :    OOJS_NATIVE_ENTER(context)
     494             : 
     495             :    BOOL         result = YES;
     496             :    ShipEntity      *shipToCheck = nil;
     497             : 
     498             :    if (argc > 0)
     499             :    {
     500             :       if (!JSVAL_IS_OBJECT(OOJS_ARGV[0]) || !JSStationGetShipEntity(context, JSVAL_TO_OBJECT(OOJS_ARGV[0]), &shipToCheck))
     501             :       {
     502             :          return NO;
     503             :       }
     504             :    }
     505             :    if (EXPECT_NOT(shipToCheck == nil))
     506             :    {
     507             :       OOJSReportBadArguments(context, @"Station", @"canDockShip", MIN(argc, 1U), OOJS_ARGV, nil, @"shipEntity");
     508             :       return NO;
     509             :    }
     510             :    
     511             :    StationEntity *station = nil;
     512             :    if (!JSStationGetStationEntity(context, OOJS_THIS, &station))  OOJS_RETURN_VOID; // stale reference, no-op
     513             :    
     514             :    OOJS_BEGIN_FULL_NATIVE(context)
     515             :    result = [station fitsInDock:shipToCheck andLogNoFit:NO];
     516             :    OOJS_END_FULL_NATIVE
     517             : 
     518             :    OOJS_RETURN_BOOL(result);
     519             :    OOJS_NATIVE_EXIT
     520             : }
     521             : 
     522             : 
     523             : // dockPlayer()
     524             : // Proposed and written by Frame 20090729
     525           0 : static JSBool StationDockPlayer(JSContext *context, uintN argc, jsval *vp)
     526             : {
     527             :         OOJS_NATIVE_ENTER(context)
     528             :         
     529             :         PlayerEntity    *player = OOPlayerForScripting();
     530             :         GameController  *gameController = [UNIVERSE gameController];
     531             :         
     532             :         if (EXPECT_NOT([gameController isGamePaused]))
     533             :         {
     534             :                 /*      Station.dockPlayer() was executed while the game was in pause.
     535             :                         Do we want to return an error or just unpause and continue?
     536             :                         I think unpausing is the sensible thing to do here - Nikos 20110208
     537             :                 */
     538             :                 [gameController setGamePaused:NO];
     539             :         }
     540             :         
     541             :         if (EXPECT(![player isDocked]))
     542             :         {
     543             :                 StationEntity *stationForDockingPlayer = nil;
     544             :                 JSStationGetStationEntity(context, OOJS_THIS, &stationForDockingPlayer); 
     545             :                 [player setDockingClearanceStatus:DOCKING_CLEARANCE_STATUS_GRANTED];
     546             :                 [player safeAllMissiles];
     547             :                 [UNIVERSE setViewDirection:VIEW_FORWARD];
     548             :                 [player enterDock:stationForDockingPlayer];
     549             :         }
     550             :         OOJS_RETURN_VOID;
     551             :         
     552             :         OOJS_NATIVE_EXIT
     553             : }
     554             : 
     555             : 
     556           0 : static JSBool StationIncreaseAlertLevel(JSContext *context, uintN argc, jsval *vp)
     557             : {
     558             :         OOJS_NATIVE_ENTER(context)
     559             :         StationEntity   *station = nil;
     560             : 
     561             :         if (!JSStationGetStationEntity(context, OOJS_THIS, &station))  OOJS_RETURN_VOID; // stale reference, no-op
     562             : 
     563             :         OOJS_BEGIN_FULL_NATIVE(context)
     564             :         if ([station alertCondition] < 3)
     565             :         {
     566             :                 [station increaseAlertLevel];
     567             :         }
     568             :         OOJS_END_FULL_NATIVE
     569             :         OOJS_RETURN_VOID;
     570             :         OOJS_NATIVE_EXIT
     571             : }
     572             : 
     573           0 : static JSBool StationDecreaseAlertLevel(JSContext *context, uintN argc, jsval *vp)
     574             : {
     575             :         OOJS_NATIVE_ENTER(context)
     576             :         StationEntity   *station = nil;
     577             : 
     578             :         if (!JSStationGetStationEntity(context, OOJS_THIS, &station))  OOJS_RETURN_VOID; // stale reference, no-op
     579             : 
     580             :         OOJS_BEGIN_FULL_NATIVE(context)
     581             :         if ([station alertCondition] > 1)
     582             :         {
     583             :                 [station decreaseAlertLevel];
     584             :         }
     585             :         OOJS_END_FULL_NATIVE
     586             :         OOJS_RETURN_VOID;
     587             :         OOJS_NATIVE_EXIT
     588             : }
     589             : 
     590             : // launchShipWithRole(role : String [, abortAllDockings : boolean]) : shipEntity
     591           0 : static JSBool StationLaunchShipWithRole(JSContext *context, uintN argc, jsval *vp)
     592             : {
     593             :         OOJS_NATIVE_ENTER(context)
     594             :         
     595             :         NSString                *shipRole = nil;
     596             :         StationEntity   *station = nil;
     597             :         ShipEntity              *result = nil;
     598             :         JSBool                  abortAllDockings = NO;
     599             :         
     600             :         if (!JSStationGetStationEntity(context, OOJS_THIS, &station))  OOJS_RETURN_VOID; // stale reference, no-op
     601             :         
     602             :         if (argc > 0)  shipRole = OOStringFromJSValue(context, OOJS_ARGV[0]);
     603             :         if (EXPECT_NOT(shipRole == nil))
     604             :         {
     605             :                 OOJSReportBadArguments(context, @"Station", @"launchShipWithRole", MIN(argc, 1U), OOJS_ARGV, nil, @"string (role)");
     606             :                 return NO;
     607             :         }
     608             :         
     609             :         if (argc > 1)  JS_ValueToBoolean(context, OOJS_ARGV[1], &abortAllDockings);
     610             : 
     611             :         OOJS_BEGIN_FULL_NATIVE(context)
     612             :         result = [station launchIndependentShip:shipRole];
     613             :         if (abortAllDockings) [station abortAllDockings];
     614             :         OOJS_END_FULL_NATIVE
     615             : 
     616             :         OOJS_RETURN_OBJECT(result);
     617             :         OOJS_NATIVE_EXIT
     618             : }
     619             : 
     620             : 
     621           0 : static JSBool StationLaunchDefenseShip(JSContext *context, uintN argc, jsval *vp)
     622             : {
     623             :         OOJS_NATIVE_ENTER(context)
     624             :         
     625             :         StationEntity *station = nil;
     626             :         if (!JSStationGetStationEntity(context, OOJS_THIS, &station))  OOJS_RETURN_VOID; // stale reference, no-op
     627             : 
     628             :         ShipEntity *launched = nil;
     629             :         OOJS_BEGIN_FULL_NATIVE(context)
     630             :         launched = [station launchDefenseShip];
     631             :         OOJS_END_FULL_NATIVE
     632             :         OOJS_RETURN_OBJECT(launched);
     633             : 
     634             :         OOJS_NATIVE_EXIT
     635             : }
     636             : 
     637             : 
     638           0 : static JSBool StationLaunchEscort(JSContext *context, uintN argc, jsval *vp)
     639             : {
     640             :         OOJS_NATIVE_ENTER(context)
     641             :         
     642             :         StationEntity *station = nil;
     643             :         if (!JSStationGetStationEntity(context, OOJS_THIS, &station))  OOJS_RETURN_VOID; // stale reference, no-op
     644             :         
     645             :         ShipEntity *launched = nil;
     646             :         OOJS_BEGIN_FULL_NATIVE(context)
     647             :         launched = [station launchEscort];
     648             :         OOJS_END_FULL_NATIVE
     649             :         OOJS_RETURN_OBJECT(launched);
     650             : 
     651             :         OOJS_NATIVE_EXIT
     652             : }
     653             : 
     654             : 
     655           0 : static JSBool StationLaunchScavenger(JSContext *context, uintN argc, jsval *vp)
     656             : {
     657             :         OOJS_NATIVE_ENTER(context)
     658             :         
     659             :         StationEntity *station = nil;
     660             :         if (!JSStationGetStationEntity(context, OOJS_THIS, &station))  OOJS_RETURN_VOID; // stale reference, no-op
     661             : 
     662             :         ShipEntity *launched = nil;
     663             :         OOJS_BEGIN_FULL_NATIVE(context)
     664             :         launched = [station launchScavenger];
     665             :         OOJS_END_FULL_NATIVE
     666             :         OOJS_RETURN_OBJECT(launched);
     667             : 
     668             :         OOJS_NATIVE_EXIT
     669             : }
     670             : 
     671             : 
     672           0 : static JSBool StationLaunchMiner(JSContext *context, uintN argc, jsval *vp)
     673             : {
     674             :         OOJS_NATIVE_ENTER(context)
     675             :         
     676             :         StationEntity *station = nil;
     677             :         if (!JSStationGetStationEntity(context, OOJS_THIS, &station))  OOJS_RETURN_VOID; // stale reference, no-op
     678             :         
     679             :         ShipEntity *launched = nil;
     680             :         OOJS_BEGIN_FULL_NATIVE(context)
     681             :         launched = [station launchMiner];
     682             :         OOJS_END_FULL_NATIVE
     683             :         OOJS_RETURN_OBJECT(launched);
     684             :         OOJS_NATIVE_EXIT
     685             : }
     686             : 
     687             : 
     688           0 : static JSBool StationLaunchPirateShip(JSContext *context, uintN argc, jsval *vp)
     689             : {
     690             :         OOJS_NATIVE_ENTER(context)
     691             :         
     692             :         StationEntity *station = nil;
     693             :         if (!JSStationGetStationEntity(context, OOJS_THIS, &station))  OOJS_RETURN_VOID; // stale reference, no-op
     694             :         
     695             :         ShipEntity *launched = nil;
     696             :         OOJS_BEGIN_FULL_NATIVE(context)
     697             :         launched = [station launchPirateShip];
     698             :         OOJS_END_FULL_NATIVE
     699             :         OOJS_RETURN_OBJECT(launched);
     700             : 
     701             :         OOJS_NATIVE_EXIT
     702             : }
     703             : 
     704             : 
     705           0 : static JSBool StationLaunchShuttle(JSContext *context, uintN argc, jsval *vp)
     706             : {
     707             :         OOJS_NATIVE_ENTER(context)
     708             :         
     709             :         StationEntity *station = nil;
     710             :         if (!JSStationGetStationEntity(context, OOJS_THIS, &station))  OOJS_RETURN_VOID; // stale reference, no-op
     711             :         
     712             :         ShipEntity *launched = nil;
     713             :         OOJS_BEGIN_FULL_NATIVE(context)
     714             :         launched = [station launchShuttle];
     715             :         OOJS_END_FULL_NATIVE
     716             :         OOJS_RETURN_OBJECT(launched);
     717             :         OOJS_NATIVE_EXIT
     718             : }
     719             : 
     720             : 
     721           0 : static JSBool StationLaunchPatrol(JSContext *context, uintN argc, jsval *vp)
     722             : {
     723             :         OOJS_NATIVE_ENTER(context)
     724             :         
     725             :         StationEntity *station = nil;
     726             :         if (!JSStationGetStationEntity(context, OOJS_THIS, &station))  OOJS_RETURN_VOID; // stale reference, no-op
     727             :         
     728             :         ShipEntity *launched = nil;
     729             :         OOJS_BEGIN_FULL_NATIVE(context)
     730             :         launched = [station launchPatrol];
     731             :         OOJS_END_FULL_NATIVE
     732             :         OOJS_RETURN_OBJECT(launched);
     733             :         OOJS_NATIVE_EXIT
     734             : }
     735             : 
     736             : 
     737           0 : static JSBool StationLaunchPolice(JSContext *context, uintN argc, jsval *vp)
     738             : {
     739             :         OOJS_NATIVE_ENTER(context)
     740             :         
     741             :         StationEntity *station = nil;
     742             :         if (!JSStationGetStationEntity(context, OOJS_THIS, &station))  OOJS_RETURN_VOID; // stale reference, no-op
     743             :         
     744             :         NSArray *launched = nil;
     745             :         OOJS_BEGIN_FULL_NATIVE(context)
     746             :         launched = [station launchPolice];
     747             :         OOJS_END_FULL_NATIVE
     748             :         OOJS_RETURN_OBJECT(launched);
     749             :         OOJS_NATIVE_EXIT
     750             : }
     751             : 
     752           0 : static JSBool StationSetInterface(JSContext *context, uintN argc, jsval *vp)
     753             : {
     754             :         OOJS_NATIVE_ENTER(context)
     755             : 
     756             :         StationEntity *station = nil;
     757             :         if (!JSStationGetStationEntity(context, OOJS_THIS, &station))  OOJS_RETURN_VOID; // stale reference, no-op
     758             : 
     759             :         if (argc < 1)
     760             :         {
     761             :                 OOJSReportBadArguments(context, @"Station", @"setInterface", MIN(argc, 1U), OOJS_ARGV, NULL, @"key [, definition]");
     762             :                 return NO;
     763             :         }
     764             :         NSString *key = OOStringFromJSValue(context, OOJS_ARGV[0]);
     765             : 
     766             :         if (argc < 2 || JSVAL_IS_NULL(OOJS_ARGV[1]))
     767             :         {
     768             :                 [station setInterfaceDefinition:nil forKey:key];
     769             :                 OOJS_RETURN_VOID;
     770             :         }
     771             :         
     772             : 
     773             :         jsval                           value = JSVAL_NULL;
     774             :         jsval                           callback = JSVAL_NULL;
     775             :         JSObject                                *callbackThis = NULL;
     776             :         JSObject                        *params = NULL;
     777             : 
     778             :         NSString      *title = nil;
     779             :         NSString      *summary = nil;
     780             :         NSString      *category = nil;
     781             : 
     782             :         if (!JS_ValueToObject(context, OOJS_ARGV[1], &params))
     783             :         {
     784             :                 OOJSReportBadArguments(context, @"Station", @"setInterface", MIN(argc, 1U), OOJS_ARGV, NULL, @"key [, definition]");
     785             :                 return NO;
     786             :         }
     787             : 
     788             :         // get and validate title
     789             :         if (JS_GetProperty(context, params, "title", &value) == JS_FALSE || JSVAL_IS_VOID(value))
     790             :         {
     791             :                 OOJSReportBadArguments(context, @"Station", @"setInterface", MIN(argc, 1U), OOJS_ARGV, NULL, @"key [, definition]; if definition is set, it must have a 'title' property.");
     792             :                 return NO;
     793             :         }
     794             :         title = OOStringFromJSValue(context, value);
     795             :         if (title == nil || [title length] == 0) 
     796             :         {
     797             :                 OOJSReportBadArguments(context, @"Station", @"setInterface", MIN(argc, 1U), OOJS_ARGV, NULL, @"key [, definition]; if definition is set, 'title' property must be a non-empty string.");
     798             :                 return NO;
     799             :         }
     800             : 
     801             :         // get category with default
     802             :         if (JS_GetProperty(context, params, "category", &value) == JS_FALSE || JSVAL_IS_VOID(value))
     803             :         {
     804             :                 category = [NSString stringWithString:DESC(@"interfaces-category-uncategorised")];
     805             :         }
     806             :         else
     807             :         {
     808             :                 category = OOStringFromJSValue(context, value);
     809             :                 if (category == nil || [category length] == 0) {
     810             :                         category = [NSString stringWithString:DESC(@"interfaces-category-uncategorised")];
     811             :                 }
     812             :         }
     813             : 
     814             :         // get and validate summary
     815             :         if (JS_GetProperty(context, params, "summary", &value) == JS_FALSE || JSVAL_IS_VOID(value))
     816             :         {
     817             :                 OOJSReportBadArguments(context, @"Station", @"setInterface", MIN(argc, 1U), OOJS_ARGV, NULL, @"key [, definition]; if definition is set, it must have a 'summary' property.");
     818             :                 return NO;
     819             :         }
     820             :         summary = OOStringFromJSValue(context, value);
     821             :         if (summary == nil || [summary length] == 0) 
     822             :         {
     823             :                 OOJSReportBadArguments(context, @"Station", @"setInterface", MIN(argc, 1U), OOJS_ARGV, NULL, @"key [, definition]; if definition is set, 'summary' property must be a non-empty string.");
     824             :                 return NO;
     825             :         }
     826             : 
     827             :         // get and validate callback
     828             :         if (JS_GetProperty(context, params, "callback", &callback) == JS_FALSE || JSVAL_IS_VOID(callback))
     829             :         {
     830             :                 OOJSReportBadArguments(context, @"Station", @"setInterface", MIN(argc, 1U), OOJS_ARGV, NULL, @"key [, definition]; if definition is set, it must have a 'callback' property.");
     831             :                 return NO;
     832             :         }
     833             :         if (!OOJSValueIsFunction(context,callback))
     834             :         {
     835             :                 OOJSReportBadArguments(context, @"Station", @"setInterface", MIN(argc, 1U), OOJS_ARGV, NULL, @"key [, definition]; 'callback' property must be a function.");
     836             :                 return NO;
     837             :         }
     838             : 
     839             :         OOJSInterfaceDefinition* definition = [[OOJSInterfaceDefinition alloc] init];
     840             :         [definition setTitle:title];
     841             :         [definition setCategory:category];
     842             :         [definition setSummary:summary];
     843             :         [definition setCallback:callback];
     844             : 
     845             :         // get callback 'this'
     846             :         if (JS_GetProperty(context, params, "cbThis", &value) == JS_TRUE && !JSVAL_IS_VOID(value))
     847             :         {
     848             :                 JS_ValueToObject(context, value, &callbackThis);
     849             :                 [definition setCallbackThis:callbackThis];
     850             :                 // can do .bind(this) for callback instead
     851             :         }
     852             :         
     853             :         [station setInterfaceDefinition:definition forKey:key];
     854             : 
     855             :         [definition release];
     856             : 
     857             :         OOJS_RETURN_VOID;
     858             : 
     859             :         OOJS_NATIVE_EXIT
     860             : }
     861             : 
     862             : 
     863           0 : static JSBool StationSetMarketPrice(JSContext *context, uintN argc, jsval *vp)
     864             : {
     865             :         OOJS_NATIVE_ENTER(context)
     866             : 
     867             :         StationEntity *station = nil;
     868             :         if (!JSStationGetStationEntity(context, OOJS_THIS, &station))  OOJS_RETURN_VOID; // stale reference, no-op
     869             : 
     870             :         if (argc < 2)
     871             :         {
     872             :                 OOJSReportBadArguments(context, @"Station", @"setMarketPrice", MIN(argc, 2U), OOJS_ARGV, NULL, @"commodity, credits");
     873             :                 return NO;
     874             :         }
     875             :         
     876             :         OOCommodityType commodity = OOStringFromJSValue(context, OOJS_ARGV[0]);
     877             :         if (EXPECT_NOT(![[UNIVERSE commodities] goodDefined:commodity]))
     878             :         {
     879             :                 OOJSReportBadArguments(context, @"Station", @"setMarketPrice", MIN(argc, 2U), OOJS_ARGV, NULL, @"Unrecognised commodity type");
     880             :                 return NO;
     881             :         }
     882             : 
     883             :         int32 price;
     884             :         BOOL gotPrice = JS_ValueToInt32(context, OOJS_ARGV[1], &price);
     885             :         if (EXPECT_NOT(!gotPrice || price < 0))
     886             :         {
     887             :                 OOJSReportBadArguments(context, @"Station", @"setMarketPrice", MIN(argc, 2U), OOJS_ARGV, NULL, @"Price must be at least 0 decicredits");
     888             :                 return NO;
     889             :         }
     890             : 
     891             :         [station setPrice:(NSUInteger)price forCommodity:commodity];
     892             : 
     893             :         if (station == [PLAYER dockedStation] && [PLAYER guiScreen] == GUI_SCREEN_MARKET)
     894             :         {
     895             :                 [PLAYER setGuiToMarketScreen]; // refresh screen
     896             :         }
     897             : 
     898             :         OOJS_RETURN_BOOL(YES);
     899             : 
     900             :         OOJS_NATIVE_EXIT
     901             : }
     902             : 
     903             : 
     904           0 : static JSBool StationSetMarketQuantity(JSContext *context, uintN argc, jsval *vp)
     905             : {
     906             :         OOJS_NATIVE_ENTER(context)
     907             : 
     908             :         StationEntity *station = nil;
     909             :         if (!JSStationGetStationEntity(context, OOJS_THIS, &station))  OOJS_RETURN_VOID; // stale reference, no-op
     910             : 
     911             :         if (argc < 2)
     912             :         {
     913             :                 OOJSReportBadArguments(context, @"Station", @"setMarketQuantity", MIN(argc, 2U), OOJS_ARGV, NULL, @"commodity, units");
     914             :                 return NO;
     915             :         }
     916             :         
     917             :         OOCommodityType commodity = OOStringFromJSValue(context, OOJS_ARGV[0]);
     918             :         if (EXPECT_NOT(![[UNIVERSE commodities] goodDefined:commodity]))
     919             :         {
     920             :                 OOJSReportBadArguments(context, @"Station", @"setMarketQuantity", MIN(argc, 2U), OOJS_ARGV, NULL, @"Unrecognised commodity type");
     921             :                 return NO;
     922             :         }
     923             : 
     924             :         int32 quantity;
     925             :         BOOL gotQuantity = JS_ValueToInt32(context, OOJS_ARGV[1], &quantity);
     926             :         if (EXPECT_NOT(!gotQuantity || quantity < 0 || (OOCargoQuantity)quantity > [[station localMarket] capacityForGood:commodity]))
     927             :         {
     928             :                 OOJSReportBadArguments(context, @"Station", @"setMarketQuantity", MIN(argc, 2U), OOJS_ARGV, NULL, @"Quantity must be between 0 and the station market capacity");
     929             :                 return NO;
     930             :         }
     931             : 
     932             :         [station setQuantity:(OOCargoQuantity)quantity forCommodity:commodity];
     933             :         
     934             :         if (station == [PLAYER dockedStation] && [PLAYER guiScreen] == GUI_SCREEN_MARKET)
     935             :         {
     936             :                 [PLAYER setGuiToMarketScreen]; // refresh screen
     937             :         }
     938             : 
     939             :         OOJS_RETURN_BOOL(YES);
     940             : 
     941             :         OOJS_NATIVE_EXIT
     942             : }
     943             : 
     944             : 
     945           0 : static JSBool StationAddShipToShipyard(JSContext *context, uintN argc, jsval *vp)
     946             : {
     947             :         OOJS_NATIVE_ENTER(context)
     948             : 
     949             :         JSObject *params = NULL;
     950             :         StationEntity *station = nil;
     951             :         if (!JSStationGetStationEntity(context, OOJS_THIS, &station))  OOJS_RETURN_VOID; // stale reference, no-op
     952             : 
     953             :         if (argc != 1 || (!JSVAL_IS_NULL(OOJS_ARGV[0]) && !JS_ValueToObject(context, OOJS_ARGV[0], &params)))
     954             :         {
     955             :                 OOJSReportBadArguments(context, @"Station", @"addShipToShipyard", MIN(argc, 1U), OOJS_ARGV, NULL, @"shipyard item definition");
     956             :                 return NO;
     957             :         }
     958             : 
     959             :         // make sure the station has a shipyard
     960             :         if (![station hasShipyard]) {
     961             :                 OOJSReportWarningForCaller(context, @"Station", @"removeShipFromShipyard", @"Station does not have shipyard.");
     962             :                 return NO;
     963             :         }
     964             :         // make sure the shipyard has been generated
     965             :         if (![station localShipyard]) [station generateShipyard];
     966             :         NSMutableArray *shipyard = [station localShipyard];
     967             : 
     968             :         if (JSVAL_IS_NULL(OOJS_ARGV[0]))  OOJS_RETURN_VOID;     // OK, do nothing for null ship.
     969             : 
     970             :         NSMutableDictionary *result = [NSMutableDictionary dictionary];
     971             :         NSDictionary *shipyardDefinition = OOJSNativeObjectFromJSObject(context, JSVAL_TO_OBJECT(OOJS_ARGV[0]));
     972             :         // validate each element of the dictionary
     973             :         if (!shipyardDefinition) 
     974             :         {
     975             :                 OOJSReportBadArguments(context, @"Station", @"addShipToShipyard", MIN(argc, 1U), OOJS_ARGV, nil, @"valid dictionary object");
     976             :                 return NO;
     977             :         }
     978             :         if (![shipyardDefinition objectForKey:KEY_SHORT_DESCRIPTION]) 
     979             :         {
     980             :                 OOJSReportBadArguments(context, @"Station", @"addShipToShipyard", MIN(argc, 1U), OOJS_ARGV, nil, @"'short_description' in dictionary");
     981             :                 return NO;
     982             :         }
     983             :         [result setObject:[shipyardDefinition oo_stringForKey:@"short_description"] forKey:KEY_SHORT_DESCRIPTION];
     984             :         if (![shipyardDefinition objectForKey:SHIPYARD_KEY_SHIPDATA_KEY]) 
     985             :         {
     986             :                 OOJSReportBadArguments(context, @"Station", @"addShipToShipyard", MIN(argc, 1U), OOJS_ARGV, nil, @"'shipdata_key' in dictionary");
     987             :                 return NO;
     988             :         }
     989             :         // get the shipInfo and shipyardInfo for this key
     990             :         NSString                        *shipKey = [shipyardDefinition oo_stringForKey:SHIPYARD_KEY_SHIPDATA_KEY defaultValue:nil];
     991             :         OOShipRegistry          *registry = [OOShipRegistry sharedRegistry];
     992             :         NSMutableDictionary     *shipInfo = [NSMutableDictionary dictionaryWithDictionary:[registry shipInfoForKey:shipKey]];
     993             :         NSDictionary            *shipyardInfo = [registry shipyardInfoForKey:shipKey];
     994             :         if (!shipInfo) 
     995             :         {
     996             :                 OOJSReportWarningForCaller(context, @"Station", @"addShipToShipyard", @"Invalid shipdata_key provided.");
     997             :                 return NO;
     998             :         }
     999             :         // make sure the ship is a player ship
    1000             :         if ([[shipInfo oo_stringForKey:@"roles"] rangeOfString:@"player"].location == NSNotFound)
    1001             :         {
    1002             :                 OOJSReportWarningForCaller(context, @"Station", @"addShipToShipyard", @"shipdata_key not suitable for player role.");
    1003             :                 return NO;
    1004             :         }
    1005             :         if (!shipyardInfo) 
    1006             :         {
    1007             :                 OOJSReportWarningForCaller(context, @"Station", @"addShipToShipyard", @"No shipyard information found for shipdata_key.");
    1008             :                 return NO;
    1009             :         }
    1010             :         // ok, feel pretty safe to include this ship now
    1011             :         [result setObject:shipKey forKey:SHIPYARD_KEY_SHIPDATA_KEY];
    1012             : 
    1013             :         // add an ID
    1014             :         Random_Seed ship_seed = [UNIVERSE marketSeed];
    1015             :         int superRand1 = ship_seed.a * 0x10000 + ship_seed.c * 0x100 + ship_seed.e;
    1016             :         uint32_t superRand2 = ship_seed.b * 0x10000 + ship_seed.d * 0x100 + ship_seed.f;
    1017             :         superRand2 &= Ranrot();
    1018             :         NSString *shipID = [NSString stringWithFormat:@"%06x-%06x", superRand1, superRand2];
    1019             :         [result setObject:shipID forKey:SHIPYARD_KEY_ID];
    1020             : 
    1021             :         if (![shipyardDefinition objectForKey:SHIPYARD_KEY_PRICE]) 
    1022             :         {
    1023             :                 // if not provided, get the price from the registry
    1024             :                 OOCreditsQuantity price = [shipyardInfo oo_unsignedIntForKey:KEY_PRICE];
    1025             :                 [result setObject:[NSNumber numberWithUnsignedLongLong:price] forKey:SHIPYARD_KEY_PRICE];
    1026             :         }
    1027             :         else 
    1028             :         {
    1029             :                 OOCreditsQuantity price = [shipyardDefinition oo_unsignedIntForKey:SHIPYARD_KEY_PRICE];
    1030             :                 if (price > 0)
    1031             :                 {
    1032             :                         [result setObject:[NSNumber numberWithUnsignedLongLong:price] forKey:SHIPYARD_KEY_PRICE];
    1033             :                 }
    1034             :                 else
    1035             :                 {
    1036             :                         OOJSReportBadArguments(context, @"Station", @"addShipToShipyard", MIN(argc, 1U), OOJS_ARGV, nil, @"'price' in dictionary");
    1037             :                         return NO;
    1038             :                 }
    1039             :         }
    1040             : 
    1041             :         if (![shipyardDefinition objectForKey:SHIPYARD_KEY_PERSONALITY]) 
    1042             :         {
    1043             :                 // default to 0 if not supplied
    1044             :                 [result setObject:0 forKey:SHIPYARD_KEY_PERSONALITY];
    1045             :         } 
    1046             :         else
    1047             :         {
    1048             :                 [result setObject:[NSNumber numberWithUnsignedLongLong:[shipyardDefinition oo_unsignedIntForKey:SHIPYARD_KEY_PERSONALITY]] forKey:SHIPYARD_KEY_PERSONALITY];
    1049             :         }
    1050             : 
    1051             :         NSArray *extras = [shipyardDefinition oo_arrayForKey:KEY_EQUIPMENT_EXTRAS];
    1052             :         if (!extras) 
    1053             :         {
    1054             :                 // pick up defaults if extras not supplied
    1055             :                 extras = [NSArray arrayWithArray:[[shipyardInfo oo_dictionaryForKey:KEY_STANDARD_EQUIPMENT] oo_arrayForKey:KEY_EQUIPMENT_EXTRAS]];
    1056             :         }
    1057             :         if ([extras count] > 0) {
    1058             :                 // go looking for lasers and add them directly to our shipInfo
    1059             :                 NSString* fwdWeaponString = [[shipyardInfo oo_dictionaryForKey:KEY_STANDARD_EQUIPMENT] oo_stringForKey:KEY_EQUIPMENT_FORWARD_WEAPON];
    1060             :                 NSString* aftWeaponString = [[shipyardInfo oo_dictionaryForKey:KEY_STANDARD_EQUIPMENT] oo_stringForKey:KEY_EQUIPMENT_AFT_WEAPON];
    1061             :                 OOWeaponFacingSet availableFacings = [shipyardInfo oo_unsignedIntForKey:KEY_WEAPON_FACINGS defaultValue:VALID_WEAPON_FACINGS] & VALID_WEAPON_FACINGS;
    1062             : 
    1063             :                 OOWeaponType fwdWeapon = OOWeaponTypeFromEquipmentIdentifierSloppy(fwdWeaponString);
    1064             :                 OOWeaponType aftWeapon = OOWeaponTypeFromEquipmentIdentifierSloppy(aftWeaponString);
    1065             : 
    1066             :                 unsigned int i;
    1067             :                 NSString *equipmentKey = nil;
    1068             :                 for (i = 0; i < [extras count]; i++) {
    1069             :                         equipmentKey = [extras oo_stringAtIndex:i];
    1070             :                         if ([equipmentKey hasPrefix:@"EQ_WEAPON"])
    1071             :                         {
    1072             :                                 OOWeaponType new_weapon = OOWeaponTypeFromEquipmentIdentifierSloppy(equipmentKey);
    1073             :                                 //fit best weapon forward
    1074             :                                 if (availableFacings & WEAPON_FACING_FORWARD && [new_weapon weaponThreatAssessment] > [fwdWeapon weaponThreatAssessment])
    1075             :                                 {
    1076             :                                         //again remember to divide price by 10 to get credits from tenths of credit
    1077             :                                         fwdWeaponString = equipmentKey;
    1078             :                                         fwdWeapon = new_weapon;
    1079             :                                         [shipInfo setObject:fwdWeaponString forKey:KEY_EQUIPMENT_FORWARD_WEAPON];
    1080             :                                 }
    1081             :                                 else 
    1082             :                                 {
    1083             :                                         //if less good than current forward, try fitting is to rear
    1084             :                                         if (availableFacings & WEAPON_FACING_AFT && (isWeaponNone(aftWeapon) || [new_weapon weaponThreatAssessment] > [aftWeapon weaponThreatAssessment]))
    1085             :                                         {
    1086             :                                                 aftWeaponString = equipmentKey;
    1087             :                                                 aftWeapon = new_weapon;
    1088             :                                                 [shipInfo setObject:aftWeaponString forKey:KEY_EQUIPMENT_AFT_WEAPON];
    1089             :                                         }
    1090             :                                 }
    1091             :                         }
    1092             :                 }
    1093             :         }
    1094             :         // add the extras
    1095             :         [result setObject:extras forKey:KEY_EQUIPMENT_EXTRAS];
    1096             :         // add the ship spec
    1097             :         [result setObject:shipInfo forKey:SHIPYARD_KEY_SHIP];
    1098             :         // add it to the station's shipyard
    1099             :         [shipyard addObject:result];
    1100             : 
    1101             :         // refresh the screen if the shipyard is currently being displayed
    1102             :         if(station == [PLAYER dockedStation] && [PLAYER guiScreen] == GUI_SCREEN_SHIPYARD)
    1103             :         {
    1104             :                 [PLAYER setGuiToShipyardScreen:0];
    1105             :         }       
    1106             : 
    1107             :         OOJS_RETURN_BOOL(YES);
    1108             : 
    1109             :         OOJS_NATIVE_EXIT
    1110             : }
    1111             : 
    1112             : 
    1113           0 : static JSBool StationRemoveShipFromShipyard(JSContext *context, uintN argc, jsval *vp)
    1114             : {
    1115             :         OOJS_NATIVE_ENTER(context)
    1116             : 
    1117             :         StationEntity *station = nil;
    1118             :         if (!JSStationGetStationEntity(context, OOJS_THIS, &station))  OOJS_RETURN_VOID; // stale reference, no-op
    1119             : 
    1120             :         // make sure the station has a shipyard
    1121             :         if (![station hasShipyard]) {
    1122             :                 OOJSReportWarningForCaller(context, @"Station", @"removeShipFromShipyard", @"Station does not have shipyard.");
    1123             :                 return NO;
    1124             :         }
    1125             :         // make sure the shipyard has been generated
    1126             :         if (![station localShipyard]) [station generateShipyard];
    1127             :         NSMutableArray *shipyard = [station localShipyard];
    1128             :         
    1129             :         int32 shipIndex = -1;
    1130             :         BOOL gotIndex = YES;
    1131             :         gotIndex = JS_ValueToInt32(context, OOJS_ARGV[0], &shipIndex);
    1132             : 
    1133             :         if (argc != 1 || (!JSVAL_IS_NULL(OOJS_ARGV[0]) && !gotIndex) || shipIndex < 0 || (shipIndex + 1) > [shipyard count]) 
    1134             :         {
    1135             :                 OOJSReportBadArguments(context, @"Station", @"removeShipFromShipyard", MIN(argc, 1U), OOJS_ARGV, NULL, @"valid ship index");
    1136             :                 return NO;
    1137             :         }
    1138             : 
    1139             :         [shipyard removeObjectAtIndex:shipIndex];
    1140             : 
    1141             :         // refresh the screen if the shipyard is currently being displayed
    1142             :         if(station == [PLAYER dockedStation] && [PLAYER guiScreen] == GUI_SCREEN_SHIPYARD)
    1143             :         {
    1144             :                 [PLAYER setGuiToShipyardScreen:0];
    1145             :         }
    1146             : 
    1147             :         OOJS_RETURN_BOOL(YES);
    1148             : 
    1149             :         OOJS_NATIVE_EXIT
    1150             : }
    1151             : 

Generated by: LCOV version 1.14