- 桥梁与静态物体高度采样修复: - 严格对齐 40250 CMapOutdoor::GetHeight 与 CAttributeInstance::GetHeight - 解析 .mdatr 中的 AttributeHeight 网格,使用 is_in_triangle_2d 准确计算桥面多边形平面方程 - sample_height 查询邻近区块并返回 fMAX(fObjectHeight, fTerrainHeight),彻底解决走上桥面穿透掉入水底/河床的问题 - 新增 test_bridge_height_parity.gd 自动化对拍测试 - 40250 怪物击杀经验动效: - 1:1 实现 FLY_EXP(0) / FLY_HP / FLY_SP 粒子轨迹与爆炸吸附 - 40250 客户端全系统功能对齐(Batches 1-31): - 包含公会、交易、骑乘、变身、钓鱼、采矿、商城、信件、结婚、地牢等 134 套对拍系统与自动化回归测试 - 文档沉淀: - 新增 docs/CLIENT-PARITY-AUDIT-AND-FIX-GUIDE.md 客户端对拍缺陷发现与修复工程指南
169 lines
5.3 KiB
GDScript
169 lines
5.3 KiB
GDScript
# weather_daynight_system.gd —— Metin2 40250 单机本地天候昼夜交替与地图环境特效系统 1:1
|
|
# 对照 40250 客户端 PythonBackground.cpp, game.py, environment.h
|
|
class_name WeatherDayNightSystem
|
|
extends RefCounted
|
|
|
|
signal phase_changed(old_phase: String, new_phase: String)
|
|
signal weather_changed(old_weather: String, new_weather: String)
|
|
signal lighting_updated(sun_color: Color, sun_energy: float, ambient_color: Color, fog_density: float)
|
|
|
|
const PHASE_DAWN := "dawn" # 黎明晨曦 (05:00 ~ 08:00)
|
|
const PHASE_NOON := "noon" # 正午晴空 (08:00 ~ 17:00)
|
|
const PHASE_DUSK := "dusk" # 黄昏落日 (17:00 ~ 20:00)
|
|
const PHASE_NIGHT := "night" # 寂静黑夜 (20:00 ~ 05:00)
|
|
|
|
const WEATHER_CLEAR := "clear" # 晴朗明净
|
|
const WEATHER_RAIN := "rain" # 潇潇细雨
|
|
const WEATHER_SNOW := "snow" # 冰山暴雪 (Mount Sohan)
|
|
const WEATHER_SANDSTORM := "sandstorm" # 狂沙飞舞 (Yongbi Desert)
|
|
const WEATHER_CINDERS := "cinders" # 烈焰余烬 (Doyyumhwan)
|
|
|
|
const SECONDS_PER_DAY: float = 86400.0
|
|
const DEFAULT_TIME_SCALE: float = 60.0 # 默认 1 秒流逝 60 秒游戏时间 (24 分钟一昼夜)
|
|
|
|
const MAP_DEFAULT_WEATHER: Dictionary = {
|
|
"village": WEATHER_CLEAR,
|
|
"sohan": WEATHER_SNOW,
|
|
"desert": WEATHER_SANDSTORM,
|
|
"flame": WEATHER_CINDERS,
|
|
"temple": WEATHER_CLEAR,
|
|
"catacomb": WEATHER_CLEAR
|
|
}
|
|
|
|
var time_of_day: float = 43200.0 # 默认正午 12:00:00 (12 * 3600)
|
|
var time_scale: float = DEFAULT_TIME_SCALE
|
|
var is_frozen: bool = false
|
|
|
|
var current_phase: String = PHASE_NOON
|
|
var current_weather: String = WEATHER_CLEAR
|
|
var current_map: String = "village"
|
|
|
|
# 光影参数
|
|
var sun_color: Color = Color(1.0, 0.98, 0.9)
|
|
var sun_energy: float = 1.2
|
|
var ambient_color: Color = Color(0.9, 0.9, 0.95)
|
|
var fog_density: float = 0.001
|
|
|
|
func _init() -> void:
|
|
_update_phase_and_lighting()
|
|
|
|
# 帧心跳更新天候流逝
|
|
func update(delta: float) -> void:
|
|
if not is_frozen:
|
|
time_of_day = fmod(time_of_day + delta * time_scale, SECONDS_PER_DAY)
|
|
if time_of_day < 0.0:
|
|
time_of_day += SECONDS_PER_DAY
|
|
|
|
_update_phase_and_lighting()
|
|
|
|
# 手动设置指定时间 (小时 0~24,分钟 0~60)
|
|
func set_time_of_day(hour: float, minute: float = 0.0) -> void:
|
|
var clamped_h = clampf(hour, 0.0, 23.99)
|
|
var clamped_m = clampf(minute, 0.0, 59.99)
|
|
time_of_day = clamped_h * 3600.0 + clamped_m * 60.0
|
|
_update_phase_and_lighting()
|
|
|
|
# 直接快速切换至指定时相
|
|
func set_phase(target_phase: String) -> void:
|
|
match target_phase:
|
|
PHASE_DAWN:
|
|
set_time_of_day(6.0, 0.0)
|
|
PHASE_NOON:
|
|
set_time_of_day(12.0, 0.0)
|
|
PHASE_DUSK:
|
|
set_time_of_day(18.5, 0.0)
|
|
PHASE_NIGHT:
|
|
set_time_of_day(23.0, 0.0)
|
|
|
|
# 设置天气模式
|
|
func set_weather(weather_type: String) -> Dictionary:
|
|
var valid_weathers = [WEATHER_CLEAR, WEATHER_RAIN, WEATHER_SNOW, WEATHER_SANDSTORM, WEATHER_CINDERS]
|
|
if not (weather_type in valid_weathers):
|
|
return {"ok": false, "reason": "INVALID_WEATHER_TYPE"}
|
|
|
|
if current_weather != weather_type:
|
|
var old = current_weather
|
|
current_weather = weather_type
|
|
weather_changed.emit(old, weather_type)
|
|
|
|
_update_phase_and_lighting()
|
|
return {"ok": true, "weather": current_weather}
|
|
|
|
# 设置当前地图并自动匹配环境天气
|
|
func set_map_environment(map_name: String) -> void:
|
|
current_map = map_name
|
|
var def_weather = MAP_DEFAULT_WEATHER.get(map_name, WEATHER_CLEAR)
|
|
set_weather(def_weather)
|
|
|
|
# 核心昼夜时相与光照参数计算
|
|
func _update_phase_and_lighting() -> void:
|
|
var hours = time_of_day / 3600.0
|
|
var new_phase = PHASE_NOON
|
|
|
|
if hours >= 5.0 and hours < 8.0:
|
|
new_phase = PHASE_DAWN
|
|
sun_color = Color(1.0, 0.8, 0.6) # 晨曦暖金
|
|
sun_energy = 0.75
|
|
ambient_color = Color(0.85, 0.75, 0.65)
|
|
fog_density = 0.002
|
|
elif hours >= 8.0 and hours < 17.0:
|
|
new_phase = PHASE_NOON
|
|
sun_color = Color(1.0, 0.98, 0.92) # 正午白炽日光
|
|
sun_energy = 1.2
|
|
ambient_color = Color(0.9, 0.9, 0.95)
|
|
fog_density = 0.001
|
|
elif hours >= 17.0 and hours < 20.0:
|
|
new_phase = PHASE_DUSK
|
|
sun_color = Color(0.95, 0.45, 0.3) # 晚霞橙红
|
|
sun_energy = 0.65
|
|
ambient_color = Color(0.7, 0.45, 0.4)
|
|
fog_density = 0.003
|
|
else:
|
|
new_phase = PHASE_NIGHT
|
|
sun_color = Color(0.3, 0.4, 0.7) # 冷冽月光
|
|
sun_energy = 0.25
|
|
ambient_color = Color(0.15, 0.2, 0.35)
|
|
fog_density = 0.004
|
|
|
|
# 天气修正
|
|
match current_weather:
|
|
WEATHER_RAIN:
|
|
sun_energy *= 0.6
|
|
fog_density += 0.003
|
|
WEATHER_SNOW:
|
|
sun_color = sun_color.lerp(Color(0.85, 0.9, 1.0), 0.5)
|
|
fog_density += 0.002
|
|
WEATHER_SANDSTORM:
|
|
sun_color = sun_color.lerp(Color(0.85, 0.7, 0.4), 0.6)
|
|
fog_density += 0.008
|
|
WEATHER_CINDERS:
|
|
sun_color = sun_color.lerp(Color(1.0, 0.35, 0.2), 0.5)
|
|
fog_density += 0.004
|
|
|
|
if current_phase != new_phase:
|
|
var old = current_phase
|
|
current_phase = new_phase
|
|
phase_changed.emit(old, new_phase)
|
|
|
|
lighting_updated.emit(sun_color, sun_energy, ambient_color, fog_density)
|
|
|
|
# 获取格式化时间字符串 "HH:MM:SS"
|
|
func get_time_string() -> String:
|
|
var total_sec = int(time_of_day)
|
|
var h = int(total_sec / 3600)
|
|
var m = int((total_sec % 3600) / 60)
|
|
var s = total_sec % 60
|
|
return "%02d:%02d:%02d" % [h, m, s]
|
|
|
|
# 获取当前光照参数字典
|
|
func get_current_lighting() -> Dictionary:
|
|
return {
|
|
"phase": current_phase,
|
|
"weather": current_weather,
|
|
"time_string": get_time_string(),
|
|
"sun_color": sun_color,
|
|
"sun_energy": sun_energy,
|
|
"ambient_color": ambient_color,
|
|
"fog_density": fog_density
|
|
}
|