212 lines
7 KiB
GDScript
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)
|