Complete remaining client gap features
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
# damage_effect —— §8.8 / §5.4 头顶伤害飘字「是否 / 如何显示」1:1:
|
||||
# CInstanceBase::AddDamageEffect + ProcessDamage 的分类(DODGE|BLOCK -> MISS、
|
||||
# self -> "damage_"、nontarget -> 不渲染、target -> "target_")+ 数字逐位拆分 +
|
||||
# CPythonSystem::IsShowDamage / SetShowDamageFlag 门。
|
||||
# (与 name_color.gd / text_tail.gd / chat_tail.gd / name_show.gd 同一套纯静态镜像套路。)
|
||||
#
|
||||
# REF(40250 ClientVS22 source/ 为唯一基线):
|
||||
# UserInterface/InstanceBase.h:300 enum DamageFlag { NORMAL 1<<0, POISON 1<<1, DODGE 1<<2, BLOCK 1<<3, PENETRATE 1<<4, CRITICAL 1<<5 }
|
||||
# UserInterface/Packet.h:1943 TPacketGCDamageInfo { BYTE header; DWORD dwVID; BYTE flag; int damage; }
|
||||
# UserInterface/PythonNetworkStreamPhaseGame.cpp:2401 RecvDamageInfoPacket:
|
||||
# pInstTarget = GetInstancePtr(dwVID);bSelf = (pInstTarget == MainInstance);
|
||||
# bTarget = (pInstTarget == m_pInstTarget);damage >= 0 才 AddDamageEffect(< 0 记 TraceError)
|
||||
# UserInterface/InstanceBaseEffect.cpp:87 AddDamageEffect:仅当 IsShowDamage() 才 push m_DamageQueue({bSelf,bTarget,damage,flag})
|
||||
# UserInterface/InstanceBaseEffect.cpp:100 ProcessDamage(InstanceBase.cpp:1910 每帧调一次):
|
||||
# 每帧 pop_front 一条;
|
||||
# (flag & DODGE) || (flag & BLOCK) -> bSelf ? EFFECT_DAMAGE_MISS : EFFECT_DAMAGE_TARGETMISS,return
|
||||
# (flag & CRITICAL) -> 该 build CreateEffect 被注释掉,落到普通数字(无独立暴击视觉)
|
||||
# POISON 分支整段注释掉
|
||||
# bSelf -> strDamageType="damage_",EFFECT_DAMAGE_SELFDAMAGE / SELFDAMAGE2 交替(m_bDamageEffectType 每次取反)
|
||||
# !bTarget -> strDamageType="nontarget_",EFFECT_DAMAGE_NOT_TARGET 后 **return(不渲染)**
|
||||
# else -> strDamageType="target_",EFFECT_DAMAGE_TARGET
|
||||
# while(damage>0):num=damage%10; damage/=10; index 0..7(>7 TraceError break);
|
||||
# 贴图 "d:/ymir work/effect/affect/damagevalue/<type><num>.dds",
|
||||
# 水平偏移 FONT_WIDTH(30)*index(相机右方向,matTrans._41 = -(FONT_WIDTH*index))
|
||||
# UserInterface/PythonSystem.cpp:308 m_Config.bShowDamage = true(默认)
|
||||
# UserInterface/PythonSystem.cpp:337 IsShowDamage() -> m_Config.bShowDamage
|
||||
# UserInterface/PythonSystem.cpp:342 SetShowDamageFlag(iFlag) -> bShowDamage = (iFlag == 1)
|
||||
# UserInterface/PythonSystem.cpp:451 config "SHOW_DAMAGE" -> atoi(value) == 1
|
||||
# UserInterface/PythonSystem.cpp:537 save "SHOW_DAMAGE %d"(仅当 == 0,即非默认时落盘)
|
||||
# UserInterface/PythonSystemModule.cpp:192/219 systemSetShowDamageFlag / systemIsShowDamage
|
||||
# root/uigameoption.py __OnClickShowDamageOn/OffButton -> systemSetting.SetShowDamageFlag(...)
|
||||
#
|
||||
# seam ⑪:参考端每位数字是一张 damagevalue/<type><digit>.dds 贴图做的 CEffectManager 特效,
|
||||
# 在相机右方向按 FONT_WIDTH*index 像素铺开;本移植 net_world 用一块 billboard Label3D 直接写
|
||||
# str(amount)(无 damagevalue dds 图集 / 无逐位特效 / 无相机右向像素铺排),MISS 写 "MISS"。
|
||||
# self 的 SELFDAMAGE/SELFDAMAGE2 交替本移植退化成落字水平抖动符号交替(仅存在感,无双特效资源)。
|
||||
# 暴击在该 40250 build 参考端本就无独立视觉,这里也不再放大 / 变色(与 <=112 的占位实现相比是回归对齐)。
|
||||
# 另:参考端 m_DamageQueue 是「每个实例一条」,ProcessDamage 每帧每实例 pop 一条;本移植是
|
||||
# net_world 一条全局队列每帧 pop 一条 —— 同一帧多个 VID 同时受击时会分帧显示。
|
||||
extends RefCounted
|
||||
|
||||
# CInstanceBase::DamageFlag
|
||||
const DAMAGE_NORMAL := 1 << 0
|
||||
const DAMAGE_POISON := 1 << 1
|
||||
const DAMAGE_DODGE := 1 << 2
|
||||
const DAMAGE_BLOCK := 1 << 3
|
||||
const DAMAGE_PENETRATE := 1 << 4
|
||||
const DAMAGE_CRITICAL := 1 << 5
|
||||
|
||||
const SHOW_DAMAGE_DEFAULT := true # m_Config.bShowDamage 默认
|
||||
const CFG_KEY := "SHOW_DAMAGE" # PythonSystem 配置行 / 存盘键
|
||||
const FONT_WIDTH := 30 # ProcessDamage 逐位水平像素步进
|
||||
const MAX_DIGITS := 8 # index > 7 -> break
|
||||
|
||||
enum Kind { MISS, DIGITS }
|
||||
|
||||
# AddDamageEffect:仅当 IsShowDamage() 才入队
|
||||
static func should_queue(show_damage: bool) -> bool:
|
||||
return show_damage
|
||||
|
||||
# SetShowDamageFlag(int iFlag): m_Config.bShowDamage = iFlag == 1
|
||||
static func show_damage_from_flag(flag: int) -> bool:
|
||||
return flag == 1
|
||||
|
||||
# config "SHOW_DAMAGE" 行:atoi(value) == 1
|
||||
static func show_damage_from_cfg(value: Variant) -> bool:
|
||||
return int(value) == 1
|
||||
|
||||
# RecvDamageInfoPacket:bSelf = 目标实例是主角
|
||||
static func is_self(vid: int, main_vid: int) -> bool:
|
||||
return vid != 0 and vid == main_vid
|
||||
|
||||
# RecvDamageInfoPacket:bTarget = 目标实例是当前目标框 VID
|
||||
static func is_target(vid: int, target_vid: int) -> bool:
|
||||
return vid != 0 and vid == target_vid
|
||||
|
||||
# RecvDamageInfoPacket:damage < 0 记 TraceError 不处理
|
||||
static func valid_amount(amount: int) -> bool:
|
||||
return amount >= 0
|
||||
|
||||
# ProcessDamage 分类。返回:
|
||||
# {"kind": Kind, "type": String("damage_"/"target_"/"nontarget_"), "show": bool, "self": bool}
|
||||
# show == false 只有一种来源:非 self 且非 target 的数字伤害(ProcessDamage 里 return,不渲染)。
|
||||
static func classify(flag: int, b_self: bool, b_target: bool) -> Dictionary:
|
||||
if (flag & DAMAGE_DODGE) != 0 or (flag & DAMAGE_BLOCK) != 0:
|
||||
# EFFECT_DAMAGE_MISS(self)/ EFFECT_DAMAGE_TARGETMISS(其它)
|
||||
return {"kind": Kind.MISS, "type": "damage_" if b_self else "target_", "show": true, "self": b_self}
|
||||
if b_self:
|
||||
return {"kind": Kind.DIGITS, "type": "damage_", "show": true, "self": true}
|
||||
if not b_target:
|
||||
return {"kind": Kind.DIGITS, "type": "nontarget_", "show": false, "self": false}
|
||||
return {"kind": Kind.DIGITS, "type": "target_", "show": true, "self": false}
|
||||
|
||||
# while(damage>0){ num=damage%10; damage/=10; } —— 低位在前,最多 8 位(index>7 break)。
|
||||
# damage <= 0 不产出任何位(与参考 while 一致)。
|
||||
static func digits(damage: int) -> Array:
|
||||
var out: Array = []
|
||||
var d := damage
|
||||
if d <= 0:
|
||||
return out
|
||||
var index := 0
|
||||
while d > 0:
|
||||
if index > MAX_DIGITS - 1:
|
||||
break
|
||||
out.append(d % 10)
|
||||
d = d / 10
|
||||
index += 1
|
||||
return out
|
||||
|
||||
# 第 index 位数字相对锚点的水平像素偏移(相机右方向)。
|
||||
static func digit_offset_px(index: int) -> float:
|
||||
return float(FONT_WIDTH * index)
|
||||
|
||||
# ProcessDamage 的 self 特效交替:m_bDamageEffectType==false -> SELFDAMAGE(0),否则 SELFDAMAGE2(1),
|
||||
# 每次自伤后取反。返回本次用的槽位(0/1)。
|
||||
static func self_damage_slot(toggle_state: bool) -> int:
|
||||
return 1 if toggle_state else 0
|
||||
Reference in New Issue
Block a user