diff --git a/Resources/Config/equipment.plist b/Resources/Config/equipment.plist index f48c689d..a1197f5c 100644 --- a/Resources/Config/equipment.plist +++ b/Resources/Config/equipment.plist @@ -177,6 +177,7 @@ "Provides life support, entertainment and comfort for a single passenger.", { available_to_all = true; + available_to_NPCs = false; requires_cargo_space = 5; } ), @@ -186,6 +187,7 @@ "Removes a passenger berth.", { available_to_all = true; + available_to_NPCs = false; requires_free_passenger_berth = true; } ), diff --git a/src/Core/Entities/ShipEntity.m b/src/Core/Entities/ShipEntity.m index 8a3210c7..53057f2c 100644 --- a/src/Core/Entities/ShipEntity.m +++ b/src/Core/Entities/ShipEntity.m @@ -2110,7 +2110,7 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other) - (BOOL) canAddEquipment:(NSString *)equipmentKey -{ +{ if ([equipmentKey hasSuffix:@"_DAMAGED"]) { equipmentKey = [equipmentKey substringToIndex:[equipmentKey length] - [@"_DAMAGED" length]]; @@ -2122,7 +2122,9 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other) if (missiles >= max_missiles) return NO; } - if ([self hasEquipmentItem:equipmentKey]) return NO; + OOEquipmentType *eqType = [OOEquipmentType equipmentTypeWithIdentifier:equipmentKey]; + + if (![eqType canAwardMultiple] && [self hasEquipmentItem:equipmentKey]) return NO; if (![self equipmentValidToAdd:equipmentKey]) return NO; return YES; @@ -2254,6 +2256,14 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other) if ([eqType requiresFreePassengerBerth] && [self passengerCount] >= [self passengerCapacity]) return NO; if ([eqType requiresFullFuel] && [self fuel] < [self fuelCapacity]) return NO; if ([eqType requiresNonFullFuel] && [self fuel] >= [self fuelCapacity]) return NO; + if ([self isPlayer]) + { + if (![eqType isAvailableToPlayer]) return NO; + } + else + { + if (![eqType isAvailableToNPCs]) return NO; + } return YES; } diff --git a/src/Core/OOEquipmentType.h b/src/Core/OOEquipmentType.h index e9198da9..86ccd3a5 100644 --- a/src/Core/OOEquipmentType.h +++ b/src/Core/OOEquipmentType.h @@ -50,7 +50,9 @@ SOFTWARE. _requiresFullFuel: 1, _requiresNonFullFuel: 1, _isMissileOrMine: 1, - _isVisible: 1; + _isVisible: 1, + _isAvailableToPlayer: 1, + _isAvailableToNPCs: 1; OOCargoQuantity _requiredCargoSpace; NSSet *_requiresEquipment; NSSet *_requiresAnyEquipment; @@ -95,6 +97,9 @@ SOFTWARE. - (BOOL) canBeDamaged; - (BOOL) isVisible; // Visible in UI? +- (BOOL) isAvailableToPlayer; +- (BOOL) isAvailableToNPCs; + - (OOCargoQuantity) requiredCargoSpace; - (NSSet *) requiresEquipment; // Set of equipment identifiers; all items required - (NSSet *) requiresAnyEquipment; // Set of equipment identifiers; any item required diff --git a/src/Core/OOEquipmentType.m b/src/Core/OOEquipmentType.m index 2fbb3c76..4878266d 100644 --- a/src/Core/OOEquipmentType.m +++ b/src/Core/OOEquipmentType.m @@ -178,6 +178,8 @@ static NSDictionary *sMissilesRegistry = nil; _requiresNonFullFuel = YES; } _isVisible = YES; + _isAvailableToPlayer = YES; + _isAvailableToNPCs = YES; } if (OK && [info count] > EQUIPMENT_EXTRA_INFO_INDEX) @@ -194,6 +196,9 @@ static NSDictionary *sMissilesRegistry = nil; if ((strict && !strictModeCompatible) || (!strict && strictModeOnly)) OK = NO; _isAvailableToAll = [extra oo_boolForKey:@"available_to_all" defaultValue:_isAvailableToAll]; + _isAvailableToPlayer = [extra oo_boolForKey:@"available_to_player" defaultValue:_isAvailableToPlayer]; + _isAvailableToNPCs = [extra oo_boolForKey:@"available_to_NPCs" defaultValue:_isAvailableToNPCs]; + _isMissileOrMine = [extra oo_boolForKey:@"is_external_store" defaultValue:_isMissileOrMine]; _requiresEmptyPylon = [extra oo_boolForKey:@"requires_empty_pylon" defaultValue:_requiresEmptyPylon]; _requiresMountedPylon = [extra oo_boolForKey:@"requires_mounted_pylon" defaultValue:_requiresMountedPylon]; @@ -426,6 +431,18 @@ static NSDictionary *sMissilesRegistry = nil; } +- (BOOL) isAvailableToPlayer +{ + return _isAvailableToPlayer; +} + + +- (BOOL) isAvailableToNPCs +{ + return _isAvailableToNPCs; +} + + - (OOCargoQuantity) requiredCargoSpace { return _requiredCargoSpace; diff --git a/src/Core/Scripting/OOJSEquipmentInfo.m b/src/Core/Scripting/OOJSEquipmentInfo.m index 59db3c33..b945914e 100644 --- a/src/Core/Scripting/OOJSEquipmentInfo.m +++ b/src/Core/Scripting/OOJSEquipmentInfo.m @@ -45,13 +45,18 @@ static JSBool EquipmentInfoStaticInfoForKey(JSContext *context, JSObject *this, enum { // Property IDs + kEquipmentInfo_canAwardMultiple, + kEquipmentInfo_canBeDamaged, kEquipmentInfo_description, kEquipmentInfo_effectiveTechLevel, kEquipmentInfo_equipmentKey, kEquipmentInfo_incompatibleEquipment, kEquipmentInfo_isAvailableToAll, + kEquipmentInfo_isAvailableToNPCs, + kEquipmentInfo_isAvailableToPlayer, kEquipmentInfo_isExternalStore, // is missile or mine kEquipmentInfo_isPortableBetweenShips, + kEquipmentInfo_isVisible, kEquipmentInfo_name, kEquipmentInfo_price, kEquipmentInfo_requiredCargoSpace, @@ -72,13 +77,18 @@ enum static JSPropertySpec sEquipmentInfoProperties[] = { // JS name ID flags + { "canAwardMultiple", kEquipmentInfo_canAwardMultiple, JSPROP_PERMANENT | JSPROP_ENUMERATE | JSPROP_READONLY }, + { "canBeDamaged", kEquipmentInfo_canBeDamaged, JSPROP_PERMANENT | JSPROP_ENUMERATE | JSPROP_READONLY }, { "description", kEquipmentInfo_description, JSPROP_PERMANENT | JSPROP_ENUMERATE | JSPROP_READONLY }, { "effectiveTechLevel", kEquipmentInfo_effectiveTechLevel, JSPROP_PERMANENT | JSPROP_ENUMERATE }, { "equipmentKey", kEquipmentInfo_equipmentKey, JSPROP_PERMANENT | JSPROP_ENUMERATE | JSPROP_READONLY }, { "incompatibleEquipment", kEquipmentInfo_incompatibleEquipment, JSPROP_PERMANENT | JSPROP_ENUMERATE | JSPROP_READONLY }, { "isAvailableToAll", kEquipmentInfo_isAvailableToAll, JSPROP_PERMANENT | JSPROP_ENUMERATE | JSPROP_READONLY }, + { "isAvailableToNPCs", kEquipmentInfo_isAvailableToNPCs, JSPROP_PERMANENT | JSPROP_ENUMERATE | JSPROP_READONLY }, + { "isAvailableToPlayer", kEquipmentInfo_isAvailableToPlayer, JSPROP_PERMANENT | JSPROP_ENUMERATE | JSPROP_READONLY }, { "isExternalStore", kEquipmentInfo_isExternalStore, JSPROP_PERMANENT | JSPROP_ENUMERATE | JSPROP_READONLY }, { "isPortableBetweenShips", kEquipmentInfo_isPortableBetweenShips, JSPROP_PERMANENT | JSPROP_ENUMERATE | JSPROP_READONLY }, + { "isVisible", kEquipmentInfo_isVisible, JSPROP_PERMANENT | JSPROP_ENUMERATE | JSPROP_READONLY }, { "name", kEquipmentInfo_name, JSPROP_PERMANENT | JSPROP_ENUMERATE | JSPROP_READONLY }, { "price", kEquipmentInfo_price, JSPROP_PERMANENT | JSPROP_ENUMERATE | JSPROP_READONLY }, { "requiredCargoSpace", kEquipmentInfo_requiredCargoSpace, JSPROP_PERMANENT | JSPROP_ENUMERATE | JSPROP_READONLY }, @@ -205,6 +215,14 @@ static JSBool EquipmentInfoGetProperty(JSContext *context, JSObject *this, jsval result = [eqType name]; break; + case kEquipmentInfo_canAwardMultiple: + *outValue = BOOLToJSVal([eqType canAwardMultiple]); + break; + + case kEquipmentInfo_canBeDamaged: + *outValue = BOOLToJSVal([eqType canBeDamaged]); + break; + case kEquipmentInfo_description: result = [eqType descriptiveText]; break; @@ -225,6 +243,14 @@ static JSBool EquipmentInfoGetProperty(JSContext *context, JSObject *this, jsval *outValue = BOOLToJSVal([eqType isAvailableToAll]); break; + case kEquipmentInfo_isAvailableToNPCs: + *outValue = BOOLToJSVal([eqType isAvailableToNPCs]); + break; + + case kEquipmentInfo_isAvailableToPlayer: + *outValue = BOOLToJSVal([eqType isAvailableToPlayer]); + break; + case kEquipmentInfo_requiresEmptyPylon: *outValue = BOOLToJSVal([eqType requiresEmptyPylon]); break; @@ -261,6 +287,10 @@ static JSBool EquipmentInfoGetProperty(JSContext *context, JSObject *this, jsval *outValue = BOOLToJSVal([eqType isPortableBetweenShips]); break; + case kEquipmentInfo_isVisible: + *outValue = BOOLToJSVal([eqType isVisible]); + break; + case kEquipmentInfo_requiredCargoSpace: *outValue = BOOLToJSVal([eqType requiredCargoSpace]); break; diff --git a/src/Core/Scripting/OOJSShip.m b/src/Core/Scripting/OOJSShip.m index b75ae7ba..a8b7d5b7 100644 --- a/src/Core/Scripting/OOJSShip.m +++ b/src/Core/Scripting/OOJSShip.m @@ -1461,6 +1461,7 @@ static JSBool ShipCanAwardEquipment(JSContext *context, JSObject *this, uintN ar { ShipEntity *thisEnt = nil; NSString *key = nil; + OOEquipmentType *eqType = nil; BOOL result; BOOL isBerth; BOOL exists; @@ -1476,23 +1477,14 @@ static JSBool ShipCanAwardEquipment(JSContext *context, JSObject *this, uintN ar if (exists) { + eqType = [OOEquipmentType equipmentTypeWithIdentifier:key]; + result = YES; + isBerth = [key isEqualToString:@"EQ_PASSENGER_BERTH"]; // can't add fuel as equipment, can add multiple berths if there's space. - result = ![key isEqualToString:@"EQ_FUEL"] && (![thisEnt hasEquipmentItem:key] || - (isBerth && [thisEnt availableCargoSpace] >= 5)); - if (result) - { - if ( ([key isEqualToString:@"EQ_ENERGY_BOMB"] && [OOEquipmentType equipmentTypeWithIdentifier:key] == nil) - || (![thisEnt isPlayer] && (isBerth || [key isEqualToString:@"EQ_PASSENGER_BERTH_REMOVAL"])) - || ([key isEqualToString:@"EQ_MISSILE_REMOVAL"] && [thisEnt missileCount] == 0) ) - { - result = NO; - } - else - { - result = [thisEnt canAddEquipment:key]; - } - } + if ([key isEqualToString:@"EQ_FUEL"]) result = NO; + + if (result) result = [thisEnt canAddEquipment:key]; } else {