You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

208 lines
5.4 KiB
GDScript

extends CharacterBody3D
class_name Character
@onready var collision: CollisionShape3D = (%Collision)
@onready var pushbox: Hitbox = (%Pushbox as Hitbox)
@onready var status: Status = (%Status as Status)
@onready var view: View = (%View as View)
@onready var buff: Buff = (%Buff as Buff)
@onready var skill: Skill = (%Skill as Skill)
@onready var battle: Battle = (%Battle as Battle)
@onready var effect: Effect = (%Effect as Effect)
@onready var move: Move = (%Move as Move)
func init(id: int, cfg: CharacterCfg, team: Enum.ETeam, owner_id: int):
status.id = id
status.owner_id = owner_id
status.team = team
status.cfg = cfg
view.init(cfg.sprite_frames)
skill.init()
effect.init(cfg.type)
effect.cast_self_particle()
set_body_scale(cfg)
func init_after():
var cfg: CharacterCfg = status.cfg as CharacterCfg
set_status("hp_max", cfg.hp_max)
set_status("shield_max", cfg.shield.shield_max)
set_status("stun_max", cfg.stun.stun_max)
set_status("mp_max", cfg.mp.mp_max)
set_status("mp_sub_max", cfg.mp.mp_sub_max)
set_status("hp", cfg.hp_max)
set_shield(cfg.shield.shield_max)
add_mp_sub(0, true)
func set_body_scale(cfg: CharacterCfg) -> void:
if not cfg:
cfg = status.cfg
if not cfg:
return
var half_height: float = Setting.pixel_size * cfg.sprite_harf_height
var height: float = half_height * 2
var width: float = Setting.pixel_size * cfg.sprite_width
var body_scale: Vector3 = Vector3(width, height, width)
collision.position = Vector3(0, half_height, 0)
collision.scale = body_scale
pushbox.position = Vector3(0, half_height, 0)
pushbox.scale = body_scale
status.basic_offset = Vector3(0, half_height, 0)
status.ui_offset = Vector3(0, height*1.1, 0)
status.ui_center_offset = Vector3(0, half_height, 0)
status.radius = width
status.height = height
effect.set_body_scale(body_scale)
func set_material(material: ShaderMaterial, material_sub: ShaderMaterial):
view.material_override = material
view.material_override.next_pass = material_sub
func is_on_stair()->bool:
if velocity.x > 0:
if raycast_stair(Vector3.RIGHT): return true
elif velocity.x < 0:
if raycast_stair(Vector3.LEFT): return true
if velocity.z > 0:
if raycast_stair(Vector3.BACK): return true
elif velocity.z < 0:
if raycast_stair(Vector3.FORWARD): return true
return false
func raycast_stair(dir: Vector3)->bool:
var width: float = Setting.pixel_size * status.cfg.sprite_width
var from: Vector3 = position + (Vector3.UP * Setting.pixel_size * 6) + (dir * width * 0.4)
var to: Vector3 = from + dir * width * 0.2
var up: Vector3 = to + Vector3.UP * Setting.pixel_size * 4
return Util.raycast_wall(from, to) and Util.raycast_wall(up, to)
#==getter==
func id()->int: return status.id
func cfg()->CharacterCfg: return status.cfg
func team()->Enum.ETeam: return status.team
func pos2D()->Vector2: return Vector2(position.x, position.z)
func pos()->Vector3: return position
func radius()->float: return status.radius
func height()->float: return status.height
func view_pos()->Vector3: return position + view.position
func ui_pos()->Vector3: return position + status.ui_offset
func ui_pos_center()->Vector3: return position + status.ui_center_offset
func target()->int: return status.target
#==interface==
func get_status(status_name: String) -> Variant: return status.get_status(status_name)
func set_status(status_name: String, value): status.set_status(status_name, value)
func set_shield(value: float):
status.set_shield(value)
func set_pos(pos: Vector3):
position = pos
SignalManager.character_pos_changed.emit(id(), pos())
func move_to(dir: Vector2): set_status("move_dir", dir.normalized())
func move_stop():
set_status("move_dir", Vector2.ZERO)
move.stop()
func add_buff(buff_name: String, duration: float, ignore_pause: bool = false): buff.add_buff(buff_name, duration, ignore_pause)
func remove_buff(buff_name: String): buff.remove_buff(buff_name)
func has_buff(buff_name: String)->bool: return buff.has_buff(buff_name)
func set_hit_move(hit_back_dir: Vector2, hit_back_speed: float, hit_up_speed: float):
status.hit_back_dir = hit_back_dir
status.hit_back_speed = hit_back_speed
status.hit_up_speed = hit_up_speed
func set_pause_time(pause_time: float):
status.pause_time=pause_time
add_buff("pause", pause_time)
func cancel_skill():
skill.cancel_skill()
func set_view_trigger(trigger_name: String):
status.set("trigger_%s" % trigger_name, true)
func show_hit_text(value: String):
SignalManager.character_hit_text.emit(id(), value)
func show_hit_damage(value: float):
SignalManager.character_hit_damage.emit(id(), value)
func add_mp_sub(value: float, from_battle: bool):
battle.add_mp_sub(value, from_battle)
func cost_mp(value: int):
battle.cost_mp(value)
func set_target(target: int):
set_status("target", target)
func cast_particle(resource: Resource, is_attach: bool, offset: Vector3 = Vector3.ZERO, scale: Vector3 = Vector3.ONE):
effect.cast_particle(resource, is_attach, offset, scale)
func get_character_owner() -> Character:
var owner: Character = Global.character_mgr.get_character(status.owner_id) as Character
if owner: return owner
return self
func attack1() -> bool:
return battle.character_attack1()
func attack2() -> bool:
return battle.character_attack2()