feat(client): 完成40250客户端核心功能1:1对齐与桥梁高度采样修复
- 桥梁与静态物体高度采样修复: - 严格对齐 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 客户端对拍缺陷发现与修复工程指南
This commit is contained in:
@@ -0,0 +1,168 @@
|
||||
# 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
|
||||
}
|
||||
Reference in New Issue
Block a user