Use worker for research
This commit is contained in:
@@ -148,10 +148,18 @@ func _grant_cycle_income(cycle_count: int) -> void:
|
|||||||
if not _is_research_active(data.research_data.id):
|
if not _is_research_active(data.research_data.id):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
var research_workers: int = game_state.get_research_workers()
|
||||||
|
if research_workers < data.research_data.min_workers_for_xp:
|
||||||
|
return
|
||||||
|
|
||||||
var amount_float: float = produced.mantissa * pow(10.0, float(produced.exponent))
|
var amount_float: float = produced.mantissa * pow(10.0, float(produced.exponent))
|
||||||
var research_xp_amount: BigNumber = BigNumber.from_float(data.research_data.xp_per_currency_produced * amount_float)
|
var base_xp: BigNumber = BigNumber.from_float(data.research_data.xp_per_currency_produced * amount_float)
|
||||||
if game_state != null and research_xp_amount.mantissa > 0.0:
|
|
||||||
game_state.add_research_xp(data.research_data.id, research_xp_amount)
|
var worker_multiplier: float = 1.0 + (float(research_workers) * data.research_data.worker_scaling_factor)
|
||||||
|
var scaled_xp: BigNumber = base_xp.multiply(BigNumber.from_float(worker_multiplier))
|
||||||
|
|
||||||
|
if game_state != null and scaled_xp.mantissa > 0.0:
|
||||||
|
game_state.add_research_xp(data.research_data.id, scaled_xp)
|
||||||
|
|
||||||
## Convenience helper for the next single-unit purchase cost.
|
## Convenience helper for the next single-unit purchase cost.
|
||||||
func get_next_cost() -> BigNumber:
|
func get_next_cost() -> BigNumber:
|
||||||
@@ -433,10 +441,18 @@ func _try_grant_click_currency() -> void:
|
|||||||
if not _is_research_active(data.research_data.id):
|
if not _is_research_active(data.research_data.id):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
var research_workers: int = game_state.get_research_workers()
|
||||||
|
if research_workers < data.research_data.min_workers_for_xp:
|
||||||
|
return
|
||||||
|
|
||||||
var amount_float: float = click_value.mantissa * pow(10.0, float(click_value.exponent))
|
var amount_float: float = click_value.mantissa * pow(10.0, float(click_value.exponent))
|
||||||
var research_xp_amount: BigNumber = BigNumber.from_float(data.research_data.xp_per_currency_produced * amount_float)
|
var base_xp: BigNumber = BigNumber.from_float(data.research_data.xp_per_currency_produced * amount_float)
|
||||||
if game_state != null and research_xp_amount.mantissa > 0.0:
|
|
||||||
game_state.add_research_xp(data.research_data.id, research_xp_amount)
|
var worker_multiplier: float = 1.0 + (float(research_workers) * data.research_data.worker_scaling_factor)
|
||||||
|
var scaled_xp: BigNumber = base_xp.multiply(BigNumber.from_float(worker_multiplier))
|
||||||
|
|
||||||
|
if game_state != null and scaled_xp.mantissa > 0.0:
|
||||||
|
game_state.add_research_xp(data.research_data.id, scaled_xp)
|
||||||
|
|
||||||
|
|
||||||
## Resolves click reward from data.
|
## Resolves click reward from data.
|
||||||
|
|||||||
@@ -23,6 +23,10 @@ signal goal_progress_changed(goal_id: StringName, progress: float)
|
|||||||
signal research_xp_changed(research_id: StringName, new_xp: BigNumber)
|
signal research_xp_changed(research_id: StringName, new_xp: BigNumber)
|
||||||
## Emitted when a research track levels up.
|
## Emitted when a research track levels up.
|
||||||
signal research_level_up(research_id: StringName, old_level: int, new_level: int)
|
signal research_level_up(research_id: StringName, old_level: int, new_level: int)
|
||||||
|
## Emitted when worker count changes (derived from currency balance).
|
||||||
|
signal worker_count_changed(currency_id: StringName, new_count: int)
|
||||||
|
## Emitted when research workers change.
|
||||||
|
signal research_workers_changed(new_count: int)
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
# EXPORTED REFERENCES
|
# EXPORTED REFERENCES
|
||||||
@@ -72,6 +76,8 @@ var _goal_completed: Dictionary = {}
|
|||||||
var research_xp: Dictionary = {}
|
var research_xp: Dictionary = {}
|
||||||
## Research levels by research ID.
|
## Research levels by research ID.
|
||||||
var research_levels: Dictionary = {}
|
var research_levels: Dictionary = {}
|
||||||
|
## Workers assigned to research (total across all tracks).
|
||||||
|
var research_workers: int = 0
|
||||||
|
|
||||||
## Unix timestamp of last save.
|
## Unix timestamp of last save.
|
||||||
var last_save_time: int = 0
|
var last_save_time: int = 0
|
||||||
@@ -81,8 +87,8 @@ var last_save_time: int = 0
|
|||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
## JSON key for save format version.
|
## JSON key for save format version.
|
||||||
const SAVE_FORMAT_VERSION_KEY: String = "save_format_version"
|
const SAVE_FORMAT_VERSION_KEY: String = "save_format_version"
|
||||||
## Current save format version (5 includes research XP BigNumber serialization).
|
## Current save format version (7 includes research workers tracking).
|
||||||
const CURRENT_SAVE_FORMAT_VERSION: int = 5
|
const CURRENT_SAVE_FORMAT_VERSION: int = 7
|
||||||
## JSON key for generator owned count.
|
## JSON key for generator owned count.
|
||||||
const GENERATOR_OWNED_KEY: String = "owned"
|
const GENERATOR_OWNED_KEY: String = "owned"
|
||||||
## JSON key for generator purchased count.
|
## JSON key for generator purchased count.
|
||||||
@@ -120,6 +126,8 @@ const LAST_SAVE_TIME_KEY: String = "last_save_time"
|
|||||||
const RESEARCH_XP_KEY: String = "research_xp"
|
const RESEARCH_XP_KEY: String = "research_xp"
|
||||||
## JSON key for research levels section.
|
## JSON key for research levels section.
|
||||||
const RESEARCH_LEVELS_KEY: String = "research_levels"
|
const RESEARCH_LEVELS_KEY: String = "research_levels"
|
||||||
|
## JSON key for research workers section.
|
||||||
|
const RESEARCH_WORKERS_KEY: String = "research_workers"
|
||||||
|
|
||||||
## Reference to the PrestigeManager autoload node (set in _ready).
|
## Reference to the PrestigeManager autoload node (set in _ready).
|
||||||
var prestige_manager: PrestigeManager
|
var prestige_manager: PrestigeManager
|
||||||
@@ -484,6 +492,31 @@ func get_research_multiplier(research_id: StringName) -> float:
|
|||||||
return 1.0
|
return 1.0
|
||||||
return research.get_multiplier_for_level(level)
|
return research.get_multiplier_for_level(level)
|
||||||
|
|
||||||
|
## Returns the total number of workers assigned to research.
|
||||||
|
func get_research_workers() -> int:
|
||||||
|
return research_workers
|
||||||
|
|
||||||
|
## Assigns a worker to research (called when spending worker currency on research).
|
||||||
|
func assign_worker_to_research() -> bool:
|
||||||
|
var worker_currency: BigNumber = get_currency_amount_by_id("worker")
|
||||||
|
if worker_currency.mantissa < 1.0:
|
||||||
|
return false
|
||||||
|
|
||||||
|
spend_currency_by_id("worker", BigNumber.from_float(1.0))
|
||||||
|
research_workers += 1
|
||||||
|
research_workers_changed.emit(research_workers)
|
||||||
|
return true
|
||||||
|
|
||||||
|
## Removes a worker from research (returns to worker currency).
|
||||||
|
func remove_worker_from_research() -> bool:
|
||||||
|
if research_workers <= 0:
|
||||||
|
return false
|
||||||
|
|
||||||
|
research_workers -= 1
|
||||||
|
add_currency_by_id("worker", BigNumber.from_float(1.0))
|
||||||
|
research_workers_changed.emit(research_workers)
|
||||||
|
return true
|
||||||
|
|
||||||
## Adds XP to a research track, applying buff modifiers and emitting signals on level up.
|
## Adds XP to a research track, applying buff modifiers and emitting signals on level up.
|
||||||
func add_research_xp(research_id: StringName, xp: BigNumber) -> void:
|
func add_research_xp(research_id: StringName, xp: BigNumber) -> void:
|
||||||
var actual_xp: BigNumber = ResearchBuffCalculator.apply_buffs(self, research_id, xp)
|
var actual_xp: BigNumber = ResearchBuffCalculator.apply_buffs(self, research_id, xp)
|
||||||
@@ -508,6 +541,11 @@ func _get_research_data(research_id: StringName) -> ResearchData:
|
|||||||
return null
|
return null
|
||||||
return research_catalogue.get_research_by_id(research_id)
|
return research_catalogue.get_research_by_id(research_id)
|
||||||
|
|
||||||
|
## Returns the current worker count (derived from "worker" currency balance).
|
||||||
|
func get_worker_count() -> int:
|
||||||
|
var worker_amount: BigNumber = get_currency_amount_by_id("worker")
|
||||||
|
return int(worker_amount.mantissa) if worker_amount.mantissa >= 0 else 0
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
@@ -588,6 +626,7 @@ func save_game() -> void:
|
|||||||
GOALS_KEY: _serialize_goals(),
|
GOALS_KEY: _serialize_goals(),
|
||||||
RESEARCH_XP_KEY: _serialize_research_xp(),
|
RESEARCH_XP_KEY: _serialize_research_xp(),
|
||||||
RESEARCH_LEVELS_KEY: research_levels.duplicate(),
|
RESEARCH_LEVELS_KEY: research_levels.duplicate(),
|
||||||
|
RESEARCH_WORKERS_KEY: research_workers,
|
||||||
LAST_SAVE_TIME_KEY: Time.get_unix_time_from_system()
|
LAST_SAVE_TIME_KEY: Time.get_unix_time_from_system()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -639,13 +678,15 @@ func load_game() -> void:
|
|||||||
research_xp = _deserialize_research_xp(parsed_data.get(RESEARCH_XP_KEY, {}))
|
research_xp = _deserialize_research_xp(parsed_data.get(RESEARCH_XP_KEY, {}))
|
||||||
if parsed_data.has(RESEARCH_LEVELS_KEY):
|
if parsed_data.has(RESEARCH_LEVELS_KEY):
|
||||||
research_levels = parsed_data.get(RESEARCH_LEVELS_KEY, {})
|
research_levels = parsed_data.get(RESEARCH_LEVELS_KEY, {})
|
||||||
|
if parsed_data.has(RESEARCH_WORKERS_KEY):
|
||||||
|
research_workers = int(parsed_data.get(RESEARCH_WORKERS_KEY, 0))
|
||||||
|
|
||||||
last_save_time = parsed_data.get(LAST_SAVE_TIME_KEY, Time.get_unix_time_from_system())
|
last_save_time = parsed_data.get(LAST_SAVE_TIME_KEY, Time.get_unix_time_from_system())
|
||||||
for save_key_variant in parsed_data.keys():
|
for save_key_variant in parsed_data.keys():
|
||||||
var save_key: String = String(save_key_variant)
|
var save_key: String = String(save_key_variant)
|
||||||
if save_key.is_empty():
|
if save_key.is_empty():
|
||||||
continue
|
continue
|
||||||
if save_key in [SAVE_FORMAT_VERSION_KEY, CURRENCIES_KEY, GENERATOR_STATES_KEY, BUFF_LEVELS_KEY, BUFF_UNLOCKED_KEY, BUFF_ACTIVE_KEY, GOALS_KEY, RESEARCH_XP_KEY, RESEARCH_LEVELS_KEY, LAST_SAVE_TIME_KEY]:
|
if save_key in [SAVE_FORMAT_VERSION_KEY, CURRENCIES_KEY, GENERATOR_STATES_KEY, BUFF_LEVELS_KEY, BUFF_UNLOCKED_KEY, BUFF_ACTIVE_KEY, GOALS_KEY, RESEARCH_XP_KEY, RESEARCH_LEVELS_KEY, RESEARCH_WORKERS_KEY, LAST_SAVE_TIME_KEY]:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
var section_payload: Variant = parsed_data.get(save_key_variant)
|
var section_payload: Variant = parsed_data.get(save_key_variant)
|
||||||
|
|||||||
@@ -19,6 +19,10 @@ extends Resource
|
|||||||
## Associated Buff (single buff per research track)
|
## Associated Buff (single buff per research track)
|
||||||
@export var associated_buff_id: StringName = &""
|
@export var associated_buff_id: StringName = &""
|
||||||
|
|
||||||
|
## Worker Scaling Configuration
|
||||||
|
@export var worker_scaling_factor: float = 0.01
|
||||||
|
@export var min_workers_for_xp: int = 1
|
||||||
|
|
||||||
func get_xp_required_for_level(level: int) -> float:
|
func get_xp_required_for_level(level: int) -> float:
|
||||||
return base_xp_required * pow(xp_growth_multiplier, float(maxi(level - 1, 0)))
|
return base_xp_required * pow(xp_growth_multiplier, float(maxi(level - 1, 0)))
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ const RESEARCH_ROW_SCENE: PackedScene = preload("res://core/research/research_ro
|
|||||||
|
|
||||||
@onready var _title_label: Label = $ScrollContainer/VBoxContainer/TitleLabel
|
@onready var _title_label: Label = $ScrollContainer/VBoxContainer/TitleLabel
|
||||||
@onready var _research_rows_container: VBoxContainer = $ScrollContainer/VBoxContainer/ResearchRows
|
@onready var _research_rows_container: VBoxContainer = $ScrollContainer/VBoxContainer/ResearchRows
|
||||||
|
@onready var _buy_worker_button: Button = $ScrollContainer/VBoxContainer/HBoxContainer/BuyWorkerButton
|
||||||
|
|
||||||
var _game_state: LevelGameState
|
var _game_state: LevelGameState
|
||||||
var _research_rows: Dictionary = {}
|
var _research_rows: Dictionary = {}
|
||||||
@@ -18,9 +19,12 @@ func _ready() -> void:
|
|||||||
|
|
||||||
_game_state.research_xp_changed.connect(_on_research_xp_changed)
|
_game_state.research_xp_changed.connect(_on_research_xp_changed)
|
||||||
_game_state.research_level_up.connect(_on_research_level_up)
|
_game_state.research_level_up.connect(_on_research_level_up)
|
||||||
|
_game_state.currency_changed.connect(_on_currency_changed)
|
||||||
|
_game_state.research_workers_changed.connect(_on_research_workers_changed)
|
||||||
|
|
||||||
_build_research_rows()
|
_build_research_rows()
|
||||||
_refresh_all()
|
_refresh_all()
|
||||||
|
_refresh_worker_button()
|
||||||
|
|
||||||
func _build_research_rows() -> void:
|
func _build_research_rows() -> void:
|
||||||
for child in _research_rows_container.get_children():
|
for child in _research_rows_container.get_children():
|
||||||
@@ -109,3 +113,43 @@ func activate_research(research_id: StringName) -> void:
|
|||||||
if _research_rows.has(research_id):
|
if _research_rows.has(research_id):
|
||||||
var row: ResearchRow = _research_rows[research_id]
|
var row: ResearchRow = _research_rows[research_id]
|
||||||
row.set_active(true)
|
row.set_active(true)
|
||||||
|
|
||||||
|
func _on_currency_changed(currency_id: StringName, _new_amount: BigNumber) -> void:
|
||||||
|
if currency_id == &"worker":
|
||||||
|
_refresh_worker_button()
|
||||||
|
|
||||||
|
func _on_research_workers_changed(_new_count: int) -> void:
|
||||||
|
_refresh_worker_button()
|
||||||
|
|
||||||
|
func _can_buy_worker() -> bool:
|
||||||
|
if _game_state == null:
|
||||||
|
return false
|
||||||
|
|
||||||
|
var worker_currency: BigNumber = _game_state.get_currency_amount_by_id(&"worker")
|
||||||
|
|
||||||
|
return worker_currency.mantissa >= 1.0
|
||||||
|
|
||||||
|
func _buy_worker() -> void:
|
||||||
|
if _game_state == null:
|
||||||
|
return
|
||||||
|
|
||||||
|
_game_state.assign_worker_to_research()
|
||||||
|
|
||||||
|
func _on_buy_worker_pressed() -> void:
|
||||||
|
_buy_worker()
|
||||||
|
_refresh_worker_button()
|
||||||
|
|
||||||
|
func _refresh_worker_button() -> void:
|
||||||
|
if _buy_worker_button == null:
|
||||||
|
return
|
||||||
|
|
||||||
|
if _game_state == null:
|
||||||
|
_buy_worker_button.disabled = true
|
||||||
|
return
|
||||||
|
|
||||||
|
var can_buy: bool = _can_buy_worker()
|
||||||
|
_buy_worker_button.disabled = not can_buy
|
||||||
|
|
||||||
|
var worker_currency: BigNumber = _game_state.get_currency_amount_by_id(&"worker")
|
||||||
|
var research_workers: int = _game_state.get_research_workers()
|
||||||
|
_buy_worker_button.text = "Assign Worker to Research (%d available, %d assigned)" % [int(worker_currency.mantissa), research_workers]
|
||||||
|
|||||||
@@ -1,26 +1,34 @@
|
|||||||
[gd_scene format=3 uid="uid://dd8roif0mqirl"]
|
[gd_scene format=3 uid="uid://6d101h70mcx"]
|
||||||
|
|
||||||
[ext_resource type="Script" uid="uid://fdl7ftxw8w1e" path="res://core/research/research_panel.gd" id="1_script"]
|
[ext_resource type="Script" uid="uid://fdl7ftxw8w1e" path="res://core/research/research_panel.gd" id="1_script"]
|
||||||
[ext_resource type="PackedScene" uid="uid://bpo8pl5tipav" path="res://core/research/research_row.tscn" id="2_3m5ee"]
|
[ext_resource type="PackedScene" uid="uid://ckr805xqy6h4w" path="res://core/research/worker_summary_label.tscn" id="3_worker"]
|
||||||
|
|
||||||
[node name="ResearchPanel" type="PanelContainer" unique_id=1105274967]
|
[node name="ResearchPanel" type="PanelContainer" unique_id=600021293]
|
||||||
custom_minimum_size = Vector2(400, 100)
|
custom_minimum_size = Vector2(400, 100)
|
||||||
offset_right = 400.0
|
offset_right = 400.0
|
||||||
offset_bottom = 100.0
|
offset_bottom = 100.0
|
||||||
script = ExtResource("1_script")
|
script = ExtResource("1_script")
|
||||||
|
|
||||||
[node name="ScrollContainer" type="ScrollContainer" parent="." unique_id=1099596602]
|
[node name="ScrollContainer" type="ScrollContainer" parent="." unique_id=973132184]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
|
|
||||||
[node name="VBoxContainer" type="VBoxContainer" parent="ScrollContainer" unique_id=692886617]
|
[node name="VBoxContainer" type="VBoxContainer" parent="ScrollContainer" unique_id=1679714014]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
|
|
||||||
[node name="TitleLabel" type="Label" parent="ScrollContainer/VBoxContainer" unique_id=1565843659]
|
[node name="TitleLabel" type="Label" parent="ScrollContainer/VBoxContainer" unique_id=990297493]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
text = "Research"
|
text = "Research"
|
||||||
|
|
||||||
[node name="ResearchRows" type="VBoxContainer" parent="ScrollContainer/VBoxContainer" unique_id=1200240263]
|
[node name="HBoxContainer" type="HBoxContainer" parent="ScrollContainer/VBoxContainer" unique_id=1419318708]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
|
|
||||||
[node name="ResearchRow" parent="ScrollContainer/VBoxContainer/ResearchRows" unique_id=245375198 instance=ExtResource("2_3m5ee")]
|
[node name="WorkerSummaryLabel" parent="ScrollContainer/VBoxContainer/HBoxContainer" unique_id=13607753 instance=ExtResource("3_worker")]
|
||||||
|
|
||||||
|
[node name="BuyWorkerButton" type="Button" parent="ScrollContainer/VBoxContainer/HBoxContainer" unique_id=1083899286]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
|
text = "Invest Worker (0 available)"
|
||||||
|
|
||||||
|
[node name="ResearchRows" type="VBoxContainer" parent="ScrollContainer/VBoxContainer" unique_id=2066050169]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[connection signal="pressed" from="ScrollContainer/VBoxContainer/HBoxContainer/BuyWorkerButton" to="." method="_buy_worker"]
|
||||||
|
|||||||
27
core/research/worker_summary_label.gd
Normal file
27
core/research/worker_summary_label.gd
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
class_name WorkerSummaryLabel
|
||||||
|
extends Label
|
||||||
|
|
||||||
|
@onready var _game_state: LevelGameState = find_parent("LevelGameState")
|
||||||
|
|
||||||
|
signal research_workers_changed(new_count: int)
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
if _game_state == null:
|
||||||
|
push_error("WorkerSummaryLabel: Could not find LevelGameState parent")
|
||||||
|
return
|
||||||
|
|
||||||
|
_game_state.currency_changed.connect(_on_currency_changed)
|
||||||
|
_game_state.research_workers_changed.connect(_on_research_workers_changed)
|
||||||
|
_update_worker_display()
|
||||||
|
|
||||||
|
func _on_currency_changed(currency_id: StringName, _new_amount: BigNumber) -> void:
|
||||||
|
if currency_id == "worker":
|
||||||
|
_update_worker_display()
|
||||||
|
|
||||||
|
func _on_research_workers_changed(new_count: int) -> void:
|
||||||
|
_update_worker_display()
|
||||||
|
|
||||||
|
func _update_worker_display() -> void:
|
||||||
|
var worker_currency: int = int(_game_state.get_currency_amount_by_id("worker").mantissa)
|
||||||
|
var research_workers: int = _game_state.get_research_workers()
|
||||||
|
text = "Workers: %d available, %d assigned" % [worker_currency, research_workers]
|
||||||
1
core/research/worker_summary_label.gd.uid
Normal file
1
core/research/worker_summary_label.gd.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://brvoy607b3nft
|
||||||
8
core/research/worker_summary_label.tscn
Normal file
8
core/research/worker_summary_label.tscn
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
[gd_scene format=3 uid="uid://ckr8z5xqy6h4w"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://core/research/worker_summary_label.gd" id="1_script"]
|
||||||
|
|
||||||
|
[node name="WorkerSummaryLabel" type="Label"]
|
||||||
|
layout_mode = 2
|
||||||
|
script = ExtResource("1_script")
|
||||||
|
text = "Workers: 0"
|
||||||
Reference in New Issue
Block a user