- item_tooltip_view.gd: 新增 avoid_rect 属性,tooltip 与装备窗口重叠时自动推到左侧 - inventory_ui.gd: 悬停装备时传入窗口矩形作为避让区域 - 包含其他累积的功能开发和测试文件
222 lines
6.3 KiB
GDScript
222 lines
6.3 KiB
GDScript
extends Node
|
|
|
|
## Shared headless client fixture for scene/skill-flow tests.
|
|
##
|
|
## It models the public M2Client surface used by GameScene, NetPlay and
|
|
## Quickbar. Quickslot mutations are server-confirmed immediately by
|
|
## emitting quickslots_changed; tests that need delayed confirmation should
|
|
## use their dedicated fixture and emit the signal manually.
|
|
|
|
signal entity_spawned(entity: Dictionary)
|
|
signal entity_despawned(vid: int)
|
|
signal entity_moved(vid: int)
|
|
signal entity_info(vid: int, entity: Dictionary)
|
|
signal entity_main_set(vid: int)
|
|
signal entity_dead(vid: int)
|
|
signal vitals_changed(vid: int)
|
|
signal point_changed(vid: int, point_type: int, value: int, amount: int)
|
|
signal points_changed(points: Dictionary)
|
|
signal target_info(vid: int, hp_percent: int)
|
|
signal observer_mode_changed(enabled: bool)
|
|
signal fishing_event(subheader: int, info: int, dir: int)
|
|
signal chat(type: int, vid: int, text: String)
|
|
signal damage(vid: int, amount: int, flag: int)
|
|
signal motion(vid: int, victim_vid: int, motion: int)
|
|
signal effect_cue(vid: int, name: String, special: int)
|
|
signal emoticon_requested(index: int)
|
|
signal gift_available()
|
|
signal script_dialog(skin: int, text: String)
|
|
signal affect_added(affect: Dictionary)
|
|
signal affect_removed(type: int)
|
|
signal guild_invite_ask(guild_id: int, guild_name: String, leader: String)
|
|
signal guild_make_requested()
|
|
signal warp(pos: Vector3, same_server: bool)
|
|
signal world_reset()
|
|
signal channel_changed(channel: int)
|
|
signal disconnected(reason: String)
|
|
signal entered_game()
|
|
signal login_failed(reason: String)
|
|
signal skills_changed()
|
|
signal skill_group_changed(group: int)
|
|
signal skill_cooldown_end(skill: int)
|
|
signal quickslots_changed()
|
|
|
|
var in_game := true
|
|
var main := 1000
|
|
var entities: Dictionary = {
|
|
1000: {"vid": 1000, "name": "Me", "race": 0, "kind": 0, "ch_type": 0,
|
|
"pos": Vector3.ZERO, "pos_cm": Vector3.ZERO, "moving_speed": 100,
|
|
"attack_speed": 100, "hp": 100, "max_hp": 100, "dead": false}
|
|
}
|
|
var ground_items: Array = []
|
|
var inventory: Array = []
|
|
var equipment: Array = []
|
|
var affects: Array = []
|
|
var skills: Array = [{"id": 1, "level": 5, "master": 0}]
|
|
var skill_group := 1
|
|
var points: Dictionary = {
|
|
"level": 30, "skill_active": 5, "skill_support": 3, "skill_horse": 2,
|
|
"casting_speed": 100, "hp": 100, "max_hp": 100, "sp": 100, "max_sp": 100,
|
|
"exp": 0, "next_exp": 1000,
|
|
}
|
|
var target_vid := 0
|
|
var quickslots: Array = []
|
|
var calls: Array = []
|
|
|
|
func is_in_game() -> bool:
|
|
return in_game
|
|
|
|
func get_main_vid() -> int:
|
|
return main
|
|
|
|
func get_entity(vid: int) -> Dictionary:
|
|
return entities.get(int(vid), {})
|
|
|
|
func get_entities() -> Array:
|
|
return entities.values()
|
|
|
|
func get_ground_items() -> Array:
|
|
return ground_items
|
|
|
|
func get_inventory() -> Array:
|
|
return inventory
|
|
|
|
func get_equipment() -> Array:
|
|
return equipment
|
|
|
|
func get_affects() -> Array:
|
|
return affects
|
|
|
|
func get_skills() -> Array:
|
|
return skills
|
|
|
|
func get_skill_group() -> int:
|
|
return skill_group
|
|
|
|
func get_points() -> Dictionary:
|
|
return points
|
|
|
|
func get_quickslots() -> Array:
|
|
return quickslots
|
|
|
|
func get_target() -> Dictionary:
|
|
return {"vid": target_vid}
|
|
|
|
func spawn(vid: int, name: String, pos: Vector3, is_main := false) -> void:
|
|
var entity := {"vid": vid, "name": name, "race": 0, "kind": 2,
|
|
"ch_type": 2, "pos": pos, "pos_cm": pos * 100.0, "moving_speed": 100,
|
|
"attack_speed": 100, "hp": 100, "max_hp": 100, "dead": false,
|
|
"is_main": is_main}
|
|
entities[vid] = entity
|
|
if is_main:
|
|
main = vid
|
|
entity_main_set.emit(vid)
|
|
entity_spawned.emit(entity)
|
|
|
|
func move(func_id: int, arg: int, rot: float, x: int, y: int) -> bool:
|
|
calls.append(["move", func_id, arg, rot, x, y])
|
|
return in_game
|
|
|
|
func attack(motion_id: int, victim: int) -> bool:
|
|
calls.append(["attack", motion_id, victim])
|
|
return in_game
|
|
|
|
func set_target(vid: int) -> bool:
|
|
target_vid = vid
|
|
calls.append(["set_target", vid])
|
|
return in_game
|
|
|
|
func click_npc(vid: int) -> bool:
|
|
calls.append(["click_npc", vid])
|
|
return in_game
|
|
|
|
func pickup_item(vid: int) -> bool:
|
|
calls.append(["pickup_item", vid])
|
|
return in_game
|
|
|
|
func add_fly_targeting(vid: int, x: int, y: int) -> bool:
|
|
calls.append(["add_fly_targeting", vid, x, y])
|
|
return in_game
|
|
|
|
func fishing(rot_deg: float) -> bool:
|
|
calls.append(["fishing", rot_deg])
|
|
return in_game
|
|
|
|
func cast_skill(motion_id: int, rot: float, x: int, y: int, arg := 0) -> bool:
|
|
calls.append(["cast_skill", motion_id, rot, x, y, arg])
|
|
return in_game
|
|
|
|
func use_skill(skill_id: int, victim: int) -> bool:
|
|
calls.append(["use_skill", skill_id, victim])
|
|
return in_game
|
|
|
|
func use_item(window: int, cell: int) -> bool:
|
|
calls.append(["use_item", window, cell])
|
|
return in_game
|
|
|
|
func send_emoticon(index: int) -> bool:
|
|
calls.append(["send_emoticon", index])
|
|
return in_game
|
|
|
|
func say(type: int, text: String) -> bool:
|
|
calls.append(["say", type, text])
|
|
return in_game
|
|
|
|
func shoot(skill_id: int) -> bool:
|
|
calls.append(["shoot", skill_id])
|
|
return in_game
|
|
|
|
func skill_up(skill_id: int) -> bool:
|
|
calls.append(["skill_up", skill_id])
|
|
return in_game
|
|
|
|
func quickslot_add(pos: int, type: int, ref: int) -> bool:
|
|
calls.append(["quickslot_add", pos, type, ref])
|
|
quickslots = quickslots.filter(func(q: Dictionary) -> bool: return int(q.get("pos", -1)) != pos)
|
|
quickslots.append({"pos": pos, "type": type, "ref": ref})
|
|
quickslots_changed.emit()
|
|
return in_game
|
|
|
|
func quickslot_del(pos: int) -> bool:
|
|
calls.append(["quickslot_del", pos])
|
|
quickslots = quickslots.filter(func(q: Dictionary) -> bool: return int(q.get("pos", -1)) != pos)
|
|
quickslots_changed.emit()
|
|
return in_game
|
|
|
|
func quickslot_swap(pos: int, change_pos: int) -> bool:
|
|
calls.append(["quickslot_swap", pos, change_pos])
|
|
var a := -1
|
|
var b := -1
|
|
for i in quickslots.size():
|
|
if int(quickslots[i].get("pos", -1)) == pos:
|
|
a = i
|
|
if int(quickslots[i].get("pos", -1)) == change_pos:
|
|
b = i
|
|
if a >= 0 and b >= 0:
|
|
var tmp: Dictionary = quickslots[a]
|
|
quickslots[a] = quickslots[b]
|
|
quickslots[b] = tmp
|
|
quickslots[a]["pos"] = pos
|
|
quickslots[b]["pos"] = change_pos
|
|
elif a >= 0:
|
|
quickslots[a]["pos"] = change_pos
|
|
elif b >= 0:
|
|
quickslots[b]["pos"] = pos
|
|
quickslots_changed.emit()
|
|
return in_game
|
|
|
|
func get_channel() -> int:
|
|
return 1
|
|
|
|
func set_item_proto(_proto: Object) -> void:
|
|
pass
|
|
|
|
func get_item_proto(_vnum: int) -> Dictionary:
|
|
return {}
|
|
|
|
func guild_answer_invite(_guild_id: int, _accept: bool) -> bool:
|
|
return in_game
|
|
|
|
func guild_answer_make(_name: String) -> bool:
|
|
return in_game
|