fix: 装备属性面板避让逻辑 + 多项功能更新
- item_tooltip_view.gd: 新增 avoid_rect 属性,tooltip 与装备窗口重叠时自动推到左侧 - inventory_ui.gd: 悬停装备时传入窗口矩形作为避让区域 - 包含其他累积的功能开发和测试文件
This commit is contained in:
@@ -49,6 +49,14 @@ const KIND_WARP := 4
|
||||
const KIND_BUILDING := 5
|
||||
const KIND_WOODEN_DOOR := 6
|
||||
|
||||
# CInstanceBase::CanPickInstance / InstanceBase.h affect ordinals.
|
||||
# EntityStore carries the two affect words as one uint64 bitset. Tests and
|
||||
# older adapters may also provide the decoded booleans/array; the helper below
|
||||
# accepts both shapes so the target gate has one authoritative implementation.
|
||||
const AFFECT_INVISIBILITY := 1
|
||||
const AFFECT_EUNHYEONG := 18
|
||||
const AFFECT_REVIVE_INVISIBILITY := 27
|
||||
|
||||
# --- alignment(善恶)---------------------------------------------------------
|
||||
|
||||
# CInstanceBase::GetAlignmentGrade(InstanceBase.cpp:502)
|
||||
@@ -111,6 +119,49 @@ static func _is_building(e: Dictionary) -> bool:
|
||||
return bool(e.get("building", false)) or _kind(e) == KIND_BUILDING \
|
||||
or _kind(e) == KIND_WOODEN_DOOR
|
||||
|
||||
static func _has_affect(e: Dictionary, affect_type: int) -> bool:
|
||||
if bool(e.get("invisibility", false)) and affect_type == AFFECT_INVISIBILITY:
|
||||
return true
|
||||
if bool(e.get("eunhyeong", false)) and affect_type == AFFECT_EUNHYEONG:
|
||||
return true
|
||||
if bool(e.get("revive_invisibility", false)) and affect_type == AFFECT_REVIVE_INVISIBILITY:
|
||||
return true
|
||||
var flags := int(e.get("affect_flags", 0))
|
||||
if affect_type < 64 and (flags & (1 << affect_type)) != 0:
|
||||
return true
|
||||
var affects: Variant = e.get("affects", [])
|
||||
if affects is Array:
|
||||
for a in affects:
|
||||
if a is Dictionary and int(a.get("type", -1)) == affect_type:
|
||||
return true
|
||||
return false
|
||||
|
||||
static func can_pick_instance(e: Dictionary, ctx: Dictionary = {}) -> bool:
|
||||
# CInstanceBase::__IsInViewFrustum. The native entity layer normally only
|
||||
# exposes actors after this check; explicit false is retained for UI/script
|
||||
# selection and headless replay fixtures.
|
||||
if e.has("in_view_frustum") and not bool(e.get("in_view_frustum", true)):
|
||||
return false
|
||||
if e.has("can_pick") and not bool(e.get("can_pick", true)):
|
||||
return false
|
||||
|
||||
# Door corpses are rejected by the dedicated door branch, then all dead
|
||||
# instances are rejected by the common IsDead() branch.
|
||||
if _is_building(e) and _kind(e) == KIND_WOODEN_DOOR and bool(e.get("dead", false)):
|
||||
return false
|
||||
if bool(e.get("dead", false)):
|
||||
return false
|
||||
|
||||
if _is_pc(e):
|
||||
# __MainCanSeeHiddenThing() in this 40250 build returns false, so
|
||||
# EUNHYEONG is not pickable. The other two invisibility affects are
|
||||
# unconditional gates as in InstanceBase.cpp:2275-2284.
|
||||
if _has_affect(e, AFFECT_EUNHYEONG) and not bool(ctx.get("can_see_hidden", false)):
|
||||
return false
|
||||
if _has_affect(e, AFFECT_REVIVE_INVISIBILITY) or _has_affect(e, AFFECT_INVISIBILITY):
|
||||
return false
|
||||
return true
|
||||
|
||||
# --- killer / party / empire / duel / pvp -----------------------------------
|
||||
|
||||
static func _is_killer(e: Dictionary) -> bool:
|
||||
|
||||
Reference in New Issue
Block a user