92 lines
5.9 KiB
GDScript
92 lines
5.9 KiB
GDScript
# 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。)
|
||
#
|
||
# REF(40250 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
|
||
|
||
# SetHPTargetBoard:vid != GetTargetVID() → 先 ResetTargetBoard()+SetEnemyVID(vid)。
|
||
static func needs_reset(new_vid: int, cur_vid: int) -> bool:
|
||
return new_vid != cur_vid
|
||
|
||
# CloseTargetBoardIfDifferent:vid != 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)
|