Files

118 lines
6.5 KiB
GDScript
Raw Permalink 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.
# 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 同一套纯静态镜像套路。)
#
# REF40250 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 ProcessDamageInstanceBase.cpp:1910 每帧调一次):
# 每帧 pop_front 一条;
# (flag & DODGE) || (flag & BLOCK) -> bSelf ? EFFECT_DAMAGE_MISS : EFFECT_DAMAGE_TARGETMISSreturn
# (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
# RecvDamageInfoPacketbSelf = 目标实例是主角
static func is_self(vid: int, main_vid: int) -> bool:
return vid != 0 and vid == main_vid
# RecvDamageInfoPacketbTarget = 目标实例是当前目标框 VID
static func is_target(vid: int, target_vid: int) -> bool:
return vid != 0 and vid == target_vid
# RecvDamageInfoPacketdamage < 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_MISSself/ 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