lab-electrolyte/src/inventory.gd
2026-06-29 00:20:57 +05:00

212 lines
7 KiB
GDScript

extends Node
class_name Inventory
@export var open_on_top: bool
@export var capacity: float = 10.
var inventory: Dictionary[StringName,RuntimeSubstanceData]
var mean_temperature: float:
set(new_temperature):
mean_temperature = new_temperature
temperature_changed.emit(new_temperature)
if new_temperature != 0:
update_temperature()
var total_amount: float:
set(value):
pass
get:
var result: float = 0
for sub in inventory:
result += inventory[sub].amount
return result
signal inventory_changed(substances: Array[RuntimeSubstanceData], capacity: float)
signal reacted_with_gasses(gasses: Array[RuntimeSubstanceData])
signal temperature_changed(to: float)
func _ready() -> void:
inventory_changed.emit(inventory.values(),capacity)
func update_solutions():
var has_water = inventory.has("Вода")
if has_water:
for sub in inventory:
inventory[sub].is_solution = ReactionRegistry.is_water_solution(inventory[sub].substance)
func add_substance(data: RuntimeSubstanceData) -> void:
if data.substance.scientific_name in inventory:
inventory[data.substance.scientific_name].add(data)
else:
inventory[data.substance.scientific_name] = data
check_for_reactions()
recalculate_temperature()
update_solutions()
inventory_changed.emit(inventory.values(),capacity)
func add_substance_no_callback(data: RuntimeSubstanceData) -> void:
if data.substance.scientific_name in inventory:
inventory[data.substance.scientific_name].add(data)
else:
inventory[data.substance.scientific_name] = data
func add_inventory(substances: Array[RuntimeSubstanceData]) -> void:
for sub in substances:
add_substance_no_callback(sub)
check_for_reactions()
recalculate_temperature()
update_solutions()
inventory_changed.emit(inventory.values(),capacity)
func extract(amount: float) -> Array[RuntimeSubstanceData]:
if len(inventory) == 0:
return []
var result: Array[RuntimeSubstanceData] = []
var extract_amount = amount/len(inventory)
var sorted_by_amount: Array[RuntimeSubstanceData] = inventory.values()
sorted_by_amount.sort_custom(sort_by_amount)
for substance: RuntimeSubstanceData in sorted_by_amount:
var result_substance: RuntimeSubstanceData = substance.duplicate()
if substance.amount >= extract_amount:
result_substance.amount = extract_amount
inventory[result_substance.substance.scientific_name].amount -= extract_amount
else:
extract_amount += (extract_amount - result_substance.amount)/len(sorted_by_amount)
inventory[result_substance.substance.scientific_name].amount = 0
result.append(result_substance)
if inventory[result_substance.substance.scientific_name].amount == 0:
inventory.erase(result_substance.substance.scientific_name)
update_solutions()
inventory_changed.emit(inventory.values(),capacity)
return result
func extract_solid(amount: float) -> Array[RuntimeSubstanceData]:
if len(inventory) == 0:
return []
var result: Array[RuntimeSubstanceData] = []
var extract_amount = amount/len(inventory)
var sorted_by_amount: Array[RuntimeSubstanceData] = inventory.values()
sorted_by_amount.sort_custom(sort_by_amount)
sorted_by_amount = sorted_by_amount.filter(filter_solids)
for substance: RuntimeSubstanceData in sorted_by_amount:
var result_substance: RuntimeSubstanceData = substance.duplicate()
if substance.amount >= extract_amount:
result_substance.amount = extract_amount
inventory[result_substance.substance.scientific_name].amount -= extract_amount
else:
extract_amount += (extract_amount - result_substance.amount)/len(sorted_by_amount)
inventory[result_substance.substance.scientific_name].amount = 0
result.append(result_substance)
if inventory[result_substance.substance.scientific_name].amount == 0:
inventory.erase(result_substance.substance.scientific_name)
update_solutions()
inventory_changed.emit(inventory.values(),capacity)
return result
func extract_substance(key: String, extract_amount: float) -> RuntimeSubstanceData:
var substance: RuntimeSubstanceData = inventory[key]
var result_substance: RuntimeSubstanceData = substance.duplicate()
if substance.amount >= extract_amount:
result_substance.amount = extract_amount
inventory[result_substance.substance.scientific_name].amount -= extract_amount
else:
inventory[result_substance.substance.scientific_name].amount = 0
if inventory[result_substance.substance.scientific_name].amount == 0:
inventory.erase(result_substance.substance.scientific_name)
update_solutions()
inventory_changed.emit(inventory.values(),capacity)
return result_substance
func sort_by_amount(a: RuntimeSubstanceData, b: RuntimeSubstanceData) -> bool:
return a.amount < b.amount
func filter_solids(a: RuntimeSubstanceData) -> bool:
return a.substance.melting_point > a.temperature
func update_temperature() -> void:
if len(inventory) == 0:
mean_temperature = 0
return
for sub in inventory:
inventory[sub].temperature = mean_temperature
check_for_reactions()
func recalculate_temperature() -> void:
if len(inventory) == 0:
mean_temperature = 0
return
var temperature_sum: float = 0
for sub in inventory:
temperature_sum += inventory[sub].temperature
mean_temperature = temperature_sum / len(inventory)
func check_for_reactions() -> void:
var substances: Array[Substance] = []
substances.resize(len(inventory))
var temp_inv: Array[RuntimeSubstanceData] = inventory.values()
for i in range(len(temp_inv)):
substances[i] = temp_inv[i].substance
var found_reaction = ReactionRegistry.find_appropriate_reaction(substances,mean_temperature)
if found_reaction == null:
return
var reagents: Dictionary[StringName, ReactionSubstance] = found_reaction.input_substances_dict()
var reaction_mass: float = INF
for key in reagents:
var reagent_mass: float = inventory[key].amount/reagents[key].coefficient
reaction_mass = min(reagent_mass,reaction_mass)
for key in reagents:
extract_substance(key,reaction_mass * reagents[key].coefficient)
for sub in found_reaction.output_substances:
var data: RuntimeSubstanceData = RuntimeSubstanceData.new()
data.amount = sub.coefficient * reaction_mass
data.substance = sub.substance
data.temperature = mean_temperature
add_substance_no_callback(data)
check_for_reactions()
recalculate_temperature()
var gasses = find_gases()
if gasses != []:
reacted_with_gasses.emit(gasses)
update_solutions()
inventory_changed.emit(inventory.values(),capacity)
GuiSignalBus.push("Произошла реакция")
if len(find_odor()) > 0:
GuiSignalBus.push("Появился запах")
func find_gases() -> Array[RuntimeSubstanceData]:
var gasses: Array[RuntimeSubstanceData] = []
for key in inventory:
if inventory[key].substance.boiling_point < mean_temperature:
gasses.append(inventory[key])
return gasses
func find_odor() -> Array[RuntimeSubstanceData]:
var result = []
for key in inventory:
if inventory[key].substance in [preload("res://assets/substances/CH3COOH.tres")]:
result.push_back(inventory[key])
return result
func get_text() -> String:
var result = ""
for key in inventory:
result += key + "+"
return result.left(len(result)-1)