class_name CropPhaseRules extends RefCounted const PHASE_EMPTY := -1 const PHASE_SEED := 0 const PHASE_SPROUT := 1 const PHASE_GROW := 2 const PHASE_RIPE := 3 const PHASE_DEAD := 4 var _game_config func _init(game_config = null) -> void: _game_config = game_config func set_game_config(game_config) -> void: _game_config = game_config func get_phase(land_data: Dictionary) -> int: if int(land_data.get("crop_id", 0)) <= 0: return PHASE_EMPTY if int(land_data.get("has_gather", 0)) == 1: return PHASE_DEAD if int(land_data.get("is_ripe", 0)) == 1: return PHASE_RIPE if is_ripe_by_time(land_data): return PHASE_RIPE var start_time := int(land_data.get("crop_start_time", 0)) if start_time <= 0: return PHASE_SEED var elapsed := int(Time.get_unix_time_from_system()) - start_time var phase_times := get_crop_phase_times(int(land_data.get("crop_id", 0))) if elapsed < phase_times[0]: return PHASE_SEED if elapsed < phase_times[0] + phase_times[1]: return PHASE_SPROUT if elapsed < phase_times[0] + phase_times[1] + phase_times[2]: return PHASE_GROW if land_data.has("crop_phase"): return clampi(int(land_data.get("crop_phase", PHASE_SEED)), PHASE_SEED, PHASE_DEAD) return PHASE_GROW func get_crop_phase_times(crop_id: int) -> Array[int]: if _game_config == null: return [120, 360, 360] return _game_config.get_crop_phase_times(crop_id) func is_ripe(land_data: Dictionary) -> bool: return int(land_data.get("is_ripe", 0)) == 1 or is_ripe_by_time(land_data) func is_ripe_by_time(land_data: Dictionary) -> bool: if int(land_data.get("crop_id", 0)) <= 0 or int(land_data.get("has_gather", 0)) == 1: return false var gather_time := int(land_data.get("crop_gather_time", 0)) return gather_time > 0 and int(Time.get_unix_time_from_system()) >= gather_time