Files
mtgodot-poc/project/target_board.gd
T

92 lines
5.9 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# target_board —— §5.4 / §8.8 目标框(TargetBoard)收包分派 1:1
# CPythonNetworkStream::RecvTargetPacket 的「目标存在 / 未死 → PC|Building 关掉异 VID 框、
# 可看血就设血条、否则关框」判定树,加 CInstanceBase::CanViewTargetHP 的
# IsStone()||IsWoodenDoor()||IsEnemy(),再加 game.py 的 SetHPTargetBoard(换 VID 先 Reset/
# CloseTargetBoardIfDifferent / CloseTargetBoard / SetPCTargetBoard 的 LCONTROL 悄悄话捷径。
# (与 name_color.gd / text_tail.gd / chat_tail.gd / name_show.gd / damage_effect.gd 同一套
# 纯静态镜像套路,本模块是第 26 个 canonical。)
#
# REF40250 ClientVS22 source/ 为唯一基线):
# UserInterface/Packet.h:1937 TPacketGCTarget { BYTE header; DWORD dwVID; BYTE bHPPercent; }
# UserInterface/PythonNetworkStreamPhaseGame.cpp:2424 RecvTargetPacket()
# :2436 if (pInstPlayer && pInstTarget) —— 主角与目标实例都在
# :2438 if (!pInstTarget->IsDead()) —— 目标没死透才动框
# :2440 if (IsPC() || IsBuilding()) CloseTargetBoardIfDifferent(dwVID)
# :2442 else if (CanViewTargetHP(*pInstTarget)) SetHPTargetBoard(dwVID, bHPPercent)
# :2444 else CloseTargetBoard()
# :2447 m_pInstTarget = pInstTarget —— 仅当目标存在且未死
# :2453 else CloseTargetBoard() —— 实例缺失
# UserInterface/InstanceBase.cpp:2293 CanViewTargetHP(victim) = victim.IsStone()||victim.IsWoodenDoor()||victim.IsEnemy()
# UserInterface/InstanceBase.cpp:2380/2390 IsBuilding() / IsWoodenDoor()vnum 13000 或 30111..30119
# root/game.py:804 SetPCTargetBoard(vid,name)Open(vid,name);若按住 LCONTROL 且 IsSameEmpire
# 且非本人且非 building → interface.OpenWhisperDialog(name)
# root/game.py:829 SetHPTargetBoard(vid,hpPct)vid != GetTargetVID() → ResetTargetBoard()+SetEnemyVID(vid)SetHP(hpPct)+Show()
# root/game.py:837 CloseTargetBoardIfDifferent(vid)vid != GetTargetVID() → Close()
# root/game.py:841 CloseTargetBoard()Close()
# root/uitarget.py:189-193 TargetBoard.Open(vid,name) 最前置过滤:
# if not constInfo.GET_VIEW_OTHER_EMPIRE_PLAYER_TARGET_BOARD():
# if not player.IsSameEmpire(vid): self.Hide(); return
# —— game-option「看他国玩家目标框」关掉时,异阵营玩家框直接不开(constinfo 默认 1 = 开)。
#
# seam ⑫:旧实体快照没有独立建筑字段;当前 net_play 已支持 fixture / mob_proto
# 的 BUILDING(5) / WOODEN_DOOR(6) 分类。没有分类信息的旧快照仍按 NPC/怪/石头路径。
# 另:poc 的 target_info 由 C++ 侧(extension/src/net/m2_client.cpp)从 EntityStore 抽出,
# 本模块只镜像 GDScript 侧对 (vid, hp%) 的分派,不改 C++ 收包。
# LCONTROL 悄悄话捷径:增量 122 接线 —— net_play._on_pick 在 KIND_PC 分支轮询
# whisper_on_ctrl_click(_lcontrol_down, same_empire, vid==_main_vid, false),真则发
# whisper_requested(name)game_scene 转 chat.start_whisper()poc 版 OpenWhisperDialog);
# _lcontrol_down 由 game_scene 的 KEY_CTRL 按下 / 松开喂。
extends RefCounted
# RecvTargetPacket 分派结果。
# CLOSE —— 关框(实例缺失 / 不可看血的非 PC 非 building 目标)
# CLOSE_IF_DIFFERENT —— 目标是 PC 或 building:仅当框上是别的 VID 才关
# SET_HP —— 可看血:设血条并显示(换 VID 先 Reset)
# NONE —— 目标已死透:不动框,但仍更新 m_pInstTarget
enum Action { CLOSE, CLOSE_IF_DIFFERENT, SET_HP, NONE }
# CanViewTargetHP(victim):石头 / 木门 / 敌对,任一即可看血。
static func can_view_target_hp(is_stone: bool, is_wooden_door: bool, is_enemy: bool) -> bool:
return is_stone or is_wooden_door or is_enemy
# RecvTargetPacket 判定树。target_exists = (pInstPlayer && pInstTarget)。
static func classify(target_exists: bool, is_dead: bool, is_pc: bool,
is_building: bool, can_view_hp: bool) -> int:
if not target_exists:
return Action.CLOSE # :2453 else CloseTargetBoard()
if is_dead:
return Action.NONE # :2438 !IsDead() 为假 —— 整块跳过
if is_pc or is_building:
return Action.CLOSE_IF_DIFFERENT # :2440
if can_view_hp:
return Action.SET_HP # :2442
return Action.CLOSE # :2444
# m_pInstTarget = pInstTarget 只在「目标存在且没死透」时写(:2447 在 !IsDead() 块内)。
static func updates_current_target(target_exists: bool, is_dead: bool) -> bool:
return target_exists and not is_dead
# SetHPTargetBoardvid != GetTargetVID() → 先 ResetTargetBoard()+SetEnemyVID(vid)。
static func needs_reset(new_vid: int, cur_vid: int) -> bool:
return new_vid != cur_vid
# CloseTargetBoardIfDifferentvid != GetTargetVID() 才 Close()。
static func should_close_if_different(vid: int, cur_vid: int) -> bool:
return vid != cur_vid
# TargetBoard.Open :189-193 前置过滤:game-option「看他国玩家目标框」(constinfo
# VIEW_OTHER_EMPIRE_PLAYER_TARGET_BOARD,默认 1) 关掉时,异阵营目标框不开。
# view_other_empire=false 且 same_empire=false → 隐藏。empire 0 的怪/NPC/石头在
# IsSameEmpire 里算「同阵营」(entity_rules._is_same_empire),故只挡真·他国 PC。
static func hidden_as_other_empire(view_other_empire: bool, same_empire: bool) -> bool:
return not view_other_empire and not same_empire
# SetPCTargetBoard 的 LCONTROL 悄悄话捷径:按住 LCONTROL 且同阵营且非本人且非 building。
static func whisper_on_ctrl_click(lcontrol_down: bool, same_empire: bool,
is_main: bool, is_building: bool) -> bool:
return lcontrol_down and same_empire and not is_main and not is_building
# bHPPercent 是 BYTE,钳到 0..100。
static func clamp_hp_pct(v: Variant) -> int:
return clampi(int(v), 0, 100)