111 lines
5.7 KiB
GDScript
111 lines
5.7 KiB
GDScript
extends RefCounted
|
|
|
|
const DEFINITIONS := [
|
|
preload("res://resources/items/recycler.tres"),
|
|
preload("res://resources/items/virus.tres"),
|
|
preload("res://resources/items/titanium_armor.tres"),
|
|
preload("res://resources/items/combat_drones.tres"),
|
|
preload("res://resources/items/teleport.tres"),
|
|
preload("res://resources/items/cloak.tres"),
|
|
preload("res://resources/items/mine_layer.tres"),
|
|
preload("res://resources/items/flares.tres"),
|
|
preload("res://resources/items/solar_shield_charge.tres"),
|
|
preload("res://resources/items/auxiliary_shield.tres"),
|
|
|
|
preload("res://resources/items/gamma_cannon.tres"),
|
|
preload("res://resources/items/plasma_cannon.tres"),
|
|
preload("res://resources/items/beam_laser.tres"),
|
|
preload("res://resources/items/pulse_laser.tres"),
|
|
preload("res://resources/items/machine_gun.tres"),
|
|
preload("res://resources/items/external_turret.tres"),
|
|
preload("res://resources/items/missile_launcher.tres"),
|
|
preload("res://resources/items/unguided_missile.tres"),
|
|
preload("res://resources/items/reinforced_shield.tres"),
|
|
preload("res://resources/items/hull_plating.tres"),
|
|
preload("res://resources/items/compact_generator.tres"),
|
|
preload("res://resources/items/engine_extension.tres"),
|
|
preload("res://resources/items/shield_recharger.tres"),
|
|
preload("res://resources/items/afterburner.tres"),
|
|
preload("res://resources/items/shield_charge.tres"),
|
|
preload("res://resources/items/repair_drones.tres"),
|
|
preload("res://resources/items/ship_computer.tres"),
|
|
]
|
|
const AFFIX_DATABASE := preload("res://resources/items/affix_database.tres")
|
|
|
|
static func generate(level: int, enemy_tier: int = 0) -> ItemInstance:
|
|
return generate_for_definition(available_definitions().pick_random(), level, enemy_tier)
|
|
|
|
static func available_definitions() -> Array:
|
|
var lab := preload("res://scripts/planets/laboratory.gd")
|
|
var pool := DEFINITIONS.filter(func(definition): return definition.item_id not in lab.IDS)
|
|
for id in lab.IDS:
|
|
if GameState.captain.expedition.laboratory_unlocks.get(id,false): pool.append(lab.definition(id))
|
|
return pool
|
|
|
|
static func generate_loot(level: int, enemy_tier: int = 0, definition: ItemDefinition = null, equipment_luck_percent: float = 0.0) -> ItemInstance:
|
|
var loot_level := GameState.captain.roll_loot_level(level, -1.0, equipment_luck_percent)
|
|
return generate_for_definition(definition if definition != null else available_definitions().pick_random(), loot_level, enemy_tier)
|
|
|
|
static func generate_for_definition(definition: ItemDefinition, level: int, enemy_tier: int = 0) -> ItemInstance:
|
|
var item := ItemInstance.new()
|
|
item.definition = definition
|
|
roll_base_values(item, level)
|
|
if definition.category == ItemDefinition.Category.ACTIVE_EXTENSION:
|
|
if item.is_passive_extension():
|
|
item.passive_value = preload("res://scripts/items/passive_extension_rolls.gd").roll_value(definition.passive_effect)
|
|
else:
|
|
item.extension_cooldown = ItemInstance.EXTENSION_COOLDOWNS.roll_seconds()
|
|
return item
|
|
var roll := randf()
|
|
var count := 1 if roll < 0.5 else (2 if roll < 0.75 else (3 if roll < 0.89 else (4 if roll < 0.97 else 5)))
|
|
if enemy_tier == 1:
|
|
count = mini(5, count + 1)
|
|
elif enemy_tier >= 2:
|
|
count = maxi(4, count)
|
|
item.additional_modifiers = AFFIX_DATABASE.roll_affixes(item.definition, item.item_level, count)
|
|
item.rarity = clampi(item.additional_modifiers.size() - 1, 0, 4)
|
|
return item
|
|
|
|
static func roll_base_values(item: ItemInstance, level: int) -> void:
|
|
var definition := item.definition
|
|
if definition.weapon_effect == "artillery": item.artillery_balance_revision = 1
|
|
item.item_level = clampi(level, 1, 1000)
|
|
var scale_factor := preload("res://scripts/levels/level_balance.gd").item_stat_scale(item.item_level)
|
|
item.primary_value_override = definition.primary_value * scale_factor * randf_range(0.8, 1.2)
|
|
if definition.primary_stat == "max_speed":
|
|
item.primary_value_override = randf_range(1.0, 5.0) * scale_factor
|
|
if definition.category == ItemDefinition.Category.WEAPON:
|
|
var lower := randi_range(mini(definition.damage_lower_roll_min, definition.damage_lower_roll_max), maxi(definition.damage_lower_roll_min, definition.damage_lower_roll_max))
|
|
var spread := randi_range(mini(definition.damage_spread_roll_min, definition.damage_spread_roll_max), maxi(definition.damage_spread_roll_min, definition.damage_spread_roll_max))
|
|
item.damage_min = maxf(1.0, roundf(lower * scale_factor))
|
|
item.damage_max = maxf(item.damage_min + 1.0, roundf((lower + spread) * scale_factor))
|
|
item.primary_value_override = (item.damage_min + item.damage_max) * 0.5
|
|
item.energy_regeneration_override = definition.energy_regeneration_bonus * scale_factor * randf_range(0.8, 1.2)
|
|
if definition.shield_regeneration_bonus > 0.0:
|
|
item.shield_regeneration_override = definition.shield_regeneration_bonus * scale_factor * randf_range(0.8, 1.2)
|
|
|
|
static func can_advance(item: ItemInstance) -> bool:
|
|
return item != null and item.definition != null and item.definition.category != ItemDefinition.Category.CONSUMABLE and item.item_level >= 1 and item.item_level < 1000
|
|
|
|
static func advance(item: ItemInstance) -> bool:
|
|
if not can_advance(item): return false
|
|
var level := item.item_level + 1
|
|
var updated: Array[ItemStatModifier] = []
|
|
for modifier in item.additional_modifiers:
|
|
if modifier == null:
|
|
updated.append(null)
|
|
continue
|
|
# Keep shared modifiers on other items untouched.
|
|
var copy := modifier.duplicate() as ItemStatModifier
|
|
if copy.affix == null:
|
|
for candidate in AFFIX_DATABASE.affixes:
|
|
if candidate != null and candidate.stat_key == copy.stat_key and candidate.can_roll(item.definition,level):
|
|
copy.affix = candidate
|
|
break
|
|
if copy.affix != null: copy.value = copy.affix.roll_value(level)
|
|
# Fixed legacy bonuses without a defined roll range stay fixed.
|
|
updated.append(copy)
|
|
roll_base_values(item,level)
|
|
item.additional_modifiers = updated
|
|
return true
|